Skip to content

Commit dfa7080

Browse files
committed
Add a release workflow that builds binaries on tag push
Pushing a v* tag cross-compiles static binaries (linux/darwin/windows, amd64/arm64), packages them with SHA256 checksums, and publishes a GitHub Release. The tag name is stamped into the binary via -ldflags, surfaced through a new -version flag.
1 parent f8407ae commit dfa7080

2 files changed

Lines changed: 101 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
name: Release
2+
3+
# Build cross-platform binaries and publish a GitHub Release whenever a
4+
# version tag (e.g. v1.2.3) is pushed.
5+
on:
6+
push:
7+
tags:
8+
- "v*"
9+
10+
# Required for softprops/action-gh-release to create the release.
11+
permissions:
12+
contents: write
13+
14+
jobs:
15+
build:
16+
name: Build ${{ matrix.goos }}/${{ matrix.goarch }}
17+
runs-on: ubuntu-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
include:
22+
- { goos: linux, goarch: amd64 }
23+
- { goos: linux, goarch: arm64 }
24+
- { goos: darwin, goarch: amd64 }
25+
- { goos: darwin, goarch: arm64 }
26+
- { goos: windows, goarch: amd64 }
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- uses: actions/setup-go@v5
31+
with:
32+
go-version-file: go.mod
33+
cache: true
34+
35+
- name: Build
36+
env:
37+
CGO_ENABLED: "0"
38+
GOOS: ${{ matrix.goos }}
39+
GOARCH: ${{ matrix.goarch }}
40+
VERSION: ${{ github.ref_name }}
41+
run: |
42+
bin=k8tc
43+
[ "$GOOS" = windows ] && bin=k8tc.exe
44+
# Static, trimmed, version-stamped — mirrors the Makefile's flags,
45+
# plus -s -w to strip debug info for a smaller release binary.
46+
go build -trimpath -ldflags "-s -w -X main.version=${VERSION}" -o "$bin" ./cmd/k8tc
47+
48+
- name: Package
49+
id: package
50+
env:
51+
GOOS: ${{ matrix.goos }}
52+
GOARCH: ${{ matrix.goarch }}
53+
VERSION: ${{ github.ref_name }}
54+
run: |
55+
name="k8tc_${VERSION}_${GOOS}_${GOARCH}"
56+
if [ "$GOOS" = windows ]; then
57+
zip "${name}.zip" k8tc.exe README.md
58+
echo "asset=${name}.zip" >> "$GITHUB_OUTPUT"
59+
else
60+
tar -czf "${name}.tar.gz" k8tc README.md
61+
echo "asset=${name}.tar.gz" >> "$GITHUB_OUTPUT"
62+
fi
63+
64+
- uses: actions/upload-artifact@v4
65+
with:
66+
name: ${{ steps.package.outputs.asset }}
67+
path: ${{ steps.package.outputs.asset }}
68+
if-no-files-found: error
69+
70+
release:
71+
name: Publish release
72+
needs: build
73+
runs-on: ubuntu-latest
74+
steps:
75+
- name: Download build artifacts
76+
uses: actions/download-artifact@v4
77+
with:
78+
path: dist
79+
merge-multiple: true
80+
81+
- name: Generate checksums
82+
working-directory: dist
83+
run: sha256sum * > SHA256SUMS
84+
85+
- name: Create release
86+
uses: softprops/action-gh-release@v2
87+
with:
88+
files: dist/*
89+
generate_release_notes: true
90+
fail_on_unmatched_files: true

cmd/k8tc/main.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import (
1919
"github.com/cosmocode/k8tc/internal/ui"
2020
)
2121

22+
// version is the build version, stamped at release time via
23+
// -ldflags "-X main.version=<tag>". It is "dev" for local builds.
24+
var version = "dev"
25+
2226
func main() {
2327
var (
2428
kubeContext string
@@ -28,6 +32,7 @@ func main() {
2832
remotePath string
2933
localPath string
3034
preserve bool
35+
showVersion bool
3136
)
3237

3338
flag.StringVar(&kubeContext, "context", "", "kube context (kubectl --context); default current")
@@ -41,8 +46,14 @@ func main() {
4146
flag.BoolVar(&preserve, "preserve-ownership", false,
4247
"attempt to restore owner UID/GID on extract (--same-owner --numeric-owner); "+
4348
"only effective against a privileged extract target")
49+
flag.BoolVar(&showVersion, "version", false, "print version and exit")
4450
flag.Parse()
4551

52+
if showVersion {
53+
fmt.Println("k8tc", version)
54+
return
55+
}
56+
4657
// Fail fast if kubectl is missing rather than surfacing it on first list.
4758
if _, err := exec.LookPath("kubectl"); err != nil {
4859
fmt.Fprintln(os.Stderr, "error: kubectl not found on PATH")

0 commit comments

Comments
 (0)