Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
466
.github/workflows/openclaw-stable-main-closeout.yml
vendored
Normal file
466
.github/workflows/openclaw-stable-main-closeout.yml
vendored
Normal file
@@ -0,0 +1,466 @@
|
||||
name: OpenClaw Stable Main Closeout
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Stable OpenClaw tag to replay or repair, for example v2026.6.8 or v2026.6.8-2
|
||||
required: false
|
||||
type: string
|
||||
rollback_drill_id:
|
||||
description: Opaque identifier for the current private rollback drill record
|
||||
required: false
|
||||
type: string
|
||||
rollback_drill_date:
|
||||
description: UTC date of the private rollback drill in YYYY-MM-DD form; must be within 90 days
|
||||
required: false
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: openclaw-stable-main-closeout-${{ github.event_name == 'workflow_dispatch' && (inputs.tag || github.run_id) || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
|
||||
jobs:
|
||||
resolve:
|
||||
name: Resolve stable release closeout inputs
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
full_release_validation_run_id: ${{ steps.inputs.outputs.full_release_validation_run_id }}
|
||||
release_publish_run_id: ${{ steps.inputs.outputs.release_publish_run_id }}
|
||||
rollback_drill_date: ${{ steps.inputs.outputs.rollback_drill_date }}
|
||||
rollback_drill_id: ${{ steps.inputs.outputs.rollback_drill_id }}
|
||||
evidence_tag: ${{ steps.inputs.outputs.evidence_tag }}
|
||||
fallback_correction: ${{ steps.inputs.outputs.fallback_correction }}
|
||||
main_ref: ${{ steps.inputs.outputs.main_ref }}
|
||||
repair_partial_closeout: ${{ steps.inputs.outputs.repair_partial_closeout }}
|
||||
should_closeout: ${{ steps.inputs.outputs.should_closeout }}
|
||||
tag: ${{ steps.inputs.outputs.tag }}
|
||||
steps:
|
||||
- name: Install GitHub API backoff helper
|
||||
run: |
|
||||
cat > "$RUNNER_TEMP/github-api-backoff.sh" <<'BASH'
|
||||
gh_with_retry() {
|
||||
local attempt output status lower_output
|
||||
for attempt in 1 2 3 4 5; do
|
||||
if output="$(gh "$@" 2>&1)"; then
|
||||
printf '%s\n' "$output"
|
||||
return 0
|
||||
fi
|
||||
status=$?
|
||||
lower_output="${output,,}"
|
||||
if [[ "$lower_output" != *"rate limit"* && "$output" != *"HTTP 429"* ]]; then
|
||||
printf '%s\n' "$output" >&2
|
||||
return "$status"
|
||||
fi
|
||||
echo "::warning::GitHub API throttled stable closeout on attempt ${attempt}; retrying after backoff." >&2
|
||||
sleep $((attempt * attempt * 5))
|
||||
done
|
||||
printf '%s\n' "$output" >&2
|
||||
return "$status"
|
||||
}
|
||||
BASH
|
||||
|
||||
- name: Checkout pushed main
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Resolve published stable release evidence
|
||||
id: inputs
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
MANUAL_TAG: ${{ inputs.tag }}
|
||||
ROLLBACK_DRILL_DATE: ${{ inputs.rollback_drill_date || vars.RELEASE_ROLLBACK_DRILL_DATE }}
|
||||
ROLLBACK_DRILL_ID: ${{ inputs.rollback_drill_id || vars.RELEASE_ROLLBACK_DRILL_ID }}
|
||||
TRIGGER_SHA: ${{ github.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "$EVENT_NAME" == "push" ]]; then
|
||||
sleep 45
|
||||
fi
|
||||
. "$RUNNER_TEMP/github-api-backoff.sh"
|
||||
if [[ "$EVENT_NAME" == "push" ]]; then
|
||||
main_ref="$TRIGGER_SHA"
|
||||
tag="$(gh_with_retry release list --repo "$GITHUB_REPOSITORY" --exclude-drafts --limit 100 \
|
||||
--json tagName,isPrerelease,publishedAt \
|
||||
--jq '[.[] | select(.isPrerelease | not) | select(.tagName | test("^v[0-9]{4}\\.[0-9]+\\.[0-9]+(-[0-9]+)?$"))] | sort_by(.publishedAt) | last | .tagName // empty')"
|
||||
if [[ -z "$tag" ]]; then
|
||||
echo "should_closeout=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
tag="$MANUAL_TAG"
|
||||
fi
|
||||
if [[ ! "$tag" =~ ^v[0-9]{4}\.[0-9]+\.[0-9]+(-[0-9]+)?$ ]]; then
|
||||
if [[ "$EVENT_NAME" == "push" ]]; then
|
||||
echo "should_closeout=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
echo "Stable main closeout accepts only a stable vYYYY.M.PATCH or vYYYY.M.PATCH-N tag, got $tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
release_asset_version="${tag#v}"
|
||||
release_package_version="$release_asset_version"
|
||||
fallback_package_version="$release_asset_version"
|
||||
if [[ "$release_package_version" =~ ^(.+)-[0-9]+$ ]]; then
|
||||
fallback_package_version="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
tag_package_content="$RUNNER_TEMP/tag-package-content.b64"
|
||||
tag_package_read=false
|
||||
for attempt in 1 2 3; do
|
||||
if gh_with_retry api "repos/$GITHUB_REPOSITORY/contents/package.json?ref=$tag" \
|
||||
--jq '.content' > "$tag_package_content"; then
|
||||
tag_package_read=true
|
||||
break
|
||||
fi
|
||||
if [[ "$attempt" != "3" ]]; then
|
||||
sleep $((attempt * 5))
|
||||
fi
|
||||
done
|
||||
if [[ "$tag_package_read" != "true" ]]; then
|
||||
echo "Stable closeout could not read package.json for $tag from GitHub API." >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! tag_package_json="$(tr -d '\n' < "$tag_package_content" | base64 --decode)"; then
|
||||
echo "Stable closeout package.json content for $tag was not valid base64." >&2
|
||||
exit 1
|
||||
fi
|
||||
tag_package_version="$(jq -r '.version // empty' <<<"$tag_package_json")"
|
||||
fallback_correction=false
|
||||
evidence_source_tag="$tag"
|
||||
if [[ "$release_package_version" != "$fallback_package_version" &&
|
||||
"$tag_package_version" == "$fallback_package_version" ]]; then
|
||||
fallback_correction=true
|
||||
evidence_source_tag="v$fallback_package_version"
|
||||
elif [[ "$tag_package_version" != "$release_package_version" ]]; then
|
||||
echo "Stable closeout requires $tag package.json to match $release_package_version, or the legacy fallback package version $fallback_package_version." >&2
|
||||
exit 1
|
||||
fi
|
||||
evidence_version="${evidence_source_tag#v}"
|
||||
evidence_asset="openclaw-${evidence_version}-postpublish-evidence.json"
|
||||
evidence_checksum_asset="${evidence_asset}.sha256"
|
||||
closeout_asset="openclaw-${release_asset_version}-stable-main-closeout.json"
|
||||
closeout_checksum_asset="${closeout_asset}.sha256"
|
||||
closeout_dir="$RUNNER_TEMP/release-closeout-evidence"
|
||||
mkdir -p "$closeout_dir"
|
||||
gh_with_retry release download "$tag" --repo "$GITHUB_REPOSITORY" \
|
||||
--pattern "$closeout_asset" --pattern "$closeout_checksum_asset" --dir "$closeout_dir" || true
|
||||
closeout_json_path="$closeout_dir/$closeout_asset"
|
||||
closeout_checksum_path="$closeout_dir/$closeout_checksum_asset"
|
||||
repair_partial_closeout=false
|
||||
existing_closeout_full_release_validation_run_id=""
|
||||
existing_closeout_release_publish_run_id=""
|
||||
if [[ -f "$closeout_json_path" && -f "$closeout_checksum_path" ]]; then
|
||||
expected_closeout_digest="$(awk 'NF { print $1; exit }' "$closeout_checksum_path")"
|
||||
actual_closeout_digest="$(sha256sum "$closeout_json_path" | awk '{print $1}')"
|
||||
if [[ ! "$expected_closeout_digest" =~ ^[0-9a-f]{64}$ ||
|
||||
"$expected_closeout_digest" != "$actual_closeout_digest" ]]; then
|
||||
echo "Stable closeout evidence for $tag has an invalid checksum; refusing to repair it." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ -f "$closeout_checksum_path" && ! -f "$closeout_json_path" ]]; then
|
||||
echo "Stable closeout evidence for $tag has a checksum without its manifest; refusing to repair it." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -f "$closeout_json_path" ]]; then
|
||||
existing_closeout_tag="$(jq -r '.releaseTag // empty' "$closeout_json_path")"
|
||||
existing_closeout_version="$(jq -r '.releaseVersion // empty' "$closeout_json_path")"
|
||||
existing_closeout_release_tag_sha="$(jq -r '.releaseTagSha // empty' "$closeout_json_path")"
|
||||
existing_closeout_main_ref="$(jq -r '.mainSha // empty' "$closeout_json_path")"
|
||||
existing_closeout_full_release_validation_run_id="$(jq -r '.fullReleaseValidationRunId // empty' "$closeout_json_path")"
|
||||
existing_closeout_release_publish_run_id="$(jq -r '.releasePublishRunId // empty' "$closeout_json_path")"
|
||||
existing_closeout_rollback_drill_id="$(jq -r '.rollbackDrill.id // empty' "$closeout_json_path")"
|
||||
existing_closeout_rollback_drill_date="$(jq -r '.rollbackDrill.date // empty' "$closeout_json_path")"
|
||||
if [[ "$existing_closeout_tag" != "$tag" ||
|
||||
"$existing_closeout_version" != "$tag_package_version" ||
|
||||
! "$existing_closeout_release_tag_sha" =~ ^[0-9a-f]{40}$ ||
|
||||
! "$existing_closeout_main_ref" =~ ^[0-9a-f]{40}$ ||
|
||||
-z "$existing_closeout_full_release_validation_run_id" ||
|
||||
-z "$existing_closeout_release_publish_run_id" ||
|
||||
-z "$existing_closeout_rollback_drill_id" ||
|
||||
! "$existing_closeout_rollback_drill_date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
|
||||
echo "Stable closeout manifest for $tag is incomplete; refusing to repair it." >&2
|
||||
exit 1
|
||||
fi
|
||||
main_ref="$existing_closeout_main_ref"
|
||||
ROLLBACK_DRILL_ID="$existing_closeout_rollback_drill_id"
|
||||
ROLLBACK_DRILL_DATE="$existing_closeout_rollback_drill_date"
|
||||
repair_partial_closeout=true
|
||||
elif [[ "$EVENT_NAME" == "push" ]]; then
|
||||
main_version="$(jq -r '.version // empty' package.json)"
|
||||
if [[ "$main_version" != "$release_package_version" &&
|
||||
"$main_version" != "$fallback_package_version" ]]; then
|
||||
echo "should_closeout=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
main_ref="main"
|
||||
fi
|
||||
evidence_dir="$RUNNER_TEMP/release-postpublish-evidence"
|
||||
mkdir -p "$evidence_dir"
|
||||
gh_with_retry release download "$evidence_source_tag" --repo "$GITHUB_REPOSITORY" \
|
||||
--pattern "$evidence_asset" --pattern "$evidence_checksum_asset" --dir "$evidence_dir" || true
|
||||
evidence_path="$evidence_dir/$evidence_asset"
|
||||
evidence_checksum_path="$evidence_dir/$evidence_checksum_asset"
|
||||
if [[ ! -f "$evidence_path" || ! -f "$evidence_checksum_path" ]]; then
|
||||
if [[ "$EVENT_NAME" == "push" ]]; then
|
||||
echo "Stable closeout skipped: $evidence_source_tag predates immutable postpublish evidence." >&2
|
||||
echo "should_closeout=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
echo "Stable closeout is required for $tag, but immutable postpublish evidence from $evidence_source_tag is missing." >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! (
|
||||
cd "$evidence_dir"
|
||||
sha256sum --strict --status -c "$evidence_checksum_asset"
|
||||
); then
|
||||
echo "Postpublish evidence checksum failed for $tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
evidence_release_tag="$(jq -r '.releaseTag // empty' "$evidence_path")"
|
||||
full_release_validation_run_id="$(jq -r '[.workflowRuns[]? | select(.label == "Full Release Validation") | .id] | if length == 1 then .[0] else empty end' "$evidence_path")"
|
||||
release_publish_run_id="$(jq -r '.releasePublishRunId // empty' "$evidence_path")"
|
||||
if [[ "$evidence_release_tag" != "$evidence_source_tag" || -z "$full_release_validation_run_id" || -z "$release_publish_run_id" ]]; then
|
||||
echo "Stable closeout is required for $tag, but postpublish evidence does not bind $evidence_source_tag to exactly one Full Release Validation run and its Publish run." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "$existing_closeout_full_release_validation_run_id" &&
|
||||
( "$existing_closeout_full_release_validation_run_id" != "$full_release_validation_run_id" ||
|
||||
"$existing_closeout_release_publish_run_id" != "$release_publish_run_id" ) ]]; then
|
||||
echo "Stable closeout manifest for $tag does not match immutable postpublish evidence; refusing to accept it." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$ROLLBACK_DRILL_ID" || -z "$ROLLBACK_DRILL_DATE" ]]; then
|
||||
if [[ "$EVENT_NAME" == "push" ]]; then
|
||||
echo "::warning::Stable closeout skipped: rollback drill repository variables are missing; manual dispatch remains required to complete closeout."
|
||||
echo "should_closeout=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
echo "Stable closeout requires repository variables RELEASE_ROLLBACK_DRILL_ID and RELEASE_ROLLBACK_DRILL_DATE, or explicit manual overrides." >&2
|
||||
exit 1
|
||||
fi
|
||||
{
|
||||
echo "full_release_validation_run_id=$full_release_validation_run_id"
|
||||
echo "release_publish_run_id=$release_publish_run_id"
|
||||
echo "rollback_drill_date=$ROLLBACK_DRILL_DATE"
|
||||
echo "rollback_drill_id=$ROLLBACK_DRILL_ID"
|
||||
echo "evidence_tag=$evidence_source_tag"
|
||||
echo "fallback_correction=$fallback_correction"
|
||||
echo "main_ref=$main_ref"
|
||||
echo "repair_partial_closeout=$repair_partial_closeout"
|
||||
echo "should_closeout=true"
|
||||
echo "tag=$tag"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
verify:
|
||||
name: Verify stable main closeout
|
||||
needs: resolve
|
||||
if: ${{ needs.resolve.outputs.should_closeout == 'true' }}
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout resolved main state
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ needs.resolve.outputs.main_ref }}
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout shipped release tag
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: refs/tags/${{ needs.resolve.outputs.tag }}
|
||||
path: release-tag
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Checkout fallback evidence tag
|
||||
if: ${{ needs.resolve.outputs.fallback_correction == 'true' }}
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: refs/tags/${{ needs.resolve.outputs.evidence_tag }}
|
||||
path: evidence-tag
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Bind fallback correction to the published package source
|
||||
if: ${{ needs.resolve.outputs.fallback_correction == 'true' }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
correction_sha="$(git -C "$GITHUB_WORKSPACE/release-tag" rev-parse HEAD)"
|
||||
evidence_sha="$(git -C "$GITHUB_WORKSPACE/evidence-tag" rev-parse HEAD)"
|
||||
if [[ "$correction_sha" != "$evidence_sha" ]]; then
|
||||
echo "Fallback correction ${{ needs.resolve.outputs.tag }} must point to the same source commit as ${{ needs.resolve.outputs.evidence_tag }} to reuse immutable package evidence." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Install GitHub API backoff helper
|
||||
run: |
|
||||
cat > "$RUNNER_TEMP/github-api-backoff.sh" <<'BASH'
|
||||
gh_with_retry() {
|
||||
local attempt output status lower_output
|
||||
for attempt in 1 2 3 4 5; do
|
||||
if output="$(gh "$@" 2>&1)"; then
|
||||
printf '%s\n' "$output"
|
||||
return 0
|
||||
fi
|
||||
status=$?
|
||||
lower_output="${output,,}"
|
||||
if [[ "$lower_output" != *"rate limit"* && "$output" != *"HTTP 429"* ]]; then
|
||||
printf '%s\n' "$output" >&2
|
||||
return "$status"
|
||||
fi
|
||||
echo "::warning::GitHub API throttled stable closeout on attempt ${attempt}; retrying after backoff." >&2
|
||||
sleep $((attempt * attempt * 5))
|
||||
done
|
||||
printf '%s\n' "$output" >&2
|
||||
return "$status"
|
||||
}
|
||||
BASH
|
||||
|
||||
- name: Verify release workflow evidence
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FULL_RELEASE_VALIDATION_RUN_ID: ${{ needs.resolve.outputs.full_release_validation_run_id }}
|
||||
RELEASE_PUBLISH_RUN_ID: ${{ needs.resolve.outputs.release_publish_run_id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
. "$RUNNER_TEMP/github-api-backoff.sh"
|
||||
gh_with_retry run view "$FULL_RELEASE_VALIDATION_RUN_ID" --repo "$GITHUB_REPOSITORY" \
|
||||
--json workflowName,event,status,conclusion \
|
||||
> "$RUNNER_TEMP/full-release-validation-run.json"
|
||||
node --input-type=module - "$RUNNER_TEMP/full-release-validation-run.json" <<'NODE'
|
||||
import { readFileSync } from "node:fs";
|
||||
const run = JSON.parse(readFileSync(process.argv[2], "utf8"));
|
||||
for (const [key, expected] of [
|
||||
["workflowName", "Full Release Validation"],
|
||||
["event", "workflow_dispatch"],
|
||||
["status", "completed"],
|
||||
["conclusion", "success"],
|
||||
]) {
|
||||
if (run[key] !== expected) {
|
||||
throw new Error(`Full Release Validation must have ${key}=${expected}, got ${run[key] ?? "<missing>"}.`);
|
||||
}
|
||||
}
|
||||
NODE
|
||||
gh_with_retry run view "$RELEASE_PUBLISH_RUN_ID" --repo "$GITHUB_REPOSITORY" \
|
||||
--json workflowName,event,status,conclusion \
|
||||
> "$RUNNER_TEMP/release-publish-run.json"
|
||||
node --input-type=module - "$RUNNER_TEMP/release-publish-run.json" <<'NODE'
|
||||
import { readFileSync } from "node:fs";
|
||||
const run = JSON.parse(readFileSync(process.argv[2], "utf8"));
|
||||
for (const [key, expected] of [
|
||||
["workflowName", "OpenClaw Release Publish"],
|
||||
["event", "workflow_dispatch"],
|
||||
["status", "completed"],
|
||||
["conclusion", "success"],
|
||||
]) {
|
||||
if (run[key] !== expected) {
|
||||
throw new Error(`OpenClaw Release Publish must have ${key}=${expected}, got ${run[key] ?? "<missing>"}.`);
|
||||
}
|
||||
}
|
||||
NODE
|
||||
|
||||
manifest_dir="$RUNNER_TEMP/full-release-validation-manifest"
|
||||
rm -rf "$manifest_dir"
|
||||
mkdir -p "$manifest_dir"
|
||||
gh_with_retry run download "$FULL_RELEASE_VALIDATION_RUN_ID" --repo "$GITHUB_REPOSITORY" \
|
||||
--name "full-release-validation-${FULL_RELEASE_VALIDATION_RUN_ID}" \
|
||||
--dir "$manifest_dir"
|
||||
tag_sha="$(git -C "$GITHUB_WORKSPACE/release-tag" rev-parse HEAD)"
|
||||
jq -e --arg tag_sha "$tag_sha" '
|
||||
.workflowName == "Full Release Validation" and
|
||||
.targetSha == $tag_sha and
|
||||
.rerunGroup == "all" and
|
||||
.runReleaseSoak == "true" and
|
||||
.controls.performanceBlocking == true and
|
||||
.childRuns.productPerformance.conclusion == "success"
|
||||
' "$manifest_dir/full-release-validation-manifest.json" >/dev/null || {
|
||||
echo "Full Release Validation manifest does not contain the required stable release controls." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Verify stable state and write closeout manifest
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RELEASE_TAG: ${{ needs.resolve.outputs.tag }}
|
||||
FULL_RELEASE_VALIDATION_RUN_ID: ${{ needs.resolve.outputs.full_release_validation_run_id }}
|
||||
RELEASE_PUBLISH_RUN_ID: ${{ needs.resolve.outputs.release_publish_run_id }}
|
||||
ROLLBACK_DRILL_ID: ${{ needs.resolve.outputs.rollback_drill_id }}
|
||||
ROLLBACK_DRILL_DATE: ${{ needs.resolve.outputs.rollback_drill_date }}
|
||||
REPAIR_PARTIAL_CLOSEOUT: ${{ needs.resolve.outputs.repair_partial_closeout }}
|
||||
CLOSEOUT_DIR: ${{ runner.temp }}/openclaw-stable-main-closeout
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p "$CLOSEOUT_DIR"
|
||||
. "$RUNNER_TEMP/github-api-backoff.sh"
|
||||
gh_with_retry release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
|
||||
--json tagName,isDraft,isPrerelease,assets \
|
||||
> "$CLOSEOUT_DIR/github-release.json"
|
||||
node scripts/verify-stable-main-closeout.mjs \
|
||||
--tag "$RELEASE_TAG" \
|
||||
--main-dir "$GITHUB_WORKSPACE" \
|
||||
--tag-dir "$GITHUB_WORKSPACE/release-tag" \
|
||||
--release-json "$CLOSEOUT_DIR/github-release.json" \
|
||||
--full-release-validation-run-id "$FULL_RELEASE_VALIDATION_RUN_ID" \
|
||||
--release-publish-run-id "$RELEASE_PUBLISH_RUN_ID" \
|
||||
--rollback-drill-id "$ROLLBACK_DRILL_ID" \
|
||||
--rollback-drill-date "$ROLLBACK_DRILL_DATE" \
|
||||
--allow-stale-rollback-drill "$REPAIR_PARTIAL_CLOSEOUT" \
|
||||
--output "$CLOSEOUT_DIR/stable-main-closeout.json"
|
||||
release_version="${RELEASE_TAG#v}"
|
||||
sha256sum "$CLOSEOUT_DIR/stable-main-closeout.json" | awk -v asset="openclaw-${release_version}-stable-main-closeout.json" \
|
||||
'{print $1 " " asset}' \
|
||||
> "$CLOSEOUT_DIR/stable-main-closeout.json.sha256"
|
||||
|
||||
- name: Attach immutable closeout evidence
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RELEASE_TAG: ${{ needs.resolve.outputs.tag }}
|
||||
CLOSEOUT_DIR: ${{ runner.temp }}/openclaw-stable-main-closeout
|
||||
run: |
|
||||
set -euo pipefail
|
||||
. "$RUNNER_TEMP/github-api-backoff.sh"
|
||||
release_version="${RELEASE_TAG#v}"
|
||||
attach_or_verify() {
|
||||
local source_path="$1"
|
||||
local asset_name="$2"
|
||||
local existing_dir="$CLOSEOUT_DIR/existing-${asset_name}"
|
||||
mkdir -p "$existing_dir"
|
||||
gh_with_retry release download "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \
|
||||
--pattern "$asset_name" --dir "$existing_dir" || true
|
||||
if [[ -f "$existing_dir/$asset_name" ]]; then
|
||||
cmp --silent "$source_path" "$existing_dir/$asset_name" || {
|
||||
echo "Existing release asset $asset_name differs from closeout evidence." >&2
|
||||
exit 1
|
||||
}
|
||||
return
|
||||
fi
|
||||
gh_with_retry release upload "$RELEASE_TAG" "$source_path#$asset_name" --repo "$GITHUB_REPOSITORY"
|
||||
}
|
||||
attach_or_verify \
|
||||
"$CLOSEOUT_DIR/stable-main-closeout.json" \
|
||||
"openclaw-${release_version}-stable-main-closeout.json"
|
||||
attach_or_verify \
|
||||
"$CLOSEOUT_DIR/stable-main-closeout.json.sha256" \
|
||||
"openclaw-${release_version}-stable-main-closeout.json.sha256"
|
||||
|
||||
- name: Upload closeout workflow evidence
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||
with:
|
||||
name: openclaw-stable-main-closeout-${{ needs.resolve.outputs.tag }}
|
||||
path: ${{ runner.temp }}/openclaw-stable-main-closeout
|
||||
if-no-files-found: error
|
||||
Reference in New Issue
Block a user