Skip to content

Commit a9d692a

Browse files
committed
ci: enhance release workflow with all features
- Add workflow_dispatch for manual trigger - Add extract-notes job for CHANGELOG-based release notes - Add Windows build support (x86_64-pc-windows-msvc) - Add binary verification step - Add SSH signing for binaries - Add artifact upload/download workflow
1 parent d915cbf commit a9d692a

1 file changed

Lines changed: 126 additions & 35 deletions

File tree

.github/workflows/release.yml

Lines changed: 126 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,167 @@ name: Release
33
on:
44
push:
55
tags: ["v*"]
6+
workflow_dispatch:
7+
inputs:
8+
tag:
9+
description: "Tag to release (e.g. v0.2.1)"
10+
required: true
11+
type: string
612

713
permissions:
814
contents: write
915

1016
env:
11-
PROJECT_NAME: "capsync"
17+
BINARY_NAME: "capsync"
18+
PACKAGE_NAME: "capsync"
1219

1320
jobs:
14-
build-and-release:
15-
runs-on: ${{ matrix.os }}
21+
extract-notes:
22+
name: Extract Release Notes
23+
runs-on: ubuntu-latest
24+
outputs:
25+
notes: ${{ steps.notes.outputs.result }}
26+
version: ${{ steps.version.outputs.version }}
27+
steps:
28+
- name: Checkout Repository
29+
uses: actions/checkout@v6
30+
with:
31+
fetch-depth: 0
32+
ref: ${{ github.event.inputs.tag || github.ref_name }}
33+
34+
- name: Extract Version
35+
id: version
36+
run: |
37+
REF="${{ github.event.inputs.tag || github.ref_name }}"
38+
VERSION="${REF#v}"
39+
echo "version=$VERSION" >> $GITHUB_OUTPUT
40+
41+
- name: Extract Release Notes from Changelog
42+
id: notes
43+
run: |
44+
VERSION="${{ steps.version.outputs.version }}"
45+
NOTES=$(awk -v ver="$VERSION" '
46+
/^## \[/ { if (p) exit; if ($2 == "["ver"]") { p=1; next } }
47+
p { print }
48+
' CHANGELOG.md)
49+
50+
echo "result<<EOF" >> $GITHUB_OUTPUT
51+
echo "$NOTES" >> $GITHUB_OUTPUT
52+
echo -e "\n---\n" >> $GITHUB_OUTPUT
53+
echo "See [\`README.md\`](./README.md) for installation info." >> $GITHUB_OUTPUT
54+
echo "EOF" >> $GITHUB_OUTPUT
55+
56+
build:
57+
name: Build Binary (${{ matrix.asset }})
58+
needs: extract-notes
1659
strategy:
1760
matrix:
1861
include:
1962
- os: ubuntu-latest
2063
target: x86_64-unknown-linux-gnu
21-
asset_name: linux
22-
arch: x86_64
64+
asset: linux-x86_64
2365
- os: macos-latest
2466
target: x86_64-apple-darwin
25-
asset_name: darwin
26-
arch: x86_64
67+
asset: darwin-x86_64
2768
- os: macos-latest
2869
target: aarch64-apple-darwin
29-
asset_name: darwin
30-
arch: aarch64
31-
70+
asset: darwin-aarch64
71+
- os: windows-latest
72+
target: x86_64-pc-windows-msvc
73+
asset: windows-x86_64
74+
runs-on: ${{ matrix.os }}
3275
steps:
33-
- name: Checkout repository
76+
- name: Checkout Repository
3477
uses: actions/checkout@v6
78+
with:
79+
ref: v${{ needs.extract-notes.outputs.version }}
3580

36-
- name: Install Rust
81+
- name: Install Rust Toolchain
3782
uses: dtolnay/rust-toolchain@stable
3883
with:
3984
targets: ${{ matrix.target }}
4085

41-
- name: Install cross-compilation tools
42-
if: matrix.target == 'aarch64-apple-darwin'
43-
run: |
44-
rustup target add aarch64-apple-darwin
86+
- name: Build Release Binary
87+
run: cargo build --release --target ${{ matrix.target }} -p ${{ env.PACKAGE_NAME }}
4588

46-
- name: Build Binary
89+
- name: Package Binary
90+
shell: bash
4791
run: |
48-
cargo build --release --target ${{ matrix.target }}
92+
mkdir -p dist
93+
EXT="${{ matrix.os == 'windows-latest' && '.exe' || '' }}"
94+
SRC="target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}${EXT}"
95+
DST="dist/${{ env.BINARY_NAME }}-${{ matrix.asset }}${EXT}"
96+
cp "$SRC" "$DST"
4997
50-
- name: Prepare Asset
98+
# Verify
99+
test -f "$DST" || { echo "Binary not found"; exit 1; }
100+
if [ "${{ matrix.os }}" != "windows-latest" ]; then
101+
chmod +x "$DST"
102+
"$DST" --help || true
103+
fi
104+
105+
- name: Sign Binary with SSH Key
106+
env:
107+
SSH_KEY: ${{ secrets.SSH_SIGNING_KEY }}
51108
shell: bash
52109
run: |
53-
mkdir -p release
54-
BINARY_NAME="${{ env.PROJECT_NAME }}"
55-
if [ "${{ matrix.os }}" = "windows-latest" ]; then
56-
BINARY_NAME="${BINARY_NAME}.exe"
57-
fi
58-
cp "target/${{ matrix.target }}/release/${BINARY_NAME}" "release/${{ env.PROJECT_NAME }}-${{ matrix.asset_name }}-${{ matrix.arch }}"
110+
mkdir -p "$HOME/.ssh"
111+
echo "$SSH_KEY" > "$HOME/.ssh/id_signing"
112+
chmod 600 "$HOME/.ssh/id_signing"
59113
60-
- name: Generate SHA-256
114+
FILE="${{ env.BINARY_NAME }}-${{ matrix.asset }}${{ matrix.os == 'windows-latest' && '.exe' || '' }}"
115+
cd dist
116+
ssh-keygen -Y sign -f "$HOME/.ssh/id_signing" -n file "$FILE"
117+
118+
rm "$HOME/.ssh/id_signing"
119+
ls -la
120+
121+
- name: Generate SHA-256 Checksums
122+
shell: bash
61123
run: |
124+
cd dist
125+
FILE="${{ env.BINARY_NAME }}-${{ matrix.asset }}${{ matrix.os == 'windows-latest' && '.exe' || '' }}"
126+
127+
# Generate checksum for binary
62128
if [ "${{ matrix.os }}" = "windows-latest" ]; then
63-
certutil -hashfile "release/${{ env.PROJECT_NAME }}-${{ matrix.asset_name }}-${{ matrix.arch }}" SHA256 | grep -v "hash" > "release/${{ env.PROJECT_NAME }}-${{ matrix.asset_name }}-${{ matrix.arch }}.sha256"
129+
certutil -hashfile "$FILE" SHA256 | grep -v "hash" > "${FILE}.sha256"
64130
else
65-
shasum -a 256 "release/${{ env.PROJECT_NAME }}-${{ matrix.asset_name }}-${{ matrix.arch }}" > "release/${{ env.PROJECT_NAME }}-${{ matrix.asset_name }}-${{ matrix.arch }}.sha256"
131+
shasum -a 256 "$FILE" > "${FILE}.sha256"
66132
fi
67133
134+
# Generate checksum for signature if it exists
135+
if [ -f "${FILE}.sig" ]; then
136+
if [ "${{ matrix.os }}" = "windows-latest" ]; then
137+
certutil -hashfile "${FILE}.sig" SHA256 | grep -v "hash" > "${FILE}.sig.sha256"
138+
else
139+
shasum -a 256 "${FILE}.sig" > "${FILE}.sig.sha256"
140+
fi
141+
fi
142+
143+
- name: Upload Build Artifact
144+
uses: actions/upload-artifact@v6
145+
with:
146+
name: ${{ matrix.asset }}
147+
path: dist/*
148+
if-no-files-found: error
149+
150+
release:
151+
name: Create GitHub Release
152+
needs: [extract-notes, build]
153+
runs-on: ubuntu-latest
154+
steps:
155+
- name: Download Build Artifacts
156+
uses: actions/download-artifact@v7
157+
with:
158+
path: dist
159+
merge-multiple: true
160+
68161
- name: Create Release
69-
uses: softprops/action-gh-release@v1
162+
uses: softprops/action-gh-release@v2.5.0
70163
with:
71-
name: "CapSync ${{ github.ref_name }}"
72-
files: |
73-
release/${{ env.PROJECT_NAME }}-${{ matrix.asset_name }}-${{ matrix.arch }}
74-
release/${{ env.PROJECT_NAME }}-${{ matrix.asset_name }}-${{ matrix.arch }}.sha256
75-
draft: false
76-
prerelease: false
164+
tag_name: v${{ needs.extract-notes.outputs.version }}
165+
name: CapSync v${{ needs.extract-notes.outputs.version }}
166+
body: ${{ needs.extract-notes.outputs.notes }}
167+
files: dist/*
77168
env:
78169
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)