Repository navigation
162 lines (155 loc) · 5.96 KB
/
Copy pathrelease.yml
File metadata and controls
162 lines (155 loc) · 5.96 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
# The npm release of @qauth-labs/plugin-github, from a tag (RELEASING.md).
#
# A tag vX.Y.Z or vX.Y.Z-rc.N starts it. The tag must name the version in
# package.json. The whole CI runs first (ci.yml: the checks, the contract test
# kit, the end-to-end suite). Then the package is packed once, and that
# tarball, checked by its digest, is staged on npm through trusted publishing
# (OIDC, no token) in the `npm` environment; npm attaches provenance on its
# own. A release candidate goes to the `next` dist-tag, a release to
# `latest`. The staged version goes live only when a maintainer approves it
# on npmjs.com with 2FA. The run leaves a draft GitHub release with the
# tarball and the version's CHANGELOG section.
#
# npm's trusted publisher for @qauth-labs/plugin-github names this file:
# release.yml, environment npm.
name: release
on:
push:
tags: ['v*']
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
ci:
uses: ./.github/workflows/ci.yml
pack:
needs: ci
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.plan.outputs.version }}
dist-tag: ${{ steps.plan.outputs.dist-tag }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# The whole history: the tagged commit must be on main.
fetch-depth: 0
- uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 26
cache: pnpm
- name: The tag points at a commit on main
run: |
set -euo pipefail
if ! git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then
echo "The tag points at $GITHUB_SHA, which is not on main: only a reviewed, merged commit is released." >&2
exit 1
fi
- id: plan
name: The tag names the package's version; the dist-tag it goes to
env:
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
version="$(node -p 'require("./package.json").version')"
if [ "$TAG" != "v$version" ]; then
echo "The tag $TAG does not name the package's version $version." >&2
exit 1
fi
case "$version" in
*-rc.*) dist_tag=next ;;
*-*) echo "Only a release candidate (-rc.N) or a release is published: $version." >&2; exit 1 ;;
*) dist_tag=latest ;;
esac
if ! grep -q "^## \[$version\]" CHANGELOG.md; then
echo "CHANGELOG.md has no section for $version." >&2
exit 1
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "dist-tag=$dist_tag" >> "$GITHUB_OUTPUT"
- run: pnpm install --frozen-lockfile
- run: pnpm run build
- name: Pack it as npm will receive it
run: |
set -euo pipefail
mkdir -p "$RUNNER_TEMP/pack"
pnpm pack --pack-destination "$RUNNER_TEMP/pack"
cd "$RUNNER_TEMP/pack"
tarball="$(ls ./*.tgz)"
sha256sum "$tarball" > "$tarball.sha256"
tar -tzf "$tarball"
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: package
path: ${{ runner.temp }}/pack/
if-no-files-found: error
retention-days: 7
publish:
needs: pack
runs-on: ubuntu-24.04
environment: npm
permissions:
contents: read
id-token: write
env:
DIST_TAG: ${{ needs.pack.outputs.dist-tag }}
steps:
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: package
path: pack
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: 26
registry-url: https://registry.npmjs.org
# pnpm builds and packs; npm stages the tarball, as QAuth's release-npm.yml does.
- name: npm with staged publishing through OIDC
run: npm install --global npm@11.21.0
- name: The tarball is the one the pack job made
working-directory: pack
run: sha256sum --check ./*.sha256
- name: Stage it on npm; a maintainer approves it there, with 2FA
working-directory: pack
run: npm stage publish ./*.tgz --tag "$DIST_TAG" --access public
draft-release:
needs: [pack, publish]
runs-on: ubuntu-24.04
permissions:
contents: write
env:
VERSION: ${{ needs.pack.outputs.version }}
DIST_TAG: ${{ needs.pack.outputs.dist-tag }}
TAG: ${{ github.ref_name }}
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: package
path: pack
- name: Draft the release with the tarball and the version's changelog section
run: |
set -euo pipefail
awk -v heading="## [$VERSION]" '
index($0, heading) == 1 { found = 1; next }
found && /^## \[/ { exit }
found { print }
' CHANGELOG.md > "$RUNNER_TEMP/notes.md"
{
echo
echo "---"
echo
echo "Staged on npm as \`$VERSION\` (dist-tag \`$DIST_TAG\`), with provenance. It goes"
echo "live when a maintainer approves the stage on npmjs.com with 2FA; publish this"
echo "draft after that."
} >> "$RUNNER_TEMP/notes.md"
prerelease=()
case "$VERSION" in *-rc.*) prerelease=(--prerelease) ;; esac
gh release create "$TAG" pack/*.tgz pack/*.sha256 \
--draft --verify-tag --title "$TAG" --notes-file "$RUNNER_TEMP/notes.md" "${prerelease[@]}"