Repository navigation
ci: a change that reaches a user has a version - #1213
Open
swapnilpaliwal-sd wants to merge 1 commit into
Open
swapnilpaliwal-sd wants to merge 1 commit into
swapnilpaliwal-sd wants to merge 1 commit into
Conversation
npm will not republish a version. Anything inside the tarball can therefore only reach anyone through a new one — and README.md is inside it, named by the `files` allowlist. A pull request that improves the README and leaves the version alone is not a small omission: the improvement is never delivered, and nothing says so. The next person reads the old text on the registry and cannot tell it apart from a README nobody has written. The inverse error costs as much. A bump demanded for a CI tweak or a test fixture teaches people to bump without asking why, and a version that moves for reasons users cannot observe stops carrying information. So the gate asks one question — could this change reach a user? — and answers it from package.json's own `files` declaration rather than a second list kept by hand, because a second list drifts. The negated entries (`!graph/test/`, `!plugins/axiomcode/validate/`, `!plugins/**/__pycache__/`) are read out of the file; `.github/` is added, since npm never packs it and no `files` entry would name it. Everything else is assumed to reach a user, so a new top-level directory is gated by default rather than exempt by default. The engine packages are deliberately untouched. `@axiomcode/engine-<os>-<cpu>` is named by ENGINE_ID, a sha256 over the Soufflé version and the rule text alone, so a README cannot move it and a rule change moves it whether or not anyone bumps anything. That gate is already correct. Runs on pull requests only, where there is a base to compare against; the job's checkout takes fetch-depth 0 for the merge base. `VERSION_GATE=off` skips it, which is what a branch that is not publishing yet wants. Verified on five cases against a fixed base: README alone without a bump fails; `graph/test/` alone, `.github/` alone, and README with a patch bump pass; a change to graph/pipeline/engine.conf without a bump fails. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
swapnilpaliwal-sd
added a commit
that referenced
this pull request
Sep 25, 2026
…m on publish - version.mjs sets and checks the version in all ten places that carry it (root, its engine pins, parser, gemini and the three plugin manifests). - The version gate (from #1213) now also requires every manifest to agree, a bump to move forward, and the new version not to be tagged already. It only demands a bump once the base version is tagged, so work before the first release joins 0.1.0. - release.yml: a push to main whose version has no tag gets one, plus a draft release with generated notes. Nothing is published. - publish-npm.yml runs when that draft is published: checks tag == manifests, builds the engines, publishes them and then @axiomcode/code-graph (which was never published before), prereleases under `next`, skips versions already on the registry, and attaches the tarballs to the release. - .github/RELEASING.md is the runbook. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
swapnilpaliwal-sd
added a commit
that referenced
this pull request
Sep 25, 2026
…m on publish - version.mjs sets and checks the version in all ten places that carry it (root, its engine pins, parser, gemini and the three plugin manifests). - The version gate (from #1213) now also requires every manifest to agree, a bump to move forward, and the new version not to be tagged already. It only demands a bump once the base version is tagged, so work before the first release joins 0.1.0. - release.yml: a push to main whose version has no tag gets one, plus a draft release with generated notes. Nothing is published. - publish-npm.yml runs when that draft is published: checks tag == manifests, builds the engines, publishes them and then @axiomcode/code-graph (which was never published before), prereleases under `next`, skips versions already on the registry, and attaches the tarballs to the release. - .github/RELEASING.md is the runbook.
swapnilpaliwal-sd
added a commit
that referenced
this pull request
Sep 25, 2026
…m on publish - version.mjs sets and checks the version in all ten places that carry it (root, its engine pins, parser, gemini and the three plugin manifests). - The version gate (from #1213) now also requires every manifest to agree, a bump to move forward, and the new version not to be tagged already. It only demands a bump once the base version is tagged, so work before the first release joins 0.1.0. - release.yml: a push to main whose version has no tag gets one, plus a draft release with generated notes. Nothing is published. - publish-npm.yml runs when that draft is published: checks tag == manifests, builds the engines, publishes them and then @axiomcode/code-graph (which was never published before), prereleases under `next`, skips versions already on the registry, and attaches the tarballs to the release. - .github/RELEASING.md is the runbook.
swapnilpaliwal-sd
added a commit
that referenced
this pull request
Sep 25, 2026
…t release per bump; npm on publish (#1318) * ci: gate main on build, repo invariants and all five language suites Carries #418 onto current main as files rather than a rebase: its branch merged engine-prebuilt, whose other changes main already has, so only .github/, graph/test/tools/lib-coverage.sh and the java suite's --no-torture flag were new. Beyond #418: - C# joins the gate: a suite leg scored against the Roslyn oracle (.NET 8), its staging map and its decls-vs-parser-schema check. - C# joins build-engines, so the engine packages carry all five languages. - protect-main.sh points at the renamed repository and also makes v* tags immutable (creatable, never moved or deleted). * release: one version everywhere, a tag and draft release per bump, npm on publish - version.mjs sets and checks the version in all ten places that carry it (root, its engine pins, parser, gemini and the three plugin manifests). - The version gate (from #1213) now also requires every manifest to agree, a bump to move forward, and the new version not to be tagged already. It only demands a bump once the base version is tagged, so work before the first release joins 0.1.0. - release.yml: a push to main whose version has no tag gets one, plus a draft release with generated notes. Nothing is published. - publish-npm.yml runs when that draft is published: checks tag == manifests, builds the engines, publishes them and then @axiomcode/code-graph (which was never published before), prereleases under `next`, skips versions already on the registry, and attaches the tarballs to the release. - .github/RELEASING.md is the runbook. * test/java: the oracle-agreement golden counts case 60 Case 60 (#1269) added a case both ground-truth oracles compare, without re-recording the agreement golden, so `run-tests.sh --oracle` on main aborted before running any case: 45 compared, 45 agreeing, against a golden of 44/44. No disagreement changed. * release: publish with the CLI_BINARY_PUBLISH secret, the npm token already set on the repo * build: darwin-arm64 on the hosted macos-15 runner, every run A public repository gets GitHub's standard runners free, Apple Silicon macOS included, so the self-hosted runner and the macos switch that skipped it are gone: CI and every publish build all four platforms. * ci: no approval required; only the admin role merges into main GitHub never lets an author approve their own pull request, so a required approval would block the sole maintainer. The PR and CI rules still bind everyone; a separate ruleset restricts updates to main to the admin role, through a pull request only. * ci: run on pushes to dev, which takes direct pushes * release: merge main back into dev after every push to main main squash-merges, so a promotion lands as a commit dev lacks and the next dev->main PR would repeat it. A clean merge is pushed to dev; a conflict (a hotfix that touched lines dev changed) pushes nothing and opens one issue with the commands to resolve it by hand. * Linux: an apostrophe in a # comment, and a sandbox PATH that kept /bin Two faults only a Linux runner shows, found on the first CI run: - Soufflé on Linux preprocesses with mcpp, which tokenises the text of a trailing # comment; "every on's listener" is an unterminated character constant there, so every TypeScript solve and the engine generate step failed. macOS's clang preprocessor accepts it. Reworded; all five languages' programs now pass mcpp. - engine-id-test.sh hid souffle by dropping its directory from PATH, compared logically. On merged-/usr Ubuntu /bin -> /usr/bin survives that, and dropping /usr/bin itself would take bash with it. Directories are now compared with pwd -P and souffle's is replaced by a shadow holding everything else. * test/tools: one souffle-hiding helper, correct on merged-/usr Linux engine-package-test.sh carried the same PATH sandbox as engine-id-test.sh and failed the same way on Ubuntu: /bin -> /usr/bin kept souffle visible, so "no souffle" runs found it. Both now source hide-souffle.sh, which compares directories with pwd -P and shadows souffle's directory instead of dropping it. Proven on a simulated merged-/usr layout: the old block leaves souffle visible, the helper hides it and keeps sh. * ci: a docs-only change runs build and hygiene only; platform engines only when what they compile changed The workflow still starts on every event, so the required CI check always reports; a changes job classifies the diff and the engine suites and the platform build skip themselves. The CI job accepts a skip only where changes asked for one. Markdown under graph/ and parser/ still counts as code, since graph/bundle/SCHEMA.md is generated and checked. Pushes to main, merge queues and manual runs run everything. * ci: dev is the default branch, a nightly from scratch, engines cached by ENGINE_ID - dev takes every pull request: build, hygiene and the five suites. The four-platform engine build runs on the way into main (a promotion PR or a push to main) and in the nightly, not on every change to dev. - protect-main.sh names refs/heads/main instead of ~DEFAULT_BRANCH, so main's protection stays on main now that dev is the default, and dev gets a ruleset that only forbids deleting it. - nightly.yml: on nights dev changed, CI with fresh=true (no restored engines, every platform), then e2e-install.sh packs the tarballs, installs them into an empty project without Souffle and runs axiomcode in four languages, then npm publish --dry-run for every package. Publishes nothing; a failure opens an issue and the next green night closes it. - The suite cache never hit: the driver writes to ~/.cache/axiomcode/souffle while CI saved .souffle-cache. The suites now point the driver there and key it by the language's ENGINE_ID. - build-engines restores the previous engines per platform and recompiles only languages whose ENGINE_ID changed (about 3 min each at -O3); fresh (nightly, publish) restores nothing. Its Souffle download is now checked against the same SHA-512 as ci.yml. * ci: cache keys cover the compile flags and, for -march=native, the CPU ENGINE_ID hashes the rules and the Souffle version, not how the binary is compiled, so a flag change reused binaries built with the old flags. - build-engines: the hash of build-engines.yml (which holds the flags) prefixes both the key and the restore prefix, so a flag change restores nothing. Computed in generate, since the build jobs never check out. - suites: the key adds the hash of run-souffle.sh (the driver's flags) and the runner's CPU model: the driver compiles with -march=native, and a binary built on one CPU can die with an illegal instruction on another. * nightly: dev's daily status, published under the nightly dist-tag when green - Runs every night, commits or not: the status is daily, and with no lock file a dependency release can break a fresh install with nothing committed. - A green night publishes every package as <next>-nightly.<date>.g<sha> under `nightly`, never `latest`. The version is computed in the run and never committed or tagged; the g keeps an all-digit sha a valid semver identifier. Skipped when that commit is already the nightly, and until a first release exists, since npm makes a first publish `latest`. - README: the static "engines: not yet published" and "nightly: not yet enabled" badges become the live npm version and nightly status. * test/csharp: one compiled engine per run, not one per case; admins can merge - devrun.sh caches its compiled engine beside the work dir it is given, and run-tests.sh hands every case a fresh one (rm -rf "$w"), so each of the 20 cases and the cross-service cases recompiled the same engine, about 70s each: the suite took 32-38 min in CI. run-tests.sh now exports one AXIOM_CS_DEV_CACHE for the run (in CI, inside the saved engine cache). The cache is content-addressed by the rule text, so sharing it is safe. Locally: three cases, one compile and two reuses, 95s in total. - main-merge-admins bypass is `always`: in `pull_request` mode GitHub refused the merge itself ("Cannot update this protected ref"), even for admins. protect-main still has no bypass, so PR and CI bind admins too.
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.
Stacked on #418 rather than pushed into it, so it can be looked at on its own. Merges into
ci/github-actionsand goes out with the rest of the OSS setup; cherry-pick it across instead ifyou'd rather keep #418 a single commit.
What it gates
npm will not republish a version, so anything inside the tarball can only reach anyone through a
new one — and
README.mdis inside it, named by thefilesallowlist. A PR that improves theREADME and leaves the version alone never delivers the improvement, and nothing says so.
The inverse error costs as much: a bump demanded for a CI tweak or a test fixture teaches people
to bump without asking why, and a version that moves for reasons users cannot observe stops
carrying information.
So the gate asks one question — could this change reach a user? — and answers it from
package.json's ownfilesdeclaration rather than a second list kept by hand, because a secondlist drifts. The negated entries (
!graph/test/,!plugins/axiomcode/validate/,!plugins/**/__pycache__/) are read out of the file;.github/is added, since npm never packsit. Everything else is assumed to reach a user, so a new top-level directory is gated by
default rather than exempt by default.
Not the engine packages
@axiomcode/engine-<os>-<cpu>is named byENGINE_ID— a sha256 over the Soufflé version andthe rule text alone (
graph/pipeline/run-souffle.sh). A README cannot move it, and a rule changemoves it whether or not anyone bumps anything. That gate is already correct and this script does
not second-guess it. Two artefacts, two different notions of "changed", which is the whole point.
Behaviour
Pull requests only, where there is a base to compare against. The
hygienejob's checkout takesfetch-depth: 0for the merge base.VERSION_GATE=offskips it — which is what a branch that isnot publishing yet wants, and worth knowing since
@axiomcode/code-graphis not on the registrytoday.
Verified against a fixed base:
README.mdalonegraph/test/alone.github/aloneREADME.mdgraph/pipeline/engine.confUses a
while readloop rather thanmapfile, since bash 3.2 is still what a macOS laptop runsand the repo already carries
portable-stat.shfor the same reason.One thing to decide
The root package is at
0.1.0and unpublished. Until the first publish the gate is advisory —nothing is unreachable yet, because nothing is reachable. If you'd rather it stay quiet until
then, set
VERSION_GATE=offin the workflow env and drop it when the first publish lands.🤖 Generated with Claude Code