-
Notifications
You must be signed in to change notification settings - Fork 16
185 lines (167 loc) · 6.62 KB
/
release.yml
File metadata and controls
185 lines (167 loc) · 6.62 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
name: Release
on:
workflow_dispatch:
inputs:
bump:
description: "Version bump type"
required: true
type: choice
options:
- patch
- minor
- major
permissions:
contents: write
id-token: write
jobs:
release:
name: Release
runs-on: depot-ubuntu-latest
timeout-minutes: 20
environment: pypi
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
python-version: "3.13"
prune-cache: false
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.10.0
- name: Setup Node.js with pnpm cache
uses: actions/setup-node@v6
with:
cache: 'pnpm'
cache-dependency-path: 'packages/pnpm-lock.yaml'
- name: Install pnpm dependencies
working-directory: packages
run: pnpm install --frozen-lockfile
- name: Install Python dependencies
run: uv sync --all-extras --dev --group release
- name: Determine versions
id: versions
env:
GH_TOKEN: ${{ github.token }}
run: |
# Derive current version from the latest semver git tag so this
# stays correct even when the pyproject.toml version-bump commit
# hasn't been merged to main yet (e.g. partial previous run).
# `|| true` prevents pipefail exit when no tags match the pattern.
LATEST_TAG=$(git tag --sort=-creatordate | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true)
if [ -z "$LATEST_TAG" ]; then
CURRENT="0.0.0"
echo "No semver tags found; starting from $CURRENT"
else
# If the latest tag has no GitHub release, a prior run failed
# after tagging. Retry that version instead of bumping again.
if ! gh release view "$LATEST_TAG" &>/dev/null; then
PREV_TAG=$(git tag --sort=-creatordate | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sed -n '2p' || true)
echo "::warning::Tag $LATEST_TAG exists without a release — retrying incomplete release."
{
echo "new=$LATEST_TAG"
echo "prev_tag=${PREV_TAG:-$LATEST_TAG}"
echo "retry=true"
} >> "$GITHUB_OUTPUT"
exit 0
fi
CURRENT="$LATEST_TAG"
fi
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
case "${{ inputs.bump }}" in
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
patch) PATCH=$((PATCH + 1)) ;;
esac
NEW="${MAJOR}.${MINOR}.${PATCH}"
# Guard: abort if this tag already exists with a completed release
if git tag -l "$NEW" | grep -q "^${NEW}$"; then
echo "::error::Tag $NEW already exists — this release may have already run. Aborting."
exit 1
fi
{
echo "new=$NEW"
echo "prev_tag=$CURRENT"
echo "retry=false"
} >> "$GITHUB_OUTPUT"
echo "Bumping $CURRENT → $NEW (${{ inputs.bump }})"
- name: Generate release notes
env:
GH_TOKEN: ${{ github.token }}
run: |
uv run python scripts/generate_release_notes.py \
--tag-from "${{ steps.versions.outputs.prev_tag }}" \
--version "${{ steps.versions.outputs.new }}" \
--date "$(date +%Y-%m-%d)" \
--output-dir /tmp
- name: Tag and push
run: |
if [ "${{ steps.versions.outputs.retry }}" = "true" ]; then
echo "Retry mode — tag ${{ steps.versions.outputs.new }} already exists, checking out tagged commit."
git checkout "${{ steps.versions.outputs.new }}"
else
git tag "${{ steps.versions.outputs.new }}"
git push origin "${{ steps.versions.outputs.new }}"
fi
# Pin hatch-vcs to the exact release version for the build step
echo "SETUPTOOLS_SCM_PRETEND_VERSION=${{ steps.versions.outputs.new }}" >> "$GITHUB_ENV"
- name: Build wheel + sdist
run: |
./scripts/full_build.sh
uv build --sdist
- name: Capture release screenshots
run: |
cd packages/buckaroo-js-core
npx playwright install chromium
npx playwright test pw-tests/theme-screenshots.spec.ts --reporter=line || true
VERSION="${{ steps.versions.outputs.new }}"
mkdir -p /tmp/screenshots-staging/"$VERSION"
for f in screenshots/*.png; do
[ -f "$f" ] || continue
base=$(basename "$f" .png)
cp "$f" /tmp/screenshots-staging/"$VERSION"/"${base}--${VERSION}.png"
done
- name: Publish screenshots to GitHub Pages
run: |
VERSION="${{ steps.versions.outputs.new }}"
git fetch origin gh-pages
git worktree add /tmp/gh-pages gh-pages
mkdir -p /tmp/gh-pages/screenshots/"$VERSION"
cp /tmp/screenshots-staging/"$VERSION"/*.png /tmp/gh-pages/screenshots/"$VERSION"/
python scripts/generate_screenshots_index.py /tmp/gh-pages/screenshots
cd /tmp/gh-pages
git add screenshots/
git diff --cached --quiet && echo "No screenshot changes" && exit 0
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit -m "screenshots: add release $VERSION screenshots"
git push origin gh-pages
- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "${{ steps.versions.outputs.new }}" \
--title "${{ steps.versions.outputs.new }}" \
--notes-file /tmp/release_notes.md
- name: Upload release assets
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release upload "${{ steps.versions.outputs.new }}" dist/*.whl dist/*.tar.gz
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
- name: Upload changelog entry artifact
# Download this artifact and apply it in your next dev PR:
# python scripts/update_changelog.py changelog_entry.md
# sed -i 's/^version = ".*"/version = "NEW"/' pyproject.toml
# uv lock
uses: actions/upload-artifact@v4
with:
name: changelog-${{ steps.versions.outputs.new }}
path: /tmp/changelog_entry.md
if-no-files-found: ignore