Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 200 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
name: Release

on:
workflow_dispatch:
inputs:
repository:
description: Package index to publish to
required: true
default: testpypi
type: choice
options:
- testpypi
- pypi
version:
description: Optional version to validate against package metadata (for example 0.1.0a1)
required: false
type: string

permissions:
contents: read

jobs:
unit:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.13"]
django-version: ["4.2.*", "5.1.*"]

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install "Django==${{ matrix.django-version }}" -e .[dev]

- name: Ruff
run: ruff check .

- name: Pytest
run: pytest

example-e2e:
runs-on: ubuntu-latest
timeout-minutes: 20

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- uses: actions/setup-python@v5
with:
python-version: "3.13"

- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"
cache-dependency-path: example/package-lock.json

- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -e .[dev]

- name: Install example dependencies
working-directory: example
run: npm ci

- name: Install Playwright browser
working-directory: example
run: npx playwright install --with-deps chromium

- name: Make example scripts executable
run: chmod +x example/bin/dev example/bin/prod example/bin/test-ci

- name: Run example smoke and Playwright suite
working-directory: example
run: ./bin/test-ci

build:
needs:
- unit
- example-e2e
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}

steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- uses: actions/setup-python@v5
with:
python-version: "3.13"

- id: version
name: Read package version
shell: bash
run: |
version="$(
python - <<'PY'
from pathlib import Path
import re

text = Path("src/react_on_django/__about__.py").read_text()
match = re.search(r'^__version__ = "([^"]+)"$', text, re.M)
if not match:
raise SystemExit("Could not find __version__ in src/react_on_django/__about__.py")
print(match.group(1))
PY
)"
echo "version=$version" >> "$GITHUB_OUTPUT"

- name: Validate release version
shell: bash
env:
PACKAGE_VERSION: ${{ steps.version.outputs.version }}
INPUT_VERSION: ${{ inputs.version }}
run: |
expected_tag="v${PACKAGE_VERSION}"

if [[ "${GITHUB_EVENT_NAME}" == "push" && "${GITHUB_REF_NAME}" != "${expected_tag}" ]]; then
echo "Tag ${GITHUB_REF_NAME} does not match package version ${PACKAGE_VERSION}."
exit 1
fi

if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" && -n "${INPUT_VERSION}" && "${INPUT_VERSION}" != "${PACKAGE_VERSION}" ]]; then
echo "Requested version ${INPUT_VERSION} does not match package version ${PACKAGE_VERSION}."
exit 1
fi

- name: Install build tooling
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unreachable push-trigger validation branch

The push branch of the version check can never execute because the workflow only declares a workflow_dispatch trigger — GITHUB_EVENT_NAME will always be "workflow_dispatch", never "push". The guard on lines 139–142 is dead code. Either add a push: tags: ["v*"] trigger to make it reachable, or remove the push block to avoid confusion.

run: |
python -m pip install --upgrade pip
python -m pip install build twine

- name: Build distributions
run: python -m build

- name: Check distribution metadata
run: twine check dist/*

- name: Store distributions
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish-testpypi:
if: inputs.repository == 'testpypi'
needs: build
runs-on: ubuntu-latest
environment:
name: testpypi
url: https://test.pypi.org/p/react-on-django
permissions:
id-token: write

steps:
- name: Download distributions
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/

publish-pypi:
if: inputs.repository == 'pypi'
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/react-on-django
permissions:
id-token: write

steps:
- name: Download distributions
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# Changelog

All notable changes to this project should be documented in this file.

## [Unreleased]
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.PHONY: release release-dry-run

PYTHON ?= python

release:
$(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,)

release-dry-run:
$(PYTHON) scripts/release.py --dry-run $(if $(VERSION),--version $(VERSION),) $(if $(REPOSITORY),--repository $(REPOSITORY),) $(if $(YES),--yes,) $(if $(SKIP_CHECKS),--skip-checks,)
Loading
Loading