Skip to content

Commit 1926ddb

Browse files
2026-05-09
1 parent 6d4b53d commit 1926ddb

2 files changed

Lines changed: 187 additions & 27 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
'use strict';
2+
3+
const fs = require('node:fs');
4+
5+
const tagVersion = process.env.RELEASE_TAG || process.env.GITHUB_REF_NAME;
6+
7+
if (!tagVersion) {
8+
throw new Error('RELEASE_TAG or GITHUB_REF_NAME is required.');
9+
}
10+
11+
function normalizeVersion(version) {
12+
const parts = version.split('.');
13+
14+
if (parts.length !== 3 || !parts.every((part) => /^\d+$/.test(part))) {
15+
throw new Error(`Version "${version}" must use numeric yyyy.mm.dd or semver-style major.minor.patch format.`);
16+
}
17+
18+
return parts.map((part) => String(Number(part))).join('.');
19+
}
20+
21+
const normalizedTagVersion = normalizeVersion(tagVersion);
22+
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
23+
24+
console.log(`Release tag: ${tagVersion}`);
25+
console.log(`Normalized release version: ${normalizedTagVersion}`);
26+
console.log(`Package version: ${packageJson.version}`);
27+
28+
if (packageJson.version !== normalizedTagVersion) {
29+
packageJson.version = normalizedTagVersion;
30+
fs.writeFileSync('package.json', `${JSON.stringify(packageJson, null, '\t')}\n`);
31+
console.log(`Updated package.json version to ${normalizedTagVersion}`);
32+
}
33+
34+
if (fs.existsSync('package-lock.json')) {
35+
const packageLock = JSON.parse(fs.readFileSync('package-lock.json', 'utf8'));
36+
let packageLockChanged = false;
37+
38+
if (packageLock.version !== normalizedTagVersion) {
39+
packageLock.version = normalizedTagVersion;
40+
packageLockChanged = true;
41+
}
42+
43+
if (packageLock.packages && packageLock.packages[''] && packageLock.packages[''].version !== normalizedTagVersion) {
44+
packageLock.packages[''].version = normalizedTagVersion;
45+
packageLockChanged = true;
46+
}
47+
48+
if (packageLockChanged) {
49+
fs.writeFileSync('package-lock.json', `${JSON.stringify(packageLock, null, '\t')}\n`);
50+
console.log(`Updated package-lock.json version to ${normalizedTagVersion}`);
51+
}
52+
}

.github/workflows/release.yml

