-
Notifications
You must be signed in to change notification settings - Fork 0
165 lines (149 loc) · 5.45 KB
/
Copy pathrelease.yml
File metadata and controls
165 lines (149 loc) · 5.45 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
name: Release
# Tag-driven publish. Push a v* tag and this builds, verifies, publishes to
# PyPI via OIDC trusted publishing, and opens a GitHub Release.
#
# NO API TOKEN IS STORED ANYWHERE. Trusted publishing has PyPI verify a
# short-lived OIDC token minted by GitHub for this specific repo + workflow +
# environment, so there is no long-lived secret to leak or rotate. One-time
# setup on PyPI (see RELEASING.md):
# pypi.org -> your project -> Publishing -> Add a new pending publisher
# Owner: pip-install-python
# Repository: dash-leaflet2
# Workflow name: release.yml
# Environment name: pypi
on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
dry_run:
description: "Build and verify, but publish to TestPyPI instead of PyPI"
type: boolean
default: true
# Read-only by default; the two jobs that need more ask for it themselves
# (`id-token: write` to publish, `contents: write` to cut the GitHub Release).
permissions:
contents: read
# Never let two releases race. NOT cancel-in-progress: a half-cancelled
# publish is the one state worth avoiding here, because a version can be
# uploaded to PyPI exactly once and is not replaceable afterwards.
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
verify:
name: Verify the tag
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Tag must match the version in pyproject.toml
# Catches the classic release mistake: bumping the code but tagging the
# old number (or the reverse). PyPI would happily accept the mismatch.
if: startsWith(github.ref, 'refs/tags/v')
run: |
TAG="${GITHUB_REF_NAME#v}"
PY_VER=$(python -c "import re;print(re.search(r'^version = \"([^\"]+)\"', open('pyproject.toml').read(), re.M).group(1))")
echo "tag=$TAG pyproject=$PY_VER"
if [ "$TAG" != "$PY_VER" ]; then
echo "::error::Tag v$TAG does not match pyproject version $PY_VER"
exit 1
fi
- name: Release consistency check
run: python scripts/check_release.py
build:
name: Build distributions
needs: verify
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Smoke test against the current Dash
run: |
python -m pip install --upgrade pip
grep -v 'COMPAT-MATRIX: dash' requirements.txt > /tmp/reqs.txt
python -m pip install "dash[fastapi]" -r /tmp/reqs.txt
# markdown2dash is NOT in requirements.txt: it declares gunicorn<22
# against the CVE-driven gunicorn>=23 floor, so it installs without
# its dependency graph. pages/markdown.py imports it, so the smoke
# test below cannot even reach a page without this line. Same pair as
# the Dockerfile and ci.yml.
python -m pip install --no-deps markdown2dash==0.1.2
python scripts/smoke_test.py
- name: Build
run: |
python -m pip install build twine
python -m build
python -m twine check dist/*
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
publish:
name: Publish to PyPI
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
# The environment name must match the pending publisher configured on PyPI.
# Add a required reviewer on this environment in repo settings if you want
# a human approval gate between the tag and the upload.
environment:
name: pypi
url: https://pypi.org/p/dash-leaflet2
permissions:
# `id-token: write` is what lets GitHub mint the OIDC token PyPI checks.
# Without it trusted publishing fails with an opaque 403.
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Publish to TestPyPI (manual dry run)
if: github.event_name == 'workflow_dispatch' && inputs.dry_run
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
- name: Publish to PyPI
if: startsWith(github.ref, 'refs/tags/v')
uses: pypa/gh-action-pypi-publish@release/v1
github-release:
name: GitHub Release
needs: publish
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Extract this version's CHANGELOG section
run: |
VERSION="${GITHUB_REF_NAME#v}"
awk -v v="$VERSION" '
$0 ~ "^## \\[" v "\\]" {found=1; next}
found && /^## \[/ {exit}
found {print}
' CHANGELOG.md > release-notes.md
if [ ! -s release-notes.md ]; then
echo "See CHANGELOG.md for details." > release-notes.md
fi
cat release-notes.md
- uses: softprops/action-gh-release@v2
with:
body_path: release-notes.md
files: dist/*
generate_release_notes: true