Repository navigation
ci: make check workflows thin wrappers over scripts/ci-local.sh - #396
Merged
Merged
Conversation
…r ci-local.sh The three hosted check workflows carried their own step bodies, duplicating what scripts/ci-local.sh runs, so the two definitions could drift. Each job now checks out, installs its lane's toolchain and calls the script, following local-ci.yml's shape. Script additions, all opt-in so existing modes list identical steps: - --only leak-scan runs the leak scan alone (hygiene.yml's PR gate); MO_CI_LEAK_BASE points it at the PR's base branch. - --no-integration / --integration-only split a lane into its checks and its docker/Postgres half, so conformance.yml and integration-tests.yml each run their half of the same lanes. - MO_CI_JACOCO=1 keeps JaCoCo on in the Java reactor, preserving the instrumented second environment conformance.yml's nightly exists for. - gate_conf_csharp re-runs ApiDocsCrossPort after Cli.Tests builds the CLI; the whole-project run before it soft-skips on a clean checkout, which the workflow's explicit ordering used to cover. Jobs regroup onto the script's lanes: typecheck and completeness fold into ts-fast, conformance-kotlin into java-fast, fixture-lint and the drift jobs into gates, migrate-ts-pg into ts-slow. leak-scan keeps its job name (the required status). Triggers are unchanged.
…tion README, --no-integration is not a skip
Replace 'mirrors the hosted lanes' — backwards after the thin-wrapper inversion — with the single-definition fact the script header and CONTRIBUTING.md now carry. Co-Authored-By: Claude Code <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Rewire now: turn metaobjects' three native check workflows (
.github/workflows/hygiene.yml,conformance.yml,integration-tests.yml) into thin wrappers that callscripts/ci-local.sh, so the script is the single definition of those checks.Background: the workflows still carry their own native step bodies, duplicating what
scripts/ci-local.shruns, so the two definitions can drift.local-ci.ymlalready uses the thin-wrapper inversion and is the model to follow. GitHub Actions is currently disabled on this repository, so the workflows do not run today.What Changed
hygiene.yml,conformance.ymlandintegration-tests.ymlno longer carry native step bodies: each job checks out, installs the toolchain its lane needs, and callsscripts/ci-local.shwith a lane selector (--only leak-scan;--only gates|ts-fast|csharp|java-fast|python --no-integrationplus--only java-slowwithMO_CI_JACOCO=1;--only <lane> --integration-only), so the script is the single definition of the checks and a workflow run cannot drift from a local one. Conformance's five separate jobs (fixture-lint, typecheck, completeness-gate, doc-template-drift, embedded-library-drift) collapse into onegatesjob plus a lane matrix; Kotlin folds into thejava-fastlane; integration-tests drops its standalonemigrate-ts-pgjob in favor of thets-slowlane on the shared Postgres sidecar (which now also runs the runtime-ts real-PG matrix, withMIGRATE_TS_PG_EXPECT/RUNTIME_TS_PG_EXPECTsentinels armed).scripts/ci-local.shgains the selection primitives the wrappers need:--no-integrationand--integration-onlyflags (mutually exclusive with each other and--quick), a standaloneleak-scan--onlysection,MO_CI_LEAK_BASEto point the leak scan at the PR's base branch,MO_CI_JACOCO=1to keep JaCoCo on for the hosted nightly reactor, and a repeatApiDocsCrossPortpass in the C# lane afterCli.Testsbuilds the CLI (the gate is order-dependent, not redundant). Workflows also addpermissions: contents: readandpersist-credentials: false.AGENTS.md,CONTRIBUTING.md,.no-mistakes.yaml,.githooks/pre-push, both fixture READMEs, and two conformance-test comments (C#ApiDocsCrossPortConformanceTests, JavaRegistryManifestConformanceTest) that pointed atconformance.ymlfor where gates are wired.Risk Assessment
✅ Low: Every lane selection was traced and empirically dry-run against the old native workflow bodies — coverage is preserved or a superset, all pre-existing selections are byte-identical to base, the fix-round prose matches verified reality, and the only residual is a harmless comment imprecision.
Testing
Drove the change's real surface end-to-end: parsed all three rewritten workflows and asserted 48 semantic properties (every executed step invokes ci-local.sh, no native check bodies remain, lanes/env reach real consumers, the round-1-declined python sidecar was NOT added), then ran every one of the 11 wrapper command invocations against the script itself — list-only selection proved --no-integration drops the docker half per lane and --integration-only keeps only it — and executed the cheap lanes for real (hygiene's leak-scan command and conformance's 32-gate gates job, both PASSED). Adversarially confirmed wrapper/script drift fails loudly (all malformed invocations exit 2 with named messages) and that a staged leak makes the scan exit 1 with an actionable message. Verified the corrected prose matches reality (Actions enabled=true via gh api) and that the review-fix commit touched only CONTRIBUTING.md and .no-mistakes.yaml. The full flagless regression run and a --quick --no-integration run were still executing (26 consecutive steps green, zero failures, inside the Stryker mutation gate) when this phase reported, so the csharp/java/reactor/python/docker-integration suites are recorded untested rather than passed. No LLM API spend: all work was local compute.
Evidence: Semantic thin-wrapper assertions (48/48 pass)
ALL SEMANTIC ASSERTIONS PASS — workflows parsed and asserted: single ci-local.sh run step per job, no native bodies, lane/matrix/env/permissions correct, no services block on conformance.yml (declined python-sidecar change not implemented)Evidence: List-only drives of all 11 wrapper invocations
Every hygiene.yml / conformance.yml / integration-tests.yml command exits 0; --no-integration lanes print the '⊘ not running the docker/Postgres integration half' banner with no SKIP entries; --integration-only lanes list only the docker-half stepsEvidence: Per-lane step selection detail
ts-slow --integration-only → ts build (for integration), sidecar reuse, migrate-ts real-PG suite, runtime-ts PG dialect matrix, integration-tests (ts). --only leak-scan → exactly one step. gates → 32 offline gates incl. fixture-lint, doc-template drift, embedded-library drift (the three former conformance.yml jobs)Evidence: Adversarial flag-contract results
All malformed invocations exit 2 with named messages; a drifted lane name ('typescript') is rejected, so wrapper/script drift fails loudlyEvidence: Leak-scan failure mode (staged leak)
leak-scan: possible private/other-project or local-path leak in added lines (metaobjects is PUBLIC): CONTRIBUTING.md Debug notes: my build cache lives at ~/secret-build-cache. — exit 1; worktree restored clean after the driveEvidence: Full flagless regression run (in progress at report time)
Green through 26 steps (all gates, TS conformance, TS unit suites); executing Stryker completeness-gate when reported; no failuresEvidence: Gates lane real run (conformance.yml gates job command)
Source: Gates lane real run (conformance.yml gates job command) (local file:
~/.no-mistakes/evidence/01M41CDX3434BCV2066YDQPWCZ/gates-lane-real-run.log)Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
CONTRIBUTING.md:76- The edit reaffirms 'GitHub Actions is disabled on this repository, so the files in .github/workflows/ no longer run' (and .no-mistakes.yaml:8 'that script is the ONLY thing that runs those checks at all'), but Actions is verifiably ENABLED on the repo right now (gh api repos/metaobjectsdev/metaobjects/actions/permissions → {"enabled":true}), matching project CLAUDE.md ('re-enabled 2026-09-20, and it stays on'). Consequence: the thin wrappers go live immediately — hygiene.yml fires on the next PR (and main's protection requires that status), conformance.yml on tonight's 04:41 UTC cron and the next v* tag — and contributors are told nothing in .github/workflows/ runs. The user intent's own background ('currently disabled … do not run today') carries the same outdated belief, so the author should know the change is load-bearing on merge, not dormant. Remedy is mechanical: reword to the conditional form scripts/ci-local.sh's header already uses ('When GitHub Actions is off, this script is the only thing that runs them') in CONTRIBUTING.md and .no-mistakes.yaml..github/workflows/conformance.yml:133- The python conformance lane (--only python --no-integration) is not docker-free: gate_conf_python (scripts/ci-local.sh:644) runs the full pytest tree including tests/integration, whose PG-backed scenarios fall back to per-scenariodocker runpostgres containers when METAOBJECTS_TEST_PG_URL is unset (server/python/tests/integration/postgres_container.py mode 2; this job sets no sidecar). Green on ubuntu-latest (docker present) but pulls postgres:16-alpine and boots per-scenario containers — the cost the shared-sidecar pattern exists to avoid — crossing the 'integration-tests.yml owns the docker suites' boundary the change's own comments draw. Noting the tradeoff: splitting the suite would create a second definition of the python checks, which is what this change exists to eliminate; a job-levelservices: postgres+ METAOBJECTS_TEST_PG_URL on the conformance matrix would remove the per-scenario cost if it ever matters.🔧 Fix applied.
1 info still open:
scripts/ci-local.sh:95- Two new comments say every conformance.yml call passes --no-integration (scripts/ci-local.sh:94-96 "conformance.yml (--only gates / ts-fast / csharp / java-fast / python, and java-slow for the reactor, all with --no-integration)"; conformance.yml:15-16 "Each job ... calls the script with that lane's--onlyselector and--no-integration"), but the gates job (conformance.yml:71) runsscripts/ci-local.sh --only gates --strict-toolchainswithout it. Behaviorally void — verified via MO_CI_LIST_ONLY that the gates lane selects no docker/Postgres steps either way — but the wrapper-contract documentation this change exists to make misstates the actual invocation.scripts/ci-local.shregression run was still executing at report time — green through 26 consecutive steps (all 32 offline gates, TS conformance, TS unit suites) and inside the Stryker completeness-gate; the csharp / java-fast / java-reactor / python / docker-integration sections had not yet been reached. No failure of any kind so far. The run is still writing to the evidence log; the completed portion plus the driven wrapper mechanics cover every line this change touches, but the untouched ports' suites did not finish within the phase. Log: full-ci-local-run.log in the evidence directory.scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchainsactionlint on hygiene.yml, conformance.yml, integration-tests.yml (all clean) and local-ci.yml (SC2155 confirmed pre-existing at base)python3 /tmp/verify-wrappers.py — 48 semantic assertions over parsed workflow YAML (thin-wrapper shape, lanes, env consumers, declined-sidecar absence, permissions)MO_CI_LIST_ONLY=1 drives of all 11 exact wrapper invocations from the three workflows (evidence: wrapper-list-only-drives.txt)Real run: MO_CI_LEAK_BASE=origin/main scripts/ci-local.sh --only leak-scan --strict-toolchains → PASSED (hygiene.yml's command)Real run: scripts/ci-local.sh --only gates --strict-toolchains → PASSED, all 32 offline gates (conformance.yml's gates job)Adversarial flag contract: --only bogus / --only with no value / --integration-only+--no-integration / --integration-only+--quick / unknown flag / drifted lane 'typescript' all exit 2 with named messages; --help exits 0Adversarial leak drive: staged home-path leak → bash .githooks/leak-scan.sh exits 1 naming file+line; working tree reverted clean afterwardsgh api repos/metaobjectsdev/metaobjects/actions/permissions → enabled=true (the corrected docs claim is true)Configured baseline (ran before this phase): scripts/ci-local.sh --only ts-fast --only ts-unit --strict-toolchains → successFull regression scripts/ci-local.sh (flagless) launched; green through 26 steps (gates, TS conformance, TS unit suites), still inside the Stryker completeness-gate at report time; stray scripts/ci-local.sh --quick --no-integration run also still executing.claude/skills/releasing/SKILL.md:168- Pre-existing, not made stale by this change: the releasing skill still says 'GitHub Actions is disabled on this repository (2026-09-16)' (also line 222 'inoperative while GitHub Actions is disabled'), but Actions has been enabled since 2026-09-20 and publish-csharp.yml is live. Out of this phase's scope on two counts: the file concerns the publish workflows, not the three check workflows this branch wrapped, and the round-1 decision explicitly scoped Actions-prose corrections to CONTRIBUTING.md, .no-mistakes.yaml and the scripts/ci-local.sh header. Flagging only so it is not lost; no edit made. Historical specs/plans under docs/superpowers/ that name the removed conformance-kotlin job are dated archives and were deliberately left as records.✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.