Repository navigation
140 lines (140 loc) · 5.16 KB
/
Copy pathprepare-release.yaml
File metadata and controls
140 lines (140 loc) · 5.16 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
name: 🛠️ Prepare release
on:
workflow_dispatch:
inputs:
bump:
description: Version bump type
required: true
type: choice
options: [auto, major, minor, patch]
default: auto
permissions:
contents: read
env:
FORCE_COLOR: "1"
jobs:
assemble:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # The next version comes from the tags.
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
python-version: "3.15"
enable-cache: false
- name: Require a news fragment
run: |
if ! compgen -G 'docs/changelog/*.*.rst' > /dev/null; then
echo '::error::add a docs/changelog/*.rst fragment before preparing a release'
exit 1
fi
for fragment in docs/changelog/*.rst; do
if [[ ! "$fragment" =~ ^docs/changelog/[0-9]+\.(breaking|feature|bugfix|doc|packaging)(\.[0-9]+)?\.rst$ ]]; then
echo "::error::unsupported news fragment: $fragment"
exit 1
fi
done
- name: Set up remote tracking
run: |
git remote -v
git fetch origin
git branch -a
- name: 🔢 Calculate next version
id: version
env:
BUMP: ${{ inputs.bump }}
run: |
current=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")
IFS='.' read -r major minor patch <<< "$current"
bump_type="$BUMP"
if [ "$bump_type" = "auto" ]; then
if [ "$(find docs/changelog -name '*.feature.rst' 2>/dev/null | wc -l)" -gt 0 ]; then
bump_type="minor"
else
bump_type="patch"
fi
fi
case "$bump_type" in
major) next="$((major + 1)).0.0" ;;
minor) next="$major.$((minor + 1)).0" ;;
patch) next="$major.$minor.$((patch + 1))" ;;
esac
echo "Next version: $next"
echo "version=$next" >> "$GITHUB_OUTPUT"
- name: Build release patch
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
uvx towncrier build --yes --version "$VERSION"
uvx prek run --files docs/changelog.rst ||
uvx prek run --files docs/changelog.rst
git diff HEAD --binary > "$RUNNER_TEMP/release.patch"
test -s "$RUNNER_TEMP/release.patch"
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-patch
path: ${{ runner.temp }}/release.patch
if-no-files-found: error
push:
needs: assemble
runs-on: ubuntu-24.04
environment: release-auth
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-patch
path: ${{ runner.temp }}/release-patch
- name: Validate release patch
env:
VERSION: ${{ needs.assemble.outputs.version }}
run: |
set -euo pipefail
git fetch origin main
git reset --hard origin/main
git apply --check "$RUNNER_TEMP/release-patch/release.patch"
git apply --index "$RUNNER_TEMP/release-patch/release.patch"
while IFS= read -r path; do
case "$path" in
docs/changelog.rst|docs/changelog/*.rst) ;;
*) echo "::error::unexpected release path: $path"; exit 1 ;;
esac
done < <(git diff --cached --name-only)
grep -qE "^ v${VERSION//./\\.} \(" docs/changelog.rst
git diff --cached --check
- id: token
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
with:
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: ${{ github.event.repository.name }}
permission-contents: write
- name: Commit and tag the release
env:
VERSION: ${{ needs.assemble.outputs.version }}
GH_TOKEN: ${{ steps.token.outputs.token }}
APP_SLUG: ${{ steps.token.outputs.app-slug }}
run: |
set -euo pipefail
app_user_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)
git config user.name "${APP_SLUG}[bot]"
git config user.email "${app_user_id}+${APP_SLUG}[bot]@users.noreply.github.com"
git commit -m "release $VERSION"
git tag -a "$VERSION" -m "release $VERSION"
gh auth setup-git --hostname github.com --force
git push --atomic origin HEAD:main "refs/tags/$VERSION"