-
Notifications
You must be signed in to change notification settings - Fork 1
192 lines (184 loc) · 9.22 KB
/
Copy pathrelease.yml
File metadata and controls
192 lines (184 loc) · 9.22 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
189
190
191
192
name: release
on:
push:
# Full semver only: the floating action major tag (v1) must NOT cut a
# release — it just tracks the latest root action.yml for `uses:` pins.
tags: ["v[0-9]+.[0-9]+.[0-9]+"]
permissions:
contents: write # create the GitHub Release + upload assets
id-token: write # cosign keyless signing (OIDC)
packages: write # push the container image to ghcr.io
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # goreleaser needs full history for the changelog
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
# syft: goreleaser's sboms block. qemu: emulation for the linux/arm64
# image build. buildx: goreleaser's docker build. (Prose stays off the
# version comments — dependabot only rewrites a trailing "# vX.Y.Z".)
- uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
- uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
# Log in so goreleaser can push the ghcr.io image; without this the docker
# step fails and takes the whole release (tarballs included) down with it.
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
with:
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Container image goes to the releasing repo's own ghcr namespace, so a
# fork's release doesn't try (and fail) to push to ghcr.io/pgrundev.
IMAGE_REPO: ghcr.io/${{ github.repository }}
# Write access to the separate pgrundev/homebrew-tap repo — EITHER the
# private half of a write deploy key on that repo (preferred) OR a
# fine-grained PAT scoped to it (Contents: write). Both are passed (empty
# when absent — the goreleaser templates need them defined); with
# neither, the brews block skips the push, the release still succeeds,
# and brew-smoke below fails to say so. See docs/release.md → Homebrew.
HOMEBREW_TAP_DEPLOY_KEY: ${{ secrets.HOMEBREW_TAP_DEPLOY_KEY }}
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
# npm distribution: assemble the wrapper + per-platform packages from the
# binaries goreleaser just built, and publish them (platform packages first,
# the wrapper last, since it pins their exact versions). Version == the tag.
# Skips cleanly when NPM_TOKEN is unset, so a release never fails for it.
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 20
registry-url: https://registry.npmjs.org
- name: publish npm packages
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -z "$NODE_AUTH_TOKEN" ]; then
echo "NPM_TOKEN not set — skipping npm publish (release still succeeds)."
exit 0
fi
VERSION="${GITHUB_REF_NAME#v}"
node npm/build.mjs "$VERSION"
for d in npm/staging/@pgbot/*/; do
npm publish "$d" --provenance --access public
done
npm publish npm/staging/pgbot --provenance --access public
# DoD 8: prove the published package actually runs — a packaging break is
# invisible to the Go test suite and only shows up here. macos-latest is
# darwin-arm64, windows-latest is win32-x64, ubuntu-latest is linux-x64.
npm-smoke:
needs: goreleaser
name: npx smoke (${{ matrix.os }})
env:
HAS_NPM: ${{ secrets.NPM_TOKEN != '' }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 20
- name: npx @pgbot/cli@<tag> --version exits 0
if: env.HAS_NPM == 'true'
shell: bash
run: |
VERSION="${GITHUB_REF_NAME#v}"
# Each attempt gets a VIRGIN npm cache. Without this, an attempt that
# runs before the platform package has propagated caches the wrapper
# WITHOUT its optionalDependency, and every later retry silently
# reuses that poisoned tree — the 0.4.2/0.4.3/0.5.0 windows reds all
# died this way while the registry was fine. 20 x 30s covers the
# propagation window itself.
for i in $(seq 1 20); do
cache="${RUNNER_TEMP:-/tmp}/npx-cache-$i"
if npx -y --cache "$cache" "@pgbot/cli@${VERSION}" --version; then exit 0; fi
echo "@pgbot/cli@${VERSION} not installable yet (attempt $i, fresh cache) — waiting for npm propagation"
sleep 30
done
echo "FAILED: npx @pgbot/cli@${VERSION} --version never succeeded"
exit 1
# Issue #8 was `brew install pgrundev/tap/pgbot` 404ing for months while every
# release stayed green, because the tap push was silently skipped. Prove the
# published formula installs THIS tag on a fresh mac, the way a user does it.
brew-smoke:
needs: goreleaser
name: brew install pgrundev/tap/pgbot
# The tap is pgrundev's; a fork has no credential for it by design, so the
# loud "formula NOT published" failure below is only meaningful upstream.
if: github.repository == 'pgrundev/pgbot'
runs-on: macos-latest
env:
HAS_TAP_CRED: ${{ secrets.HOMEBREW_TAP_DEPLOY_KEY != '' || secrets.HOMEBREW_TAP_TOKEN != '' }}
steps:
- name: brew install the tap formula and check the version
run: |
if [ "$HAS_TAP_CRED" != "true" ]; then
echo "::error::neither HOMEBREW_TAP_DEPLOY_KEY nor HOMEBREW_TAP_TOKEN is set — the Homebrew formula was NOT published for this release (brew install pgrundev/tap/pgbot will lag behind). See docs/release.md."
exit 1
fi
VERSION="${GITHUB_REF_NAME#v}"
export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1
for i in $(seq 1 10); do
brew untap pgrundev/tap >/dev/null 2>&1 || true
if brew install pgrundev/tap/pgbot && [ "$(pgbot --version)" = "pgbot version ${VERSION}" ]; then
echo "brew install pgrundev/tap/pgbot → $(pgbot --version) ✓"
brew test pgbot
exit 0
fi
echo "tap formula not at ${VERSION} yet (attempt $i) — waiting"
sleep 20
done
echo "FAILED: brew install pgrundev/tap/pgbot never yielded pgbot ${VERSION}"
exit 1
# The container image must be ANONYMOUSLY pullable. ghcr packages default to
# private, and a private image passes every other check while nobody outside the
# org can `docker run` it (this bit us for real). A fresh runner isn't logged in
# to ghcr, so this run is anonymous by construction.
docker-smoke:
needs: goreleaser
name: image is public + runs
runs-on: ubuntu-latest
steps:
- name: anonymous docker run --version
run: |
VERSION="${GITHUB_REF_NAME#v}"
IMAGE="ghcr.io/$(echo "$GITHUB_REPOSITORY" | tr '[:upper:]' '[:lower:]')"
docker logout ghcr.io || true # ensure the pull is anonymous
out="$(docker run --rm "$IMAGE":"$VERSION" --version)"
echo "$out"
case "$out" in
"pgbot version"*) echo "image is public and runs ✓" ;;
*) echo "FAILED: unexpected --version output (or image not anonymously pullable)"; exit 1 ;;
esac
# Verify the release's own cosign signature — the release SIGNS the checksums but
# never checked that the signature actually verifies. A broken signing chain
# would silently ship and only surface when a user runs install.sh with
# PGBOT_REQUIRE_SIGNATURE=1. Verify the bundle against the release workflow's
# OIDC identity.
verify-signature:
needs: goreleaser
name: published signature verifies
runs-on: ubuntu-latest
steps:
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: cosign verify-blob --bundle
run: |
VERSION="${GITHUB_REF_NAME}"
base="https://github.com/${GITHUB_REPOSITORY}/releases/download/${VERSION}"
curl -fsSL "$base/checksums.txt" -o checksums.txt
curl -fsSL "$base/checksums.txt.cosign.bundle" -o checksums.txt.cosign.bundle
cosign verify-blob --bundle checksums.txt.cosign.bundle \
--certificate-identity "https://github.com/${GITHUB_REPOSITORY}/.github/workflows/release.yml@${GITHUB_REF}" \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
checksums.txt
echo "published cosign bundle verifies ✓"