-
Notifications
You must be signed in to change notification settings - Fork 1
130 lines (116 loc) · 5.07 KB
/
Copy pathrelease.yml
File metadata and controls
130 lines (116 loc) · 5.07 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
name: Release
on:
repository_dispatch:
types: [openapi-updated]
schedule:
- cron: '0 6 * * *'
workflow_dispatch:
inputs:
version_bump:
description: 'patch | minor | major'
required: false
default: 'patch'
jobs:
release:
runs-on: ubuntu-latest
environment: pypi
permissions:
contents: write
id-token: write
actions: write
steps:
- uses: actions/checkout@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
- uses: astral-sh/setup-uv@v7
with:
python-version: '3.12'
enable-cache: true
- name: Install deps
run: uv sync --all-extras --dev
- name: Regenerate SDK from live spec
run: uv run python generate.py
- name: Check if spec changed
id: diff
run: |
if git diff --quiet specs/openapi.json src/roxy_sdk/factory.py; then
echo "changed=false" >> $GITHUB_OUTPUT
else
echo "changed=true" >> $GITHUB_OUTPUT
fi
- name: Lint
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
run: uv run ruff check .
- name: Typecheck
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
run: uv run mypy src/roxy_sdk/__init__.py
- name: Test
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
run: uv run pytest tests/test_factory.py -v
- name: Bump version in pyproject.toml and version.py
id: bump
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
run: |
python3 - <<'PY'
import re
bump = "${{ github.event.inputs.version_bump || 'patch' }}"
pp = open("pyproject.toml").read()
ver = re.search(r'^version = "(.+?)"', pp, re.M).group(1)
parts = [int(x) for x in ver.split(".")]
if bump == "major": parts = [parts[0] + 1, 0, 0]
elif bump == "minor": parts = [parts[0], parts[1] + 1, 0]
else: parts = [parts[0], parts[1], parts[2] + 1]
new_ver = ".".join(str(x) for x in parts)
open("pyproject.toml", "w").write(
re.sub(r'^version = ".+?"', f'version = "{new_ver}"', pp, count=1, flags=re.M)
)
open("src/roxy_sdk/version.py", "w").write(f'VERSION = "{new_ver}"\n')
open("/tmp/new_version.txt", "w").write(new_ver)
print(f"Bumped {ver} -> {new_ver} ({bump})")
PY
echo "version=$(cat /tmp/new_version.txt)" >> $GITHUB_OUTPUT
- name: Build
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
run: uv build
- name: Publish to PyPI
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
uses: pypa/gh-action-pypi-publish@release/v1
with:
# a crashed run can publish and then fail before the git push lands, leaving the registry ahead of the repo; skip-existing makes the rerun converge instead of dying on the duplicate upload
skip-existing: true
- name: Commit, tag, push
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
VERSION=$(cat /tmp/new_version.txt)
uv lock
git add pyproject.toml uv.lock src/roxy_sdk/version.py specs/openapi.json src/roxy_sdk/factory.py
git commit -m "release: v$VERSION"
git tag "v$VERSION"
# Protected main requires the ci-ok context green on every pushed SHA, and a direct push can never carry one. So park the commit on a temp branch, run the real CI there via workflow_dispatch (GITHUB_TOKEN pushes trigger no workflows on their own), and push to main only after it reports green.
SHA=$(git rev-parse HEAD)
git push --force origin "HEAD:refs/heads/release-checks"
gh workflow run ci.yml --ref release-checks
RUN_ID=""
for _ in $(seq 1 24); do
sleep 5
RUN_ID=$(gh run list --workflow=ci.yml --branch=release-checks --limit 5 --json databaseId,headSha --jq "[.[] | select(.headSha == \"$SHA\")][0].databaseId // empty")
[ -n "$RUN_ID" ] && break
done
[ -n "$RUN_ID" ] || { echo "dispatched CI run never appeared for $SHA"; exit 1; }
gh run watch "$RUN_ID" --exit-status
git push --follow-tags
git push origin --delete release-checks || true
- name: Create GitHub release
if: steps.diff.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
uses: softprops/action-gh-release@v3
with:
tag_name: v${{ steps.bump.outputs.version }}
generate_release_notes: true
make_latest: 'true'
files: |
dist/*.whl
dist/*.tar.gz