Skip to content

Commit 34bb66e

Browse files
committed
Add maintainer release flow
1 parent cd181e1 commit 34bb66e

9 files changed

Lines changed: 1126 additions & 3 deletions

File tree

.github/workflows/release.yml

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
repository:
7+
description: Package index to publish to
8+
required: true
9+
default: testpypi
10+
type: choice
11+
options:
12+
- testpypi
13+
- pypi
14+
version:
15+
description: Optional version to validate against package metadata (for example 0.1.0a1)
16+
required: false
17+
type: string
18+
19+
permissions:
20+
contents: read
21+
22+
jobs:
23+
unit:
24+
runs-on: ubuntu-latest
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
python-version: ["3.10", "3.13"]
29+
django-version: ["4.2.*", "5.1.*"]
30+
31+
steps:
32+
- uses: actions/checkout@v4
33+
with:
34+
persist-credentials: false
35+
36+
- uses: actions/setup-python@v5
37+
with:
38+
python-version: ${{ matrix.python-version }}
39+
40+
- name: Install Python dependencies
41+
run: |
42+
python -m pip install --upgrade pip
43+
python -m pip install "Django==${{ matrix.django-version }}" -e .[dev]
44+
45+
- name: Ruff
46+
run: ruff check .
47+
48+
- name: Pytest
49+
run: pytest
50+
51+
example-e2e:
52+
runs-on: ubuntu-latest
53+
timeout-minutes: 20
54+
55+
steps:
56+
- uses: actions/checkout@v4
57+
with:
58+
persist-credentials: false
59+
60+
- uses: actions/setup-python@v5
61+
with:
62+
python-version: "3.13"
63+
64+
- uses: actions/setup-node@v4
65+
with:
66+
node-version: "22"
67+
cache: "npm"
68+
cache-dependency-path: example/package-lock.json
69+
70+
- name: Install Python dependencies
71+
run: |
72+
python -m pip install --upgrade pip
73+
python -m pip install -e .[dev]
74+
75+
- name: Install example dependencies
76+
working-directory: example
77+
run: npm ci
78+
79+
- name: Install Playwright browser
80+
working-directory: example
81+
run: npx playwright install --with-deps chromium
82+
83+
- name: Make example scripts executable
84+
run: chmod +x example/bin/dev example/bin/prod example/bin/test-ci
85+
86+
- name: Run example smoke and Playwright suite
87+
working-directory: example
88+
run: ./bin/test-ci
89+
90+
build:
91+
needs:
92+
- unit
93+
- example-e2e
94+
runs-on: ubuntu-latest
95+
outputs:
96+
version: ${{ steps.version.outputs.version }}
97+
98+
steps:
99+
- uses: actions/checkout@v4
100+
with:
101+
persist-credentials: false
102+
103+
- uses: actions/setup-python@v5
104+
with:
105+
python-version: "3.13"
106+
107+
- id: version
108+
name: Read package version
109+
shell: bash
110+
run: |
111+
version="$(
112+
python - <<'PY'
113+
from pathlib import Path
114+
import re
115+
116+
text = Path("src/react_on_django/__about__.py").read_text()
117+
match = re.search(r'^__version__ = "([^"]+)"$', text, re.M)
118+
if not match:
119+
raise SystemExit("Could not find __version__ in src/react_on_django/__about__.py")
120+
print(match.group(1))
121+
PY
122+
)"
123+
echo "version=$version" >> "$GITHUB_OUTPUT"
124+
125+
- name: Validate release version
126+
shell: bash
127+
env:
128+
PACKAGE_VERSION: ${{ steps.version.outputs.version }}
129+
INPUT_VERSION: ${{ inputs.version }}
130+
run: |
131+
expected_tag="v${PACKAGE_VERSION}"
132+
133+
if [[ "${GITHUB_EVENT_NAME}" == "push" && "${GITHUB_REF_NAME}" != "${expected_tag}" ]]; then
134+
echo "Tag ${GITHUB_REF_NAME} does not match package version ${PACKAGE_VERSION}."
135+
exit 1
136+
fi
137+
138+
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" && -n "${INPUT_VERSION}" && "${INPUT_VERSION}" != "${PACKAGE_VERSION}" ]]; then
139+
echo "Requested version ${INPUT_VERSION} does not match package version ${PACKAGE_VERSION}."
140+
exit 1
141+
fi
142+
143+
- name: Install build tooling
144+
run: |
145+
python -m pip install --upgrade pip
146+
python -m pip install build twine
147+
148+
- name: Build distributions
149+
run: python -m build
150+
151+
- name: Check distribution metadata
152+
run: twine check dist/*
153+
154+
- name: Store distributions
155+
uses: actions/upload-artifact@v4
156+
with:
157+
name: python-package-distributions
158+
path: dist/
159+
160+
publish-testpypi:
161+
if: inputs.repository == 'testpypi'
162+
needs: build
163+
runs-on: ubuntu-latest
164+
environment:
165+
name: testpypi
166+
url: https://test.pypi.org/p/react-on-django
167+
permissions:
168+
id-token: write
169+
170+
steps:
171+
- name: Download distributions
172+
uses: actions/download-artifact@v4
173+
with:
174+
name: python-package-distributions
175+
path: dist/
176+
177+
- name: Publish to TestPyPI
178+
uses: pypa/gh-action-pypi-publish@release/v1
179+
with:
180+
repository-url: https://test.pypi.org/legacy/
181+
182+
publish-pypi:
183+
if: inputs.repository == 'pypi'
184+
needs: build
185+
runs-on: ubuntu-latest
186+
environment:
187+
name: pypi
188+
url: https://pypi.org/p/react-on-django
189+
permissions:
190+
id-token: write
191+
192+
steps:
193+
- name: Download distributions
194+
uses: actions/download-artifact@v4
195+
with:
196+
name: python-package-distributions
197+
path: dist/
198+
199+
- name: Publish to PyPI
200+
uses: pypa/gh-action-pypi-publish@release/v1

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
# Changelog
22

3+
All notable changes to this project should be documented in this file.
4+
5+
## [Unreleased]

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.PHONY: release release-dry-run
2+
3+
PYTHON ?= python
4+
5+
release:
6+
$(PYTHON) scripts/release.py $(if $(VERSION),--version $(VERSION),) $(if $(REPOSITORY),--repository $(REPOSITORY),) $(if $(YES),--yes,) $(if $(SKIP_CHECKS),--skip-checks,) $(if $(SKIP_PUSH),--skip-push,)
7+
8+
release-dry-run:
9+
$(PYTHON) scripts/release.py --dry-run $(if $(VERSION),--version $(VERSION),) $(if $(REPOSITORY),--repository $(REPOSITORY),) $(if $(YES),--yes,) $(if $(SKIP_CHECKS),--skip-checks,)

0 commit comments

Comments
 (0)