mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 20:35:39 -06:00
fix(release): bind npm publishers to live tooling
This commit is contained in:
@@ -1407,11 +1407,25 @@ jobs:
|
||||
id: publish
|
||||
env:
|
||||
BYPASS_EXTENDED_STABLE_GUARD: ${{ inputs.bypass_extended_stable_guard }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
OPENCLAW_PREPACK_PREPARED: "1"
|
||||
OPENCLAW_NPM_PUBLISH_TAG: ${{ inputs.npm_dist_tag }}
|
||||
PUBLISH_TARBALL_PATH: ${{ steps.preflight_provenance.outputs.tarball_path }}
|
||||
RELEASE_PUBLISH_RUN_ID: ${{ inputs.release_publish_run_id }}
|
||||
WORKFLOW_FULL_REF: ${{ github.ref }}
|
||||
WORKFLOW_REF: ${{ github.ref_name }}
|
||||
WORKFLOW_SHA: ${{ github.workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
verify_release_tooling_identity() {
|
||||
node trusted-workflow/scripts/release-tooling-identity.mjs verify \
|
||||
--repository "$GITHUB_REPOSITORY" \
|
||||
--workflow-ref "$WORKFLOW_REF" \
|
||||
--workflow-full-ref "$WORKFLOW_FULL_REF" \
|
||||
--workflow-sha "$WORKFLOW_SHA" \
|
||||
--release-publish-run-id "$RELEASE_PUBLISH_RUN_ID" \
|
||||
--allow-prevalidated-ref
|
||||
}
|
||||
publish_target="${PUBLISH_TARBALL_PATH}"
|
||||
if [[ -n "${publish_target}" ]]; then
|
||||
publish_target="./${publish_target}"
|
||||
@@ -1429,11 +1443,13 @@ jobs:
|
||||
echo "${package_name}@${package_version} is already published; reusing it."
|
||||
return 0
|
||||
fi
|
||||
verify_release_tooling_identity
|
||||
bash scripts/openclaw-npm-publish.sh --publish "./${tarball_path}"
|
||||
}
|
||||
while IFS=$'\t' read -r package_name tarball_name; do
|
||||
publish_if_missing "$package_name" "preflight-tarball/$tarball_name"
|
||||
done < <(jq -r '(.corePackageTarballs // [])[] | [.packageName, .tarballName] | @tsv' preflight-tarball/preflight-manifest.json)
|
||||
verify_release_tooling_identity
|
||||
bash scripts/openclaw-npm-publish.sh --publish "${publish_target}"
|
||||
|
||||
- name: Verify extended-stable registry readback
|
||||
|
||||
@@ -962,6 +962,7 @@ jobs:
|
||||
CHILD_WORKFLOW_REF: ${{ github.ref_name }}
|
||||
PARENT_WORKFLOW_SHA: ${{ github.sha }}
|
||||
PARENT_WORKFLOW_BRANCH: ${{ github.ref_name }}
|
||||
PARENT_WORKFLOW_FULL_REF: ${{ github.ref }}
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
PREFLIGHT_RUN_ID: ${{ inputs.preflight_run_id }}
|
||||
FULL_RELEASE_VALIDATION_RUN_ID: ${{ inputs.full_release_validation_run_id }}
|
||||
@@ -2283,6 +2284,13 @@ jobs:
|
||||
if [[ "$(jq -r '.normal.shouldDispatch' "${clawhub_plan_path}")" == "true" ]]; then
|
||||
clawhub_dispatch_args=()
|
||||
append_clawhub_dispatch_args normal
|
||||
if [[ "${PARENT_WORKFLOW_FULL_REF}" == "refs/heads/main" ||
|
||||
"${PARENT_WORKFLOW_FULL_REF}" =~ ^refs/tags/release-publish/[a-f0-9]{12}-[1-9][0-9]*$ ]]; then
|
||||
clawhub_dispatch_args+=(
|
||||
-f release_publish_full_ref="${PARENT_WORKFLOW_FULL_REF}"
|
||||
-f release_publish_workflow_sha="${PARENT_WORKFLOW_SHA}"
|
||||
)
|
||||
fi
|
||||
plugin_clawhub_run_id="$(dispatch_workflow_at_ref \
|
||||
"$(jq -r '.normal.ref' "${clawhub_plan_path}")" \
|
||||
"${TARGET_SHA}" \
|
||||
|
||||
@@ -28,6 +28,16 @@ on:
|
||||
description: Branch name of the approving OpenClaw Release Publish workflow run
|
||||
required: false
|
||||
type: string
|
||||
release_publish_full_ref:
|
||||
description: Exact full ref of the approving OpenClaw Release Publish workflow tooling
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
release_publish_workflow_sha:
|
||||
description: Exact workflow SHA of the approving OpenClaw Release Publish tooling
|
||||
required: false
|
||||
default: ""
|
||||
type: string
|
||||
dry_run:
|
||||
description: Validate the full ClawHub artifact handoff without publishing.
|
||||
required: false
|
||||
@@ -61,6 +71,7 @@ jobs:
|
||||
matrix: ${{ steps.plan.outputs.matrix }}
|
||||
bootstrap_matrix: ${{ steps.plan.outputs.bootstrap_matrix }}
|
||||
missing_trusted_publisher_matrix: ${{ steps.plan.outputs.missing_trusted_publisher_matrix }}
|
||||
trusted_tooling_identity_json: ${{ steps.tooling_identity.outputs.json }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
@@ -92,6 +103,55 @@ jobs:
|
||||
fi
|
||||
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Capture trusted tooling identity
|
||||
id: tooling_identity
|
||||
env:
|
||||
CALLER_FULL_REF: ${{ github.ref }}
|
||||
CALLER_REF: ${{ github.ref_name }}
|
||||
CALLER_RUN_ATTEMPT: ${{ github.run_attempt }}
|
||||
CALLER_RUN_ID: ${{ github.run_id }}
|
||||
CALLER_SHA: ${{ github.sha }}
|
||||
TOOLING_FULL_REF: ${{ inputs.release_publish_full_ref }}
|
||||
TOOLING_REF: ${{ inputs.release_publish_branch }}
|
||||
TOOLING_SHA: ${{ inputs.release_publish_workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "${TOOLING_FULL_REF}${TOOLING_SHA}" ]]; then
|
||||
echo "json=" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
[[ -n "$TOOLING_FULL_REF" && -n "$TOOLING_REF" && -n "$TOOLING_SHA" ]] || {
|
||||
echo "Trusted release tooling ref, full ref, and SHA must be provided together." >&2
|
||||
exit 1
|
||||
}
|
||||
identity="$(
|
||||
jq -cn \
|
||||
--arg repository "$GITHUB_REPOSITORY" \
|
||||
--arg workflow ".github/workflows/plugin-clawhub-release.yml" \
|
||||
--arg runId "$CALLER_RUN_ID" \
|
||||
--arg runAttempt "$CALLER_RUN_ATTEMPT" \
|
||||
--arg ref "$CALLER_REF" \
|
||||
--arg fullRef "$CALLER_FULL_REF" \
|
||||
--arg sha "$CALLER_SHA" \
|
||||
--arg toolingRef "$TOOLING_REF" \
|
||||
--arg toolingFullRef "$TOOLING_FULL_REF" \
|
||||
--arg toolingSha "$TOOLING_SHA" \
|
||||
'{
|
||||
version: 1,
|
||||
repository: $repository,
|
||||
workflow: $workflow,
|
||||
runId: $runId,
|
||||
runAttempt: $runAttempt,
|
||||
ref: $ref,
|
||||
fullRef: $fullRef,
|
||||
sha: $sha,
|
||||
toolingRef: $toolingRef,
|
||||
toolingFullRef: $toolingFullRef,
|
||||
toolingSha: $toolingSha
|
||||
}'
|
||||
)"
|
||||
echo "json=${identity}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Validate OIDC source matches workflow ref
|
||||
env:
|
||||
TARGET_SHA: ${{ steps.ref.outputs.sha }}
|
||||
@@ -388,7 +448,7 @@ jobs:
|
||||
needs:
|
||||
[preview_plugins_clawhub, pack_plugins_clawhub_artifacts, approve_plugins_clawhub_release]
|
||||
if: always() && github.event_name == 'workflow_dispatch' && needs.preview_plugins_clawhub.outputs.has_candidates == 'true' && needs.pack_plugins_clawhub_artifacts.result == 'success' && (inputs.dry_run == true || needs.approve_plugins_clawhub_release.result == 'success')
|
||||
uses: openclaw/clawhub/.github/workflows/package-publish.yml@d8096dfc039e86ab942ddf9ef117d04849fd84c1
|
||||
uses: openclaw/clawhub/.github/workflows/package-publish.yml@6dc1e2bd67a90b5e5c54b3a026dbdfe3691f1202
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
@@ -411,6 +471,7 @@ jobs:
|
||||
source_path: ${{ matrix.plugin.packageDir }}
|
||||
inspector_artifact_name: ${{ matrix.plugin.artifactName }}-inspector
|
||||
publish_json_artifact_name: ${{ matrix.plugin.artifactName }}-publish-json
|
||||
trusted_tooling_identity_json: ${{ needs.preview_plugins_clawhub.outputs.trusted_tooling_identity_json }}
|
||||
|
||||
verify_published_clawhub_package:
|
||||
needs: [preview_plugins_clawhub, publish_plugins_clawhub]
|
||||
|
||||
@@ -22,6 +22,8 @@ on:
|
||||
- "scripts/lib/actions-artifact-archive.mjs"
|
||||
- "scripts/plugin-npm-publish.sh"
|
||||
- "scripts/plugin-publication-artifact.mjs"
|
||||
- "scripts/release-tooling-identity.d.mts"
|
||||
- "scripts/release-tooling-identity.mjs"
|
||||
- "scripts/plugin-npm-release-check.ts"
|
||||
- "scripts/plugin-npm-release-plan.ts"
|
||||
- "scripts/verify-plugin-npm-published-runtime.mts"
|
||||
@@ -1103,6 +1105,7 @@ jobs:
|
||||
PACKAGE_NAME: ${{ matrix.plugin.packageName }}
|
||||
PACKAGE_VERSION: ${{ matrix.plugin.version }}
|
||||
PUBLISH_TAG: ${{ matrix.plugin.publishTag }}
|
||||
RELEASE_PUBLISH_RUN_ID: ${{ inputs.release_publish_run_id }}
|
||||
TARGET_SHA: ${{ needs.preview_plugins_npm.outputs.ref_revision }}
|
||||
WORKFLOW_HEAD_BRANCH: ${{ github.ref_name }}
|
||||
WORKFLOW_REF: ${{ github.ref }}
|
||||
@@ -1161,35 +1164,12 @@ jobs:
|
||||
exit 1
|
||||
}
|
||||
if [[ "$publish_route" == "npm-token-bootstrap" ]]; then
|
||||
sha_pinned_release_publish=false
|
||||
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" ]] || {
|
||||
echo "npm token bootstrap release-publish tag does not match the workflow SHA." >&2
|
||||
exit 1
|
||||
}
|
||||
workflow_tag="${WORKFLOW_REF#refs/tags/}"
|
||||
remote_workflow_sha="$(
|
||||
gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${workflow_tag}" \
|
||||
--jq '.object | select(.type == "commit") | .sha | select(test("^[a-f0-9]{40}$"))'
|
||||
)"
|
||||
[[ "$remote_workflow_sha" == "$WORKFLOW_SHA" ]] || {
|
||||
echo "npm token bootstrap release-publish tag does not resolve to the workflow SHA." >&2
|
||||
exit 1
|
||||
}
|
||||
sha_pinned_release_publish=true
|
||||
fi
|
||||
[[ "$WORKFLOW_REF" == "refs/heads/main" || "$sha_pinned_release_publish" == "true" ]] || {
|
||||
echo "npm token bootstrap requires trusted main tooling or a protected SHA-pinned release-publish tag." >&2
|
||||
exit 1
|
||||
}
|
||||
if [[ "$WORKFLOW_REF" == "refs/heads/main" ]]; then
|
||||
timeout --signal=TERM --kill-after=10s 120s git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
|
||||
git merge-base --is-ancestor "$WORKFLOW_SHA" origin/main || {
|
||||
echo "npm token bootstrap workflow revision is not reachable from current main." >&2
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
node scripts/release-tooling-identity.mjs verify \
|
||||
--repository "$GITHUB_REPOSITORY" \
|
||||
--workflow-ref "$WORKFLOW_HEAD_BRANCH" \
|
||||
--workflow-full-ref "$WORKFLOW_REF" \
|
||||
--workflow-sha "$WORKFLOW_SHA" \
|
||||
--release-publish-run-id "$RELEASE_PUBLISH_RUN_ID"
|
||||
fi
|
||||
artifact_id="$(jq -er '.id' "$artifact_metadata")"
|
||||
artifact_digest="$(jq -er '.digest' "$artifact_metadata")"
|
||||
@@ -1318,8 +1298,16 @@ jobs:
|
||||
- name: Publish with trusted publisher
|
||||
if: steps.publication_evidence.outputs.publish_route == 'npm-oidc' && steps.npm_package_version.outputs.already_published != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
OPENCLAW_NPM_PUBLISH_AUTH_MODE: trusted-publisher
|
||||
OPENCLAW_PLUGIN_NPM_PUBLISH_TAG: ${{ inputs.npm_dist_tag == 'extended-stable' && inputs.npm_dist_tag || '' }}
|
||||
OPENCLAW_RELEASE_PUBLISH_RUN_ID: ${{ inputs.release_publish_run_id }}
|
||||
OPENCLAW_RELEASE_TOOLING_ALLOW_PREVALIDATED_REF: "true"
|
||||
OPENCLAW_RELEASE_TOOLING_FULL_REF: ${{ github.ref }}
|
||||
OPENCLAW_RELEASE_TOOLING_IDENTITY_REQUIRED: "true"
|
||||
OPENCLAW_RELEASE_TOOLING_REF: ${{ github.ref_name }}
|
||||
OPENCLAW_RELEASE_TOOLING_REPOSITORY: ${{ github.repository }}
|
||||
OPENCLAW_RELEASE_TOOLING_SHA: ${{ github.workflow_sha }}
|
||||
run: bash scripts/plugin-npm-publish.sh --repo-root .publication-target --publish "${{ matrix.plugin.packageDir }}"
|
||||
|
||||
- name: Verify OIDC published runtime
|
||||
@@ -1379,12 +1367,17 @@ jobs:
|
||||
- name: Publish approved bootstrap tarball
|
||||
if: steps.publication_evidence.outputs.publish_route == 'npm-token-bootstrap' && steps.bootstrap_npm_package_version.outputs.already_published != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
PACKAGE_DIR: ${{ matrix.plugin.packageDir }}
|
||||
PACKAGE_NAME: ${{ steps.publication_evidence.outputs.package_name }}
|
||||
PACKAGE_VERSION: ${{ steps.publication_evidence.outputs.package_version }}
|
||||
PUBLISH_TAG: ${{ steps.publication_evidence.outputs.publish_tag }}
|
||||
RELEASE_PUBLISH_RUN_ID: ${{ inputs.release_publish_run_id }}
|
||||
TARBALL_PATH: ${{ steps.publication_evidence.outputs.tarball_path }}
|
||||
WORKFLOW_FULL_REF: ${{ github.ref }}
|
||||
WORKFLOW_REF: ${{ github.ref_name }}
|
||||
WORKFLOW_SHA: ${{ github.workflow_sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
[[ "$PACKAGE_VERSION" == *"-beta."* && "$PUBLISH_TAG" == "beta" ]] || {
|
||||
@@ -1410,6 +1403,12 @@ jobs:
|
||||
unset NODE_AUTH_TOKEN NPM_TOKEN NODE_OPTIONS
|
||||
# A timeout can race a committed publish. On rerun, the preceding check
|
||||
# accepts only this tarball's exact integrity and shasum before skipping.
|
||||
node scripts/release-tooling-identity.mjs verify \
|
||||
--repository "$GITHUB_REPOSITORY" \
|
||||
--workflow-ref "$WORKFLOW_REF" \
|
||||
--workflow-full-ref "$WORKFLOW_FULL_REF" \
|
||||
--workflow-sha "$WORKFLOW_SHA" \
|
||||
--release-publish-run-id "$RELEASE_PUBLISH_RUN_ID"
|
||||
HOME="$publish_home" \
|
||||
NPM_CONFIG_GLOBALCONFIG=/dev/null \
|
||||
NPM_CONFIG_IGNORE_SCRIPTS=true \
|
||||
|
||||
Reference in New Issue
Block a user