Repository navigation
194 lines (167 loc) · 5.77 KB
/
Copy pathrelease.yml
File metadata and controls
194 lines (167 loc) · 5.77 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
193
194
name: Release
# Publishing happens on a tag, never on a branch: the tag names the exact
# commit whose artifacts are published, so "which commit is 0.0.2?" has one
# answer. Everything the registry can hold onto — metadata, changelog, code —
# is checked before the first upload, because PyPI and npm do not allow a
# version number to be re-used.
#
# Both registries are set up for TRUSTED PUBLISHING (OIDC): there is no
# long-lived API token in this repo's secrets. The workflow proves its identity
# with the `id-token: write` permission and the registry checks it against the
# publisher configured for the project. See docs/guides/releasing.md for the
# one-time setup on pypi.org and npmjs.com.
on:
push:
tags: ["v*"]
permissions:
contents: read
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
defaults:
run:
shell: bash
jobs:
verify:
name: verify the tag against the tree
# Pinned for the same reason CI is: `ubuntu-latest` moved to 26.04 on
# 2026-10-28, where the brace bubblewrap tests report SIGXCPU as exit 152
# and the egress-grant controls exit 1. This job runs the full suite, so a
# floating image would turn every tag into a failed release.
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v5
with:
# The changelog check must read the tagged commit, not a merge ref.
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: pip
cache-dependency-path: pyproject.toml
- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]" build twine
- name: Tag agrees with pyproject.toml, js/package.json and CHANGELOG.md
id: version
run: |
version="$(python3 scripts/check_release.py --print-version "${GITHUB_REF_NAME}")"
echo "version=${version}" >> "$GITHUB_OUTPUT"
- name: Test suite
run: python3 -m pytest -q
- name: Build the sdist and wheel
run: python3 -m build
- name: Check the distribution metadata
run: python3 -m twine check dist/*
- name: The wheel is importable and carries the version
run: |
python3 -m venv /tmp/wheelcheck
/tmp/wheelcheck/bin/pip install --quiet dist/*.whl
/tmp/wheelcheck/bin/python - <<'PY'
import importlib.metadata
import interlock
expected = importlib.metadata.version("interlock-guard")
print("installed", expected, "from", interlock.__file__)
assert expected == "${{ steps.version.outputs.version }}"
PY
- uses: actions/upload-artifact@v4
with:
name: python-dist
path: dist/
if-no-files-found: error
verify-node:
name: verify the npm package
runs-on: ubuntu-latest
defaults:
run:
working-directory: js
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: actions/setup-node@v5
with:
node-version: "22"
cache: npm
cache-dependency-path: js/package-lock.json
- run: npm ci
- run: npm test
- run: npm run build
- name: The tarball contains exactly what ships
run: npm pack --dry-run
publish-pypi:
name: publish to PyPI
needs: [verify]
runs-on: ubuntu-latest
environment: pypi
permissions:
# The only credential: an OIDC token GitHub mints for this run and the
# registry verifies. No password, no PYPI_API_TOKEN secret.
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: python-dist
path: dist/
- name: Publish
# `release/v1` is the action's maintained release branch; it uploads
# with `pypa/gh-action-pypi-publish`'s default attestations, so the
# PyPI page shows a PEP 740 provenance attestation for the files.
uses: pypa/gh-action-pypi-publish@release/v1
with:
attestations: true
print-hash: true
publish-npm:
name: publish to npm
needs: [verify, verify-node]
runs-on: ubuntu-latest
environment: npm
permissions:
# npm trusted publishing: the CLI exchanges this OIDC token for a
# short-lived publish token, and `--provenance` attaches a signed
# statement that the tarball was built in this repository at this ref.
id-token: write
defaults:
run:
working-directory: js
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: actions/setup-node@v5
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"
- name: Trusted publishing needs a recent npm
# Node 22 bundles npm 10; OIDC publishing landed in npm 11.5.
run: npm install --global npm@11
- run: npm ci
- run: npm run build
- name: Publish with provenance
run: npm publish --provenance --access public
github-release:
name: attach the artifacts to a GitHub release
needs: [verify, publish-pypi, publish-npm]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: actions/download-artifact@v4
with:
name: python-dist
path: dist/
- name: Create the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${GITHUB_REF_NAME}" dist/* \
--verify-tag \
--title "interlock ${GITHUB_REF_NAME}" \
--generate-notes