Qualify a published release for staging
Human verified
A human reviewed this page, but it may be out of date. Later edits may not have been reviewed.
Overview
Check published controller and runtime images with trusted startup tests before
considering a staging installation. The default mode checks container startup on
amd64. An optional mode stages a controller pair for a sign-in rehearsal.
Set rehearse_signin explicitly to install a prepared pair on a fresh, disposable runner. No mode promotes a release. See the release guides
for publication and recovery procedures.
Trigger
Manual dispatch from protected main in openclaw/openclaw-enterprise. Runs for
the same configured installation share a concurrency group. The workflow is not
a PR merge gate.
Scenarios
The runner checks the published controller and runtime images using the
images-packaging and images-runtime-startup files. It also validates the
publication evidence and image identity before executing those startup checks.
Source and credential constraints
The workflow command checks the
trusted checkout against the workflow SHA, protected same-repository main,
local workflow ancestry in main, and release ancestry in the workflow commit.
It requires the exact successful Enterprise Containers run and attempt, a
successful image publication job for that source, and one unexpired publication
artifact. Dispatch IDs must be positive safe decimal integers. Source IDs must
be full lowercase Git SHAs.
The named artifact download retains an archive. Before reading it, the command
repeats producer checks and compares its size and SHA-256 with GitHub metadata.
The archive directory must contain exactly one regular file, at most 1 MiB.
The command passes the verified archive bytes to Python 3's standard ZIP decoder
on the runner. It reads only publication.json, at most 64 KiB, without
extracting files or passing a GitHub token. The receipt must match a successful
same-repository main push returned by the CI workflow's source-SHA query.
Only service-derived run IDs and attempts select the exact CI run and job checks.
The script does not write Actions outputs.
Only the workflow commit is checked out. In the default startup job, setup, dependencies, preparation,
tests, manifests, and cleanup come from that checkout. Historical Git objects
supply only the ordinary deploy/runtime/Dockerfile blob, at most 64 KiB, as
inert data. The current 0.164.0 profile requires the current recipe. The reviewed
0.163.0-alpha.2 profile requires source
54bfa7fc1b99e362450beb5f9211e164991fa7b4 and its pinned recipe hash.
Other recipes, including the October 9 0.160.0 profile, fail before pulls.
The receipt, recipe, and trusted packaging manifest must agree on the Node base.
After checking GitHub metadata, the command removes GitHub tokens before image operations. Git and ZIP decoder subprocesses never receive those tokens. A private Docker config supplies GHCR authentication only for digest pulls on the runner's local Docker socket. The command removes that config before inspection or startup. A failed pull reports the reference and access guidance without printing subprocess output.
The command verifies each pulled digest, Linux amd64 platform, and source label, then passes the exact local image IDs to trusted tests. It rechecks source labels before smoke preparation. The selected profile's Codex version controls the real seccomp probe and explicit runtime-suite expectations; normal CI retains 0.164.0 assertions. The runner records the workflow SHA as its test source, while the pull receipt records the historical image source separately. No historical host code is built or executed. Historical images receive only the existing isolated fixture mounts, not the runner workspace, Docker socket, or Actions credentials.
Execution
Run Staging Release Qualification
with the trusted main workflow. Supply installation, the full source_sha,
publication_run_id, and its exact publication_attempt. The publication must be
a successful manual Enterprise Containers run for that source on main.
The Enterprise Containers publisher
issues receipts only for public GitHub Container Registry (GHCR) packages.
Private and internal packages are ineligible even if the package names match or
the qualification token has read access.
Active qualification runs are not cancelled by a later dispatch.
Configure the staging-qualification environment with STAGING_INSTALLATION,
GHCR_CONTROLLER_IMAGE, and GHCR_RUNTIME_IMAGE.
The installation input must equal the configured ID. Use an ID of 1–63 lowercase
letters, digits, or hyphens, starting with a letter. GHCR values are explicit
ghcr.io/openclaw/ repositories without tags or digests. Restrict this environment
to main. The qualification job authenticates the two image pulls with its
workflow token, which has packages: read. The job uses a disposable runner-local
k3d fixture and needs no staging cluster configuration or provider credentials.
For local command coverage, run:
node --test tests/integration/staging-qualification.test.tsnode scripts/ci/run-tests.mjs auditThe command test uses local Git history and independent GitHub and Docker transport fixtures. It checks digest handoff, credential isolation, hostile Actions output paths, archive tampering, rejection before pulls, and a real preparer failure before any suite. Hosted token permissions, registry pulls, container startup, and live installations need separate proof.
Prepare a controller pair
Supply all three optional inputs: previous_source_sha,
previous_publication_run_id, and previous_publication_attempt. The existing
source and publication inputs identify the candidate. A partial previous tuple
fails validation. With all three omitted and rehearse_signin off, the original startup job runs.
The pair job validates two ordered main publications and their underlying CI runs and verifies each downloaded receipt before using its registry references. It pulls only three Linux/amd64 images: the two controllers and the previous runtime, which remains fixed. Each selected image needs a publication seal with its platform manifest and config digests. An older seal without these fields can still be used for the original single-release check. A source tag, a local image, or a preparation-only artifact cannot substitute for a publication receipt.
Using the local Docker image store, the job checks the root, platform manifest, config, and revision in the exported config against the publication. It rejects a store without platform descriptors. The existing staging environment and read-only package permissions apply. No model or cluster credentials are needed.
After preparation succeeds, the job uploads staging-pair-images.json and
staging-signin-plan.json. These files remain available if a later installed
rehearsal fails. The plan binds the observed images to the intended
sign-in test: the source inputs must match a reviewed controller reader profile
and both releases must share its migration tree. The current profile is the v3
reader and catalog at 7e1ac6d88e3893c3d4e6444fb3b9b9776519a3fb.
Both releases must match its production-input projection. A change to those
inputs requires a new review of the reader behavior and test expectations.
This admits only releases with that exact projection, not every v3 controller.
The publisher takes its source from the then-current main workflow commit.
Publish two distinct, ordered main revisions with the same intended production-input
projection, each using its own successful exact-source CI. Then review the immutable
pair and bind the matching profile before installed qualification. The profile update
may land after both publications; it creates no images or publication receipts.
A controller change between publications requires a newly reviewed compatible pair.
A later qualification workflow can use published ancestors even if its own controller inputs have changed. For the current Codex 0.164.0 profile, its runtime Dockerfile must still match the published recipe byte for byte, and its CI Node base pin must match that recipe. Its chart and test harness must also remain compatible with the pair.
These artifacts establish input preparation only. Preparing a pair does not start
the controllers, exercise a callback or rollback, measure availability, or
write the single-release startup qualification receipt. Publish and retain the
preparatory release before merging a protocol activation when both generations
must be tested: a later dispatch of Enterprise Containers cannot select an
unpublished historical main revision. For a rehearsal publication, set
publish: true and choose a dedicated image_tag unless you intend to update
latest for both images. Run pair preparation while both publication receipts
are available; the publisher retains them for 30 days.
Rehearse installed sign-in
With both publication tuples supplied, select rehearse_signin to run the installed
case after preparation on the same Linux/amd64 runner. Leaving it off keeps the
preparation-only path. The job creates one k3d server with its own database and
synthetic HTTPS identity provider. The cluster is separate from the configured
staging installation; no application, model or operator-cluster credentials are needed.
Both controllers and the unchanged runtime must be reachable by their verified public digest from the node. The job also checks the exact PostgreSQL and Node support images. It builds the fixture CLI and selects the chart from the trusted workflow checkout. The two image generations share a populated database and one issuer across replacements.
For two compatible v3 releases, the case checks forward and return replacement with live, one-use collection and replay refusal. The job refuses unreviewed production inputs, a different migration catalog, and inconclusive expiry windows. Every receipt must be observed with positive remaining lifetime at issuance; an already-expired control cannot establish a later expiry rejection. Historical v2-to-v3 qualification remains unavailable: the old reader references are incompatible with the current runtime profile. This v3-to-v3 rehearsal does not establish that historical transition.
Only a passing selected case, complete transition evidence, a normally exited
runner with no surviving descendants, and confirmed cluster cleanup produce
staging-signin-qualification.json. Missing or ambiguous ownership evidence
blocks automatic cleanup. No raw identity-provider material, cluster config,
or session data is uploaded. This verifies sequential controller replacement;
it does not measure normal-ingress availability or qualify overlapping writers.
Results and limits
The single-release job selects the controller and runtime startup files from
images-packaging and images-runtime-startup. Missing, failed, or skipped cases
fail the lane. Preparation, tests, and cleanup must succeed before the command
writes staging-qualification.json. The always-run upload explicitly retains
staging-pulled-images.json, staging-images-packaging.json,
staging-images-runtime-startup.json, and staging-qualification.json when
produced. An early preparation failure retains the pull receipt without a
success receipt or invented suite results.
The single-release job provides container startup qualification on amd64, not an installation or rollout. The installed private Git test lane builds a separate repository-service image and a runtime with a test CA through first-agent-smoke; the two-image publication receipt cannot supply that installation unchanged. Full Integration and QA Advisory retain their existing installation and provider requirements.
For an installed sign-in rehearsal, use staging-signin-qualification.json as
the success receipt. The pair inputs alone do not establish an installed result.
This workflow does not promote to production or prove staging readiness, installed Agent workflows, or arm64 behavior.
Files
- Workflow: trusted source, inputs, and artifact retention.
- Qualification command: publication validation, image selection, and startup checks.
- Command tests: local Git and transport fixtures.
- Packaging manifest and startup manifest: runtime test inventories.
