Skip to content

Commit fb5832e

Browse files
silv-ioclaude
andauthored
Cut patch releases automatically for dependency updates (#50)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 9636e6d commit fb5832e

1 file changed

Lines changed: 83 additions & 0 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Cuts a patch release when dependency updates have changed the shipped
2+
# dist/ since the last release, so users of the floating major tag (e.g. v4)
3+
# pick up fixes in bundled dependencies without someone releasing by hand.
4+
#
5+
# If src/ or action.yml changed since the last release, nothing is released:
6+
# those changes may need a minor or major version, so release them with
7+
# script/release instead.
8+
name: Patch Release
9+
10+
on:
11+
schedule:
12+
- cron: '0 6 * * 1'
13+
workflow_dispatch:
14+
15+
permissions: {}
16+
17+
concurrency:
18+
group: release
19+
cancel-in-progress: false
20+
21+
jobs:
22+
release:
23+
name: Patch Release
24+
if: github.ref == 'refs/heads/main'
25+
runs-on: ubuntu-latest
26+
permissions:
27+
contents: write
28+
checks: read
29+
30+
steps:
31+
- name: Checkout
32+
id: checkout
33+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
34+
with:
35+
fetch-depth: 0
36+
fetch-tags: true
37+
# needed to push tags below; this job runs no dependency code
38+
persist-credentials: true # zizmor: ignore[artipacked]
39+
40+
- name: Check for Releasable Changes
41+
id: check
42+
env:
43+
GH_TOKEN: ${{ github.token }}
44+
run: |
45+
latest=$(git tag --list 'v*.*.*' --sort=-v:refname | head -n 1)
46+
echo "Latest release: $latest"
47+
48+
if git diff --quiet "$latest" HEAD -- dist/; then
49+
echo "dist/ is unchanged since $latest, nothing to release"
50+
exit 0
51+
fi
52+
53+
if [ -n "$(git log --format=%H "$latest"..HEAD -- src/ action.yml)" ]; then
54+
echo "::notice::src/ or action.yml changed since $latest, release manually with script/release"
55+
exit 0
56+
fi
57+
58+
failed=$(gh api "repos/$GITHUB_REPOSITORY/commits/$GITHUB_SHA/check-runs" --paginate \
59+
--jq '.check_runs[] | select(.name != "Patch Release") | select(.status != "completed" or (.conclusion | IN("success", "skipped", "neutral") | not)) | .name')
60+
if [ -n "$failed" ]; then
61+
echo "::error::Checks on main are not green, not releasing: $(echo "$failed" | paste -sd, -)"
62+
exit 1
63+
fi
64+
65+
IFS=. read -r major minor patch <<< "${latest#v}"
66+
echo "tag=v$major.$minor.$((patch + 1))" >> "$GITHUB_OUTPUT"
67+
echo "major=v$major" >> "$GITHUB_OUTPUT"
68+
69+
- name: Tag and Release
70+
id: release
71+
if: steps.check.outputs.tag != ''
72+
env:
73+
GH_TOKEN: ${{ github.token }}
74+
TAG: ${{ steps.check.outputs.tag }}
75+
MAJOR: ${{ steps.check.outputs.major }}
76+
run: |
77+
git config user.name 'github-actions[bot]'
78+
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
79+
git tag -a "$TAG" -m "$TAG Release"
80+
git tag -fa "$MAJOR" -m "$TAG"
81+
git push origin "refs/tags/$TAG"
82+
git push --force origin "refs/tags/$MAJOR"
83+
gh release create "$TAG" --verify-tag --generate-notes --latest

0 commit comments

Comments
 (0)