Skip to content

Commit bcd903e

Browse files
authored
feat(release): automate OSS release pipeline with just release (#757)
1 parent af8b0b4 commit bcd903e

10 files changed

Lines changed: 598 additions & 702 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Auto-tag on Release PR Merge
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
branches: [main]
7+
8+
permissions:
9+
contents: write
10+
actions: write
11+
12+
jobs:
13+
auto-tag:
14+
if: >
15+
github.event.pull_request.merged == true &&
16+
startsWith(github.event.pull_request.head.ref, 'version-bump/')
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
20+
with:
21+
ref: ${{ github.event.pull_request.merge_commit_sha }}
22+
fetch-depth: 0
23+
24+
- name: Extract version from branch name
25+
env:
26+
BRANCH: ${{ github.event.pull_request.head.ref }}
27+
run: |
28+
VERSION="${BRANCH#version-bump/}"
29+
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
30+
echo "::error::Invalid version in branch name: '$VERSION'"
31+
exit 1
32+
fi
33+
echo "version=$VERSION" >> "$GITHUB_ENV"
34+
echo "Tagging v${VERSION}"
35+
36+
- name: Create and push tag
37+
env:
38+
VERSION: ${{ env.version }}
39+
run: |
40+
EXISTING_SHA="$(git ls-remote --tags origin "refs/tags/v$VERSION" | awk '{print $1}')"
41+
if [ -n "$EXISTING_SHA" ]; then
42+
if [ "$EXISTING_SHA" = "$GITHUB_SHA" ]; then
43+
echo "Tag v$VERSION already exists at $GITHUB_SHA — skipping tag creation"
44+
exit 0
45+
else
46+
echo "::error::Tag v$VERSION already exists at $EXISTING_SHA (expected $GITHUB_SHA)"
47+
exit 1
48+
fi
49+
fi
50+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
51+
git config user.name "github-actions[bot]"
52+
git tag "v$VERSION"
53+
git push origin "v$VERSION"
54+
55+
- name: Trigger release build
56+
env:
57+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
58+
VERSION: ${{ env.version }}
59+
run: |
60+
gh workflow run release.yml \
61+
-f version="$VERSION" \
62+
-f ref="v$VERSION"

.github/workflows/release.yml

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
name: Release
22

33
on:
4+
push:
5+
tags:
6+
- 'v[0-9]*'
47
workflow_dispatch:
58
inputs:
69
version:
7-
description: "Semver version (e.g. 0.4.0)"
10+
description: "Semver version (e.g. 0.4.0) — only for manual runs"
811
required: true
912
ref:
10-
description: "Branch, tag, or SHA to build"
13+
description: "Branch, tag, or SHA to build — only for manual runs"
1114
default: main
1215
required: true
1316

@@ -19,10 +22,25 @@ jobs:
1922
permissions:
2023
contents: write
2124
id-token: write # required by block/apple-codesign-action for OIDC
22-
env:
23-
VERSION: ${{ inputs.version }}
25+
outputs:
26+
version: ${{ steps.version.outputs.version }}
2427
steps:
28+
- name: Determine version
29+
id: version
30+
env:
31+
EVENT_NAME: ${{ github.event_name }}
32+
INPUT_VERSION: ${{ inputs.version }}
33+
run: |
34+
if [[ "$EVENT_NAME" == "push" ]]; then
35+
VERSION="${GITHUB_REF_NAME#v}"
36+
else
37+
VERSION="$INPUT_VERSION"
38+
fi
39+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
40+
2541
- name: Validate version
42+
env:
43+
VERSION: ${{ steps.version.outputs.version }}
2644
run: |
2745
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then
2846
echo "::error::Invalid version '$VERSION'. Expected semver (e.g. 0.4.0 or 1.0.0-beta.1)"
@@ -31,7 +49,7 @@ jobs:
3149
3250
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
3351
with:
34-
ref: ${{ inputs.ref }}
52+
ref: ${{ github.event_name == 'push' && github.ref || inputs.ref }}
3553
persist-credentials: false
3654

3755
- uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1
@@ -40,6 +58,8 @@ jobs:
4058
run: just desktop-install-ci
4159

4260
- name: Patch version
61+
env:
62+
VERSION: ${{ steps.version.outputs.version }}
4363
run: |
4464
cd desktop && node scripts/set-version-from-tag.mjs "$VERSION"
4565
cd src-tauri && cargo update --workspace
@@ -153,20 +173,26 @@ jobs:
153173
> latest.json
154174
cat latest.json
155175
env:
176+
VERSION: ${{ steps.version.outputs.version }}
156177
SIG_PATH: ${{ steps.artifacts.outputs.sig }}
157178
ARCHIVE_NAME: ${{ steps.artifacts.outputs.archive_name }}
158179

159180
- name: Create versioned GitHub release
181+
env:
182+
VERSION: ${{ steps.version.outputs.version }}
183+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
184+
DMG_PATH: ${{ steps.artifacts.outputs.dmg }}
160185
run: |
161186
RELEASE_SHA=$(git rev-parse HEAD)
187+
NOTES=$(awk "/^## v${VERSION}$/,/^## v/" CHANGELOG.md | head -n -1)
188+
if [[ -z "$NOTES" ]]; then
189+
NOTES="Sprout Desktop v${VERSION}"
190+
fi
162191
gh release create "v${VERSION}" \
163192
--target "$RELEASE_SHA" \
164193
--title "Sprout Desktop v${VERSION}" \
165-
--notes "Sprout Desktop v${VERSION}" \
194+
--notes "$NOTES" \
166195
"$DMG_PATH"
167-
env:
168-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
169-
DMG_PATH: ${{ steps.artifacts.outputs.dmg }}
170196
171197
- name: Update rolling release for auto-updater
172198
run: |
@@ -192,12 +218,10 @@ jobs:
192218
timeout-minutes: 60
193219
permissions:
194220
contents: write
195-
env:
196-
VERSION: ${{ inputs.version }}
197221
steps:
198222
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
199223
with:
200-
ref: ${{ inputs.ref }}
224+
ref: ${{ github.event_name == 'push' && github.ref || inputs.ref }}
201225
persist-credentials: false
202226

203227
- uses: cashapp/activate-hermit@e49f5cb4dd64ff0b0b659d1d8df499595451155a # v1
@@ -237,6 +261,8 @@ jobs:
237261
run: just desktop-install-ci
238262

239263
- name: Patch version
264+
env:
265+
VERSION: ${{ needs.release.outputs.version }}
240266
run: |
241267
cd desktop && node scripts/set-version-from-tag.mjs "$VERSION"
242268
cd src-tauri && cargo update --workspace
@@ -271,12 +297,13 @@ jobs:
271297
echo "appimage=$APPIMAGE" >> "$GITHUB_OUTPUT"
272298
273299
- name: Upload Linux artifacts to versioned GitHub release
274-
run: |
275-
gh release upload "v${VERSION}" \
276-
"$DEB_PATH" \
277-
"$APPIMAGE_PATH" \
278-
--clobber
279300
env:
301+
VERSION: ${{ needs.release.outputs.version }}
280302
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
281303
DEB_PATH: ${{ steps.linux-artifacts.outputs.deb }}
282304
APPIMAGE_PATH: ${{ steps.linux-artifacts.outputs.appimage }}
305+
run: |
306+
gh release upload "v$VERSION" \
307+
"$DEB_PATH" \
308+
"$APPIMAGE_PATH" \
309+
--clobber

AGENTS.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@ code style, PR process, architecture), see [CONTRIBUTING.md](CONTRIBUTING.md).
66

