mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
fix(release): preserve focused evidence lineage (#129060)
* fix(release): preserve focused evidence lineage * fix(release): bind focused evidence to authorized tooling * fix(release): revalidate focused evidence after Docker approval
This commit is contained in:
committed by
GitHub
parent
ccd8ede95e
commit
afa89f03ee
@@ -134,5 +134,7 @@ jobs:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
permissions:
|
||||
actions: read
|
||||
attestations: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
@@ -16,6 +16,26 @@ on:
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
focused_release_evidence_run_id:
|
||||
description: Optional immutable authorized beta focused evidence producer run
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
focused_release_evidence_run_attempt:
|
||||
description: Exact previously verified focused evidence producer attempt
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
focused_release_evidence_workflow_full_ref:
|
||||
description: Exact previously verified focused evidence producer tag
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
focused_release_evidence_workflow_sha:
|
||||
description: Exact previously verified focused evidence producer SHA
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
outputs:
|
||||
version:
|
||||
description: Resolved Docker release version without the v prefix
|
||||
@@ -178,6 +198,8 @@ jobs:
|
||||
if: ${{ always() && needs.approve_docker_publish.result == 'success' && needs.resolve_release_policy.result == 'success' && needs.validate_publish_config.result == 'success' }}
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
actions: read
|
||||
attestations: read
|
||||
contents: read
|
||||
outputs:
|
||||
built_at: ${{ steps.build_provenance.outputs.built_at }}
|
||||
@@ -188,6 +210,95 @@ jobs:
|
||||
with:
|
||||
ref: ${{ inputs.release_sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout trusted focused evidence verifier
|
||||
if: ${{ inputs.focused_release_evidence_run_id != '' }}
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
path: .release-harness
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Revalidate focused evidence producer after Docker approval
|
||||
if: ${{ inputs.focused_release_evidence_run_id != '' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ID: ${{ inputs.focused_release_evidence_run_id }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT: ${{ inputs.focused_release_evidence_run_attempt }}
|
||||
PRODUCER_WORKFLOW_FULL_REF: ${{ inputs.focused_release_evidence_workflow_full_ref }}
|
||||
PRODUCER_WORKFLOW_SHA: ${{ inputs.focused_release_evidence_workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ ! "${FOCUSED_RELEASE_EVIDENCE_RUN_ID}" =~ ^[1-9][0-9]*$ ||
|
||||
! "${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}" =~ ^[1-9][0-9]*$ ||
|
||||
! "${PRODUCER_WORKFLOW_SHA}" =~ ^[a-f0-9]{40}$ ||
|
||||
! "${PRODUCER_WORKFLOW_FULL_REF}" =~ ^refs/tags/release-publish/([a-f0-9]{12})-[1-9][0-9]*$ ||
|
||||
"${PRODUCER_WORKFLOW_SHA:0:12}" != "${BASH_REMATCH[1]}" ]]; then
|
||||
echo "Focused evidence producer identity is missing or invalid after Docker approval." >&2
|
||||
exit 1
|
||||
fi
|
||||
producer_ref="${PRODUCER_WORKFLOW_FULL_REF#refs/tags/}"
|
||||
run_json="$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${FOCUSED_RELEASE_EVIDENCE_RUN_ID}")"
|
||||
if ! jq -e \
|
||||
--arg run_id "${FOCUSED_RELEASE_EVIDENCE_RUN_ID}" \
|
||||
--arg attempt "${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}" \
|
||||
--arg producer_ref "${producer_ref}" \
|
||||
--arg producer_sha "${PRODUCER_WORKFLOW_SHA}" \
|
||||
'.id == ($run_id | tonumber) and .run_attempt == ($attempt | tonumber) and
|
||||
.name == "Authorized Beta Focused Validation" and
|
||||
.path == ".github/workflows/authorized-beta-focused-validation.yml" and
|
||||
.event == "workflow_dispatch" and .status == "completed" and .conclusion == "success" and
|
||||
.head_branch == $producer_ref and .head_sha == $producer_sha' \
|
||||
<<<"${run_json}" >/dev/null; then
|
||||
echo "Focused evidence producer changed after Docker approval." >&2
|
||||
exit 1
|
||||
fi
|
||||
remote_producer_sha="$(
|
||||
gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${producer_ref}" \
|
||||
--jq '.object | select(.type == "commit") | .sha'
|
||||
)"
|
||||
if [[ "${remote_producer_sha}" != "${PRODUCER_WORKFLOW_SHA}" ]]; then
|
||||
echo "Focused evidence producer tag is missing, moved, or annotated after Docker approval." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Download focused release evidence after Docker approval
|
||||
if: ${{ inputs.focused_release_evidence_run_id != '' }}
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: authorized-beta-focused-v1-${{ inputs.focused_release_evidence_run_id }}-${{ inputs.focused_release_evidence_run_attempt }}
|
||||
path: ${{ runner.temp }}/authorized-beta-focused-evidence
|
||||
repository: ${{ github.repository }}
|
||||
run-id: ${{ inputs.focused_release_evidence_run_id }}
|
||||
github-token: ${{ github.token }}
|
||||
|
||||
- name: Verify focused release evidence after Docker approval
|
||||
if: ${{ inputs.focused_release_evidence_run_id != '' }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ID: ${{ inputs.focused_release_evidence_run_id }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT: ${{ inputs.focused_release_evidence_run_attempt }}
|
||||
PRODUCER_WORKFLOW_FULL_REF: ${{ inputs.focused_release_evidence_workflow_full_ref }}
|
||||
PRODUCER_WORKFLOW_SHA: ${{ inputs.focused_release_evidence_workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
evidence="${RUNNER_TEMP}/authorized-beta-focused-evidence/evidence.json"
|
||||
gh attestation verify "${evidence}" \
|
||||
--repo "${GITHUB_REPOSITORY}" \
|
||||
--signer-workflow "${GITHUB_REPOSITORY}/.github/workflows/authorized-beta-focused-validation.yml" \
|
||||
--signer-digest "${PRODUCER_WORKFLOW_SHA}" \
|
||||
--source-digest "${PRODUCER_WORKFLOW_SHA}" \
|
||||
--source-ref "${PRODUCER_WORKFLOW_FULL_REF}" \
|
||||
--deny-self-hosted-runners
|
||||
node .release-harness/scripts/validate-authorized-beta-focused-evidence.mts verify \
|
||||
--candidate-root . \
|
||||
--artifact "${evidence}" \
|
||||
--producer-run-id "${FOCUSED_RELEASE_EVIDENCE_RUN_ID}" \
|
||||
--producer-run-attempt "${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}" \
|
||||
--producer-workflow-full-ref "${PRODUCER_WORKFLOW_FULL_REF}" \
|
||||
--producer-workflow-sha "${PRODUCER_WORKFLOW_SHA}"
|
||||
|
||||
- name: Resolve shared build provenance
|
||||
id: build_provenance
|
||||
|
||||
@@ -128,6 +128,8 @@ jobs:
|
||||
preflight_tarball_sha256: ${{ steps.manifest.outputs.tarball_sha256 }}
|
||||
full_release_validation_run_attempt: ${{ steps.full_run.outputs.attempt }}
|
||||
focused_release_evidence_run_attempt: ${{ steps.focused_run.outputs.attempt }}
|
||||
focused_release_evidence_workflow_full_ref: ${{ steps.focused_run.outputs.workflow_full_ref }}
|
||||
focused_release_evidence_workflow_sha: ${{ steps.focused_run.outputs.workflow_sha }}
|
||||
windows_node_installer_digests: ${{ steps.windows_source.outputs.installer_digests }}
|
||||
steps:
|
||||
- name: Validate inputs
|
||||
@@ -726,17 +728,63 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ID: ${{ inputs.focused_release_evidence_run_id }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT: ${{ inputs.focused_release_evidence_run_attempt }}
|
||||
WORKFLOW_SHA: ${{ github.workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
run_attempt="$(
|
||||
gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${FOCUSED_RELEASE_EVIDENCE_RUN_ID}" \
|
||||
--jq '.run_attempt'
|
||||
)"
|
||||
if [[ "${run_attempt}" != "${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}" ]]; then
|
||||
echo "Focused evidence run attempt mismatch: expected ${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}, got ${run_attempt}." >&2
|
||||
run_json="$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${FOCUSED_RELEASE_EVIDENCE_RUN_ID}")"
|
||||
if ! jq -e \
|
||||
--arg run_id "${FOCUSED_RELEASE_EVIDENCE_RUN_ID}" \
|
||||
--arg attempt "${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}" \
|
||||
'.id == ($run_id | tonumber) and .run_attempt == ($attempt | tonumber) and
|
||||
.name == "Authorized Beta Focused Validation" and
|
||||
.path == ".github/workflows/authorized-beta-focused-validation.yml" and
|
||||
.event == "workflow_dispatch" and .status == "completed" and .conclusion == "success"' \
|
||||
<<<"${run_json}" >/dev/null; then
|
||||
echo "Focused evidence producer must be the exact successful authorized workflow run and attempt." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "attempt=${run_attempt}" >> "$GITHUB_OUTPUT"
|
||||
producer_ref="$(jq -r '.head_branch // empty' <<<"${run_json}")"
|
||||
producer_sha="$(jq -r '.head_sha // empty' <<<"${run_json}")"
|
||||
if [[ ! "${producer_ref}" =~ ^release-publish/([a-f0-9]{12})-[1-9][0-9]*$ ]]; then
|
||||
echo "Focused evidence producer must use a protected release-publish tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
producer_prefix="${BASH_REMATCH[1]}"
|
||||
if [[ ! "${producer_sha}" =~ ^[a-f0-9]{40}$ || "${producer_sha:0:12}" != "${producer_prefix}" ]]; then
|
||||
echo "Focused evidence producer tag does not match its workflow SHA." >&2
|
||||
exit 1
|
||||
fi
|
||||
remote_producer_sha="$(
|
||||
gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${producer_ref}" \
|
||||
--jq '.object | select(.type == "commit") | .sha'
|
||||
)"
|
||||
if [[ "${remote_producer_sha}" != "${producer_sha}" ]]; then
|
||||
echo "Focused evidence producer tag is missing, moved, or annotated." >&2
|
||||
exit 1
|
||||
fi
|
||||
producer_workflow_path=".github/workflows/authorized-beta-focused-validation.yml"
|
||||
producer_policy_path="scripts/authorized-beta-focused-policy.json"
|
||||
for trusted_path in "${producer_workflow_path}" "${producer_policy_path}"; do
|
||||
producer_blob="$(git rev-parse "${producer_sha}:${trusted_path}")"
|
||||
consumer_blob="$(git rev-parse "${WORKFLOW_SHA}:${trusted_path}")"
|
||||
if [[ "${producer_blob}" != "${consumer_blob}" ]]; then
|
||||
echo "Focused evidence producer does not match the trusted ${trusted_path}." >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
historical_tooling_sha="$(
|
||||
git show "${WORKFLOW_SHA}:${producer_policy_path}" |
|
||||
jq -er '.historicalToolingSha | select(type == "string" and test("^[a-f0-9]{40}$"))'
|
||||
)"
|
||||
if ! git merge-base --is-ancestor "${historical_tooling_sha}" "${producer_sha}"; then
|
||||
echo "Focused evidence producer is not descended from the fixed authorized tooling." >&2
|
||||
exit 1
|
||||
fi
|
||||
{
|
||||
echo "attempt=${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}"
|
||||
echo "workflow_full_ref=refs/tags/${producer_ref}"
|
||||
echo "workflow_sha=${producer_sha}"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download focused release evidence
|
||||
if: ${{ inputs.release_evidence_mode == 'authorized-beta-focused-v1' }}
|
||||
@@ -754,25 +802,25 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ID: ${{ inputs.focused_release_evidence_run_id }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT: ${{ steps.focused_run.outputs.attempt }}
|
||||
WORKFLOW_FULL_REF: ${{ github.ref }}
|
||||
WORKFLOW_SHA: ${{ github.workflow_sha }}
|
||||
PRODUCER_WORKFLOW_FULL_REF: ${{ steps.focused_run.outputs.workflow_full_ref }}
|
||||
PRODUCER_WORKFLOW_SHA: ${{ steps.focused_run.outputs.workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
evidence="${RUNNER_TEMP}/authorized-beta-focused-evidence/evidence.json"
|
||||
gh attestation verify "${evidence}" \
|
||||
--repo "${GITHUB_REPOSITORY}" \
|
||||
--signer-workflow "${GITHUB_REPOSITORY}/.github/workflows/authorized-beta-focused-validation.yml" \
|
||||
--signer-digest "${WORKFLOW_SHA}" \
|
||||
--source-digest "${WORKFLOW_SHA}" \
|
||||
--source-ref "${WORKFLOW_FULL_REF}" \
|
||||
--signer-digest "${PRODUCER_WORKFLOW_SHA}" \
|
||||
--source-digest "${PRODUCER_WORKFLOW_SHA}" \
|
||||
--source-ref "${PRODUCER_WORKFLOW_FULL_REF}" \
|
||||
--deny-self-hosted-runners
|
||||
node "${RUNNER_TEMP}/release-validation-tooling/validate-authorized-beta-focused-evidence.mts" verify \
|
||||
--candidate-root . \
|
||||
--artifact "${evidence}" \
|
||||
--producer-run-id "${FOCUSED_RELEASE_EVIDENCE_RUN_ID}" \
|
||||
--producer-run-attempt "${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}" \
|
||||
--producer-workflow-full-ref "${WORKFLOW_FULL_REF}" \
|
||||
--producer-workflow-sha "${WORKFLOW_SHA}"
|
||||
--producer-workflow-full-ref "${PRODUCER_WORKFLOW_FULL_REF}" \
|
||||
--producer-workflow-sha "${PRODUCER_WORKFLOW_SHA}"
|
||||
|
||||
- name: Validate release tag is reachable from a trusted release branch
|
||||
env:
|
||||
@@ -890,25 +938,25 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ID: ${{ inputs.focused_release_evidence_run_id }}
|
||||
FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT: ${{ needs.resolve_release_target.outputs.focused_release_evidence_run_attempt }}
|
||||
WORKFLOW_FULL_REF: ${{ github.ref }}
|
||||
WORKFLOW_SHA: ${{ github.workflow_sha }}
|
||||
PRODUCER_WORKFLOW_FULL_REF: ${{ needs.resolve_release_target.outputs.focused_release_evidence_workflow_full_ref }}
|
||||
PRODUCER_WORKFLOW_SHA: ${{ needs.resolve_release_target.outputs.focused_release_evidence_workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
evidence="${RUNNER_TEMP}/authorized-beta-focused-evidence/evidence.json"
|
||||
gh attestation verify "${evidence}" \
|
||||
--repo "${GITHUB_REPOSITORY}" \
|
||||
--signer-workflow "${GITHUB_REPOSITORY}/.github/workflows/authorized-beta-focused-validation.yml" \
|
||||
--signer-digest "${WORKFLOW_SHA}" \
|
||||
--source-digest "${WORKFLOW_SHA}" \
|
||||
--source-ref "${WORKFLOW_FULL_REF}" \
|
||||
--signer-digest "${PRODUCER_WORKFLOW_SHA}" \
|
||||
--source-digest "${PRODUCER_WORKFLOW_SHA}" \
|
||||
--source-ref "${PRODUCER_WORKFLOW_FULL_REF}" \
|
||||
--deny-self-hosted-runners
|
||||
node .release-harness/scripts/validate-authorized-beta-focused-evidence.mts verify \
|
||||
--candidate-root . \
|
||||
--artifact "${evidence}" \
|
||||
--producer-run-id "${FOCUSED_RELEASE_EVIDENCE_RUN_ID}" \
|
||||
--producer-run-attempt "${FOCUSED_RELEASE_EVIDENCE_RUN_ATTEMPT}" \
|
||||
--producer-workflow-full-ref "${WORKFLOW_FULL_REF}" \
|
||||
--producer-workflow-sha "${WORKFLOW_SHA}"
|
||||
--producer-workflow-full-ref "${PRODUCER_WORKFLOW_FULL_REF}" \
|
||||
--producer-workflow-sha "${PRODUCER_WORKFLOW_SHA}"
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
@@ -2743,10 +2791,16 @@ jobs:
|
||||
with:
|
||||
tag: ${{ inputs.tag }}
|
||||
release_sha: ${{ needs.resolve_release_target.outputs.sha }}
|
||||
focused_release_evidence_run_id: ${{ inputs.release_evidence_mode == 'authorized-beta-focused-v1' && inputs.focused_release_evidence_run_id || '' }}
|
||||
focused_release_evidence_run_attempt: ${{ needs.resolve_release_target.outputs.focused_release_evidence_run_attempt }}
|
||||
focused_release_evidence_workflow_full_ref: ${{ needs.resolve_release_target.outputs.focused_release_evidence_workflow_full_ref }}
|
||||
focused_release_evidence_workflow_sha: ${{ needs.resolve_release_target.outputs.focused_release_evidence_workflow_sha }}
|
||||
secrets:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
permissions:
|
||||
actions: read
|
||||
attestations: read
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
|
||||
Reference in New Issue
Block a user