Repository navigation
188 lines (164 loc) · 6.64 KB
/
Copy pathrelease.yml
File metadata and controls
188 lines (164 loc) · 6.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
name: Release
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
tag:
description: Existing release tag to verify and finish (for example v0.1.2)
required: true
type: string
env:
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
concurrency:
group: release-${{ inputs.tag || github.ref_name }}
cancel-in-progress: false
permissions:
contents: read
jobs:
verify:
name: Verify and package
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
steps:
- name: Validate release tag
run: |
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Expected a release tag in vX.Y.Z form."
exit 1
fi
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: refs/tags/${{ env.RELEASE_TAG }}
fetch-depth: 0
- name: Verify the tagged commit is on main
run: |
commit=$(git rev-parse "HEAD^{commit}")
if git merge-base --is-ancestor "$commit" origin/main; then
echo "Tag $RELEASE_TAG points at $commit, which is on main."
else
echo "::error::Tag $RELEASE_TAG points at $commit, which is not on main. Releases are cut from main only."
exit 1
fi
- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: .nvmrc
cache: npm
- name: Install dependencies
run: npm ci
- name: Verify release version and conventions
env:
BASICRUM_RELEASE_TAG: ${{ env.RELEASE_TAG }}
run: npm run conventions
- name: Build and check TypeScript and lint
run: |
npm run typecheck
npm run lint
- name: Install Chromium
run: npx playwright install --with-deps chromium
- name: Unit and browser tests
run: |
npm run test:unit
npm run test:browser
- name: Lint tarball, verify installed types and both loader builds
run: npm run verify:package
- name: Build and lint release tarball, then checksum
run: |
mkdir -p release
tarball=$(npm pack --pack-destination release --silent | tail -n 1)
npm exec --no -- publint "release/$tarball" --strict
(cd release && shasum -a 256 "$tarball" > "$tarball.sha256")
cat "release/$tarball.sha256"
- name: Upload verified tarball
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-tarball
path: release
if-no-files-found: error
retention-days: 7
# Only this job holds release authority. It runs no project code and no
# dependency install: it publishes the tarball the verify job produced.
publish:
name: Create GitHub release and publish
needs: verify
runs-on: ubuntu-latest
timeout-minutes: 10
environment: release
permissions:
contents: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: refs/tags/${{ env.RELEASE_TAG }}
- name: Download verified tarball
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-tarball
path: release
- name: Verify checksum
working-directory: release
run: shasum -a 256 -c -- *.sha256
- name: Setup Node.js for npm publishing
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version-file: .nvmrc
registry-url: https://registry.npmjs.org
# The only step that receives the npm credential. It publishes before
# the GitHub release is created, so a publish failure leaves no
# half-release, and it skips a version already on the registry so a
# re-run is safe. An existing version must match the verified tarball.
# Version 0.1.2 adds a migration notice if the old package still exists.
# Without NPM_TOKEN it does nothing.
- name: Publish to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -z "$NODE_AUTH_TOKEN" ]; then
echo "NPM_TOKEN is not set; skipping npm publish."
exit 0
fi
version="${RELEASE_TAG#v}"
metadata="$RUNNER_TEMP/npm-version.json"
status=$(curl --silent --show-error --retry 3 --output "$metadata" --write-out '%{http_code}' \
"https://registry.npmjs.org/@basicrum%2fbasicrum-astro/${version}")
case "$status" in
200)
node --input-type=module - "$metadata" ./release/*.tgz <<'NODE'
import { readFileSync } from "node:fs";
import { createHash } from "node:crypto";
const metadata = JSON.parse(readFileSync(process.argv[2], "utf8"));
const integrity = "sha512-" + createHash("sha512").update(readFileSync(process.argv[3])).digest("base64");
if (metadata.dist?.integrity !== integrity) {
throw new Error("Published package differs from the verified release tarball.");
}
console.log("Published package matches the verified tarball; skipping publish.");
NODE
;;
404) npm publish ./release/*.tgz --provenance --access public ;;
*) echo "::error::Cannot check npm publication (HTTP $status)."; exit 1 ;;
esac
if [ "$version" = "0.1.2" ]; then
status=$(curl --silent --show-error --retry 3 --output /dev/null --write-out '%{http_code}' \
'https://registry.npmjs.org/@basicrum%2fastro')
case "$status" in
200) npm deprecate '@basicrum/astro@<=0.1.1' 'Renamed to @basicrum/basicrum-astro. Replace the dependency and update imports, including /client. See https://github.com/basicrum/basicrum-astro#readme' ;;
404) echo "The former @basicrum/astro package has been removed; no migration notice is needed." ;;
*) echo "::error::Cannot check the former npm package (HTTP $status)."; exit 1 ;;
esac
fi
- name: Create GitHub release and upload assets
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
with:
tag_name: ${{ env.RELEASE_TAG }}
generate_release_notes: true
fail_on_unmatched_files: true
files: |
release/*.tgz
release/*.tgz.sha256