-
Notifications
You must be signed in to change notification settings - Fork 1.3k
247 lines (209 loc) · 9.36 KB
/
post-release.yml
File metadata and controls
247 lines (209 loc) · 9.36 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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# =============================================================================
# Post-Release Automation
# =============================================================================
#
# Triggered after the pypi.yml workflow succeeds for a release event. Automates:
# A) Tagging main with the next dev tag (e.g., v0.5.1-dev after v0.5.0)
# B) Bumping fallback_version on main via PR (main is a protected branch)
# C) Updating npm lockfile on the release branch via PR
#
# =============================================================================
name: Post-release automation
on:
workflow_run:
workflows: ["Build, test, and publish packages"]
types:
- completed
workflow_dispatch:
inputs:
tag:
description: 'Release tag (e.g., v0.6.0). Use to re-run post-release steps after a failure.'
required: true
type: string
permissions:
contents: write
pull-requests: write
jobs:
post-release:
name: Post-release housekeeping
# Only run when:
# - workflow_dispatch (manual testing), OR
# - the pypi.yml workflow completed successfully AND was triggered by a release
if: |
github.event_name == 'workflow_dispatch' || (
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'release'
)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
token: ${{ secrets.RELEASE_PAT }}
- name: Parse release version
id: parse
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
TAG="${{ inputs.tag }}"
else
# The triggering workflow was a release event — find the tag from the
# commit SHA that the workflow ran on, or fall back to the latest release.
HEAD_SHA="${{ github.event.workflow_run.head_sha }}"
TAG=$(git tag --points-at "$HEAD_SHA" 2>/dev/null | grep '^v' | head -1)
if [ -z "$TAG" ]; then
# Fallback: query the latest published release via GitHub API
TAG=$(gh api repos/${{ github.repository }}/releases/latest --jq '.tag_name')
fi
if [ -z "$TAG" ]; then
echo "::error::Could not determine release tag"
exit 1
fi
fi
# Strip 'v' prefix
VERSION="${TAG#v}"
# Split into components
MAJOR="${VERSION%%.*}"
REST="${VERSION#*.}"
MINOR="${REST%%.*}"
PATCH="${REST#*.}"
# Strip any pre-release suffix from patch (e.g., rc1)
PATCH="${PATCH%%[a-zA-Z-]*}"
NEXT_PATCH=$((PATCH + 1))
NEXT_DEV_TAG="v${MAJOR}.${MINOR}.${NEXT_PATCH}-dev"
NEXT_FALLBACK="${MAJOR}.${MINOR}.${NEXT_PATCH}.dev0"
RELEASE_BRANCH="release-${MAJOR}.${MINOR}.x"
{
echo "version=${VERSION}"
echo "major=${MAJOR}"
echo "minor=${MINOR}"
echo "patch=${PATCH}"
echo "next_patch=${NEXT_PATCH}"
echo "next_dev_tag=${NEXT_DEV_TAG}"
echo "next_fallback=${NEXT_FALLBACK}"
echo "release_branch=${RELEASE_BRANCH}"
} >> "$GITHUB_OUTPUT"
echo "Release version: ${VERSION}"
echo "Next dev tag: ${NEXT_DEV_TAG}"
echo "Next fallback: ${NEXT_FALLBACK}"
echo "Release branch: ${RELEASE_BRANCH}"
# -----------------------------------------------------------------------
# Step A: Tag main with the next dev tag
# -----------------------------------------------------------------------
- name: Push dev tag to main
run: |
DEV_TAG="${{ steps.parse.outputs.next_dev_tag }}"
# Check if tag already exists
if git rev-parse "$DEV_TAG" >/dev/null 2>&1; then
echo "Tag $DEV_TAG already exists, skipping"
exit 0
fi
# Tag the HEAD of main
MAIN_SHA=$(git rev-parse origin/main)
git tag "$DEV_TAG" "$MAIN_SHA"
git push origin "$DEV_TAG"
echo "Pushed tag $DEV_TAG to main ($MAIN_SHA)"
- name: Set up uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
# -----------------------------------------------------------------------
# Step B: Bump fallback_version on main and open PR
# -----------------------------------------------------------------------
- name: Create fallback_version bump PR
env:
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
run: |
NEXT_FALLBACK="${{ steps.parse.outputs.next_fallback }}"
VERSION="${{ steps.parse.outputs.version }}"
BRANCH="post-release/bump-fallback-${VERSION}"
# Check if PR already exists
EXISTING=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number')
if [ -n "$EXISTING" ]; then
echo "PR #${EXISTING} already exists for $BRANCH, skipping"
exit 0
fi
git checkout -b "$BRANCH" origin/main
# Update fallback_version in root pyproject.toml
sed -i "s/^fallback_version = .*/fallback_version = \"${NEXT_FALLBACK}\"/" pyproject.toml
# Update fallback_version in src/llama_stack_api/pyproject.toml
sed -i "s/^fallback_version = .*/fallback_version = \"${NEXT_FALLBACK}\"/" src/llama_stack_api/pyproject.toml
# Bump llama-stack-client minimum version to match the release
sed -i "s/\"llama-stack-client>=.*\"/\"llama-stack-client>=${VERSION}\"/" pyproject.toml
# Regenerate lockfile to resolve the updated client version
uv lock
# Check if there are changes
if git diff --quiet; then
echo "No changes to fallback_version, skipping PR"
exit 0
fi
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git add pyproject.toml src/llama_stack_api/pyproject.toml uv.lock
git commit -s -m "chore: bump fallback_version to ${NEXT_FALLBACK} after ${VERSION} release"
git push origin "$BRANCH"
gh pr create \
--base main \
--head "$BRANCH" \
--title "chore: bump fallback_version to ${NEXT_FALLBACK}" \
--body "$(cat <<EOF
Automated post-release version bump after v${VERSION}.
Updates fallback_version in both pyproject.toml files to ${NEXT_FALLBACK}.
This PR was created automatically by the post-release workflow.
EOF
)"
echo "Created PR for fallback_version bump to ${NEXT_FALLBACK}"
# -----------------------------------------------------------------------
# Step C: Update npm lockfile on release branch via PR
# -----------------------------------------------------------------------
- name: Set up Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Create npm lockfile update PR for release branch
env:
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
run: |
VERSION="${{ steps.parse.outputs.version }}"
RELEASE_BRANCH="${{ steps.parse.outputs.release_branch }}"
BRANCH="post-release/npm-lockfile-${VERSION}"
# Check if release branch exists
if ! git rev-parse "origin/${RELEASE_BRANCH}" >/dev/null 2>&1; then
echo "Release branch ${RELEASE_BRANCH} does not exist, skipping npm update"
exit 0
fi
# Check if PR already exists
EXISTING=$(gh pr list --head "$BRANCH" --state open --json number --jq '.[0].number')
if [ -n "$EXISTING" ]; then
echo "PR #${EXISTING} already exists for $BRANCH, skipping"
exit 0
fi
git checkout -b "$BRANCH" "origin/${RELEASE_BRANCH}"
# Regenerate uv lockfile so pre-commit passes
uv lock
# Update npm lockfile
cd src/llama_stack_ui
npm install "llama-stack-client@^${VERSION}"
cd ../..
# Check if there are changes
if git diff --quiet; then
echo "No npm lockfile changes, skipping PR"
exit 0
fi
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git add uv.lock src/llama_stack_ui/package.json src/llama_stack_ui/package-lock.json
git commit -s -m "chore: update llama-stack-client to ^${VERSION} in UI lockfile"
git push origin "$BRANCH"
gh pr create \
--base "$RELEASE_BRANCH" \
--head "$BRANCH" \
--title "chore: update llama-stack-client to ^${VERSION} in UI lockfile" \
--body "$(cat <<EOF
Automated post-release npm lockfile update after v${VERSION}.
Updates llama-stack-client to ^${VERSION} in the UI package lockfile.
This PR was created automatically by the post-release workflow.
EOF
)"
echo "Created PR for npm lockfile update on ${RELEASE_BRANCH}"