fix: require npm publish proof artifact

This commit is contained in:
Vincent Koc
2026-06-13 18:06:27 +08:00
parent 7d69b337c7
commit e86aa30a77
3 changed files with 95 additions and 0 deletions
@@ -236,6 +236,47 @@ jobs:
exit 1
fi
- name: Verify publish proof artifact
if: ${{ inputs.publish_run_id != '' }}
env:
GH_TOKEN: ${{ github.token }}
PUBLISH_RUN_ID: ${{ inputs.publish_run_id }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
PROOF_DIR="$RUNNER_TEMP/clawhub-cli-github-release-publish-proof"
rm -rf "$PROOF_DIR"
mkdir -p "$PROOF_DIR"
gh run download "$PUBLISH_RUN_ID" \
--repo "$GITHUB_REPOSITORY" \
--name "clawhub-cli-npm-publish-${RELEASE_TAG}" \
--dir "$PROOF_DIR"
if [[ "$(tr -d '\r\n' < "$PROOF_DIR/release-tag.txt")" != "$RELEASE_TAG" ]]; then
echo "Publish artifact tag does not match ${RELEASE_TAG}." >&2
exit 1
fi
if [[ "$(tr -d '\r\n' < "$PROOF_DIR/release-sha.txt")" != "$RELEASE_SHA" ]]; then
echo "Publish artifact SHA does not match ${RELEASE_SHA}." >&2
exit 1
fi
if [[ "$(tr -d '\r\n' < "$PROOF_DIR/package-version.txt")" != "$PACKAGE_VERSION" ]]; then
echo "Publish artifact version does not match ${PACKAGE_VERSION}." >&2
exit 1
fi
if [[ "$(tr -d '\r\n' < "$PROOF_DIR/preflight-only.txt")" != "false" ]]; then
echo "Publish artifact must come from a real publish run." >&2
exit 1
fi
if [[ "$(tr -d '\r\n' < "$PROOF_DIR/npm-tarball-url.txt")" != "$NPM_TARBALL_URL" ]]; then
echo "Publish artifact tarball URL does not match npm metadata." >&2
exit 1
fi
if [[ "$(tr -d '\r\n' < "$PROOF_DIR/npm-integrity.txt")" != "$NPM_INTEGRITY" ]]; then
echo "Publish artifact integrity does not match npm metadata." >&2
exit 1
fi
- name: Build release notes
env:
RELEASE_TAG: ${{ inputs.tag }}
@@ -381,6 +381,31 @@ jobs:
echo "RELEASE_TITLE=clawhub ${PACKAGE_VERSION}"
} >> "$GITHUB_ENV"
- name: Write npm publish proof artifact
id: publish_proof
env:
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
PUBLISH_PROOF_DIR="$RUNNER_TEMP/clawhub-cli-npm-publish-proof"
rm -rf "$PUBLISH_PROOF_DIR"
mkdir -p "$PUBLISH_PROOF_DIR"
printf '%s\n' "$RELEASE_TAG" > "$PUBLISH_PROOF_DIR/release-tag.txt"
git rev-parse HEAD > "$PUBLISH_PROOF_DIR/release-sha.txt"
printf '%s\n' "$PACKAGE_VERSION" > "$PUBLISH_PROOF_DIR/package-version.txt"
printf '%s\n' "$NPM_TARBALL_URL" > "$PUBLISH_PROOF_DIR/npm-tarball-url.txt"
printf '%s\n' "$NPM_INTEGRITY" > "$PUBLISH_PROOF_DIR/npm-integrity.txt"
printf '%s\n' "$GITHUB_RUN_ID" > "$PUBLISH_PROOF_DIR/publish-run-id.txt"
printf '%s\n' "false" > "$PUBLISH_PROOF_DIR/preflight-only.txt"
echo "dir=$PUBLISH_PROOF_DIR" >> "$GITHUB_OUTPUT"
- name: Upload npm publish proof artifact
uses: actions/upload-artifact@v7
with:
name: clawhub-cli-npm-publish-${{ inputs.tag }}
path: ${{ steps.publish_proof.outputs.dir }}
if-no-files-found: error
- name: Build GitHub Release notes
env:
RELEASE_TAG: ${{ inputs.tag }}
@@ -0,0 +1,29 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
describe("ClawHub CLI release workflows", () => {
it("requires publish-specific proof before adding npm publish release proof", () => {
const npmRelease = readFileSync(
resolve(".github/workflows/clawhub-cli-npm-release.yml"),
"utf8",
);
const githubRelease = readFileSync(
resolve(".github/workflows/clawhub-cli-github-release.yml"),
"utf8",
);
expect(npmRelease).toContain("Write npm publish proof artifact");
expect(npmRelease).toContain("Upload npm publish proof artifact");
expect(npmRelease).toContain("clawhub-cli-npm-publish-${{ inputs.tag }}");
expect(npmRelease).toContain(
'printf \'%s\\n\' "false" > "$PUBLISH_PROOF_DIR/preflight-only.txt"',
);
expect(githubRelease).toContain("Verify publish proof artifact");
expect(githubRelease).toContain("clawhub-cli-npm-publish-${RELEASE_TAG}");
expect(githubRelease).toContain("Publish artifact must come from a real publish run.");
expect(githubRelease).toContain("Publish artifact tarball URL does not match npm metadata.");
expect(githubRelease).toContain("Publish artifact integrity does not match npm metadata.");
});
});