forked from ChelseaKR/power-content-check
-
Notifications
You must be signed in to change notification settings - Fork 0
122 lines (108 loc) · 3.97 KB
/
Copy pathrelease.yml
File metadata and controls
122 lines (108 loc) · 3.97 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
name: Release
# Two jobs with different authority.
#
# The first job can read but not write. It checks out trusted main, confirms
# the requested ref really is an annotated, signed tag object, and confirms
# that tag points at a commit already on main.
#
# The first job also re-runs the same `make verify` gate CI runs, at the exact
# commit the tag names, and refuses a tag whose name disagrees with the package
# version, so nothing unverified can be published under a verified-looking tag.
#
# The second job can write but never checks out a working tree, so nothing in
# the repository at the tagged ref can influence what it does. It re-resolves
# the tag through the API before publishing, so a tag moved between the two
# jobs does not slip through.
on:
workflow_dispatch:
inputs:
tag:
description: "Signed tag to publish, for example v0.1.0"
required: true
type: string
permissions:
contents: read
jobs:
verify-tag:
name: Verify the signed tag against trusted main
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check out trusted main
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: main
fetch-depth: 0
persist-credentials: false
- name: Refuse to run from anywhere but main
run: |
echo "dispatched from ${GITHUB_REF}"
test "${GITHUB_REF}" = "refs/heads/main"
- name: Confirm the ref is an annotated tag object
env:
TAG: ${{ inputs.tag }}
run: |
git fetch --force origin "refs/tags/${TAG}:refs/tags/${TAG}"
test "$(git cat-file -t "${TAG}")" = "tag"
- name: Refuse a signer list that names no principal
run: |
# Present is not the same as populated. A file of comments would let
# verify-tag run against an empty principal list, and the failure
# would read like a bad signature rather than a missing key.
grep -qv '^[[:space:]]*\(#\|$\)' .github/allowed_signers
- name: Verify the tag signature
env:
TAG: ${{ inputs.tag }}
run: |
git config gpg.format ssh
git config gpg.ssh.allowedSignersFile .github/allowed_signers
git verify-tag "${TAG}"
- name: Confirm the tag is an ancestor of main
env:
TAG: ${{ inputs.tag }}
run: |
git merge-base --is-ancestor "${TAG}^{commit}" origin/main
- name: Install uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
enable-cache: false
python-version: "3.12"
- name: Run the full gate at the tagged commit
env:
TAG: ${{ inputs.tag }}
run: |
git checkout --detach "${TAG}^{commit}"
make verify
- name: Confirm the tag and the package version agree
env:
TAG: ${{ inputs.tag }}
run: |
want="${TAG#v}"
have="$(uv run python -c 'import tomllib, pathlib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])')"
test "${want}" = "${have}"
publish:
name: Publish the release
needs: verify-tag
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Re-resolve the tag object through the API
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ inputs.tag }}
run: |
sha="$(gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/${TAG}" --jq '.object.sha')"
test -n "${sha}"
echo "TAG_SHA=${sha}" >> "${GITHUB_ENV}"
- name: Create the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ inputs.tag }}
run: |
gh release create "${TAG}" \
--repo "${GITHUB_REPOSITORY}" \
--target "${TAG_SHA}" \
--title "${TAG}" \
--notes "See CHANGELOG.md for the entry covering ${TAG}."