Skip to content

Commit 19ab99a

Browse files
authored
Use GoReleaser for GitHub release workflow (zarf-dev#498)
* use GoReleaser for github release workflow * add org token for brew recipe pushes * init command looks for init-package in executable directory * include init-package in the GoReleaser generated release * add nerd-note doc about GoReleaser creating a homebrew recipe for Zarf
1 parent 8aaf4e1 commit 19ab99a

File tree

6 files changed

+137
-27
lines changed

6 files changed

+137
-27
lines changed

.github/workflows/release.yml

+24-24
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- name: Install GoLang
13-
uses: actions/setup-go@v2
13+
uses: actions/setup-go@v3
1414
with:
1515
go-version: 1.18.x
16-
16+
1717
- name: Checkout Repo
18-
uses: actions/checkout@v2
19-
18+
uses: actions/checkout@v3
19+
with:
20+
fetch-depth: 0
21+
2022
- name: "Setup caching"
2123
uses: actions/cache@v3
2224
with:
@@ -25,30 +27,28 @@ jobs:
2527
~/go/pkg/mod
2628
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
2729
restore-keys: |
28-
${{ runner.os }}-go-
29-
30-
- name: Build Things For Release
31-
run: make build-cli init-package
32-
30+
${{ runner.os }}-go-
31+
32+
# Set up AWS credentials for GoReleaser to upload backups of artifacts to S3
3333
- name: Set AWS Credentials
3434
uses: aws-actions/configure-aws-credentials@v1
3535
with:
3636
aws-access-key-id: ${{ secrets.AWS_GOV_ACCESS_KEY_ID }}
3737
aws-secret-access-key: ${{ secrets.AWS_GOV_SECRET_ACCESS_KEY }}
3838
aws-region: us-gov-west-1
39-
40-
- name: Push Release Artifacts to S3 Bucket
41-
run: aws s3 cp build s3://zarf-public/release/${{ github.ref_name }} --region us-gov-west-1 --recursive
42-
43-
- name: Create a Release For This Tag
44-
uses: softprops/action-gh-release@v1
45-
if: startsWith(github.ref, 'refs/tags/')
39+
40+
# Builds init packages since GoReleaser won't handle this for us
41+
- name: "Build init-packages For Release"
42+
run: |
43+
make build-cli-linux-amd init-package
44+
45+
# Create the GitHub release notes, upload artifact backups to S3, publish homebrew recipe
46+
- name: Run GoReleaser
47+
uses: goreleaser/goreleaser-actions@v3
4648
with:
47-
generate_release_notes: true # Generates basic release notes that we can edit later
48-
files: |
49-
build/zarf
50-
build/zarf-mac-intel
51-
build/zarf-mac-apple
52-
build/zarf-init-amd64.tar.zst
53-
build/zarf-init-arm64.tar.zst
54-
build/zarf.sha256
49+
distribution: goreleaser
50+
version: latest
51+
args: release --rm-dist
52+
env:
53+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN}}
54+
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.ZARF_ORG_PROJECT_TOKEN }}

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,5 @@ zarf-pki
2828
.scratch/
2929
zarf-sbom/
3030
clidocs/
31+
32+
dist/

