Release
One GigaLoom release binds Python, npm, Git, and embedded Web assets. The only
hand-edited identity is release/version.toml; scripts/release.py generates
and verifies release/release.json and every ecosystem projection. For the
first stable Native Agent Gateway release the exact identity is:
| Surface | Identity |
|---|---|
| Canonical release | 0.9.1 |
| Git tag | v0.9.1 |
| PyPI | gigaloom==0.9.1 |
| npm | @gigaloom/web@0.9.1 |
The root Python metadata, npm metadata, generated manifest, changelog skeleton,
package-documentation snippets, and release/artifact-set.toml must match the
canonical file exactly. CI fails when any projection is edited by hand.
Bump a version
From the repository root, run one hermetic source-to-projection operation:
git switch -c release/0.8.0-alpha.1
./scripts/release bump 0.8.0-alpha.1
bump updates every version projection with in-process rollback, then verifies
the result, including the packaged product inventory. Its JSON receipt lists
the exact changed paths and the remaining human and external gates. It does not
build, commit, tag, publish, or call a provider. Running it again for the same
version is a byte-identical no-op.
Use ./scripts/release diff <version> to review a proposed version without
writing and ./scripts/release show to inspect the canonical identity. The
legacy prepare command remains compatible. verify remains an independent
CI and tag-boundary check; it is unnecessary immediately after a successful
bump.
Tag policy
New releases use only the standard v<release> tag. Create the protected tag
at the exact reviewed main commit. The tag starts the immutable candidate
build; publication begins only after its build, parity, checksum, denylist, and
attestation gates pass. Neither workflow creates, moves, or repairs a tag.
Historical prefix-shaped tags remain history. Do not reuse those prefixes for new releases. Never move or delete a tag after either registry accepts the version. A bad unpublished tag is an audited repository-policy correction, not something the workflow guesses around.
Maintainer checklist
- Confirm the named GitHub and PyPI backup owners have accepted access with 2FA under the governance policy.
- Run the documented
bump, complete both generated changelog skeletons, and review the exact changed paths from its receipt. - Build frontend assets and run the complete non-live quality gate.
- Ensure the release commit is on
mainand the documented main/tag rulesets are active. - Confirm PyPI and npm Trusted Publishers name the exact project/package,
repository, publish workflow, and
release-productionenvironment. Confirm that the environment has no required-reviewer gate for automatic releases. - Create the protected standard tag at that exact source SHA. The tag push builds and attests one candidate, then automatically starts publication from that same workflow run after success.
- Monitor the candidate, registry checks, and GitHub Release creation. Record
the candidate run ID, full source SHA, and
candidate-manifest.jsonSHA-256 for recovery.
Two-phase workflow
.github/workflows/publish-pypi.yml runs on a protected v* tag push to build
and attest one retained candidate. It has no registry or GitHub Release
publication step.
.github/workflows/release-publish.yml is a separate workflow protected by the
release-production environment. A successful completion of the candidate
workflow starts it through workflow_run; the resolver consumes that exact run
ID and requires one unexpired artifact with the exact SHA-bound name. The
protected job rechecks the tag, ancestry, metadata, checksums, byte parity, and
legacy denylist and does not rebuild. Before an initial or missing-registry
publication it also requires the exact GitHub Release tag to be vacant. It then
checks public registry state before requesting OIDC credentials. After both
registries are proven, the final boundary accepts either a vacant tag or one
mutable exact-tag Release with zero uploaded assets. The latter is adopted
without asset overwrite and its release-channel metadata is normalized. Manual
dispatch remains recovery-only; it additionally requires the recorded run ID,
SHA, tag, manifest digest, and recovery mode.
Choose exactly one mode:
initial: both versions are absent; publish npm with provenance, then PyPI;recover-pypi: exact npm bytes exist and PyPI is absent; publish only PyPI;recover-npm: exact PyPI files exist and npm is absent; publish only npm;release-assets-only: both registries contain the exact candidate bytes; publish neither registry and create the GitHub Release last, or adopt one empty mutable exact-tag Release without overwriting assets.
Any unexpected existing filename or digest, malformed registry response, or
registry outage stops the workflow. A successful registry is never
republished during recovery. A pre-created GitHub Release stops the workflow
before either registry write. Only after exact registry-byte proof may an
explicit release-assets-only recovery adopt it, and only when the exact-tag
Release is mutable and has no uploaded assets; every collision or immutable
boundary fails closed.
Release channels
The release guard derives channels from the canonical manifest version. Alpha,
beta, and release-candidate versions publish npm under the next dist-tag and
create a GitHub Pre-release with Latest explicitly disabled. A stable version
publishes npm under latest and explicitly marks its GitHub Release as
Latest. PyPI keeps the manifest's native PEP 440 prerelease or stable version.
The existing @gigaloom/web package must bind release-publish.yml plus the
release-production environment as its npm Trusted Publisher before the tag is
created. Do not put an npm token in GitHub.
Rollback and recovery
Before any registry accepts a version, revert release automation or source and build a new candidate from a new commit. After npm or PyPI succeeds, the version and tag are immutable. Reuse only the exact retained candidate to finish the missing registry, or advance all release identities and issue a new version. Never rebuild a partial release, overwrite package files, or move its tag.
Public Trusted Publisher registration, tags, GitHub releases, and package publication are external mutations and remain separate authorized gates. See the repository's release recovery runbook.