main
yml 263 lines 8.66 KB
Raw
1 name: GitHub Release
2
3 # Dispatched by release-crates.yml once the crate publish succeeds.
4 on:
5 workflow_dispatch:
6 inputs:
7 tag:
8 description: "Release tag (e.g. v0.4.0)"
9 required: true
10
11 permissions:
12 contents: write
13 actions: write
14
15 env:
16 PROJECT_NAME: onde
17 CARGO_TERM_COLOR: always
18 ONDE_APP_ID: ${{ secrets.ONDE_APP_ID }}
19 ONDE_APP_SECRET: ${{ secrets.ONDE_APP_SECRET }}
20 GRESIQ_API_KEY: ${{ secrets.GRESIQ_API_KEY }}
21 GRESIQ_API_SECRET: ${{ secrets.GRESIQ_API_SECRET }}
22 HF_TOKEN: ${{ secrets.HF_TOKEN }}
23
24 jobs:
25 build:
26 name: Build binary (${{ matrix.name }})
27 runs-on: ${{ matrix.runner }}
28
29 strategy:
30 fail-fast: false
31 matrix:
32 include:
33 - name: linux-amd64
34 runner: ubuntu-latest
35 target: x86_64-unknown-linux-gnu
36 - name: linux-arm64
37 runner: ubuntu-24.04-arm
38 target: aarch64-unknown-linux-gnu
39 - name: win-amd64
40 runner: windows-latest
41 target: x86_64-pc-windows-msvc
42 - name: win-arm64
43 runner: windows-latest
44 target: aarch64-pc-windows-msvc
45 - name: macos-amd64
46 runner: macos-26-intel
47 target: x86_64-apple-darwin
48 - name: macos-arm64
49 runner: macos-26
50 target: aarch64-apple-darwin
51
52 steps:
53 - name: Checkout
54 uses: actions/checkout@v6
55 with:
56 ref: ${{ github.event.inputs.tag || github.ref }}
57
58 - name: Set the release version
59 shell: bash
60 run: |
61 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
62 release_version="${GITHUB_REF_NAME#v}"
63 else
64 release_version="${{ github.event.inputs.tag }}"
65 release_version="${release_version#v}"
66 fi
67 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
68
69 - name: Read Rust toolchain
70 shell: bash
71 run: |
72 rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
73 if [ -z "$rust_toolchain" ]; then
74 echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
75 exit 1
76 fi
77 echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
78
79 - name: Install Rust toolchain
80 uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
81 with:
82 toolchain: ${{ env.RUST_TOOLCHAIN }}
83 targets: ${{ matrix.target }}
84
85 - name: Setup Rust cache
86 uses: Swatinem/rust-cache@v2
87 with:
88 key: github-${{ matrix.target }}
89
90 - name: Build binary
91 shell: bash
92 run: cargo build --locked --release --target ${{ matrix.target }}
93
94 # The exe must not import the VC++ runtime DLLs (see .cargo/config.toml), or it fails to
95 # load on a machine without the redistributable. Hostx64 dumpbin reads arm64 PE files too.
96 - name: Check static CRT
97 if: matrix.runner == 'windows-latest'
98 shell: pwsh
99 run: ./packaging/windows/check-static-crt.ps1 -Path target/${{ matrix.target }}/release/onde.exe
100
101 - name: Package binary
102 shell: bash
103 run: |
104 BIN_SUFFIX=""
105 if [[ "${{ matrix.runner }}" == "windows-latest" ]]; then
106 BIN_SUFFIX=".exe"
107 fi
108
109 BIN_OUTPUT="target/${{ matrix.target }}/release/${PROJECT_NAME}${BIN_SUFFIX}"
110 BIN_RELEASE="${PROJECT_NAME}-${{ matrix.name }}${BIN_SUFFIX}"
111
112 mkdir -p ./release
113 mv "${BIN_OUTPUT}" "./release/${BIN_RELEASE}"
114
115 - name: Package macOS tarball for Homebrew
116 if: contains(matrix.target, 'apple-darwin')
117 shell: bash
118 run: |
119 ARCHIVE_NAME="${PROJECT_NAME}-${{ matrix.name }}.tar.gz"
120
121 mkdir -p staging-brew
122 cp "./release/${PROJECT_NAME}-${{ matrix.name }}" "staging-brew/${PROJECT_NAME}"
123 strip "staging-brew/${PROJECT_NAME}"
124
125 tar -C staging-brew -czf "${ARCHIVE_NAME}" "${PROJECT_NAME}"
126
127 shasum -a 256 "${ARCHIVE_NAME}" | awk '{print $1}' > "${ARCHIVE_NAME}.sha256"
128
129 echo "Archive: ${ARCHIVE_NAME}"
130 echo "SHA256: $(cat "${ARCHIVE_NAME}.sha256")"
131
132 # Scoop and winget consume the raw Windows binaries rather than a
133 # tarball, and both need a SHA256 sidecar. Windows runners use bash from
134 # Git for Windows, which has sha256sum; macOS only has shasum.
135 - name: Checksum release assets
136 shell: bash
137 run: |
138 cd release
139 for asset in *; do
140 case "${asset}" in *.sha256) continue ;; esac
141
142 if command -v sha256sum >/dev/null 2>&1; then
143 sha256sum "${asset}" | awk '{print $1}' > "${asset}.sha256"
144 else
145 shasum -a 256 "${asset}" | awk '{print $1}' > "${asset}.sha256"
146 fi
147
148 echo "${asset}: $(cat "${asset}.sha256")"
149 done
150
151 - name: Upload binary artifact
152 uses: actions/upload-artifact@v4
153 with:
154 name: binary-${{ matrix.name }}
155 path: release/*
156
157 - name: Upload macOS Homebrew artifacts
158 if: contains(matrix.target, 'apple-darwin')
159 uses: actions/upload-artifact@v4
160 with:
161 name: homebrew-${{ matrix.name }}
162 path: |
163 ${{ env.PROJECT_NAME }}-${{ matrix.name }}.tar.gz
164 ${{ env.PROJECT_NAME }}-${{ matrix.name }}.tar.gz.sha256
165
166 release:
167 name: Create GitHub Release
168 needs: build
169 runs-on: ubuntu-latest
170 if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch'
171
172 steps:
173 - name: Resolve tag
174 id: tag
175 shell: bash
176 run: |
177 if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
178 echo "tag=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT"
179 else
180 echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
181 fi
182
183 - name: Download binary artifacts
184 uses: actions/download-artifact@v4
185 with:
186 pattern: "binary-*"
187 path: release
188 merge-multiple: true
189
190 - name: Download Homebrew artifacts
191 uses: actions/download-artifact@v4
192 with:
193 pattern: "homebrew-*"
194 path: release
195 merge-multiple: true
196
197 - name: Release
198 uses: softprops/action-gh-release@v2
199 with:
200 tag_name: ${{ steps.tag.outputs.tag }}
201 files: release/*
202
203 - name: Trigger Homebrew release
204 uses: actions/github-script@v7
205 with:
206 script: |
207 await github.rest.actions.createWorkflowDispatch({
208 owner: context.repo.owner,
209 repo: context.repo.repo,
210 workflow_id: 'release-homebrew.yml',
211 ref: '${{ steps.tag.outputs.tag }}',
212 inputs: {
213 tag: '${{ steps.tag.outputs.tag }}'
214 }
215 })
216 console.log('Dispatched release-homebrew.yml for tag ${{ steps.tag.outputs.tag }}')
217
218 - name: Trigger pub.dev release
219 uses: actions/github-script@v7
220 with:
221 script: |
222 await github.rest.actions.createWorkflowDispatch({
223 owner: context.repo.owner,
224 repo: context.repo.repo,
225 workflow_id: 'release-pub.yml',
226 ref: '${{ steps.tag.outputs.tag }}',
227 inputs: {
228 tag: '${{ steps.tag.outputs.tag }}'
229 }
230 })
231 console.log('Dispatched release-pub.yml for tag ${{ steps.tag.outputs.tag }}')
232
233 # These channels publish outside this repo (a Scoop bucket,
234 # microsoft/winget-pkgs) and read checksums off the release created
235 # above, so they hang off this job rather than firing on the tag
236 # directly.
237 - name: Trigger OS package manager releases
238 uses: actions/github-script@v7
239 with:
240 script: |
241 const tag = '${{ steps.tag.outputs.tag }}'
242 const workflows = [
243 'release-scoop.yml',
244 'release-winget.yml',
245 ]
246
247 for (const workflow_id of workflows) {
248 try {
249 await github.rest.actions.createWorkflowDispatch({
250 owner: context.repo.owner,
251 repo: context.repo.repo,
252 workflow_id,
253 ref: tag,
254 inputs: { tag },
255 })
256 console.log(`Dispatched ${workflow_id} for tag ${tag}`)
257 } catch (error) {
258 // One packaging channel being unconfigured (a missing secret,
259 // a bucket repo that does not exist yet) should not take the
260 // rest of the fan-out down with it.
261 core.warning(`Failed to dispatch ${workflow_id}: ${error.message}`)
262 }
263 }