fix(release): allow beta Docker backfills (#124999)

This commit is contained in:
Patrick Erichsen
2026-08-16 20:16:40 -07:00
committed by GitHub
parent d64c5161e2
commit 305e38f5d9
3 changed files with 65 additions and 6 deletions
@@ -68,7 +68,7 @@ on:
default: true
type: boolean
publish_docker_only:
description: Publish Docker only after independently verifying an already-published extended-stable npm package
description: Publish Docker only after independently verifying an already-published beta or extended-stable npm package
required: true
default: false
type: boolean
@@ -184,8 +184,8 @@ jobs:
echo "publish_docker_only requires publish_openclaw_npm=false." >&2
exit 1
fi
if [[ "${RELEASE_NPM_DIST_TAG}" != "extended-stable" ]]; then
echo "publish_docker_only is reserved for an already-published extended-stable release." >&2
if [[ "${RELEASE_NPM_DIST_TAG}" != "beta" && "${RELEASE_NPM_DIST_TAG}" != "extended-stable" ]]; then
echo "publish_docker_only supports already-published beta or extended-stable releases only." >&2
exit 1
fi
fi
@@ -2480,14 +2480,15 @@ jobs:
- name: Verify exact npm and selector readback matches preflight bytes
env:
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
EXPECTED_TARBALL_SHA256: ${{ needs.resolve_release_target.outputs.preflight_tarball_sha256 }}
run: |
set -euo pipefail
version="${RELEASE_TAG#v}"
exact_version="$(npm view "openclaw@${version}" version)"
selector_version="$(npm view openclaw@extended-stable version)"
selector_version="$(npm view "openclaw@${RELEASE_NPM_DIST_TAG}" version)"
if [[ "${exact_version}" != "${version}" || "${selector_version}" != "${version}" ]]; then
echo "npm exact-version or extended-stable selector readback does not match ${version}." >&2
echo "npm exact-version or ${RELEASE_NPM_DIST_TAG} selector readback does not match ${version}." >&2
exit 1
fi
tarball_url="$(npm view "openclaw@${version}" dist.tarball)"
+19 -1
View File
@@ -565,6 +565,24 @@ gh workflow run openclaw-release-publish.yml \
Include `plugin_sdk_api_acknowledgement` only when the npm preflight's Plugin SDK API report contains changes.
If a beta package is already published but its container images are missing,
do not rerun npm or plugin publication. Reuse the immutable beta tag plus its
successful npm preflight and Full Release Validation evidence through the
Docker-only recovery path. The workflow rechecks the exact npm version, the
`beta` selector, and the published tarball digest before building containers:
```bash
gh workflow run openclaw-release-publish.yml \
--ref main \
-f tag=vYYYY.M.PATCH-beta.N \
-f preflight_run_id=<successful-openclaw-npm-preflight-run-id> \
-f full_release_validation_run_id=<successful-full-release-validation-run-id> \
-f full_release_validation_run_attempt=<successful-full-release-validation-run-attempt> \
-f npm_dist_tag=beta \
-f publish_openclaw_npm=false \
-f publish_docker_only=true
```
Stable publish to the default beta dist-tag:
```bash
@@ -681,7 +699,7 @@ readback confirms that every exact package and `extended-stable` tag converged.
- `windows_node_installer_digests`: candidate-approved compact JSON map of the current Windows installer names to their pinned `sha256:` digests; required for stable OpenClaw publish
- `npm_telegram_run_id`: optional successful `NPM Telegram Beta E2E` run id to include in final release evidence
- `npm_dist_tag`: npm target tag for the OpenClaw package, one of `alpha`, `beta`, `latest`, or `extended-stable`
- `publish_docker_only`: extended-stable-only recovery/closeout path. It requires `publish_openclaw_npm=false`, complete preflight and Full Release Validation evidence, then verifies the exact npm package, selector, and tarball digest before invoking Docker publication.
- `publish_docker_only`: beta or extended-stable recovery/closeout path. It requires `publish_openclaw_npm=false`, complete preflight and Full Release Validation evidence, then verifies the exact npm package, selected dist-tag, and tarball digest before invoking Docker publication.
- `plugin_publish_scope`: defaults to `all-publishable`; use `selected` only for focused plugin-only repair work with `publish_openclaw_npm=false`
- `plugins`: comma-separated `@openclaw/*` package names when `plugin_publish_scope=selected`
- `publish_openclaw_npm`: defaults to `true`; set `false` only when using the workflow as a plugin-only repair orchestrator
@@ -1141,6 +1141,46 @@ describe("package acceptance workflow", () => {
);
});
it("allows Docker-only recovery for beta and extended-stable releases", () => {
for (const release of [
{ distTag: "beta", tag: "v2026.8.1-beta.2" },
{ distTag: "extended-stable", tag: "v2026.7.33" },
]) {
const result = runReleasePublishInputValidation({
PUBLISH_DOCKER_ONLY: "true",
PUBLISH_OPENCLAW_NPM: "false",
RELEASE_NPM_DIST_TAG: release.distTag,
RELEASE_TAG: release.tag,
});
expect(result.status, result.stderr).toBe(0);
}
const latest = runReleasePublishInputValidation({
PUBLISH_DOCKER_ONLY: "true",
PUBLISH_OPENCLAW_NPM: "false",
RELEASE_NPM_DIST_TAG: "latest",
RELEASE_TAG: "v2026.8.1",
});
expect(latest.status).toBe(1);
expect(latest.stderr).toContain(
"publish_docker_only supports already-published beta or extended-stable releases only",
);
const workflow = readWorkflow(RELEASE_PUBLISH_WORKFLOW);
const input = workflow.on?.workflow_dispatch?.inputs?.publish_docker_only as
| { description?: string }
| undefined;
const verifyJob = workflowJob(RELEASE_PUBLISH_WORKFLOW, "verify_core_npm_registry");
const verifyStep = workflowStep(
verifyJob,
"Verify exact npm and selector readback matches preflight bytes",
);
expect(input?.description).toContain("beta or extended-stable");
expect(verifyStep.env?.RELEASE_NPM_DIST_TAG).toBe("${{ inputs.npm_dist_tag }}");
expect(verifyStep.run).toContain('npm view "openclaw@${RELEASE_NPM_DIST_TAG}" version');
expect(verifyStep.run).not.toContain("npm view openclaw@extended-stable version");
});
it("accepts only main-reachable protected SHA-pinned release publish tags", () => {
const workflowSha = "a".repeat(40);
const binDir = tempDirs.make("release-publish-gh-");