|
1 | | -# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist |
2 | | -# |
3 | | -# Copyright 2022-2024, axodotdev |
4 | | -# SPDX-License-Identifier: MIT or Apache-2.0 |
5 | | -# |
6 | | -# CI that: |
7 | | -# |
8 | | -# * checks for a Git Tag that looks like a release |
9 | | -# * builds artifacts with dist (archives, installers, hashes) |
10 | | -# * uploads those artifacts to temporary workflow zip |
11 | | -# * on success, uploads the artifacts to a GitHub Release |
12 | | -# |
13 | | -# Note that the GitHub Release will be created with a generated |
14 | | -# title/body based on your changelogs. |
| 1 | +name: goreleaser |
15 | 2 |
|
16 | | -name: Release |
17 | | -permissions: |
18 | | - "contents": "write" |
19 | | - |
20 | | -# This task will run whenever you push a git tag that looks like a version |
21 | | -# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc. |
22 | | -# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where |
23 | | -# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION |
24 | | -# must be a Cargo-style SemVer Version (must have at least major.minor.patch). |
25 | | -# |
26 | | -# If PACKAGE_NAME is specified, then the announcement will be for that |
27 | | -# package (erroring out if it doesn't have the given version or isn't dist-able). |
28 | | -# |
29 | | -# If PACKAGE_NAME isn't specified, then the announcement will be for all |
30 | | -# (dist-able) packages in the workspace with that version (this mode is |
31 | | -# intended for workspaces with only one dist-able package, or with all dist-able |
32 | | -# packages versioned/released in lockstep). |
33 | | -# |
34 | | -# If you push multiple tags at once, separate instances of this workflow will |
35 | | -# spin up, creating an independent announcement for each one. However, GitHub |
36 | | -# will hard limit this to 3 tags per commit, as it will assume more tags is a |
37 | | -# mistake. |
38 | | -# |
39 | | -# If there's a prerelease-style suffix to the version, then the release(s) |
40 | | -# will be marked as a prerelease. |
41 | 3 | on: |
42 | | - pull_request: |
43 | 4 | push: |
44 | 5 | tags: |
45 | | - - '**[0-9]+.[0-9]+.[0-9]+*' |
| 6 | + - "*" |
46 | 7 |
|
47 | | -jobs: |
48 | | - # Run 'dist plan' (or host) to determine what tasks we need to do |
49 | | - plan: |
50 | | - runs-on: "ubuntu-22.04" |
51 | | - outputs: |
52 | | - val: ${{ steps.plan.outputs.manifest }} |
53 | | - tag: ${{ !github.event.pull_request && github.ref_name || '' }} |
54 | | - tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }} |
55 | | - publishing: ${{ !github.event.pull_request }} |
56 | | - env: |
57 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
58 | | - steps: |
59 | | - - uses: actions/checkout@v6 |
60 | | - with: |
61 | | - persist-credentials: false |
62 | | - submodules: recursive |
63 | | - - name: Install dist |
64 | | - # we specify bash to get pipefail; it guards against the `curl` command |
65 | | - # failing. otherwise `sh` won't catch that `curl` returned non-0 |
66 | | - shell: bash |
67 | | - run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.31.0/cargo-dist-installer.sh | sh" |
68 | | - - name: Cache dist |
69 | | - uses: actions/upload-artifact@v6 |
70 | | - with: |
71 | | - name: cargo-dist-cache |
72 | | - path: ~/.cargo/bin/dist |
73 | | - # sure would be cool if github gave us proper conditionals... |
74 | | - # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible |
75 | | - # functionality based on whether this is a pull_request, and whether it's from a fork. |
76 | | - # (PRs run on the *source* but secrets are usually on the *target* -- that's *good* |
77 | | - # but also really annoying to build CI around when it needs secrets to work right.) |
78 | | - - id: plan |
79 | | - run: | |
80 | | - dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json |
81 | | - echo "dist ran successfully" |
82 | | - cat plan-dist-manifest.json |
83 | | - echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT" |
84 | | - - name: "Upload dist-manifest.json" |
85 | | - uses: actions/upload-artifact@v6 |
86 | | - with: |
87 | | - name: artifacts-plan-dist-manifest |
88 | | - path: plan-dist-manifest.json |
89 | | - |
90 | | - # Build and packages all the platform-specific things |
91 | | - build-local-artifacts: |
92 | | - name: build-local-artifacts (${{ join(matrix.targets, ', ') }}) |
93 | | - # Let the initial task tell us to not run (currently very blunt) |
94 | | - needs: |
95 | | - - plan |
96 | | - if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }} |
97 | | - strategy: |
98 | | - fail-fast: false |
99 | | - # Target platforms/runners are computed by dist in create-release. |
100 | | - # Each member of the matrix has the following arguments: |
101 | | - # |
102 | | - # - runner: the github runner |
103 | | - # - dist-args: cli flags to pass to dist |
104 | | - # - install-dist: expression to run to install dist on the runner |
105 | | - # |
106 | | - # Typically there will be: |
107 | | - # - 1 "global" task that builds universal installers |
108 | | - # - N "local" tasks that build each platform's binaries and platform-specific installers |
109 | | - matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} |
110 | | - runs-on: ${{ matrix.runner }} |
111 | | - container: ${{ matrix.container && matrix.container.image || null }} |
112 | | - env: |
113 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
114 | | - BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json |
115 | | - steps: |
116 | | - - name: enable windows longpaths |
117 | | - run: | |
118 | | - git config --global core.longpaths true |
119 | | - - uses: actions/checkout@v6 |
120 | | - with: |
121 | | - persist-credentials: false |
122 | | - submodules: recursive |
123 | | - - name: Install Rust non-interactively if not already installed |
124 | | - if: ${{ matrix.container }} |
125 | | - run: | |
126 | | - if ! command -v cargo > /dev/null 2>&1; then |
127 | | - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y |
128 | | - echo "$HOME/.cargo/bin" >> $GITHUB_PATH |
129 | | - fi |
130 | | - - name: Install dist |
131 | | - run: ${{ matrix.install_dist.run }} |
132 | | - # Get the dist-manifest |
133 | | - - name: Fetch local artifacts |
134 | | - uses: actions/download-artifact@v7 |
135 | | - with: |
136 | | - pattern: artifacts-* |
137 | | - path: target/distrib/ |
138 | | - merge-multiple: true |
139 | | - - name: Install dependencies |
140 | | - run: | |
141 | | - ${{ matrix.packages_install }} |
142 | | - - name: Build artifacts |
143 | | - run: | |
144 | | - # Actually do builds and make zips and whatnot |
145 | | - dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json |
146 | | - echo "dist ran successfully" |
147 | | - - id: cargo-dist |
148 | | - name: Post-build |
149 | | - # We force bash here just because github makes it really hard to get values up |
150 | | - # to "real" actions without writing to env-vars, and writing to env-vars has |
151 | | - # inconsistent syntax between shell and powershell. |
152 | | - shell: bash |
153 | | - run: | |
154 | | - # Parse out what we just built and upload it to scratch storage |
155 | | - echo "paths<<EOF" >> "$GITHUB_OUTPUT" |
156 | | - dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT" |
157 | | - echo "EOF" >> "$GITHUB_OUTPUT" |
158 | | -
|
159 | | - cp dist-manifest.json "$BUILD_MANIFEST_NAME" |
160 | | - - name: "Upload artifacts" |
161 | | - uses: actions/upload-artifact@v6 |
162 | | - with: |
163 | | - name: artifacts-build-local-${{ join(matrix.targets, '_') }} |
164 | | - path: | |
165 | | - ${{ steps.cargo-dist.outputs.paths }} |
166 | | - ${{ env.BUILD_MANIFEST_NAME }} |
167 | | -
|
168 | | - # Build and package all the platform-agnostic(ish) things |
169 | | - build-global-artifacts: |
170 | | - needs: |
171 | | - - plan |
172 | | - - build-local-artifacts |
173 | | - runs-on: "ubuntu-22.04" |
174 | | - env: |
175 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
176 | | - BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json |
177 | | - steps: |
178 | | - - uses: actions/checkout@v6 |
179 | | - with: |
180 | | - persist-credentials: false |
181 | | - submodules: recursive |
182 | | - - name: Install cached dist |
183 | | - uses: actions/download-artifact@v7 |
184 | | - with: |
185 | | - name: cargo-dist-cache |
186 | | - path: ~/.cargo/bin/ |
187 | | - - run: chmod +x ~/.cargo/bin/dist |
188 | | - # Get all the local artifacts for the global tasks to use (for e.g. checksums) |
189 | | - - name: Fetch local artifacts |
190 | | - uses: actions/download-artifact@v7 |
191 | | - with: |
192 | | - pattern: artifacts-* |
193 | | - path: target/distrib/ |
194 | | - merge-multiple: true |
195 | | - - id: cargo-dist |
196 | | - shell: bash |
197 | | - run: | |
198 | | - dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json |
199 | | - echo "dist ran successfully" |
200 | | -
|
201 | | - # Parse out what we just built and upload it to scratch storage |
202 | | - echo "paths<<EOF" >> "$GITHUB_OUTPUT" |
203 | | - jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT" |
204 | | - echo "EOF" >> "$GITHUB_OUTPUT" |
| 8 | +permissions: |
| 9 | + contents: write |
205 | 10 |
|
206 | | - cp dist-manifest.json "$BUILD_MANIFEST_NAME" |
207 | | - - name: "Upload artifacts" |
208 | | - uses: actions/upload-artifact@v6 |
209 | | - with: |
210 | | - name: artifacts-build-global |
211 | | - path: | |
212 | | - ${{ steps.cargo-dist.outputs.paths }} |
213 | | - ${{ env.BUILD_MANIFEST_NAME }} |
214 | | - # Determines if we should publish/announce |
215 | | - host: |
216 | | - needs: |
217 | | - - plan |
218 | | - - build-local-artifacts |
219 | | - - build-global-artifacts |
220 | | - # Only run if we're "publishing", and only if plan, local and global didn't fail (skipped is fine) |
221 | | - if: ${{ always() && needs.plan.result == 'success' && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }} |
222 | | - env: |
223 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
224 | | - runs-on: "ubuntu-22.04" |
225 | | - outputs: |
226 | | - val: ${{ steps.host.outputs.manifest }} |
| 11 | +jobs: |
| 12 | + goreleaser: |
| 13 | + runs-on: ubuntu-latest |
227 | 14 | steps: |
228 | | - - uses: actions/checkout@v6 |
229 | | - with: |
230 | | - persist-credentials: false |
231 | | - submodules: recursive |
232 | | - - name: Install cached dist |
233 | | - uses: actions/download-artifact@v7 |
234 | | - with: |
235 | | - name: cargo-dist-cache |
236 | | - path: ~/.cargo/bin/ |
237 | | - - run: chmod +x ~/.cargo/bin/dist |
238 | | - # Fetch artifacts from scratch-storage |
239 | | - - name: Fetch artifacts |
240 | | - uses: actions/download-artifact@v7 |
241 | | - with: |
242 | | - pattern: artifacts-* |
243 | | - path: target/distrib/ |
244 | | - merge-multiple: true |
245 | | - - id: host |
246 | | - shell: bash |
247 | | - run: | |
248 | | - dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json |
249 | | - echo "artifacts uploaded and released successfully" |
250 | | - cat dist-manifest.json |
251 | | - echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT" |
252 | | - - name: "Upload dist-manifest.json" |
253 | | - uses: actions/upload-artifact@v6 |
254 | | - with: |
255 | | - # Overwrite the previous copy |
256 | | - name: artifacts-dist-manifest |
257 | | - path: dist-manifest.json |
258 | | - # Create a GitHub Release while uploading all files to it |
259 | | - - name: "Download GitHub Artifacts" |
260 | | - uses: actions/download-artifact@v7 |
261 | | - with: |
262 | | - pattern: artifacts-* |
263 | | - path: artifacts |
264 | | - merge-multiple: true |
265 | | - - name: Cleanup |
266 | | - run: | |
267 | | - # Remove the granular manifests |
268 | | - rm -f artifacts/*-dist-manifest.json |
269 | | - - name: Create GitHub Release |
| 15 | + - name: Extract Release Notes |
| 16 | + run: | |
| 17 | + # This sed command finds the line starting with "# Version ${TAG}" |
| 18 | + # and prints until it hits the next line starting with "# Version" |
| 19 | + TAG=${{ github.ref_name }} |
| 20 | + sed -n "/^# Version ${TAG}/,/^# Version/p" CHANGELOG.md | sed '$d' > GORELEASER_NOTES.md |
| 21 | + - name: Checkout |
| 22 | + uses: actions/checkout@v6 |
| 23 | + with: |
| 24 | + fetch-depth: 0 |
| 25 | + - name: Set up Go |
| 26 | + uses: actions/setup-go@v6 |
| 27 | + - name: Run GoReleaser |
| 28 | + uses: goreleaser/goreleaser-action@v7.1.0 |
| 29 | + with: |
| 30 | + distribution: goreleaser |
| 31 | + # 'latest', 'nightly', or a semver |
| 32 | + version: "latest" |
| 33 | + args: release --clean |
270 | 34 | env: |
271 | | - PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}" |
272 | | - ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}" |
273 | | - ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}" |
274 | | - RELEASE_COMMIT: "${{ github.sha }}" |
275 | | - run: | |
276 | | - # Write and read notes from a file to avoid quoting breaking things |
277 | | - echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt |
278 | | -
|
279 | | - gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/* |
280 | | -
|
281 | | - publish-homebrew-formula: |
282 | | - needs: |
283 | | - - plan |
284 | | - - host |
285 | | - runs-on: "ubuntu-22.04" |
286 | | - env: |
287 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
288 | | - PLAN: ${{ needs.plan.outputs.val }} |
289 | | - GITHUB_USER: "axo bot" |
290 | | - GITHUB_EMAIL: "admin+bot@axo.dev" |
291 | | - if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }} |
292 | | - steps: |
293 | | - - uses: actions/checkout@v6 |
294 | | - with: |
295 | | - persist-credentials: true |
296 | | - repository: "freepicheep/homebrew-tap" |
297 | | - token: ${{ secrets.HOMEBREW_TAP_TOKEN }} |
298 | | - # So we have access to the formula |
299 | | - - name: Fetch homebrew formulae |
300 | | - uses: actions/download-artifact@v7 |
301 | | - with: |
302 | | - pattern: artifacts-* |
303 | | - path: Formula/ |
304 | | - merge-multiple: true |
305 | | - # This is extra complex because you can make your Formula name not match your app name |
306 | | - # so we need to find releases with a *.rb file, and publish with that filename. |
307 | | - - name: Commit formula files |
308 | | - run: | |
309 | | - git config --global user.name "${GITHUB_USER}" |
310 | | - git config --global user.email "${GITHUB_EMAIL}" |
311 | | -
|
312 | | - for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith(".rb")] | any)'); do |
313 | | - filename=$(echo "$release" | jq '.artifacts[] | select(endswith(".rb"))' --raw-output) |
314 | | - name=$(echo "$filename" | sed "s/\.rb$//") |
315 | | - version=$(echo "$release" | jq .app_version --raw-output) |
316 | | -
|
317 | | - export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH" |
318 | | - brew update |
319 | | - # We avoid reformatting user-provided data such as the app description and homepage. |
320 | | - brew style --except-cops FormulaAudit/Homepage,FormulaAudit/Desc,FormulaAuditStrict --fix "Formula/${filename}" || true |
321 | | -
|
322 | | - git add "Formula/${filename}" |
323 | | - git commit -m "${name} ${version}" |
324 | | - done |
325 | | - git push |
326 | | -
|
327 | | - announce: |
328 | | - needs: |
329 | | - - plan |
330 | | - - host |
331 | | - - publish-homebrew-formula |
332 | | - # use "always() && ..." to allow us to wait for all publish jobs while |
333 | | - # still allowing individual publish jobs to skip themselves (for prereleases). |
334 | | - # "host" however must run to completion, no skipping allowed! |
335 | | - if: ${{ always() && needs.host.result == 'success' && (needs.publish-homebrew-formula.result == 'skipped' || needs.publish-homebrew-formula.result == 'success') }} |
336 | | - runs-on: "ubuntu-22.04" |
337 | | - env: |
338 | | - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
339 | | - steps: |
340 | | - - uses: actions/checkout@v6 |
341 | | - with: |
342 | | - persist-credentials: false |
343 | | - submodules: recursive |
| 35 | + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
0 commit comments