Skip to content

fix: check -p applies exec's version gates (mendixlabs/mxcli#1434) - #1385

Merged
ako merged 1 commit into
mainfrom
fix/1434-check-version-aware
Oct 15, 2026
Merged

ako merged 1 commit into
mainfrom
fix/1434-check-version-aware

Conversation

@ako

@ako ako commented Oct 15, 2026

Copy link
Copy Markdown
Owner

Fixes mendixlabs#1434.

The bug

mxcli check script.mdl -p app.mpr passed scripts that exec then refused because of the project's Mendix version.

The issue's own error was the write-time property floor (StableId / CaseValues on 9.24), which #1410 already fixed. The gap that remained, reproduced on the 9.24.30 fixture modelsdk/mpr/testdata/v1-project/App.mpr:

  • A script with a module, a microflow and create view entity passes check.
  • Exec writes statements 1–2, refuses the third with "create view entity requires Mendix 10.18.0+", and rolls back.

Root cause

Every version gate was an inline checkFeature(ctx, …) call inside a statement handler: about two dozen calls across 17 files, several conditional on the statement's contents. Neither check nor exec's pre-flight runs handlers, so neither could see a gate. This is the check-versus-exec case in docs-wiki/bug-patterns/duplicate-resolver-drift.md.

The fix

  • New mdl/executor/version_gates.go.
    • statementVersionGates(stmt) is now the one mapping from a statement to the features it needs. The minimum versions stay in sdk/versions/*.yaml.
    • The handlers refuse through checkVersionGates.
    • Executor.CheckVersionGates(prog) reports the same refusals as MDL-VERSION01, numbered by statement, with exec's own message and hint.
  • Check and pre-flight call it. cmd_check.go calls it once the project is connected, read-only. exec_preflight.go calls it too, so exec (and diff) now refuse before writing anything.
  • Without -p nothing changes. There is no version to check against.

Gates covered:

  • REST client, data transformer, published REST (create, alter, grant)
  • OData SupportsGraphQL
  • Message definition document
  • Workflow settings groups
  • View entity
  • Agent documents
  • Page parameters
  • Microflow send email and deep-link URL
  • Nanoflow synchronize unsynchronized
  • Workflow event handlers, agent tasks, event sub-processes and timer event sub-processes, notification events
  • Alter workflow

Tests (written first)

  • TestCheck_RefusesWhatTheProjectVersionCannotStore:
    • Check on a 9.24 copy reports "statement 5: create view entity requires Mendix 10.18.0+" and exits 1.
    • The control without the view entity passes.
    • The project files are unchanged.
  • TestExecPreflight_AgreesWithCheckOnVersionGates: the pre-flight refuses the gated script ("Nothing was written"). The ungated flows pass the pre-flight and write on 9.24.
  • TestCheckVersionGates_ReportsEveryHandlerGate: every gate is reported below its minimum version with the handler's exact text, and none is reported at 11.99.
  • TestCheckVersionGates_UngatedFormsPass.
  • TestCheckFeatureIsOnlyCalledFromTheGateTable: a source scan that fails on a direct checkFeature call outside the table, so a new gate can't bypass check.

Revert check: with only the check and pre-flight wiring reverted, both cmd tests fail with the reported symptom. They pass with it restored.

Also in this PR

  • Finding file, and bug-test mdl-examples/bug-tests/1434-check-version-gates.mdl.
  • Docs: check-syntax/reference/references-resolved.md, with a one-line pointer from the skill so it stays under 700 lines, plus docs-site/src/tutorial/validation.md.
  • make build, make lint and make check-findings pass. The executor and cmd/mxcli tests pass on the current base.

Behaviour changes

  • exec now refuses a version-gated script before writing, instead of mid-way with a rollback.
  • In alter workflow, the agent-task and notification gates run before the completion-rule check. This only changes which error appears when both apply.

Not done (exec-only; check cannot know these from the script)

  • Gates that depend on stored content: drop or alter a message definition document that isn't there.
  • The write-time property floor, which needs the encoded BSON.
  • Version checks inside builders that read the version directly instead of through checkFeature: showpage args, notify, contract, the 11.15 message-definition collection removal, workflow handler/ref checks, the pluggable database source.
  • workflows.basic has a 9.0.0 minimum in the registry while the hint says 9.12+. This mismatch was already there and is left alone.

🤖 Generated with Claude Code

https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF


Generated by Claude Code

`mxcli check -p` passed scripts that `mxcli exec` then refused for the
project's Mendix version (e.g. `create view entity` on a 9.24 project),
after running the statements before the refused one. Every version gate
lived inline in its handler as a checkFeature call, which neither check
nor exec's pre-flight ever reaches.

The gates now come from one statement-to-feature table,
statementVersionGates (mdl/executor/version_gates.go). The handlers
refuse through checkVersionGates(ctx, stmt); Executor.CheckVersionGates
reports the same refusals as MDL-VERSION01, run by `check -p` and by
exec's pre-flight, so exec refuses before anything is written. A test
fails on any new direct checkFeature call outside the table.

Still exec-only: gates that depend on stored state (drop/alter of a
message definition document that is not there) and the write-time
property floor. The issue's own StableId/CaseValues refusal was the
latter and is already cured by #1410; the flows now pass both check and
exec on 9.24.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W3x8Fyvir8kLyPgJs1BDmF
@ako
ako merged commit 26f9a06 into main Oct 15, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check is not version-aware: it passes scripts that exec then refuses for a version reason

2 participants