Repository navigation
179 lines (172 loc) · 7.47 KB
/
Copy pathrelease.yml
File metadata and controls
179 lines (172 loc) · 7.47 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
name: Release
# How releases work, and the one-time setup: docs/releasing.md.
on:
push:
branches: [main]
# Each job asks for only the permissions it needs.
permissions: {}
concurrency:
# One release run at a time. Never cancel a run in the middle of a release.
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
release-please:
# Skip until the GitHub App is set up (see docs/releasing.md).
if: vars.RELEASE_APP_CLIENT_ID != ''
runs-on: ubuntu-latest
# The App private key is a secret of this environment. Only main may use
# the environment, so only runs on main can read the key.
environment: release
# This job uses the App token, not GITHUB_TOKEN.
permissions: {}
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
version: ${{ steps.release.outputs.version }}
steps:
- id: app-token
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write
- id: release
uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
with:
token: ${{ steps.app-token.outputs.token }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# Builds the files. It can only read the repository: no OIDC token, and no
# write access to the release.
build:
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
env:
TAG: ${{ needs.release-please.outputs.tag_name }}
VERSION: ${{ needs.release-please.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: refs/tags/${{ needs.release-please.outputs.tag_name }}
persist-credentials: false
- name: Check that the tag is the commit of this run
# The provenance attestation names $GITHUB_SHA as the source commit.
# Build only that commit.
run: |
set -euo pipefail
head="$(git rev-parse HEAD)"
tagged="$(git rev-parse "refs/tags/${TAG}^{commit}")"
echo "HEAD: $head tag ${TAG}: $tagged run: $GITHUB_SHA"
if [ "$head" != "$GITHUB_SHA" ] || [ "$tagged" != "$GITHUB_SHA" ]; then
echo "::error::The tag ${TAG} is not the commit of this run. See docs/releasing.md."
exit 1
fi
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
# The newest Go, so the binaries get the newest standard library fixes.
go-version: stable
# No cache for release builds: a bad cache entry could change the binaries.
cache: false
- name: Build
# -w drops the debug data. The symbol table stays (no -s): govulncheck
# needs it to check the published binaries (see ci.yml).
run: |
set -euo pipefail
mkdir -p dist
# Fixed owner, mode and time in the tarball, so a rebuild of the
# same commit with the same Go version gives the same file.
mtime="@$(git log -1 --format=%ct)"
for arch in amd64 arm64; do
name="pullgate_${VERSION}_linux_${arch}"
stage="${RUNNER_TEMP}/${name}"
mkdir -p "$stage"
CGO_ENABLED=0 GOOS=linux GOARCH="$arch" \
go build -trimpath -ldflags "-w -X main.version=${VERSION}" \
-o "${stage}/pullgate" ./cmd/pullgate
cp LICENSE README.md "$stage/"
tar --owner=0 --group=0 --numeric-owner --mode=go-w --mtime="$mtime" \
-C "$stage" -cf - pullgate LICENSE README.md | gzip -9n > "dist/${name}.tar.gz"
done
cd dist
sha256sum -- *.tar.gz > SHA256SUMS
cat SHA256SUMS
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-files
path: dist/
if-no-files-found: error
# Signs and publishes the files from the build job. It runs no code from
# the repository.
publish:
needs: [release-please, build]
if: needs.release-please.outputs.release_created == 'true'
runs-on: ubuntu-latest
permissions:
contents: write # upload the files and publish the draft release
id-token: write # sign the attestation (Sigstore)
attestations: write # store the attestation
env:
TAG: ${{ needs.release-please.outputs.tag_name }}
VERSION: ${{ needs.release-please.outputs.version }}
steps:
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-files
path: dist
- name: Check the files and the tag
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
(cd dist && sha256sum --strict -c SHA256SUMS)
# The version names the bundle file. An empty or wrong version
# would go out in a release that nobody can change.
if [ "$TAG" != "v${VERSION}" ]; then
echo "::error::The tag ${TAG} does not match the version ${VERSION}. See docs/releasing.md."
exit 1
fi
tagged="$(gh api "repos/${GITHUB_REPOSITORY}/commits/refs/tags/${TAG}" --jq .sha)"
if [ "$tagged" != "$GITHUB_SHA" ]; then
echo "::error::The tag ${TAG} points to ${tagged}, not to ${GITHUB_SHA}. See docs/releasing.md."
exit 1
fi
- uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
id: attest
with:
subject-path: dist/*.tar.gz
# The attestation is also a file of the release. With this file,
# gh attestation verify --bundle needs no GitHub login. One bundle
# covers both tarballs.
- name: Save the attestation bundle
env:
BUNDLE: ${{ steps.attest.outputs.bundle-path }}
run: cp -- "$BUNDLE" "dist/pullgate_${VERSION}.sigstore.json"
# The same check as in docs/releasing.md, with no login. A bundle that
# fails it never goes out: the release stays a draft.
- name: Check the tarballs with the bundle
run: |
set -euo pipefail
gh --version
for f in dist/*.tar.gz; do
gh attestation verify "$f" \
--bundle "dist/pullgate_${VERSION}.sigstore.json" \
--repo "$GITHUB_REPOSITORY" \
--cert-identity "https://github.com/${GITHUB_REPOSITORY}/.github/workflows/release.yml@refs/heads/main" \
--deny-self-hosted-runners
echo "$f: OK"
done
# release-please made a draft release (see release-please-config.json).
# Add the files first and publish after that, so the release is never
# public without its files. Immutable releases need this order.
- name: Upload the files to the draft release
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload "$TAG" dist/*.tar.gz dist/SHA256SUMS "dist/pullgate_${VERSION}.sigstore.json" --clobber --repo "$GITHUB_REPOSITORY"
- name: Publish the release
env:
GH_TOKEN: ${{ github.token }}
run: gh release edit "$TAG" --draft=false --repo "$GITHUB_REPOSITORY"