@@ -3,22 +3,83 @@ name: Publish to npm
33on :
44 release :
55 types : [published]
6+ workflow_dispatch :
7+ inputs :
8+ release_tag :
9+ description : Existing unpublished GitHub release tag to recover
10+ required : true
11+ type : string
612
713jobs :
814 publish :
9- if : github.event.release.target_commitish == 'main'
15+ if : >-
16+ (github.event_name == 'release' && github.event.release.target_commitish == 'main') ||
17+ (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')
1018 runs-on : ubuntu-latest
1119 permissions :
1220 contents : read
1321 id-token : write
22+ env :
23+ RELEASE_TAG : ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.event.release.tag_name }}
24+ TERM_SESSION_ID : ${{ format('jumbo-publish-{0}-{1}', github.run_id, github.run_attempt) }}
1425 steps :
1526 - uses : actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
27+ with :
28+ ref : refs/tags/${{ env.RELEASE_TAG }}
1629
1730 - uses : actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
1831 with :
1932 node-version : ' 22'
2033 registry-url : ' https://registry.npmjs.org'
2134
35+ - name : Validate unpublished release tag
36+ env :
37+ GH_TOKEN : ${{ github.token }}
38+ run : |
39+ node --input-type=module --eval '
40+ import { readFile } from "node:fs/promises";
41+
42+ const releaseTag = process.env.RELEASE_TAG;
43+ if (!releaseTag) {
44+ throw new Error("A release tag is required");
45+ }
46+
47+ const packageJson = JSON.parse(await readFile("package.json", "utf8"));
48+ const tagVersion = releaseTag.startsWith("v") ? releaseTag.slice(1) : releaseTag;
49+ if (packageJson.version !== tagVersion) {
50+ throw new Error(`Release tag ${releaseTag} does not match package version ${packageJson.version}`);
51+ }
52+
53+ const releaseUrl = `https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/releases/tags/${encodeURIComponent(releaseTag)}`;
54+ const githubHeaders = {
55+ Accept: "application/vnd.github+json",
56+ "X-GitHub-Api-Version": "2022-11-28",
57+ };
58+ if (process.env.GH_TOKEN) {
59+ githubHeaders.Authorization = `Bearer ${process.env.GH_TOKEN}`;
60+ }
61+ const releaseResponse = await fetch(releaseUrl, { headers: githubHeaders });
62+ if (!releaseResponse.ok) {
63+ throw new Error(`GitHub release ${releaseTag} is unavailable (${releaseResponse.status})`);
64+ }
65+
66+ const release = await releaseResponse.json();
67+ if (release.draft || !release.published_at || release.target_commitish !== "main") {
68+ throw new Error(`GitHub release ${releaseTag} is not a published main-branch release`);
69+ }
70+
71+ const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(packageJson.name)}/${encodeURIComponent(packageJson.version)}`;
72+ const registryResponse = await fetch(registryUrl);
73+ if (registryResponse.status === 200) {
74+ throw new Error(`${packageJson.name}@${packageJson.version} is already published`);
75+ }
76+ if (registryResponse.status !== 404) {
77+ throw new Error(`Could not verify npm publication state (${registryResponse.status})`);
78+ }
79+
80+ console.log(`Validated unpublished release ${releaseTag}`);
81+ '
82+
2283 - run : npm ci
2384
2485 - run : npm run build
0 commit comments