Verified platform releases
Decision 0056 separates official release publication from personal development and production activation.
Shared sources
gitops/manifests/images.yaml defines every image's Dockerfile, context, target,
arguments and fingerprint inputs. Both in-cluster builds and the reusable CI
workflow read it. Add an image there, with its owner manifest; no handwritten CI
matrix is required. Existing optional development publication retains its image
lock artefacts and adds complete evidence for official packaging.
Shared release code lives in devops/platform/scripts/platform_release:
plan.py reads that catalogue, package.py produces deterministic OCI payloads,
promotion.py selects a package through Git and health.py waits for Argo's
exact-release notifications. Workstation takeover and browser tooling stay in DX.
Commands
Changelog preparation
Before tagging a platform release, create a release-preparation PR from current
main. Pending notes live in changelog fragments.
Preview them with the intended tag and release date:
Preview leaves files and the Git index unchanged. Commit any edits to the fragments, changelog or Towncrier configuration before assembling:
The pinned Towncrier dependency inserts the new release above earlier history,
stages CHANGELOG.md and removes and stages the consumed fragments. Review the
staged diff, commit it and merge the release-preparation PR. Tag its merge commit
once that commit's main-push CI succeeds.
An existing version is rejected even if a different date is supplied.
Assemble once per release. Feature PRs continue to add unique fragments while release preparation is reviewed; notes merged after preparation remain pending for the next release. The tag workflow retains its existing generated GitHub release notes and performs no changelog commits.
Release and deployment commands
These commands run from a clean checkout of the selected source:
The first command is read-only. release checks that HEAD matches SOURCE and is
on main's history, refuses an existing remote tag, then creates and pushes an
annotated tag. It applies the same forward-only check before creating the tag.
Configure protected release tags and the workflow's package permissions before
using it. Release tags are forward-only and must be greater than every earlier
tag reachable from main. Never move a published tag. The workflow repeats the
policy check and waits for successful main-push CI for the exact source before
building and publishing.
Every catalogue image participates, including administration and identity images.
The catalogue at the audited main commit 32cea6102 contained fourteen images;
the workflow always reads gitops/manifests/images.yaml, so no documentation or CI
matrix carries a second count. Their credentials remain runtime private inputs,
never build arguments. The workflow verifies
signatures and complete source-matched evidence before publishing
ghcr.io/pharos-ai-factory/pharos-platform/release:<version>. Consumers resolve
that name once and use its digest.
One built archive supplies both publication channels. The workflow pushes the
exact release.tar.gz to OCI and uploads the same bytes to the GitHub Release,
together with the extracted release.json, SHA256SUMS and a Sigstore blob
bundle. It never rebuilds the bytes between channels. The archive contains only
committed GitOps files plus release.json; it excludes workstation files and
private runner state. Archive reading is bounded and never extracts untrusted
paths.
The repository tag ruleset must protect refs/tags/platform-v*,
refs/tags/hpc-site-v* and refs/tags/dx-v*, as well as the legacy v* rule.
Ruleset administration is an external repository-owner action; a workflow cannot
enforce it.
The HPC Site archive follows the same reviewed tag path:
hpc-release refuses a source outside main, an existing remote tag or a version
not greater than every earlier hpc-site-v* tag reachable from main. The tag
workflow then builds, verifies and signs pharos-hpc-site-v1.2.3.tar.gz and
publishes it with its checksum and Sigstore bundle. A tag can be created only
after the reviewed installer source is on main; this release-management PR
itself does not publish or activate an HPC Site release.
After activation, the ordinary interface selects an existing release:
These commands require oras, cosign, authenticated GHCR access and GH_TOKEN
with the intended selection-branch permission. Set PHAROS_RELEASE_STATUS_CREATOR_ID
to the dedicated notification App bot's numeric user ID. CI uses the corresponding
RELEASE_STATUS_CREATOR_ID repository variable. Selection validates these inputs
before changing Git, verifies package/image signatures and waits for all selected
Applications to report exact-release health from that App. Another CI status or an
older deployment attempt cannot satisfy it. No cluster credential is required.
Rollback requires unchanged contract/migration fingerprints. One conservative fingerprint covers all packaged compositions: committed contracts, every PostgreSQL context's manifest and SQL from the migration catalogue, service delivery migrations and retained Themelio migrations. Catalogue owners and checksums are validated against the selected Git commit; untracked files cannot contribute. SQLite and storage-free contexts need no PostgreSQL manifest. Rollback does not undo database migrations or restore data. A removed Application or unknown selection branch file requires an explicit reviewed transition rather than ordinary promotion.
Production remains disabled
devops/platform/environments/production.yml declares release.enabled: false.
Tags can publish artefacts; the production selection job remains skipped. No
production overlay or external-identity integration is fabricated by this change.
Before enabling selection, the deferred identity/application composition must add
the reviewed production Application overlay and pass real environment qualification.
Bootstrap must configure Argo OCI repository access and permit that exact source in
each existing owner AppProject. A root Application follows the engineering
repository's deploy/production branch at path apps; child Applications use the
verified OCI package. Fence earlier writers before adopting existing services.
Install the dedicated notification App and triggers matching the selected child's
pharos.platform/deployment-context and pharos.platform/source annotations.
Success requires Synced, Healthy, a successful operation and both observed sync
revisions equal to spec.source.targetRevision. Failure must identify that same
revision. Bootstrap credentials and public origin/AAI client bindings stay outside
the release package. Package publication alone does not establish a working site.
Verification
scripts/test_platform_release.py exercises real Git fixtures, Kustomize rendering
and archive bytes, complete image evidence, tamper/path rejection, disabled targets,
non-forced selection and notification identity/attempt fencing. pnpm verify
includes these checks. Live GHCR publication, signature identity, Argo OCI rendering,
notification delivery, browser/UAT and production rollout require separate evidence.
Page source
Source snapshot ยท Revision f928834c8.