Skip to content

Commit d1b2603

Browse files
committed
ci: add release workflow — linux/amd64, linux/arm64, macOS/arm64
Triggers on version tags (v0.1.0, etc.). Builds release binaries for 3 targets using cross (linux) and native cargo (macOS). Uploads tar.xz archives + sha256 checksums to GitHub Release. Usage: git tag v0.1.0 && git push origin v0.1.0
1 parent 6492f9a commit d1b2603

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Reusable release workflow for Tangle blueprint operators.
2+
# Copy this to .github/workflows/release.yml in each blueprint repo.
3+
#
4+
# Triggers on version tags (v0.1.0, v1.2.3, etc.).
5+
# Builds for linux/amd64, linux/arm64, macOS/arm64.
6+
# Uploads binaries + sha256 checksums as GitHub Release assets.
7+
#
8+
# Prerequisites:
9+
# - Cargo.toml has [[bin]] with the operator binary name
10+
# - rust-toolchain.toml pins the Rust version (e.g. 1.91)
11+
#
12+
# Usage:
13+
# git tag v0.1.0 && git push origin v0.1.0
14+
15+
name: Release
16+
17+
on:
18+
push:
19+
tags: ['v*']
20+
21+
permissions:
22+
contents: write
23+
24+
env:
25+
CARGO_TERM_COLOR: always
26+
# The binary name from [[bin]] in operator/Cargo.toml.
27+
# Override per repo if different.
28+
BINARY_NAME: ${{ vars.BINARY_NAME || 'embedding-operator' }}
29+
30+
jobs:
31+
build:
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
include:
36+
- target: x86_64-unknown-linux-gnu
37+
os: ubuntu-latest
38+
use_cross: true
39+
- target: aarch64-unknown-linux-gnu
40+
os: ubuntu-latest
41+
use_cross: true
42+
- target: aarch64-apple-darwin
43+
os: macos-14
44+
use_cross: false
45+
46+
runs-on: ${{ matrix.os }}
47+
steps:
48+
- uses: actions/checkout@v4
49+
50+
- name: Install Rust toolchain
51+
uses: dtolnay/rust-toolchain@stable
52+
with:
53+
targets: ${{ matrix.target }}
54+
55+
- name: Install cross
56+
if: matrix.use_cross
57+
run: cargo install cross --git https://github.com/cross-rs/cross
58+
59+
# Strip CI-incompatible patches (local paths that only exist on dev machines).
60+
# The committed Cargo.lock already pins transitive deps (like yanked core2).
61+
- name: Prepare for CI build
62+
run: |
63+
# Remove [patch.crates-io] and [patch."https://..."] sections that
64+
# reference local paths (e.g. /Users/drew/.cargo/...).
65+
if grep -q 'patch.crates-io' Cargo.toml; then
66+
python3 -c "
67+
import re
68+
with open('Cargo.toml') as f: text = f.read()
69+
# Remove [patch.*] sections with local path = entries
70+
text = re.sub(r'\[patch[^\]]*\]\n(?:(?!^\[)[^\n]*\n)*', '', text, flags=re.MULTILINE)
71+
with open('Cargo.toml', 'w') as f: f.write(text)
72+
"
73+
echo 'Stripped local-path patches from Cargo.toml for CI'
74+
fi
75+
76+
- name: Build release binary
77+
run: |
78+
BUILD_CMD="cargo"
79+
if [ "${{ matrix.use_cross }}" = "true" ]; then
80+
BUILD_CMD="cross"
81+
fi
82+
$BUILD_CMD build --release --target ${{ matrix.target }} --locked
83+
84+
- name: Package archive
85+
run: |
86+
BIN="target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}"
87+
ARCHIVE="${{ env.BINARY_NAME }}-${{ matrix.target }}.tar.xz"
88+
89+
# Strip debug symbols (saves 50-80% size)
90+
if command -v llvm-strip &>/dev/null; then
91+
llvm-strip "$BIN" 2>/dev/null || true
92+
elif command -v strip &>/dev/null; then
93+
strip "$BIN" 2>/dev/null || true
94+
fi
95+
96+
tar -cJf "$ARCHIVE" -C "$(dirname "$BIN")" "${{ env.BINARY_NAME }}"
97+
98+
# Generate checksums
99+
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"
100+
echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV"
101+
echo "SHA256_FILE=${ARCHIVE}.sha256" >> "$GITHUB_ENV"
102+
echo "Binary size: $(du -h "$BIN" | cut -f1)"
103+
echo "Archive size: $(du -h "$ARCHIVE" | cut -f1)"
104+
cat "${ARCHIVE}.sha256"
105+
106+
- name: Upload artifact
107+
uses: actions/upload-artifact@v4
108+
with:
109+
name: ${{ env.BINARY_NAME }}-${{ matrix.target }}
110+
path: |
111+
${{ env.ARCHIVE }}
112+
${{ env.SHA256_FILE }}
113+
114+
release:
115+
needs: build
116+
runs-on: ubuntu-latest
117+
steps:
118+
- uses: actions/checkout@v4
119+
120+
- name: Download all artifacts
121+
uses: actions/download-artifact@v4
122+
with:
123+
path: artifacts/
124+
125+
- name: Create GitHub Release
126+
env:
127+
GH_TOKEN: ${{ github.token }}
128+
run: |
129+
TAG="${GITHUB_REF_NAME}"
130+
131+
# Collect all archives and checksums
132+
FILES=$(find artifacts/ -name "*.tar.xz" -o -name "*.sha256" | sort)
133+
134+
# Generate release notes from tag message or changelog
135+
NOTES="## Binary Downloads
136+
137+
| Platform | Archive | SHA256 |
138+
|----------|---------|--------|"
139+
140+
for f in $(find artifacts/ -name "*.tar.xz" | sort); do
141+
BASENAME=$(basename "$f")
142+
SHA=$(cat "${f}.sha256" | awk '{print $1}')
143+
TARGET=$(echo "$BASENAME" | sed "s/${BINARY_NAME}-//" | sed 's/\.tar\.xz//')
144+
NOTES="$NOTES
145+
| \`$TARGET\` | \`$BASENAME\` | \`${SHA:0:16}...\` |"
146+
done
147+
148+
NOTES="$NOTES
149+
150+
### Verify checksums
151+
\`\`\`bash
152+
sha256sum -c *.sha256
153+
\`\`\`
154+
155+
### Install
156+
\`\`\`bash
157+
curl -sSL https://github.com/${{ github.repository }}/releases/download/$TAG/${BINARY_NAME}-x86_64-unknown-linux-gnu.tar.xz | tar xJ
158+
chmod +x ${BINARY_NAME}
159+
\`\`\`
160+
"
161+
162+
gh release create "$TAG" \
163+
--title "$TAG" \
164+
--notes "$NOTES" \
165+
$FILES

0 commit comments

Comments
 (0)