Skip to content

Commit 0f80726

Browse files
committed
switch to goreleaser for github releases
1 parent d426d8d commit 0f80726

3 files changed

Lines changed: 97 additions & 335 deletions

File tree

.github/workflows/release.yml

Lines changed: 27 additions & 335 deletions
Original file line numberDiff line numberDiff line change
@@ -1,343 +1,35 @@
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
152

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.
413
on:
42-
pull_request:
434
push:
445
tags:
45-
- '**[0-9]+.[0-9]+.[0-9]+*'
6+
- "*"
467

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
20510

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
22714
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
27034
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 }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ target
1919
# and can be added to the global gitignore or merged into this file. For a more nuclear
2020
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
2121
#.idea/
22+
# Added by goreleaser init:
23+
dist/
24+
.intentionally-empty-file.o
25+
target/

0 commit comments

Comments
 (0)