0
0
Fork 0

bump_project_version: resume from GVL when Project Information missing

Previously, when a project had no Project Information node (e.g. one
created from the Standard template via create_project), the bump
flow read pi.version as None, the seed-check fired, and every call
re-seeded to 1.0.0.0 -- subsequent revision/minor/major bumps were
no-ops because the script never saw the actual current version.

Surfaced on MCPTest2 today: bumping revision after editing PLC_PRG
returned '1.0.0.0' instead of '1.0.1.0' because the seed kept firing.

Fix: when Project Information is missing, fall back to reading the
existing _MCP_PROJECT_VERSION.sVersion via the textual_declaration
of the GVL we ourselves maintain. So the source-of-truth chain is:

  pi.version (when Project Information exists)
    -> falls back to GVL.sVersion (when Project Information missing
                                    but the GVL has been written
                                    by a prior bump)
    -> falls back to seed at 1.0.0.0 (true first-run, no GVL yet)

Implementation: read_version_from_gvl(primary_project) walks the
active Application's children for the named GVL and parses the
sVersion := '...' literal out of its textual_declaration with a
4-part regex. Returns None if the GVL doesn't exist OR its decl
doesn't match the expected shape; caller treats None as "no prior
version, seed". Soft-fails on any access exception (the bump is
the primary outcome, this is just resume-from-state).

This is the kind of "every arising problem fixed at the fork, not
worked around in one-offs" hygiene the user called out.
This commit is contained in:
Karstein Phobic Nyvold Kvistad 2026-04-26 00:53:10 +02:00
parent b07c24559e
commit 5cbd540fde

View file

@ -1,4 +1,4 @@
import sys, scriptengine as script_engine, traceback
import sys, scriptengine as script_engine, traceback, re
# Bumps one part of the 4-part Project Information.version field of the
# primary project. Convention (per CODESYS / 3S / WAGO library practice):
@ -58,6 +58,42 @@ def parse_version(v):
return tuple(nums)
def read_version_from_gvl(primary_project):
"""When Project Information is missing, read the current version back
from the runtime anchor GVL (_MCP_PROJECT_VERSION.sVersion) so subsequent
bumps can resume from the actual current state instead of re-seeding to
1.0.0.0 on every call. Returns the version string or None if the GVL
doesn't exist yet (true first-run)."""
try:
app = getattr(primary_project, 'active_application', None)
except Exception:
app = None
if app is None:
try:
apps = primary_project.find('Application', True)
if apps:
app = apps[0]
except Exception:
pass
if app is None:
return None
try:
for child in app.get_children(False):
try:
if child.get_name() != VERSION_GVL_NAME:
continue
decl = child.textual_declaration.text or ''
m = re.search(r"sVersion\s*:\s*STRING\s*:=\s*'(\d+\.\d+\.\d+\.\d+)'", decl)
if m:
return m.group(1)
return None
except Exception:
pass
except Exception:
pass
return None
def maintain_version_gvl(primary_project, version_str):
"""Find or create the _MCP_PROJECT_VERSION GVL under the active
Application, and set its declaration so the running PLC carries the
@ -179,7 +215,11 @@ try:
"maintained. To add the Project Information node, open the "
"Project menu -> Project Information in the IDE; subsequent bumps "
"will then update both metadata and GVL.")
before_raw = None
# Fall back to reading the existing GVL so we resume from the actual
# current version instead of re-seeding to 1.0.0.0 every call.
before_raw = read_version_from_gvl(primary_project)
if before_raw:
print("DEBUG: Project Information missing, resuming from GVL: %s" % before_raw)
else:
before_raw = pi.version
before_str = str(before_raw) if before_raw is not None else None