Skip to content

Sync ako/mxcli: agent loop efficiency, page/widget writes, workflow fixes #1751

Sync ako/mxcli: agent loop efficiency, page/widget writes, workflow fixes

Sync ako/mxcli: agent loop efficiency, page/widget writes, workflow fixes #1751

Workflow file for this run

name: Build, Test & Lint
on: [push, pull_request]
permissions:
contents: read
jobs:
# The tunnel seam has a !linux half (stub + its tests) that the ubuntu job can
# only compile, never run. This job actually executes it on real Windows and
# macOS runners, so "--hub fails with an actionable message" is a tested claim
# rather than a cross-compile that type-checked. See ADR-0009.
#
# Neither package depends on the generated ANTLR parser, so this needs no
# grammar step and stays fast.
tunnel-seam-cross-platform:
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version: '1.26.6'
- name: Test the tunnel seam
shell: bash
# Scoped with -run to the seam's own tests. The full test binaries are still
# COMPILED for this platform, so a Windows/macOS build break is still caught;
# only the !linux stub behaviour is executed.
#
# Running the whole packages here fails on Windows for reasons that predate
# this change and are unrelated to the tunnel: several tests assert POSIX file
# modes (0600) that Windows does not implement — os.Chmod only toggles the
# read-only bit, so Stat reports 666 — plus one path-separator assumption.
# Tracked separately in #897; widening this job is that issue's job, not this
# one's.
#
# -run can pass vacuously if the tests are renamed or deleted, so assert that
# the expected number actually ran.
#
# `tee` rather than a command substitution: the runner's shell is
# `bash -e -o pipefail`, so capturing into `out=$(go test ...)` aborts the
# step AT THE ASSIGNMENT when go test fails, and the `echo "$out"` below
# never runs. The log then holds nothing but "Process completed with exit
# code 1" — no test name, no failure message, no way to tell a real break
# from a flake. Write the output as it is produced, then judge it.
run: |
set +e
go test -v -count=1 -run 'Unsupported' ./cmd/mxcli/docker/... ./cmd/mxcli/tunnelhub/... 2>&1 | tee go-test-output.txt
status=${PIPESTATUS[0]}
set -e
n=$(grep -c '^--- PASS: Test.*Unsupported' go-test-output.txt || true)
echo "seam tests executed: $n"
if [ "$status" -ne 0 ]; then
echo "FAIL: go test exited $status. Its output is above."
exit "$status"
fi
if [ "$n" -lt 4 ]; then
echo "FAIL: expected at least 4 tunnel-seam tests to run, -run matched $n."
echo " The !linux stubs in cmd/mxcli/docker and cmd/mxcli/tunnelhub"
echo " must each keep a test whose name contains 'Unsupported'."
exit 1
fi
# The Windows process helpers (cmd/mxcli/docker/procgroup_windows.go) cannot be
# exercised by the ubuntu job: Signal(0) succeeds on Linux and there is no
# process tree to reap. `mxcli run --local` hung forever on Windows at
# "Starting mxbuild --serve..." because alive() asked Signal(0) (unsupported on
# Windows, so a live mxbuild read as dead) and Stop() killed only the wrapper,
# leaving mxbuild's Deno web-ext worker holding the stdout pipe so cmd.Wait()
# blocked. This job runs the Windows-only regression tests on a real Windows
# runner so neither half can come back.
windows-process-regression:
runs-on: windows-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version: '1.26.6'
- name: Test the Windows process helpers
shell: bash
# Scoped with -run: the rest of the docker package's tests assert POSIX
# file modes and shell out to `sh`, so the full package does not pass on
# Windows (tracked in #897). The test binary is still COMPILED for this
# platform, so a Windows build break in the package is caught too.
#
# -run can pass vacuously if the tests are renamed or deleted, so assert
# that the expected number actually ran.
#
# `tee` rather than a command substitution — see the tunnel-seam job above.
# This job is where it bit: a run of these tests failed with the log holding
# only "Process completed with exit code 1", so the failing test could not be
# named and the leftover `ping` in the runner's orphan-process cleanup was
# the only evidence of WHICH test had tripped (ako/mxcli#594).
run: |
set +e
go test -v -count=1 -run 'TestProcessAlive|TestKillProcessGroup|TestServeServer_AliveTracksProcess|TestLocalRuntime_AliveTracksProcess' ./cmd/mxcli/docker/ 2>&1 | tee go-test-output.txt
status=${PIPESTATUS[0]}
set -e
n=$(grep -c '^--- PASS: Test' go-test-output.txt || true)
echo "windows process tests executed: $n"
if [ "$status" -ne 0 ]; then
echo "FAIL: go test exited $status. Its output is above."
exit "$status"
fi
if [ "$n" -lt 5 ]; then
echo "FAIL: expected at least 5 Windows process tests to run, -run matched $n."
echo " procgroup_windows_test.go must keep its processAlive / tree-kill /"
echo " alive() tests, or the Windows local-boot regression is unguarded."
exit 1
fi
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-go@v7
with:
go-version: '1.26.6'
- name: Cache ANTLR4 JAR
uses: actions/cache@v6
with:
path: ~/.m2/repository/org/antlr/antlr4
key: antlr4-4.13.2
- name: Install ANTLR4
run: pip install 'antlr4-tools==0.2.2'
- name: Generate parser
run: make grammar
env:
ANTLR4_TOOLS_ANTLR_VERSION: '4.13.2'
- name: Build
run: make build
- name: Test
run: make test
- name: Check tunnel stays Linux-only
# The embedded tunnel (chisel) must never reach the Windows/macOS builds —
# it gets mxcli flagged by Defender and enterprise EDR on managed corporate
# endpoints, which is most of our audience. See ADR-0009. The script also
# asserts a positive control (chisel IS in the linux graph) so it cannot
# pass vacuously.
run: ./scripts/check-tunnel-deps.sh
- name: Check MDL example scripts
# Single source of truth: `make check-mdl` covers BOTH doctype-tests/ and
# bug-tests/ (skipping *.test.mdl, inverting *.fail.mdl negative tests, and
# honouring the pre-existing-failure SKIP list). Previously this step only
# iterated doctype-tests/, so bug-test regression fixtures had no CI gate.
run: make check-mdl
- name: Check skill pack JavaScript
# Nothing else in this repo compiles a pack's widget — it is built in
# the user's project — so logic shipped there is otherwise ungated. The
# #574 case: the widget must attach the session's CSRF token to
# same-origin fetches and never to any other host.
run: make check-skill-pack-js
- name: Check bug findings
# One JSON object per line, an area, a date, and either the four
# structured fields or a raw row. DuckDB rejects a whole file on one bad
# line, so a typo in an appended finding takes out every query over that
# area. Also prints how far docs-wiki/bug-patterns/ has fallen behind.
run: make check-findings
- name: Check wiki page list
# The table of contents must describe the wiki, both directions. It
# drifted for three months before anyone noticed.
run: make check-wiki-pages
- name: Check skill MDL blocks
run: ./scripts/check-skill-mdl.sh ./bin/mxcli .claude/skills/mendix
- name: Check docs-site MDL blocks
run: ./scripts/check-skill-mdl.sh ./bin/mxcli docs-site/src
- name: Setup mxbuild
run: ./bin/mxcli setup mxbuild --version 11.12.2
# One engine since the legacy sdk/mpr backend was deleted
# (docs/plans/2026-09-14-retire-legacy-engine.md), so there is no matrix to
# narrow here any more and MXCLI_TEST_ENGINES is left unset.
- name: Integration tests
run: make test-integration
timeout-minutes: 30
- name: Lint Go
run: make lint-go
- name: Vulnerability scan
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...