-
Notifications
You must be signed in to change notification settings - Fork 22
164 lines (147 loc) · 8.13 KB
/
Copy pathrelease.yml
File metadata and controls
164 lines (147 loc) · 8.13 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
name: Release
on:
push:
tags:
- "v*"
# Serialize all release runs. If two v* tags land close together (e.g.
# rc.3 then rc.4 within a minute), queue rather than race — they share
# mutable outputs (the GHCR `:latest` tag, the homebrew cask in the
# separate tap repo, the GitHub Releases page) and parallel runs would
# interleave nondeterministically. Group is intentionally NOT keyed by
# `github.ref`: we want different tag names to serialize too, not just
# repeat pushes of the same tag. cancel-in-progress=false so a queued
# tag never aborts a release mid-publish (which could leave GHCR and the
# brew tap in inconsistent states).
concurrency:
group: release
cancel-in-progress: false
permissions:
contents: write
packages: write
# id-token: write is required for keyless cosign signing (GitHub OIDC
# exchanges this workflow's identity token for a short-lived Fulcio
# certificate) and for actions/attest-build-provenance to mint SLSA
# v1 provenance statements.
id-token: write
# attestations: write is required by actions/attest-build-provenance so
# the resulting provenance bundles can be stored against the repo.
attestations: write
# All third-party Actions are pinned to a 40-char commit SHA with a trailing
# '# vX.Y.Z' comment so a compromised maintainer or moved tag cannot silently
# execute attacker code in the release pipeline (this workflow has
# contents:write + packages:write + the GHCR token, so a malicious action
# here could publish tampered binaries). Bump the SHA + comment together.
jobs:
release:
name: Build & Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26"
- name: Allow Go to fetch the toolchain go.mod pins
# actions/setup-go pins GOTOOLCHAIN=local, which blocks the toolchain
# go.mod requires (`go 1.26.5` floor, `toolchain go1.26.6`) from being
# fetched. `auto`, written after setup-go so it wins the $GITHUB_ENV
# last-write, lets Go pull it on demand. Mirrors the CI workflow; see
# #896. As of BUG-2565 this also decides which stdlib the RELEASED
# binaries carry — under `local` they would ship the 1.26.5 stdlib and
# its 8 reachable advisories.
run: echo "GOTOOLCHAIN=auto" >> "$GITHUB_ENV"
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24"
cache: "npm"
cache-dependency-path: web/package-lock.json
- name: Create web build placeholder for tests
run: mkdir -p web/build && echo "placeholder" > web/build/.gitkeep
- name: Run tests
# Explicit -timeout, same reasoning as ci.yml's steps (TASK-2545):
# `go test` defaults to 10m per test binary, and this is the RELEASE
# gate — the one place an unchosen default is most expensive. SQLite
# only here (no PAD_TEST_POSTGRES_URL), so it is the faster driver,
# but it grows on the same curve.
run: go test -timeout=45m ./...
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Login to GitHub Container Registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# cosign + syft need to be on PATH before goreleaser runs — goreleaser
# shells out to both for the signs/docker_signs/sboms sections.
- name: Install cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- name: Install syft (for SBOM generation)
uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
# Build the SvelteKit web UI before GoReleaser so the static assets
# get embedded into the Go binary. Done as a dedicated step (instead
# of a goreleaser `before:` hook) so the npm install/build does NOT
# inherit the MACOS_* signing secrets — those are scoped only to the
# `Run GoReleaser` step's env block below. This isolates the 5-year
# Developer ID cert from any npm supply-chain compromise during
# dependency install.
- name: Build web UI
run: cd web && npm ci && npm run build
- name: Run GoReleaser
id: goreleaser
# GoReleaser binary is pinned to an exact version (not "~> v2") to
# match the SHA-pinning policy applied to the Actions themselves —
# see the comment at the top of this file. With Apple signing
# credentials now flowing through this step, a compromised or
# regressed GoReleaser release would carry meaningful blast radius;
# pinning forces an explicit, reviewed bump.
uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
with:
version: "v2.15.4"
# --timeout=2h overrides GoReleaser's 1h default. With Apple
# notarization (`wait: true`, up to 20m per the .goreleaser.yaml
# notarize block) layered on top of build + cosign blob-sign +
# SBOM + multi-arch docker manifest, slow notary days could push
# close to the default ceiling. 2h gives comfortable headroom
# without burning excessive Action minutes when notarization
# actually fails fast (the worker exits as soon as Apple replies).
args: release --clean --timeout=2h
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Force-set the release tag from the triggering ref to bypass
# goreleaser's git-describe-based auto-detection. When two
# lightweight tags point at the same commit (e.g. v0.4.0 cut
# right on top of v0.4.0-rc.1 with no intervening commits),
# git-describe's tiebreaker is non-deterministic across hosts
# — locally it picked v0.4.0, the CI runner picked v0.4.0-rc.1
# during the v0.4.0 ship and stamped artifacts with the RC
# version. github.ref_name is unambiguous: it's exactly the
# tag that triggered the workflow. See PLAYB-1160 failure modes.
GORELEASER_CURRENT_TAG: ${{ github.ref_name }}
# Cross-repo PAT for pushing the brew formula to PerpetualSoftware/homebrew-tap.
# The default GITHUB_TOKEN above only has access to PerpetualSoftware/pad.
# Add this secret in repo settings before tagging a release that ships
# a brew formula — without it goreleaser fails at the brew publish step.
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
# macOS code-signing + Apple notarization (per IDEA-830). The
# `notarize:` block in .goreleaser.yaml is gated on MACOS_CERT_P12
# being set, so PR builds + snapshot mode skip cleanly when these
# are absent. The .p12 cert and .p8 notary key are stored
# base64-encoded; GoReleaser's Quill backend decodes them in-process,
# so no external signing tool needs to be installed on the runner.
MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }}
MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }}
MACOS_NOTARY_KEY_P8: ${{ secrets.MACOS_NOTARY_KEY_P8 }}
MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }}
# SLSA build provenance for every archive GoReleaser produced.
# Writes a Sigstore-backed attestation to the repo so downstream
# consumers can verify this binary was actually built by this
# workflow from this commit, e.g.:
# gh attestation verify pad_v1.0.0_linux_amd64.tar.gz \
# --repo PerpetualSoftware/pad
- name: Generate build provenance for archives
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: "dist/pad_*_*_*.tar.gz,dist/pad_*_*_*.zip"