Lines changed: 135 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,155 @@
11
name: Release
2+
23
on:
3-
release:
4-
types: [published]
4+
push:
5+
tags:
6+
- '*.*.*'
7+
workflow_dispatch:
8+
inputs:
9+
release_tag:
10+
description: 'Release tag to publish, for example 2026.05.09'
11+
required: true
12+
type: string
13+
14+
permissions:
15+
contents: read
16+
17+
concurrency:
18+
group: release-${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
19+
cancel-in-progress: false
20+
21+
env:
22+
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
523

624
jobs:
7-
tag:
8-
name: Add/update 'latest' tag
25+
validate:
26+
name: Validate package
927
runs-on: ubuntu-latest
1028
steps:
1129
- name: Checkout repository
12-
uses: actions/checkout@v2
13-
- name: Run latest-tag
14-
uses: EndBug/latest-tag@v1
15-
env:
16-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
uses: actions/checkout@v6
31+
32+
- name: Set up Node.js
33+
uses: actions/setup-node@v6
34+
with:
35+
node-version: 22
36+
cache: npm
37+
38+
- name: Normalize release version
39+
run: node .github/scripts/normalize-release-version.js
40+
41+
- name: Install dependencies
42+
run: |
43+
if [ -f package-lock.json ]; then
44+
npm ci
45+
else
46+
npm install
47+
fi
48+
49+
- name: Run tests
50+
run: npm run test --if-present
51+
52+
- name: Run lint
53+
run: npm run lint --if-present
54+
55+
- name: Preview package contents
56+
run: npm pack --dry-run
1757

1858
publish-npm:
19-
name: Publish on NPM
59+
name: Publish to npm
2060
runs-on: ubuntu-latest
21-
needs: tag
61+
needs: validate
62+
permissions:
63+
contents: read
64+
id-token: write
2265
steps:
23-
- uses: actions/checkout@v2
24-
- name: Set up Node.js for NPM
25-
uses: actions/setup-node@v1
66+
- name: Checkout repository
67+
uses: actions/checkout@v6
68+
69+
- name: Set up Node.js for npm
70+
uses: actions/setup-node@v6
2671
with:
72+
node-version: 24
2773
registry-url: 'https://registry.npmjs.org'
28-
- run: npm install
29-
- run: npm publish
30-
env:
31-
NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
74+
package-manager-cache: false
75+
76+
- name: Normalize release version
77+
run: node .github/scripts/normalize-release-version.js
78+
79+
- name: Install dependencies
80+
run: |
81+
if [ -f package-lock.json ]; then
82+
npm ci
83+
else
84+
npm install
85+
fi
86+
87+
- name: Check npm package version
88+
id: npm-package
89+
run: |
90+
PACKAGE_NAME=$(node -p "require('./package.json').name")
91+
PACKAGE_VERSION=$(node -p "require('./package.json').version")
3292
33-
publish-gpr:
34-
name: Publish on GPR
93+
if npm view "${PACKAGE_NAME}@${PACKAGE_VERSION}" version --registry=https://registry.npmjs.org >/dev/null 2>&1; then
94+
echo "${PACKAGE_NAME}@${PACKAGE_VERSION} already exists on npm. Skipping publish."
95+
echo "exists=true" >> "${GITHUB_OUTPUT}"
96+
else
97+
echo "${PACKAGE_NAME}@${PACKAGE_VERSION} does not exist on npm. Publishing."
98+
echo "exists=false" >> "${GITHUB_OUTPUT}"
99+
fi
100+
101+
- name: Publish to npm
102+
if: steps.npm-package.outputs.exists != 'true'
103+
run: npm publish --access public
104+
105+
publish-github-packages:
106+
name: Publish to GitHub Packages
35107
runs-on: ubuntu-latest
36-
needs: tag
108+
needs: validate
109+
permissions:
110+
contents: read
111+
packages: write
37112
steps:
38-
- uses: actions/checkout@v2
39-
- name: Set up Node.js for GPR
40-
uses: actions/setup-node@v1
113+
- name: Checkout repository
114+
uses: actions/checkout@v6
115+
116+
- name: Set up Node.js for GitHub Packages
117+
uses: actions/setup-node@v6
41118
with:
119+
node-version: 22
42120
registry-url: 'https://npm.pkg.github.com/'
43121
scope: '@markbattistella'
44-
- run: npm install
45-
- run: npm publish
122+
cache: npm
123+
124+
- name: Normalize release version
125+
run: node .github/scripts/normalize-release-version.js
126+
127+
- name: Install dependencies
128+
run: |
129+
if [ -f package-lock.json ]; then
130+
npm ci
131+
else
132+
npm install
133+
fi
134+
135+
- name: Check GitHub Packages version
136+
id: github-package
137+
run: |
138+
PACKAGE_NAME=$(node -p "require('./package.json').name")
139+
PACKAGE_VERSION=$(node -p "require('./package.json').version")
140+
141+
if npm view "${PACKAGE_NAME}@${PACKAGE_VERSION}" version --registry=https://npm.pkg.github.com/ >/dev/null 2>&1; then
142+
echo "${PACKAGE_NAME}@${PACKAGE_VERSION} already exists on GitHub Packages. Skipping publish."
143+
echo "exists=true" >> "${GITHUB_OUTPUT}"
144+
else
145+
echo "${PACKAGE_NAME}@${PACKAGE_VERSION} does not exist on GitHub Packages. Publishing."
146+
echo "exists=false" >> "${GITHUB_OUTPUT}"
147+
fi
148+
env:
149+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
150+
151+
- name: Publish to GitHub Packages
152+
if: steps.github-package.outputs.exists != 'true'
153+
run: npm publish
46154
env:
47-
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
155+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)