@@ -3,76 +3,167 @@ name: Release
33on :
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
713permissions :
814 contents : write
915
1016env :
11- PROJECT_NAME : " capsync"
17+ BINARY_NAME : " capsync"
18+ PACKAGE_NAME : " capsync"
1219
1320jobs :
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