@@ -26,15 +26,17 @@ jobs:
2626 runs-on : ${{ matrix.os }}
2727 strategy :
2828 matrix :
29- os : [ubuntu-latest, macos-latest, windows-latest]
3029 include :
3130 - os : ubuntu-latest
31+ target : x86_64-unknown-linux-musl
3232 artifact_name : tslime
3333 asset_name : tslime-linux-x86_64
3434 - os : macos-latest
35+ target : aarch64-apple-darwin
3536 artifact_name : tslime
36- asset_name : tslime-macos-x86_64
37+ asset_name : tslime-macos-arm64
3738 - os : windows-latest
39+ target : x86_64-pc-windows-msvc
3840 artifact_name : tslime.exe
3941 asset_name : tslime-windows-x86_64.exe
4042
4446
4547 - name : Install Rust toolchain
4648 uses : dtolnay/rust-toolchain@stable
49+ with :
50+ targets : ${{ matrix.target }}
51+
52+ - name : Install musl tools (Linux)
53+ if : runner.os == 'Linux'
54+ run : sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends musl-tools
4755
4856 - name : Cache cargo registry
4957 uses : actions/cache@v4
@@ -64,26 +72,34 @@ jobs:
6472 key : ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
6573
6674 - name : Build release binary
67- run : cargo build --release --verbose
75+ run : cargo build --release --verbose --target ${{ matrix.target }}
6876
6977 - name : Check binary size
7078 if : runner.os == 'Linux'
7179 run : |
72- size target/release/tslime
73- SIZE=$(stat -c%s target/release/tslime)
74- # Headroom over the ~3.1MB Linux release binary.
80+ BIN="target/${{ matrix. target }} /release/tslime"
81+ size "$BIN" || true
82+ SIZE=$(stat -c%s "$BIN")
7583 MAX_SIZE=4000000
7684 if [ "$SIZE" -gt "$MAX_SIZE" ]; then
7785 echo "Binary size $SIZE exceeds $MAX_SIZE limit"
7886 exit 1
7987 fi
8088 echo "Binary size $SIZE is under $MAX_SIZE limit"
8189
90+ # Stage the binary under its release asset name so the downloaded artifact
91+ # is named correctly for `gh release create` (no post-download rename).
92+ - name : Stage binary
93+ shell : bash
94+ run : |
95+ mkdir -p dist
96+ cp "target/${{ matrix.target }}/release/${{ matrix.artifact_name }}" "dist/${{ matrix.asset_name }}"
97+
8298 - name : Upload artifact
8399 uses : actions/upload-artifact@v4
84100 with :
85101 name : ${{ matrix.asset_name }}
86- path : target/release/ ${{ matrix.artifact_name }}
102+ path : dist/ ${{ matrix.asset_name }}
87103
88104 gui-build :
89105 name : GUI Build
@@ -148,3 +164,90 @@ jobs:
148164 with :
149165 name : ${{ matrix.asset_name }}
150166 path : target/release/${{ matrix.artifact_name }}
167+
168+ # Publish a GitHub Release with the CLI binaries attached and notes pulled
169+ # from the matching CHANGELOG section. Tag pushes only (skipped for manual
170+ # workflow_dispatch runs, which have no tag to release).
171+ release :
172+ name : Publish GitHub Release
173+ needs : build
174+ if : startsWith(github.ref, 'refs/tags/v')
175+ runs-on : ubuntu-latest
176+ permissions :
177+ contents : write
178+ steps :
179+ - name : Checkout code
180+ uses : actions/checkout@v4
181+
182+ - name : Download Linux binary
183+ uses : actions/download-artifact@v4
184+ with :
185+ name : tslime-linux-x86_64
186+ path : dist
187+
188+ - name : Download Windows binary
189+ uses : actions/download-artifact@v4
190+ with :
191+ name : tslime-windows-x86_64.exe
192+ path : dist
193+
194+ - name : Extract release notes from CHANGELOG
195+ shell : bash
196+ run : |
197+ version="${GITHUB_REF_NAME#v}"
198+ awk -v v="$version" '
199+ $0 ~ ("^## \\[" v "\\]") { found=1; next }
200+ found && /^## \[/ { exit }
201+ found { print }
202+ ' CHANGELOG.md > RELEASE_NOTES.md
203+ if [ ! -s RELEASE_NOTES.md ]; then
204+ printf 'tslime %s\n' "$GITHUB_REF_NAME" > RELEASE_NOTES.md
205+ fi
206+
207+ - name : Create GitHub Release
208+ env :
209+ GH_TOKEN : ${{ github.token }}
210+ shell : bash
211+ run : |
212+ gh release create "$GITHUB_REF_NAME" \
213+ --repo "$GITHUB_REPOSITORY" \
214+ --title "tslime $GITHUB_REF_NAME" \
215+ --notes-file RELEASE_NOTES.md \
216+ dist/tslime-linux-x86_64 \
217+ dist/tslime-windows-x86_64.exe
218+
219+ # Publish a container image to GHCR so users can `docker run --rm -it
220+ # ghcr.io/<owner>/tslime` without installing anything. Self-contained build
221+ # (the Dockerfile compiles the static musl binary onto a scratch image). Tag
222+ # pushes only. linux/amd64; arm64 is a follow-up.
223+ docker :
224+ name : Publish Docker image
225+ needs : hygiene
226+ if : startsWith(github.ref, 'refs/tags/v')
227+ runs-on : ubuntu-latest
228+ permissions :
229+ contents : read
230+ packages : write
231+ steps :
232+ - name : Checkout code
233+ uses : actions/checkout@v4
234+
235+ - name : Log in to GitHub Container Registry
236+ uses : docker/login-action@v3
237+ with :
238+ registry : ghcr.io
239+ username : ${{ github.actor }}
240+ password : ${{ secrets.GITHUB_TOKEN }}
241+
242+ - name : Set up Docker Buildx
243+ uses : docker/setup-buildx-action@v3
244+
245+ - name : Build and push image
246+ uses : docker/build-push-action@v6
247+ with :
248+ context : .
249+ platforms : linux/amd64
250+ push : true
251+ tags : |
252+ ghcr.io/${{ github.repository }}:latest
253+ ghcr.io/${{ github.repository }}:${{ github.ref_name }}
0 commit comments