fix(release): accept trusted extended-stable validation evidence (#119264)

* fix(release): accept trusted extended-stable validation evidence

* fix(release): document trusted candidate promotion

* docs(release): clarify validation evidence recovery
This commit is contained in:
Dallin Romney
2026-08-05 04:14:30 +08:00
committed by GitHub
parent 11027a3712
commit 7c93cff84a
5 changed files with 173 additions and 84 deletions
+60 -47
View File
@@ -32,6 +32,11 @@ on:
description: Successful Plugin NPM Release run id for the exact extended-stable branch and release SHA
required: false
type: string
release_candidate_branch:
description: Canonical extended-stable branch when a trusted main workflow promotes its immutable tag
required: false
default: ""
type: string
npm_dist_tag:
description: npm dist-tag to publish to
required: true
@@ -709,6 +714,7 @@ jobs:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ inputs.release_candidate_branch != '' && format('refs/tags/{0}', inputs.tag) || github.sha }}
fetch-depth: 0
filter: blob:none
persist-credentials: false
@@ -718,13 +724,14 @@ jobs:
BYPASS_EXTENDED_STABLE_GUARD: ${{ inputs.bypass_extended_stable_guard }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
RELEASE_TAG: ${{ inputs.tag }}
NPM_WORKFLOW_REF: ${{ github.ref }}
NPM_WORKFLOW_REF: ${{ inputs.release_candidate_branch != '' && format('refs/heads/{0}', inputs.release_candidate_branch) || github.ref }}
run: node scripts/openclaw-npm-extended-stable-release.mjs validate-request
- name: Require trusted workflow ref for publish
env:
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
RELEASE_CANDIDATE_BRANCH: ${{ inputs.release_candidate_branch }}
WORKFLOW_REF: ${{ github.ref }}
WORKFLOW_SHA: ${{ github.workflow_sha }}
run: |
@@ -732,12 +739,29 @@ jobs:
tideclaw_alpha_publish=false
extended_stable_publish=false
sha_pinned_release_publish=false
release_candidate_branch="${RELEASE_CANDIDATE_BRANCH:-}"
if [[ "${RELEASE_TAG}" == *"-alpha."* && "${RELEASE_NPM_DIST_TAG}" == "alpha" && "${WORKFLOW_REF}" =~ ^refs/heads/tideclaw/alpha/[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{4}Z$ ]]; then
tideclaw_alpha_publish=true
fi
if [[ "${RELEASE_NPM_DIST_TAG}" == "extended-stable" && "${WORKFLOW_REF}" == refs/heads/extended-stable/* ]]; then
extended_stable_publish=true
fi
if [[ -n "${release_candidate_branch}" ]]; then
if [[ "${RELEASE_NPM_DIST_TAG}" != "extended-stable" || "${WORKFLOW_REF}" != "refs/heads/main" ]]; then
echo "release_candidate_branch is only valid for an extended-stable publish dispatched from main." >&2
exit 1
fi
if [[ ! "${RELEASE_TAG}" =~ ^v([0-9]{4})\.([1-9][0-9]*)\.[1-9][0-9]*$ ]]; then
echo "release_candidate_branch requires an exact final release tag." >&2
exit 1
fi
expected_candidate_branch="extended-stable/${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.33"
if [[ "${release_candidate_branch}" != "${expected_candidate_branch}" ]]; then
echo "release_candidate_branch must be ${expected_candidate_branch} for ${RELEASE_TAG}." >&2
exit 1
fi
extended_stable_publish=true
fi
if [[ "${WORKFLOW_REF}" =~ ^refs/tags/release-publish/([a-f0-9]{12})-[1-9][0-9]*$ ]]; then
workflow_sha_prefix="${BASH_REMATCH[1]}"
[[ "${WORKFLOW_SHA}" =~ ^[a-f0-9]{40}$ && "${WORKFLOW_SHA:0:12}" == "${workflow_sha_prefix}" ]] || {
@@ -857,6 +881,16 @@ jobs:
# tarball, so real publishes do not need the repository's full history.
fetch-depth: ${{ inputs.preflight_run_id != '' && 1 || 0 }}
- name: Checkout trusted validation verifier
if: ${{ inputs.full_release_validation_run_id != '' }}
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ github.workflow_sha }}
path: trusted-workflow
fetch-depth: 0
filter: blob:none
persist-credentials: false
- name: Validate Tideclaw alpha publish target
if: startsWith(github.ref, 'refs/heads/tideclaw/alpha/')
env:
@@ -902,7 +936,7 @@ jobs:
GH_TOKEN: ${{ github.token }}
PREFLIGHT_RUN_ID: ${{ inputs.preflight_run_id }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
EXPECTED_EXTENDED_STABLE_BRANCH: ${{ github.ref_name }}
EXPECTED_EXTENDED_STABLE_BRANCH: ${{ inputs.release_candidate_branch || github.ref_name }}
RUN_KIND: preflight
run: |
set -euo pipefail
@@ -911,37 +945,32 @@ jobs:
RUN_JSON="$(gh run view "$PREFLIGHT_RUN_ID" --repo "$GITHUB_REPOSITORY" --json workflowName,headBranch,headSha,event,conclusion,url)"
printf '%s' "$RUN_JSON" | node scripts/openclaw-npm-extended-stable-release.mjs verify-run
- name: Verify full release validation run metadata
id: full_run
- name: Download full release validation manifest
if: ${{ inputs.full_release_validation_run_id != '' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: full-release-validation-${{ inputs.full_release_validation_run_id }}-${{ inputs.full_release_validation_run_attempt }}
path: full-release-validation
repository: ${{ github.repository }}
run-id: ${{ inputs.full_release_validation_run_id }}
github-token: ${{ github.token }}
- name: Verify full release validation evidence
if: ${{ inputs.full_release_validation_run_id != '' }}
env:
GH_TOKEN: ${{ github.token }}
FULL_RELEASE_VALIDATION_RUN_ID: ${{ inputs.full_release_validation_run_id }}
FULL_RELEASE_VALIDATION_RUN_ATTEMPT: ${{ inputs.full_release_validation_run_attempt }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
EXPECTED_EXTENDED_STABLE_BRANCH: ${{ github.ref_name }}
RUN_KIND: validation
EXPECTED_WORKFLOW_BRANCH: ${{ inputs.release_candidate_branch || github.ref_name }}
STRICT_VALIDATOR_FILE: ${{ github.workspace }}/trusted-workflow/scripts/release-ci-summary.mjs
run: |
set -euo pipefail
EXPECTED_RELEASE_SHA="$(git rev-parse HEAD)"
export EXPECTED_RELEASE_SHA
run_file="${RUNNER_TEMP}/full-release-validation-run.json"
gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${FULL_RELEASE_VALIDATION_RUN_ID}/attempts/${FULL_RELEASE_VALIDATION_RUN_ATTEMPT}" > "$run_file"
jq '{
workflowName: .name,
headBranch: .head_branch,
headSha: .head_sha,
event,
status,
conclusion,
url: .html_url
}' "$run_file" | node scripts/openclaw-npm-extended-stable-release.mjs verify-run
run_attempt="$(jq -r '.run_attempt // ""' "$run_file")"
if [[ "$run_attempt" != "$FULL_RELEASE_VALIDATION_RUN_ATTEMPT" ]]; then
echo "Full Release Validation run ${FULL_RELEASE_VALIDATION_RUN_ID} attempt mismatch: expected ${FULL_RELEASE_VALIDATION_RUN_ATTEMPT}, got ${run_attempt:-<missing>}." >&2
exit 1
fi
echo "attempt=$run_attempt" >> "$GITHUB_OUTPUT"
EXPECTED_SHA="$(git rev-parse HEAD)"
MANIFEST_FILE="full-release-validation/full-release-validation-manifest.json"
export EXPECTED_SHA MANIFEST_FILE
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${FULL_RELEASE_VALIDATION_RUN_ID}/attempts/${FULL_RELEASE_VALIDATION_RUN_ATTEMPT}" | \
node trusted-workflow/scripts/validate-full-release-validation-evidence.mjs
- name: Verify plugin npm release run metadata
if: ${{ inputs.npm_dist_tag == 'extended-stable' }}
@@ -949,7 +978,7 @@ jobs:
GH_TOKEN: ${{ github.token }}
PLUGIN_NPM_RUN_ID: ${{ inputs.plugin_npm_run_id }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
EXPECTED_EXTENDED_STABLE_BRANCH: ${{ github.ref_name }}
EXPECTED_EXTENDED_STABLE_BRANCH: ${{ inputs.release_candidate_branch || github.ref_name }}
RUN_KIND: plugin
run: |
set -euo pipefail
@@ -1011,16 +1040,6 @@ jobs:
download_preflight_artifact
- name: Download full release validation manifest
if: ${{ inputs.full_release_validation_run_id != '' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: full-release-validation-${{ inputs.full_release_validation_run_id }}-${{ steps.full_run.outputs.attempt }}
path: full-release-validation
repository: ${{ github.repository }}
run-id: ${{ inputs.full_release_validation_run_id }}
github-token: ${{ github.token }}
- name: Validate release tag and package metadata
if: ${{ inputs.preflight_run_id == '' }}
env:
@@ -1167,20 +1186,14 @@ jobs:
env:
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
EXPECTED_WORKFLOW_REF: ${{ github.ref_name }}
FULL_RELEASE_VALIDATION_RUN_ID: ${{ inputs.full_release_validation_run_id }}
FULL_RELEASE_VALIDATION_RUN_ATTEMPT: ${{ steps.full_run.outputs.attempt }}
run: |
set -euo pipefail
EXPECTED_RELEASE_SHA="$(git rev-parse HEAD)"
MANIFEST_FILE="full-release-validation/full-release-validation-manifest.json"
if [[ ! -f "$MANIFEST_FILE" ]]; then
echo "Full release validation manifest is missing." >&2
ls -la full-release-validation >&2 || true
exit 1
fi
export EXPECTED_RELEASE_SHA MANIFEST_FILE
node scripts/openclaw-npm-extended-stable-release.mjs verify-manifest
RERUN_GROUP="$(jq -r '.rerunGroup // ""' "$MANIFEST_FILE")"
RUN_RELEASE_SOAK="$(jq -r '.runReleaseSoak // ""' "$MANIFEST_FILE")"
PERFORMANCE_BLOCKING="$(jq -r '.controls.performanceBlocking // false' "$MANIFEST_FILE")"
@@ -1202,7 +1215,7 @@ jobs:
BYPASS_EXTENDED_STABLE_GUARD: ${{ inputs.bypass_extended_stable_guard }}
RELEASE_NPM_DIST_TAG: ${{ inputs.npm_dist_tag }}
RELEASE_TAG: ${{ inputs.tag }}
NPM_WORKFLOW_REF: ${{ github.ref }}
NPM_WORKFLOW_REF: ${{ inputs.release_candidate_branch != '' && format('refs/heads/{0}', inputs.release_candidate_branch) || github.ref }}
run: node scripts/openclaw-npm-extended-stable-release.mjs validate-request
- name: Capture previous extended-stable selector
@@ -1255,8 +1268,7 @@ jobs:
env:
BYPASS_EXTENDED_STABLE_GUARD: ${{ inputs.bypass_extended_stable_guard }}
RELEASE_TAG: ${{ inputs.tag }}
RELEASE_SHA: ${{ github.sha }}
EXTENDED_STABLE_BRANCH: ${{ github.ref_name }}
EXTENDED_STABLE_BRANCH: ${{ inputs.release_candidate_branch || github.ref_name }}
PREFLIGHT_RUN_ID: ${{ inputs.preflight_run_id }}
FULL_RELEASE_VALIDATION_RUN_ID: ${{ inputs.full_release_validation_run_id }}
TARBALL_NAME: ${{ steps.preflight_provenance.outputs.tarball_name }}
@@ -1270,13 +1282,14 @@ jobs:
run: |
set -euo pipefail
release_version="${RELEASE_TAG#v}"
release_sha="$(git rev-parse HEAD)"
{
echo "## npm extended-stable publication"
echo "- Package: openclaw@${release_version}"
echo "- Extended-stable guard bypass: ${BYPASS_EXTENDED_STABLE_GUARD}"
echo "- Extended-stable branch: ${EXTENDED_STABLE_BRANCH}"
echo "- Release tag: ${RELEASE_TAG}"
echo "- Release SHA: ${RELEASE_SHA}"
echo "- Release SHA: ${release_sha}"
echo "- npm preflight run: ${PREFLIGHT_RUN_ID}"
echo "- Full Release Validation run: ${FULL_RELEASE_VALIDATION_RUN_ID}"
echo "- Tarball: ${TARBALL_NAME:-unavailable}"