.goreleaser.yaml

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
before:
2+
hooks:
3+
- go mod tidy
4+
5+
# Build a universal macOS binary
6+
universal_binaries:
7+
- replace: false
8+
9+
# Build the different combination of goos/arch binaries
10+
builds:
11+
-
12+
env:
13+
- CGO_ENABLED=0
14+
goos:
15+
- linux
16+
- darwin
17+
dir: src
18+
ldflags:
19+
- -s -w -X github.com/defenseunicorns/zarf/src/config.CLIVersion={{.Version}}
20+
goarch:
21+
- amd64
22+
- arm64
23+
ignore:
24+
- goos: linux
25+
goarch: arm64
26+
27+
28+
# Save the built artifacts as binaries (instead of wrapping them in a tarball)
29+
archives:
30+
-
31+
format: binary
32+
replacements:
33+
darwin: Darwin
34+
linux: Linux
35+
36+
# generate a sha256 checksum of all release artifacts
37+
# NOTE: We are explicitly adding the init-packages that are built prior to GoReleaser stage in the GitHub Actions workflow
38+
checksum:
39+
name_template: 'checksums.txt'
40+
extra_files:
41+
- glob: ./build/zarf-init-*
42+
algorithm: sha256
43+
44+
snapshot:
45+
name_template: "{{ incpatch .Version }}-snapshot"
46+
47+
# Use the auto-generated changlog github provides
48+
changelog:
49+
use: github-native
50+
51+
# Generate a GitHub release and publish the release for the tag
52+
# NOTE: We are explicitly adding the init-packages that are built prior to GoReleaser stage in the GitHub Actions workflow
53+
release:
54+
github:
55+
owner: defenseunicorns
56+
name: zarf
57+
prerelease: auto
58+
mode: append
59+
extra_files:
60+
- glob: ./build/zarf-init-*
61+
62+
# Create a brew tap recipe that uses the new binary artifacts and push it to our tap
63+
brews:
64+
- name: zarf
65+
tap:
66+
owner: defenseunicorns
67+
name: homebrew-tap
68+
token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
69+
commit_msg_template: "Brew formula update for {{ .ProjectName }} version {{ .Tag }}"
70+
homepage: "https://zarf.dev/"
71+
description: "An airgap delivery tool!"
72+
73+
# Upload artifact backups to s3
74+
blobs:
75+
-
76+
provider: s3
77+
region: us-gov-west-1
78+
bucket: zarf-public
79+
folder: "release/{{.Version}}"

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ Zarf is written entirely in [go](https://go.dev/), except for a single 400Kb bin
297297
- An init container runs the rust binary to re-assemble and extract the zarf binary and registry image
298298
- The container then starts and runs the zarf binary to host the registry image in an embedded docker registry
299299
- After this, the main docker registry chart is deployed, pulls the image from the ephemeral pod, and finally destroys the created configmaps, pod, and service
300-
300+
- We have published a [Homebrew Tap](https://github.com/defenseunicorns/homebrew-tap) for this project that you can install with `brew tap defenseunicorns/tap && brew install zarf`
301+
- This recipe is updated with each new version release via [GoReleaser](https://goreleaser.com/customization/homebrew/) as part of the release pipeline that runs on GitHub Actions.
301302
 
302303
### Zarf Architecture
303304
![Architecture Diagram](./docs/architecture.drawio.svg)

src/cmd/initialize.go

+16-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ package cmd
33
import (
44
"fmt"
55
"os"
6+
"path"
7+
"path/filepath"
68

79
"github.com/defenseunicorns/zarf/src/config"
810
"github.com/defenseunicorns/zarf/src/internal/message"
911
"github.com/defenseunicorns/zarf/src/internal/packager"
12+
"github.com/defenseunicorns/zarf/src/internal/utils"
1013

1114
"github.com/spf13/cobra"
1215
)
@@ -22,8 +25,19 @@ var initCmd = &cobra.Command{
2225
_, _ = fmt.Fprintln(os.Stderr, zarfLogo)
2326

2427
// Continue running package deploy for all components like any other package
25-
config.DeployOptions.PackagePath = fmt.Sprintf("zarf-init-%s.tar.zst", config.GetArch())
26-
28+
initPackageName := fmt.Sprintf("zarf-init-%s.tar.zst", config.GetArch())
29+
config.DeployOptions.PackagePath = initPackageName
30+
31+
// Use an init-package in the executable directory if none exist in current working directory
32+
if utils.InvalidPath(config.DeployOptions.PackagePath) {
33+
executablePath, err := utils.GetFinalExecutablePath()
34+
if err != nil {
35+
message.Fatal(err, "Unable to get the directory where the zarf cli executable lives")
36+
}
37+
38+
executableDir := path.Dir(executablePath)
39+
config.DeployOptions.PackagePath = filepath.Join(executableDir, initPackageName)
40+
}
2741
// Run everything
2842
packager.Deploy()
2943
},

src/internal/utils/io.go

+14
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,17 @@ func CreatePathAndCopy(source string, destination string) {
136136
}
137137
pterm.Success.Printfln("Copying %s", source)
138138
}
139+
140+
// GetFinalExecutablePath returns the absolute path to the zarf executable, following any symlinks along the way
141+
func GetFinalExecutablePath() (string, error) {
142+
message.Debug("utils.GetExecutablePath()")
143+
144+
binaryPath, err := os.Executable()
145+
if err != nil {
146+
return "", err
147+
}
148+
149+
// In case the binary is symlinked somewhere else, get the final destination!!
150+
linkedPath, err := filepath.EvalSymlinks(binaryPath)
151+
return linkedPath, err
152+
}

0 commit comments

Comments
 (0)