Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
70d589f
ci: run the no-compile checks first and gate every job on them
claude Nov 2, 2026
5655b9f
fix(describe): print the concurrency error message in the default lan…
ako Nov 2, 2026
da719de
TEMP CONTROL: add an unformatted Go file (to be reverted)
claude Nov 2, 2026
40ee1ec
Revert the TEMP CONTROL unformatted file
claude Nov 2, 2026
59d89b4
Merge pull request #1898 from ako/fix/1869-concurrency-message-language
ako Nov 2, 2026
3e05898
Merge pull request #1899 from ako/feature/1887-quick-checks-first
ako Nov 2, 2026
8a7d181
fix(test): no MDL-V1-SLASH / MDL-DEPR001 per test on a headerless sui…
ako Nov 2, 2026
1f29526
fix(test): no "Module 'MxTest' already exists" on a clean project (#1…
ako Nov 2, 2026
54aab8e
fix(visitor): store a doc comment above alter entity … add attribute …
ako Nov 2, 2026
1cf67b0
fix(test): repeat a failed build's errors above the summary (#1834)
ako Nov 2, 2026
985e232
fix(test): retry the boot's build once when mxbuild --serve times out…
ako Nov 2, 2026
2c1a82a
fix(pages): store a dynamic-text parameter's dateFormat in Mendix's s…
ako Nov 2, 2026
2431f38
fix(test): each --local hsqldb run starts on an empty test database (…
ako Nov 2, 2026
eda66b0
fix(check): refuse like/between/in/is null instead of dropping them (…
ako Nov 2, 2026
69cffcc
fix(describe): print a pop-up page's width and height when they are 0…
ako Nov 2, 2026
8cb4f97
fix(diff-local): list untracked units as new against the working copy…
ako Nov 2, 2026
ad2e2cb
fix(check): refuse an unparenthesised if-expression as an operand (#1…
ako Nov 2, 2026
448f633
fix(security): modify a demo user in place (#1859)
ako Nov 2, 2026
242c770
fix(test): each --local run also starts on an empty PostgreSQL test d…
ako Nov 2, 2026
dc86325
Merge pull request #1907 from ako/fix/1835-xpath-enum-like-check
ako Nov 2, 2026
9c94196
Merge main into fix/1868-plus-if-operand
ako Nov 2, 2026
ad9bf7e
Merge branch 'main' of https://github.com/ako/mxcli into fix/1863-alt…
ako Nov 2, 2026
2d9d6cd
Merge branch 'main' of https://github.com/ako/mxcli into fix/1864-dyn…
ako Nov 2, 2026
70d152e
Merge branch 'main' of https://github.com/ako/mxcli into fix/1867-dif…
ako Nov 2, 2026
fc477b2
Merge branch 'main' of https://github.com/ako/mxcli into fix/1881-pop…
ako Nov 2, 2026
c93bbd7
Merge branch 'main' of https://github.com/ako/mxcli into fix/1859-dem…
ako Nov 2, 2026
cc41b50
Merge pull request #1908 from ako/fix/1868-plus-if-operand
ako Nov 2, 2026
dcc0b83
Merge pull request #1901 from ako/fix/1856-mxtest-already-exists
ako Nov 2, 2026
c1e13a8
Merge pull request #1900 from ako/fix/1855-test-slash-warnings
ako Nov 2, 2026
71d2198
Merge pull request #1902 from ako/fix/1853-fresh-hsqldb-test-db
ako Nov 2, 2026
c2d8688
Merge pull request #1903 from ako/fix/1834-test-build-error-first
ako Nov 2, 2026
d5eb7e1
Merge branch 'main' into fix/1881-popup-dimensions-describe
ako Nov 2, 2026
4166abb
Merge pull request #1904 from ako/fix/1881-popup-dimensions-describe
ako Nov 2, 2026
f49afc6
Merge branch 'main' into fix/1867-diff-local-untracked
ako Nov 2, 2026
3279bbe
Merge pull request #1905 from ako/fix/1867-diff-local-untracked
ako Nov 2, 2026
714f830
Merge branch 'main' of https://github.com/ako/mxcli into fix/1863-alt…
ako Nov 2, 2026
8fe24f6
Merge branch 'main' of https://github.com/ako/mxcli into fix/1864-dyn…
ako Nov 2, 2026
5963137
Merge branch 'main' of https://github.com/ako/mxcli into fix/1859-dem…
ako Nov 2, 2026
d46078a
Merge branch 'main' of https://github.com/ako/mxcli into fix/1863-alt…
ako Nov 2, 2026
adc06bb
Merge pull request #1906 from ako/fix/1859-demo-user-in-place
ako Nov 2, 2026
6300878
Merge branch 'mendixlabs:main' into main
ako Nov 2, 2026
7c0f2b5
Merge branch 'main' of https://github.com/ako/mxcli into fix/1863-alt…
ako Nov 2, 2026
8823a40
Merge branch 'main' of https://github.com/ako/mxcli into fix/1864-dyn…
ako Nov 2, 2026
43b74be
Merge pull request #1909 from ako/fix/1863-alter-add-attribute-doc
ako Nov 2, 2026
12f7798
Merge branch 'main' of https://github.com/ako/mxcli into fix/1864-dyn…
ako Nov 2, 2026
c57f29d
Merge pull request #1910 from ako/fix/1864-dynamictext-dateformat-custom
ako Nov 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli/testrunner", "date": "2026-11-02", "symptom": "A suite with one test that does not build (CE0161 in an XPath that passes `mxcli check`) ended `mxcli test --local` in \"Passed: 0, Errors: 1, Skipped: 108\", and read as if every test had failed for no reason. Separately, a `mxbuild --serve` that stopped answering ended the run in \"local runtime: build: serve build request to http://127.0.0.1:6544/build: ... context deadline exceeded\", and the next run passed with nothing changed", "cause": "The build error was attributed (since mendixlabs/mxcli#1104) but printed only on its ERROR row, among one SKIP row per other test that each repeated \"not run: another test in this run failed to build\" — the cause was present and buried. The boot's build called `ServeServer.Build` once, so a wedged serve process was reported as the run's error although a fresh process builds the same project fine", "file": "`cmd/mxcli/testrunner/results.go` (`printBuildFailure`, `SuiteResult.BuildFailed` set by `resultsForBuildFailure`); `cmd/mxcli/docker/serve_timeout_retry.go` (`buildRetryingServeTimeout`, used by `StartLocalApp`)", "insight": "Surfacing is about position, not presence: the error had been in the output for months. Put it directly above the summary line, where the eye lands at the end of a long run. For the retry, retry only on a timeout (`net.Error.Timeout()`), once, on a FRESH process — a failed build is the model's verdict and a refused connection is a dead process, and retrying either hides it. The fake timeout in the unit test is cross-checked against a real `http.Client{Timeout}` error wrapped as `ServeServer.Build` wraps it, so the detection cannot pass against a shape net/http never produces. Runtime control on 11.12.2 with a real CE0161 test: main printed the error on its row only, the fix also in the block above the summary", "refs": ["ako/mxcli#1834", "mendixlabs/mxcli#1685", "mendixlabs/mxcli#1104"], "rules": [], "ce": ["CE0161"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli", "date": "2026-11-02", "symptom": "`mxcli test` on a headerless (mdl 0) `.test.mdl` printed one MDL-V1-SLASH and one MDL-DEPR001 warning per test, before any result — 104 warnings for a 52-test suite — although the `/` separators are what the test format requires. A suite with `mdl 1;` printed none, and `mxcli check` of the test file printed none either", "cause": "The warnings were about the script the runner generated, not the author's file. `GenerateTestFlows` and `GenerateTestRunner` kept the mdl 0 spellings — `CREATE OR REPLACE MICROFLOW` and a `/` line after every `END;` — on the theory that a headerless suite should get the script it always had; but mdl 0 warns on both, and the injecting `mxcli exec` printed those warnings verbatim. #943 had fixed the endpoint script and #847 the check rendering, both by writing the canonical form; the per-test generators were the last caller still switching on the version", "file": "`cmd/mxcli/testrunner/generator.go` (`createFlow` is now a constant `CREATE OR MODIFY MICROFLOW`; `writeFlowEnd` writes `END;` alone under every version)", "insight": "The canonical spelling is valid under mdl 0 as well, so the generators never needed a version switch for it — only the header follows the suite. Test generated scripts through `visitor.Build` and assert `LanguageNotes` and `Deprecations` are empty, with bodies valid under both versions so any note is the generator's; the previous test (`TestGeneratorsHeaderlessSuiteUnchanged`) only asserted the script parsed, which the warning-laden one did. Runtime control on an 11.12.2 app, same headerless file: main 2 MDL-V1-SLASH + 2 MDL-DEPR001, fix 0, both runs 2/2 PASS", "refs": ["ako/mxcli#1855", "mendixlabs/mxcli#1697", "ako/mxcli#943"], "rules": ["MDL-V1-SLASH", "MDL-DEPR001"], "ce": []}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli/docker", "date": "2026-11-02", "symptom": "`mxcli test --local --db-type hsqldb` kept `deployment/data/database/hsqldb/<app>_test` between runs. Data a previous run committed (an after-startup seed, an `@cleanup none` test) was still there on the next run, so an idempotent init skipped seeding and tests failed on stale data. Measured on 11.12.2: a test asserting an empty table PASSed on run 1 and FAILed on run 2 after another test committed one row", "cause": "The file database is created by the runtime the first time it boots and opened as-is afterwards. `prepareLocalAppDatabase` had nothing to do for it, so nothing ever removed it; the `_test` suffix kept it off the dev loop's data but not off the previous test run's", "file": "`cmd/mxcli/docker/localapp.go` (`LocalAppOptions.FreshFileDB`, `removeFileDatabase` — refuses a name that is not one path element); `cmd/mxcli/testrunner/localapp_options.go` sets it for the file database", "insight": "Scope the reset to the caller whose database is its own scratch: the option lives on `LocalAppOptions` but only the test runner sets it, so `run --local --db-type hsqldb` (the developer's data) is untouched, and the test pins that the dev database beside the scratch one survives. The name is joined onto the deployment dir and removed recursively, so it is refused unless it is a single path element. Runtime control: same two-test file, main run 2 FAIL (count 1), fix both runs PASS. PostgreSQL's `<app>_test` database has the same carry-over (measured: run 2 FAIL) and is not reset by this change", "refs": ["ako/mxcli#1853", "mendixlabs/mxcli#1695"], "rules": [], "ce": []}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli/docker", "date": "2026-11-02", "symptom": "`mxcli test --local` on PostgreSQL (the default) kept the `<app>_test` scratch database between runs, as the file database did before ako/mxcli#1853: a test asserting an empty table PASSed on run 1 and FAILed on run 2 after an `@cleanup none` test committed one row (11.12.2, PostgreSQL 15)", "cause": "`EnsureDatabase` creates the role and database only when missing and is otherwise a no-op, so a second run boots on whatever the first left. Nothing in the boot ever emptied it", "file": "`cmd/mxcli/docker/localapp.go` (`LocalAppOptions.FreshDB`, renamed from FreshFileDB, now also covers PostgreSQL via `emptyPostgresDatabase`); `cmd/mxcli/testrunner/localapp_options.go` sets it for every --local run", "insight": "Empty in place rather than drop and recreate: `DROP OWNED BY CURRENT_USER`, as the app role, connected to the scratch database, removes only objects in that database, so the dev loop's database owned by the same role cannot be reached, and nothing depends on CREATEDB or a superuser at the moment the data is already gone. Public survives (owned by pg_database_owner from PG15; by postgres before) and the role can still create in it. Measured before choosing: 88 relations to 0 on a database the runtime had booted on. Runtime control: main run 2 FAIL, fix both runs PASS, and the dev database `tapp` kept its 87 tables across both runs", "refs": ["ako/mxcli#1853"], "rules": [], "ce": []}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "cmd/mxcli", "date": "2026-11-02", "symptom": "`mxcli test tests/ --local` printed \"Module 'MxTest' already exists\" on a project that had no MxTest module before the run, between \"Created microflow: MxTest.RegisterEndpoint\" and the first test microflow", "cause": "The endpoint runner injects two scripts in sequence: `GenerateEndpointMDL` (which creates the module) and then `GenerateTestFlows`, which began with its own `CREATE MODULE MxTest;`. The second create found the module the first had just made, and exec's no-op message for an existing module went straight to the user's terminal. The message was true about the second script and false about the project", "file": "`cmd/mxcli/testrunner/generator_endpoint.go` (`GenerateTestFlows` no longer emits `CREATE MODULE`; every caller — the --local boot, `reinjectTests` under --watch, `runAttached` — runs it into a project that already holds the module)", "insight": "Read the run's own output for messages about the runner's scripts rather than the project: the line names a fact (the module exists) whose cause is mxcli's injection order, so it reads as the user's project being dirty. Before dropping the statement, check every caller's precondition — --attach and --watch reinject the test-flow script alone, and both run into a project hosting the endpoint, so the module is always there; if it were not, the microflow create fails loudly rather than the module being silently minted. The test pins both halves: the flow script creates no module, and the endpoint script still does. Runtime control on an 11.12.2 app: main printed the line once per run, the fix zero, both 2/2 PASS", "refs": ["ako/mxcli#1856", "mendixlabs/mxcli#1698"], "rules": [], "ce": []}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-02", "symptom": "`create or modify demo user 'x'` on an existing user made `mxcli diff` show DemoUsers[1].Password, DemoUsers[1].UserName, DemoUsers[2].Entity … changing for users the statement never named; after exec the modified user was last in the list", "cause": "execCreateDemoUser modified a user by RemoveDemoUser + AddDemoUser, which appends — the user moved to the end and every later user shifted one index; AddDemoUser already updates by user name in place", "file": "mdl/executor/cmd_security_write.go (execCreateDemoUser: drop the RemoveDemoUser call)", "insight": "A remove-then-add 'update' of a list member is a reorder, and an index-keyed diff blames every sibling. Use the backend's update-in-place path. The test mock of AddDemoUser appended unconditionally, which hid that the backend contract is add-or-update; make mocks honour the contract they stand in for.", "refs": ["mendixlabs/mxcli#1701", "ako/mxcli#1859", "mdl/executor/demo_user_modify_in_place_test.go"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-02", "symptom": "On an en_US project with de_DE also enabled, describe microflow prints the concurrency error message in German ('-- also translated into en_US'); drop + create from that output stores the German text under en_US, so the English message is gone. check, exec and mx check are clean; a show message text in the same flow describes and rebuilds correctly", "cause": "describableMessage (cmd_microflows_show.go) chose the alphabetically first language (de_DE < en_US) instead of the project-default rule every other described text uses (pickTextTranslation, #702)", "file": "mdl/executor/cmd_microflows_show.go, describe_language.go", "insight": "A describer that picks its own language for one property is a write on the round trip, the same class as #705: exec stores what describe prints in the project default. The existing test passed only because en_US < nl_NL sorts the default first; a language test needs a pair where the default does NOT sort first, plus a control with the default flipped. Grep for any other sort.Strings over Translations keys in a describer", "refs": ["ako/mxcli#1869", "mendixlabs/mxcli#1711", "#702"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-02", "symptom": "`describe page` of a pop-up page (Atlas_Core.PopupLayout) printed neither `PopupWidth:` nor `PopupHeight:` when both were 0, so an auto-size pop-up read the same as one whose size was never set; a review gate built on DESCRIBE passed unconfigured pages", "cause": "#713 made DESCRIBE suppress the default 0 everywhere, which is lossless for exec but erases a value a reviewer reads; and the obvious way to know the layout (FormCall.Layout, a binary ID) is absent on Studio Pro pages, which store FormCall.Form as a qualified name", "file": "mdl/executor/cmd_pages_describe.go (popupDimensionProps, layoutTypeByName)", "insight": "Print the dimensions, 0 included, only where they mean something: a page whose layout's LayoutType is ModalPopup; elsewhere keep suppressing the default. Resolve the layout by FormCall.Form's qualified name, not by ID: the first fix keyed on FormCall.Layout passed review-by-reading and did nothing on a real page, caught only by describing a Studio Pro-authored page (testapp Administration.ChangePasswordForm, 0/0 on PopupLayout). Field names PopupWidth/PopupHeight measured on testapp pages, present on every page, popup or not.", "refs": ["mendixlabs/mxcli#1713", "ako/mxcli#1881", "mdl/executor/describe_page_popup_dimensions_test.go"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-02", "symptom": "`diff-local --ref HEAD` (MPR v2) reported `0 new, 3 modified` while dozens of untracked .mxunit files sat under mprcontents/ — a new module's pages and flows, never `git add`ed, were missing", "cause": "findChangedMxunitFiles asked only `git diff --name-status <ref>`, which lists tracked files; an untracked file is invisible to it", "file": "mdl/executor/cmd_diff_local.go (findChangedMxunitFiles: `git ls-files --others --exclude-standard` in single-ref mode)", "insight": "Against the working tree the question is 'what is in the folder that is not at ref', and git splits the answer between diff (tracked) and ls-files --others (untracked). Ask both; a range compares two commits and must not look at the working tree. Stubbed-git tests must answer the new command, or they fail with exit 128. Real-git test: commit a unit, write a second one untracked, diff HEAD → want 1 new.", "refs": ["mendixlabs/mxcli#1709", "ako/mxcli#1867", "mdl/executor/cmd_diff_local_untracked_test.go"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-02", "symptom": "ako/mxcli#1864 / mendixlabs/mxcli#1706: `ContentParams: ({1} = Starts format (dateFormat: custom, customDateFormat: 'd MMM yyyy, HH:mm'))` — check and exec clean, but the runtime shows the default date format (the report's `diff` churn did not reproduce on PedApp 11.13: a create-or-replace rerun diffs clean with the pre-fix binary too)", "cause": "MDL-WIDGET18 accepts dateFormat/enumFormat case-insensitively, but formattingInfoFromParamFormat copied the value verbatim, so the BSON held \"DateFormat\": \"custom\" — not a Mendix enum value. The date picker's path (inputFormattingInfo) already went through pages.CanonicalDateFormat; the template-parameter path never did", "file": "mdl/executor/cmd_pages_builder_v3_widgets.go (formattingInfoFromParamFormat), sdk/pages/formatting.go (CanonicalEnumFormat)", "fix": "Canonicalise dateFormat via pages.CanonicalDateFormat and enumFormat via the new pages.CanonicalEnumFormat. The converter is the one source for every ClientTemplateParameter FormattingInfo (dynamic text, Data grid 2 column templates, ALTER PAGE column path), so all of them are covered", "test": "mdl/executor TestFormattingInfoFromParamFormat_EnumCase (custom, datetime, TIME, enumformat image; control Custom). Fails on main with \"custom\" stored; bson dump on PedApp 11.13 shows DateFormat \"custom\" before the fix", "insight": "The report read as a drop (\"stored with only customDateFormat\") but the value was stored — in a spelling Mendix reads as the default. A validator that lowercases before checking an enum and a writer that does not is the shape to grep for: compare every strings.ToLower in a check against the matching store, since the existing test passed `Custom` capitalised and so never exercised the gap", "refs": ["ako/mxcli#1864", "mendixlabs/mxcli#1706"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-02", "symptom": "ako/mxcli#1868 (mendixlabs/mxcli#1710, 11.12.4): `declare $L String = 'x' + if $c then 'a' else 'b';` passed check (\"Syntax OK\", \"Check passed!\") and exec, and mx check failed CE0117", "cause": "MDL's expression grammar admits an if-expression at any primary position, Mendix's only where a whole expression goes; the writer stores the source as written, so the unparenthesised operand reached the model. No rule compared the two grammars", "file": "mdl/executor/validate_if_operand.go (ifOperands, checkIfOperand, called from checkExprFunctions so microflows and nanoflows share it), mdl/executor/validate.go (execEnforcedMicroflowRules)", "fix": "MDL-IFOPERAND01 error, exec-enforced: an IfThenElseExpr as a direct operand of a binary operator or a unary minus, with the parenthesised form as the fix", "test": "mdl/executor/if_operand_test.go — +, and, =, unary minus, return, nanoflow, check/exec agreement; controls parenthesised, else-branch absorbing the +, function argument, not() argument, if as else branch. Revert (hook call commented out): the five bad shapes and the nanoflow and agreement tests failed. Measured on mxbuild 11.12.2, one microflow per shape and mx check -j to attribute each error: every bad shape CE0117, every control clean", "insight": "mx check prints the element (\"Create variable activity 'Create Boolean variable'\"), not the microflow, so a one-microflow-per-shape matrix is unattributable from the console; `mx check -j out.json` carries document-name per error. The boundary was not the operator but the position: `if … else 'b' + 'x'` builds because the else branch takes the `+`, so a rule on `+ if` in the source text would have been right by accident and wrong for `-if`", "refs": ["ako/mxcli#1868", "mendixlabs/mxcli#1710"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-11-02", "symptom": "ako/mxcli#1835 (mendixlabs/mxcli#1686, 11.12.4): `retrieve $L from Mod.Item where Name like 'A-%'` passed check and exec, then failed the build with CE0161. The reported second shape, `Status = Mod.ENUM_X.VALUE`, no longer reproduced: the writer already stores 'VALUE' and it builds clean on 11.12.2", "cause": "the MDL expression rule is shared with OQL and admits LIKE / NOT LIKE / BETWEEN / IN / MATCH, but visitor buildComparisonExpression returned only the left operand for them, so the constraint was stored as `[Name]` (and `where N between 1 and 5` as `[N]`); in a microflow expression `$s like 'A%'` was stored as `$s`. IS NULL / IS NOT NULL were kept as a BinaryExpr but nothing refused them", "file": "mdl/visitor/visitor_microflow_expression.go (oqlOnlyComparisonOperator), mdl/executor/validate_oql_comparisons.go (checkXPathOQLComparisons, checkExpressionOQLComparisons)", "fix": "the visitor keeps the comparison as written (SourceExpr over a BinaryExpr with the lowercased operator); check reports MDL091 (exec-enforced) naming the operator, CE0161 in a retrieve constraint and CE0117 in an expression, with the XPath/expression spelling of the same test", "test": "mdl/executor/xpath_oql_comparison_test.go — like/not like/between/in in a constraint, like in a declare, check and exec agreeing; controls starts-with, contains, >= and <=, a literal containing 'like', an enum key. Revert: every bad case got [] and the constraint serialized as \"Name\". Measured on mxbuild 11.12.2: [Name like 'A-%'], [Name not like …], [N between 1 and 5], [N in (1, 2)], [Name is null] CE0161; $s like / is null / in (…) CE0117; starts-with, not(contains()), >= and <=, = or =, = empty, Status = Mod.Enum.Value, startsWith() clean", "insight": "A check cannot see what the visitor never put in the AST: the report read as a missing rule, but the operator was gone before any rule ran, so the stored constraint differed from the script and describe printed the truncated form. When a grammar rule is shared with another language (here OQL), audit every alternative the visitor ignores — each one is a silent drop. describe's own XPath reader drops the same operators on the way out (a stored [Name like 'A-%'] describes as `where Name`)", "refs": ["ako/mxcli#1835", "mendixlabs/mxcli#1686"]}
Loading
Loading