-
Notifications
You must be signed in to change notification settings - Fork 0
313 lines (276 loc) · 11.2 KB
/
release.yml
File metadata and controls
313 lines (276 loc) · 11.2 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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
name: Release
run-name: Release ${{ github.ref_name }}
on:
# Trigger when pushing to release branches
push:
branches:
- 'release/**'
# Allow manual triggering
workflow_dispatch:
permissions:
contents: write
pull-requests: write
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# 1. Determine version first before any other jobs
version:
name: Determine Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.set-version.outputs.version }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Determine Version
id: semver
uses: PaulHatch/semantic-version@v6.0.1
with:
tag_prefix: "v"
major_pattern: "BREAKING CHANGE:"
minor_pattern: "feat:"
version_format: "${major}.${minor}.${patch}"
search_commit_body: true
debug: true
- name: Set VERSION output
id: set-version
run: |
VERSION="${{ steps.semver.outputs.version }}"
echo "Calculated semantic version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
# 2. Run tests and linting as a quality gate.
test:
name: Test & Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Format check
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Run tests
run: cargo test --all --locked
# 3. Build all required binaries with the correct version.
# This job runs only after tests have passed and version is determined.
build:
name: Build Binaries
needs: [version, test]
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
asset_name_suffix: linux-x86_64
- os: macos-latest
target: x86_64-apple-darwin
asset_name_suffix: macos-x86_64
- os: macos-latest
target: aarch64-apple-darwin
asset_name_suffix: macos-arm64
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Update Cargo.toml version before build
run: |
VERSION="${{ needs.version.outputs.version }}"
echo "Building with version: $VERSION"
# Update version in main Cargo.toml
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "s/^version = \".*\"/version = \"$VERSION\"/" Cargo.toml
else
sed -i "s/^version = \".*\"/version = \"$VERSION\"/" Cargo.toml
fi
- name: Build main binary and plugins
run: cargo build --release --target ${{ matrix.target }} --workspace
- name: Strip binaries for size
run: |
if [[ "${{ runner.os }}" == "Linux" ]]; then
strip target/${{ matrix.target }}/release/repos
strip target/${{ matrix.target }}/release/repos-health
strip target/${{ matrix.target }}/release/repos-review
strip target/${{ matrix.target }}/release/repos-fix
else
strip -x target/${{ matrix.target }}/release/repos
strip -x target/${{ matrix.target }}/release/repos-health
strip -x target/${{ matrix.target }}/release/repos-review
strip -x target/${{ matrix.target }}/release/repos-fix
fi
- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
name: build-artifacts-${{ matrix.asset_name_suffix }}
path: |
target/${{ matrix.target }}/release/repos
target/${{ matrix.target }}/release/repos-health
target/${{ matrix.target }}/release/repos-validate
target/${{ matrix.target }}/release/repos-review
target/${{ matrix.target }}/release/repos-fix
# 4. Create the universal macOS binary from the previously built artifacts.
# This job is very fast as it does not re-compile anything.
package-universal:
name: Package Universal macOS
needs: [version, build]
runs-on: macos-latest
steps:
- name: Download macOS arm64 artifacts
uses: actions/download-artifact@v7
with:
name: build-artifacts-macos-arm64
path: arm64
- name: Download macOS x86_64 artifacts
uses: actions/download-artifact@v7
with:
name: build-artifacts-macos-x86_64
path: x86_64
- name: Create universal binaries
run: |
lipo -create -output repos arm64/repos x86_64/repos
lipo -create -output repos-health arm64/repos-health x86_64/repos-health
lipo -create -output repos-validate arm64/repos-validate x86_64/repos-validate
lipo -create -output repos-review arm64/repos-review x86_64/repos-review
lipo -create -output repos-fix arm64/repos-fix x86_64/repos-fix
strip -x repos repos-health repos-validate repos-review repos-fix
- name: Upload universal artifact
uses: actions/upload-artifact@v6
with:
name: build-artifacts-macos-universal
path: |
repos
repos-health
repos-validate
repos-review
repos-fix
# 5. Create the GitHub Release and upload all artifacts.
# This is the final publishing step.
publish:
name: Publish Release
needs: [version, build, package-universal]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set VERSION from version job
run: |
VERSION="${{ needs.version.outputs.version }}"
echo "Publishing version: $VERSION"
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Download all build artifacts
uses: actions/download-artifact@v7
with:
path: dist
- name: Package artifacts for release
id: package
run: |
VERSION=${{ env.VERSION }}
# Package platform-specific artifacts (excludes universal which is handled separately)
for dir in dist/build-artifacts-linux-* dist/build-artifacts-macos-x86_64 dist/build-artifacts-macos-arm64; do
if [ -d "$dir" ]; then
suffix=$(basename "$dir" | sed 's/build-artifacts-//')
tar -czf "repos-${VERSION}-${suffix}.tar.gz" -C "$dir" repos
tar -czf "repos-health-${VERSION}-${suffix}.tar.gz" -C "$dir" repos-health
tar -czf "repos-validate-${VERSION}-${suffix}.tar.gz" -C "$dir" repos-validate
tar -czf "repos-review-${VERSION}-${suffix}.tar.gz" -C "$dir" repos-review
tar -czf "repos-fix-${VERSION}-${suffix}.tar.gz" -C "$dir" repos-fix
fi
done
# Package universal macOS artifacts separately
if [ -d "dist/build-artifacts-macos-universal" ]; then
tar -czf "repos-${VERSION}-macos-universal.tar.gz" -C "dist/build-artifacts-macos-universal" repos
tar -czf "repos-health-${VERSION}-macos-universal.tar.gz" -C "dist/build-artifacts-macos-universal" repos-health
tar -czf "repos-validate-${VERSION}-macos-universal.tar.gz" -C "dist/build-artifacts-macos-universal" repos-validate
tar -czf "repos-review-${VERSION}-macos-universal.tar.gz" -C "dist/build-artifacts-macos-universal" repos-review
tar -czf "repos-fix-${VERSION}-macos-universal.tar.gz" -C "dist/build-artifacts-macos-universal" repos-fix
fi
# List final assets
ls -lh *.tar.gz
# Create space-separated list of all archives for upload
ASSETS=$(ls *.tar.gz | tr '\n' ' ')
echo "ASSETS<<EOF" >> $GITHUB_ENV
echo "$ASSETS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Create GitHub Release and Upload Assets
uses: softprops/action-gh-release@v2
with:
token: ${{ secrets.PAT_TOKEN }}
tag_name: v${{ env.VERSION }}
name: Release v${{ env.VERSION }}
generate_release_notes: true
draft: true
files: |
*.tar.gz
# 6. After a successful release, create a PR to bump version in main
sync-main:
name: Sync Back to Main
needs: [version, publish]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.PAT_TOKEN }} # Use PAT for creating PR
- name: Configure Git
run: |
git config user.name "GitHub Action"
git config user.email "action@github.com"
- name: Create version bump branch from main
id: versioning
run: |
RELEASE_VERSION=${{ needs.version.outputs.version }}
# Calculate next version (e.g., 0.2.1 -> 0.3.0-rc)
MAJOR=$(echo "$RELEASE_VERSION" | cut -d. -f1)
MINOR=$(echo "$RELEASE_VERSION" | cut -d. -f2)
NEXT_MINOR=$((MINOR + 1))
NEXT_VERSION="${MAJOR}.${NEXT_MINOR}.0-rc"
echo "NEXT_VERSION=${NEXT_VERSION}" >> $GITHUB_ENV
BUMP_BRANCH="chore/version-bump-${NEXT_VERSION}"
echo "BUMP_BRANCH=${BUMP_BRANCH}" >> $GITHUB_ENV
# Create the new branch from the main branch
git fetch origin main
git checkout -b "$BUMP_BRANCH" origin/main
- name: Update Cargo.toml and push branch
run: |
# Update version in Cargo.toml
sed -i "s/^version = \".*\"/version = \"${{ env.NEXT_VERSION }}\"/" Cargo.toml
# Commit changes
git add Cargo.toml
if git diff --cached --quiet; then
echo "No changes to commit"
else
git commit -m "chore: bump version to ${{ env.NEXT_VERSION }}"
fi
# Delete remote branch if exists, then force push
git push origin --delete "${{ env.BUMP_BRANCH }}" 2>/dev/null || true
git push origin "${{ env.BUMP_BRANCH }}"
- name: Create Pull Request
env:
GH_TOKEN: ${{ secrets.PAT_TOKEN }}
run: |
# Check if there are commits to PR
git fetch origin main
COMMITS_AHEAD=$(git rev-list --count origin/main.."${{ env.BUMP_BRANCH }}")
if [ "$COMMITS_AHEAD" -eq "0" ]; then
echo "No commits to create PR for - branch is up to date with main"
exit 0
fi
# Check if PR already exists
EXISTING_PR=$(gh pr list --head "${{ env.BUMP_BRANCH }}" --base main --json number --jq '.[0].number' 2>/dev/null || echo "")
if [ -n "$EXISTING_PR" ]; then
echo "PR #$EXISTING_PR already exists, skipping creation"
else
gh pr create \
--base main \
--head "${{ env.BUMP_BRANCH }}" \
--title "chore: Post-release version bump to ${{ env.NEXT_VERSION }}" \
--body "This PR merges the changes from release \`${{ github.ref_name }}\` back into main and prepares for the next development cycle by bumping the version to \`${{ env.NEXT_VERSION }}\`."
fi