Repository navigation
131 lines (119 loc) · 5.67 KB
/
Copy pathrelease.yml
File metadata and controls
131 lines (119 loc) · 5.67 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
name: Release
# Automated release flow (release-please + npm publish).
#
# How it works:
# 1. Every push to `main` runs release-please, which maintains a "Release PR"
# that bumps the version and updates CHANGELOG.md from Conventional Commits
# (feat/fix/perf/deps/revert). docs/refactor/test/ci/chore do not release.
# 2. When you MERGE that Release PR, release-please creates a GitHub Release +
# git tag. That sets `release_created=true`, which triggers the publish job
# below — building, testing, and publishing to npm as @spinabot/brigade.
#
# One-time setup (repo settings):
# - Add a repository secret `NPM_TOKEN` = an npm Automation token with publish
# rights to the @spinabot scope.
# - (Optional, more secure) Switch to npm Trusted Publishing (OIDC) instead of
# NPM_TOKEN: configure a trusted publisher for @spinabot/brigade on npmjs.com
# pointing at this repo + `release.yml`, then drop `NODE_AUTH_TOKEN` below.
# `id-token: write` is already granted for provenance either way.
on:
push:
branches: [main]
# Escape hatch. `publish-npm` only fires when release-please CREATES a release, so
# when the publish step itself fails (a broken runner npm, an npm outage, an expired
# token) the tag and GitHub Release exist while npm never receives the package — and
# re-running the job just replays the same failing commit. This lets an operator
# publish whatever version `main` currently declares, once the cause is fixed.
workflow_dispatch:
inputs:
publish:
description: "Publish the version in package.json to npm"
type: boolean
default: false
permissions:
contents: write
pull-requests: write
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
release-please:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
# This enterprise DISABLES write permissions for the Actions GITHUB_TOKEN
# ("Write permissions for workflows are disabled by the enterprise"), so
# the bot cannot open the Release PR. A PAT (RELEASE_PLEASE_TOKEN) acts as
# a real user and is NOT subject to that restriction — set it as a repo
# secret and release-please will open + label the Release PR automatically
# (it also makes the Release PR trigger CI). Falls back to GITHUB_TOKEN
# (PR creation will fail, but the rest of the workflow still runs) when
# the PAT secret is absent.
token: ${{ secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
publish-npm:
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' || (github.event_name == 'workflow_dispatch' && inputs.publish) }}
runs-on: ubuntu-latest
environment: npm-release
permissions:
contents: read
id-token: write # required for npm provenance / OIDC trusted publishing
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
cache: npm
# Do NOT `npm install -g npm@latest` here. npm overwriting itself in the runner's
# tool-cache leaves its own dependency tree half-written, and the first thing to
# notice is `npm publish --provenance`:
#
# npm error Cannot find module 'sigstore'
# npm error - .../npm/node_modules/libnpmpublish/lib/provenance.js
#
# That failed the 1.26.0 AND 1.26.1 publishes after every test had passed. Node 24
# already ships an npm new enough for provenance + trusted publishing, so verify
# rather than upgrade — and fail with a readable reason if a future runner regresses.
- name: Verify npm supports provenance + trusted publishing
run: |
set -euo pipefail
v="$(npm --version)"
echo "runner npm: $v"
node -e '
const [maj, min, pat] = process.argv[1].split(".").map(Number);
const ok = maj > 11 || (maj === 11 && (min > 5 || (min === 5 && pat >= 1)));
if (!ok) {
console.error(`npm ${process.argv[1]} is too old — provenance + trusted publishing need >= 11.5.1`);
process.exit(1);
}
' "$v"
# Advisory only — `npm publish` is the real check, and a false negative here
# must never block a healthy release.
node -e "require.resolve('sigstore', { paths: [require('node:child_process').execSync('npm root -g').toString().trim() + '/npm/node_modules/libnpmpublish'] }); console.log('sigstore resolvable')" \
|| echo "::warning::could not resolve 'sigstore' from this runner's npm — provenance may fail at publish time"
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Test
run: npm test
- name: Publish to npm
# Provenance requires a public repo + public CI run. We enable it
# automatically once the repo is public, and skip it while private so the
# publish still succeeds. No manual edit needed when you flip visibility.
run: |
if [ "${{ github.event.repository.private }}" = "false" ]; then
echo "Repo is public — publishing with provenance."
npm publish --provenance --access public
else
echo "Repo is private — publishing without provenance."
npm publish --access public
fi
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}