Today I spent way to much time trying to figure out how to set up github actions to release a binary of my Rust application on MacOS, Ubuntu and Windows all at once. GitHub actions are powerful, but sadly very under documented. After reading many blog posts, talking to many differnt LLMs and making many git tags I finally landed on a solution that works!
Here it is! Some of this may not be needed, but this file does the job.
1name: Create Release
2
3on:
4 push:
5 tags:
6 - "v*"
7
8permissions:
9 contents: write
10
11jobs:
12 create_release:
13 name: Create Release
14 runs-on: ubuntu-latest
15 outputs:
16 release_id: ${{ steps.create_release.outputs.id }}
17 steps:
18 - name: Checkout code
19 uses: actions/checkout@v3
20
21 - name: Create Release
22 id: create_release
23 uses: softprops/action-gh-release@v1
24 with:
25 tag_name: ${{ github.ref }}
26 name: Release ${{ github.ref_name }}
27 draft: false
28 prerelease: false
29 env:
30 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31
32 build_release:
33 name: Build & Upload Artifacts
34 needs: create_release
35 strategy:
36 matrix:
37 include:
38 - os: ubuntu-latest
39 target: x86_64-unknown-linux-gnu
40 artifact_name: tc-linux
41 - os: macos-latest
42 target: x86_64-apple-darwin
43 artifact_name: tc-macos
44 - os: windows-latest
45 target: x86_64-pc-windows-msvc
46 artifact_name: tc-windows.exe
47 runs-on: ${{ matrix.os }}
48 steps:
49 - name: Checkout code
50 uses: actions/checkout@v3
51
52 - name: Set up Rust
53 uses: actions-rs/toolchain@v1
54 with:
55 toolchain: stable
56 target: ${{ matrix.target }}
57 override: true
58
59 - name: Build
60 run: cargo build --release --target ${{ matrix.target }}
61
62 - name: Rename Binary
63 run: |
64 mkdir -p artifacts
65 if [[ "${{ matrix.os }}" == 'windows-latest' ]]; then
66 mv target/${{ matrix.target }}/release/tc.exe artifacts/${{ matrix.artifact_name }}
67 else
68 mv target/${{ matrix.target }}/release/tc artifacts/${{ matrix.artifact_name }}
69 fi
70 shell: bash
71
72 - name: Upload Artifact
73 uses: actions/upload-artifact@v4
74 with:
75 name: ${{ matrix.artifact_name }}
76 path: artifacts/${{ matrix.artifact_name }}
77
78 - name: Upload to Release
79 uses: softprops/action-gh-release@v1
80 with:
81 files: artifacts/${{ matrix.artifact_name }}
82 env:
83 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The idea is that this workflow will kick off any time you push a tag to your repository that matches 'v*' (e.g. v0.1.0, v3.2.3, etc...). The matrix strategy allows this to run multiple builds in paralell for each value.
My binary was named 'tc', if you use this for your own work make sure to update all the 'tc's you see to match your binary name.
A big issue I kept running into was Linux and Mac shared a binary name, so when the slower build finished it deleted the others binary.
From the GitHub action logs:
♻️ Deleting previously uploaded asset tc...
⬆️ Uploading tc...
Simply renaming the binaries does the trick.
Also the versions of the different tools seems to silently go out of support. Don't be surprised if you come across this post and all of the versions are no longer supported. I will attempt to keep this post up to date as I use this with the most up to date versions.