Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 49 additions & 23 deletions .github/workflows/npm-stage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,12 @@ jobs:
const repository = process.env.GITHUB_REPOSITORY ?? "";
const currentRunId = process.env.GITHUB_RUN_ID ?? "";
const resolvedStageVersion = process.env.RESOLVED_STAGE_VERSION ?? "";
const legacyStages = new Map([
const legacyStageJobs = new Map([
["33269920554", Object.freeze({
headSha: "e12d3fd05ffaa722ac1c43a8ecaa7d21fece679a",
jobConclusion: "success",
jobId: 99146963354,
mutationConclusion: "success",
runAttempt: 1,
version: "0.17.3",
})],
Expand Down Expand Up @@ -472,7 +475,11 @@ jobs:
) {
throw new Error(`npm-stage run ${runId} contains an invalid job`);
}
if (!job.name.startsWith("Stage exact package")) continue;
const terminalWrites = job.steps.filter((step) => (
step?.name === "Revalidate current main and stage exact package"
&& step?.conclusion !== null
&& step?.conclusion !== "skipped"
));
const intents = job.steps.filter((step) => (
step?.name === "Record exclusive stable-stage intent"
&& step?.conclusion === "success"
Expand All @@ -482,35 +489,54 @@ jobs:
&& step.name.startsWith("Record cleared stable-stage intent")
&& step?.conclusion === "success"
));
const hasSafePositiveStepNumber = (step) => (
Number.isSafeInteger(step?.number) && step.number > 0
);
if (intents.length > 1 || resolutions.length > 1) {
throw new Error(`npm-stage run ${runId} has ambiguous intent history`);
}
const match = /^Stage exact package v((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*))$/u.exec(job.name);
if (intents.length === 0 && resolutions.length === 0) {
const legacy = legacyStages.get(String(runId));
if (job.name === "Stage exact package") {
const legacy = legacyStageJobs.get(String(runId));
const legacyMutations = job.steps.filter((step) => (
step?.name === "Revalidate current main and stage exact package"
));
if (
job.conclusion === "success"
&& job.name === "Stage exact package"
legacy === undefined
|| job.id !== legacy.jobId
|| job.head_sha !== legacy.headSha
|| job.run_attempt !== legacy.runAttempt
|| job.status !== "completed"
|| job.conclusion !== legacy.jobConclusion
|| legacyMutations.length !== 1
|| legacyMutations[0]?.conclusion !== legacy.mutationConclusion
|| intents.length !== 0
|| resolutions.length !== 0
) {
if (
legacy === undefined
|| job.head_sha !== legacy.headSha
|| job.run_attempt !== legacy.runAttempt
) {
throw new Error(`Successful npm-stage run ${runId} lacks a version-bound intent`);
}
reserve(legacy.version, runId);
continue;
throw new Error(`npm-stage run ${runId} has an unsealed generic stage job`);
}
const legacyMutation = job.steps.filter((step) => (
step?.name === "Revalidate current main and stage exact package"
&& (step?.conclusion === "success" || step?.conclusion === "failure")
));
if (match !== null && legacyMutation.length === 1) {
reserve(match[1], runId);
reserve(legacy.version, runId);
continue;
}
if (
terminalWrites.length > 1
|| (terminalWrites.length === 1 && (
intents.length !== 1
|| !hasSafePositiveStepNumber(terminalWrites[0])
|| !hasSafePositiveStepNumber(intents[0])
|| intents[0].number !== terminalWrites[0].number - 1
))
) {
throw new Error(
`npm-stage run ${runId} has a terminal write without one immediately preceding durable intent`,
);
}
if (!job.name.startsWith("Stage exact package")) {
if (terminalWrites.length > 0 || intents.length > 0 || resolutions.length > 0) {
throw new Error(`npm-stage run ${runId} contains staging controls outside a version-bound stage job`);
}
continue;
}
const match = /^Stage exact package v((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*))$/u.exec(job.name);
if (match === null) {
throw new Error(`npm-stage run ${runId} lacks a version-bound stage job`);
}
Expand Down Expand Up @@ -887,7 +913,7 @@ jobs:
throw new Error("Packed package.json tar header is invalid");
}
const name = tarText(header, 0, 100);
const prefix = tarText(header, 345, 155);
const prefix = tarText(header, 345, header[475] === 0 ? 130 : 155);
const path = prefix === "" ? name : `${prefix}/${name}`;
if (
path.startsWith("/")
Expand Down
70 changes: 63 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ jobs:
with:
fetch-depth: 0
persist-credentials: false
ref: main
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24"
Expand Down Expand Up @@ -129,15 +130,25 @@ jobs:
echo "::error::Release tag did not resolve to one commit"
exit 1
fi
if [[ "$GITHUB_SHA" != "$tag_commit" || \
"$checked_out_head" != "$tag_commit" ]]; then
echo "::error::Tag does not match the checked release commit $tag_commit"
if [[ "$GITHUB_SHA" != "$tag_commit" ]]; then
echo "::error::Tag event does not match release commit $tag_commit"
exit 1
fi
if [[ "$checked_out_head" != "$default_head" ]]; then
echo "::error::Reviewed checkout is not exact current $DEFAULT_BRANCH"
exit 1
fi
if ! git merge-base --is-ancestor "$tag_commit" "$default_head"; then
echo "::error::Tag $release_tag is not reachable from current $DEFAULT_BRANCH"
exit 1
fi
if ! git diff --quiet --no-ext-diff --no-textconv \
"$tag_commit" "$default_head" -- \
.github/workflows/release.yml \
.github/workflows/npm-stage.yml; then
echo "::error::Tagged and current release workflow controls differ"
exit 1
fi

package_manifest="$RUNNER_TEMP/kb-release-package.json"
git show "$tag_commit:package.json" > "$package_manifest"
Expand Down Expand Up @@ -201,7 +212,7 @@ jobs:
fi

printf 'default_branch=%s\nsource_sha=%s\ntag=%s\nworkflow_sha=%s\n' \
"$DEFAULT_BRANCH" "$tag_commit" "$release_tag" "$checked_out_head" \
"$DEFAULT_BRANCH" "$tag_commit" "$release_tag" "$default_head" \
>> "$GITHUB_OUTPUT"
- name: Materialize exact tagged source
id: source
Expand Down Expand Up @@ -409,6 +420,11 @@ jobs:
VERIFIED_TAG: ${{ needs.verify.outputs.verified_tag }}
WORKFLOW_SHA: ${{ needs.verify.outputs.workflow_sha }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
persist-credentials: false
ref: main
- name: Reauthorize current release attempt
env:
EXPECTED_ACTOR_ID: "894119"
Expand Down Expand Up @@ -507,14 +523,49 @@ jobs:
fi
if [[ "$GITHUB_EVENT_NAME" != push || \
"$GITHUB_REF" != "refs/tags/$VERIFIED_TAG" || \
"$GITHUB_SHA" != "$VERIFIED_SOURCE_SHA" || \
"$GITHUB_SHA" != "$WORKFLOW_SHA" ]]; then
"$GITHUB_SHA" != "$VERIFIED_SOURCE_SHA" ]]; then
echo "::error::Protected tag release event changed after verification"
exit 1
fi

verify_current_release_controls() {
local advertised_main imported_main
advertised_main="$(gh api "/repos/$GITHUB_REPOSITORY/commits/$DEFAULT_BRANCH" --jq '.sha')"
git fetch --no-tags --force origin \
"refs/heads/$DEFAULT_BRANCH:refs/remotes/kb-release-current/$DEFAULT_BRANCH"
imported_main="$(git rev-parse "refs/remotes/kb-release-current/$DEFAULT_BRANCH")"
if [[ ! "$advertised_main" =~ ^[a-f0-9]{40}$ || \
"$imported_main" != "$advertised_main" ]]; then
echo "::error::Could not import one exact current $DEFAULT_BRANCH authority" >&2
return 1
fi
if ! git merge-base --is-ancestor "$VERIFIED_SOURCE_SHA" "$imported_main" || \
! git merge-base --is-ancestor "$WORKFLOW_SHA" "$imported_main"; then
echo "::error::Release source or reviewed workflow is no longer on current $DEFAULT_BRANCH" >&2
return 1
fi
if ! git diff --quiet --no-ext-diff --no-textconv \
"$VERIFIED_SOURCE_SHA" "$imported_main" -- \
.github/workflows/release.yml \
.github/workflows/npm-stage.yml; then
echo "::error::Tagged and current release workflow controls differ" >&2
return 1
fi
if ! git diff --quiet --no-ext-diff --no-textconv \
"$WORKFLOW_SHA" "$imported_main" -- \
scripts/package-artifact.ts \
scripts/npm-package-identity.ts \
scripts/npm-release-attestation.ts \
scripts/package-smoke.ts \
scripts/prepare-npm-package.ts; then
echo "::error::Current release verifier controls changed after verification" >&2
return 1
fi
printf '%s\n' "$imported_main"
}

current_tag_sha="$(gh api "/repos/$GITHUB_REPOSITORY/commits/$VERIFIED_TAG" --jq '.sha')"
current_default_sha="$(gh api "/repos/$GITHUB_REPOSITORY/commits/$DEFAULT_BRANCH" --jq '.sha')"
current_default_sha="$(verify_current_release_controls)"
if [[ "$current_tag_sha" != "$VERIFIED_SOURCE_SHA" ]]; then
echo "::error::Tag $VERIFIED_TAG moved to $current_tag_sha after verification"
exit 1
Expand Down Expand Up @@ -613,6 +664,11 @@ jobs:
printf -v expected_release_body \
'Automated immutable release for @hraness/kb@%s.\n\nSource commit: %s\nWorkflow run: %s' \
"$verified_version" "$VERIFIED_SOURCE_SHA" "$GITHUB_RUN_ID"
final_default_sha="$(verify_current_release_controls)"
if [[ "$final_default_sha" != "$current_default_sha" ]]; then
echo "::error::Current $DEFAULT_BRANCH moved during final release authorization"
exit 1
fi
release_json="$(mktemp "$RUNNER_TEMP/kb-release.XXXXXX")"
if ! gh release create "$VERIFIED_TAG" \
--verify-tag \
Expand Down
Loading