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
11 changes: 10 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
Expand Down Expand Up @@ -52,4 +55,10 @@ jobs:
with:
node-version: '22.23.2'
- run: npm install --global npm@12.2.0
- run: npm publish ./artifacts/*.tgz --access public --provenance --ignore-scripts
- id: select
run: |
state=$(node scripts/release-files.mjs select artifacts)
echo "state=$state" >> "$GITHUB_OUTPUT"
- if: steps.select.outputs.state == 'missing'
run: npm publish ./artifacts/*.tgz --access public --provenance --ignore-scripts
- run: node scripts/release-files.mjs verify artifacts
41 changes: 41 additions & 0 deletions scripts/release-files.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { createHash } from "node:crypto";
import { readFile, readdir } from "node:fs/promises";
import { join } from "node:path";
import { setTimeout } from "node:timers/promises";

const [mode, directory] = process.argv.slice(2);
if (!["select", "verify"].includes(mode) || !directory) {
throw new Error("Expected select or verify and a package directory");
}
const { name, version } = JSON.parse(await readFile("package.json", "utf8"));
const [filename, ...other] = await readdir(directory);
if (
!/^\d+\.\d+\.\d+$/.test(version) ||
filename !== `${name.replace(/^@/, "").replace("/", "-")}-${version}.tgz` ||
other.length
) {
throw new Error("Expected one tarball for the checked package version");
}
const data = await readFile(join(directory, filename));
const integrity = `sha512-${createHash("sha512").update(data).digest("base64")}`;
const url = `https://registry.npmjs.org/${encodeURIComponent(name)}/${version}`;

async function published() {
const response = await fetch(url, { signal: AbortSignal.timeout(30000) });
if (response.status === 404) return false;
if (!response.ok) throw new Error(`npm lookup returned HTTP ${response.status}`);
const metadata = await response.json();
if (metadata.name !== name || metadata.version !== version || metadata.dist?.integrity !== integrity) {
throw new Error("Published npm tarball differs from the checked release");
}
return true;
}

if (mode === "select") {
console.log((await published()) ? "present" : "missing");
} else {
for (let attempt = 0; !(await published()); attempt++) {
if (attempt === 5) throw new Error("Published npm tarball is missing");
await setTimeout(5000);
}
}
Loading