77
---
88

9+
## Ecosystem
10+
11+
Sprout spans five repos. This one (`block/sprout`) is the OSS source for the relay, desktop, mobile, and CLI. The others handle internal builds and deployment:
12+
13+
| Repo | Purpose |
14+
|------|---------|
15+
| [block/sprout](https://github.com/block/sprout) | OSS source — relay, desktop app, mobile app, CLI, agent harness |
16+
| [squareup/sprout-releases](https://github.com/squareup/sprout-releases) | Buildkite pipeline producing Block-signed macOS + iOS builds with `-block` version suffix |
17+
| [squareup/sprout-oss](https://github.com/squareup/sprout-oss) | CI pipeline building the relay Docker image and pushing to internal ECR |
18+
| [squareup/block-coder-tf-stacks](https://github.com/squareup/block-coder-tf-stacks) | Terraform + ArgoCD deploying the relay to the staging Kubernetes cluster |
19+
| [squareup/sprout-backend-blox](https://github.com/squareup/sprout-backend-blox) | Desktop backend provider script connecting Blox workstation agents to the relay |
20+
21+
```
22+
block/sprout (source)
23+
├─► sprout-releases (desktop + mobile builds → Artifactory, GitHub, Mobile Releases)
24+
├─► sprout-oss (relay Docker image → ECR)
25+
│ └─► block-coder-tf-stacks (Helm chart → ArgoCD → staging cluster)
26+
└─── sprout-backend-blox (Blox compute provider for Desktop agent launch)
27+
```
28+
29+
See [RELEASING.md](RELEASING.md) for the desktop release flow across `block/sprout` and `sprout-releases`.
30+
31+
---
32+
933
## Repo Structure
1034

1135
```
@@ -281,4 +305,5 @@ Or from repo root: `just mobile-fmt` (auto-fix), `just mobile-check` (lint + fmt
281305
- [CONTRIBUTING.md](CONTRIBUTING.md) — setup, code style, PR process, how to add event kinds / CLI subcommands / API endpoints
282306
- [TESTING.md](TESTING.md) — multi-agent E2E test guide
283307
- [ARCHITECTURE.md](ARCHITECTURE.md) — system design and component relationships
308+
- [RELEASING.md](RELEASING.md) — release process: `just release`, auto-tag, internal builds
284309
- [README.md](README.md) — project overview and quick start

0 commit comments

Comments
 (0)