Skip to content

Commit c9ffd94

Browse files
authored
🤖 fix: render GoReleaser channel templates when GORELEASER_CHANNEL is unset (#138)
## What broke The v0.1.1 release build ([run](https://github.com/coder/coder-k8s/actions/runs/36110595919)) failed before publishing anything: ``` template: failed to apply "{{ eq .Env.GORELEASER_CHANNEL \"main\" }}": map has no entry for key "GORELEASER_CHANNEL" ``` `release.yaml` never sets `GORELEASER_CHANNEL`, and GoReleaser rejects a template that reads a missing `.Env` key. The changelog template already used `index .Env`; the `release.disable` and both `dockers_v2` `disable` templates did not. No binaries, archives or images were published for v0.1.1. ## Fix - `.goreleaser.yaml`: read the channel with `index .Env "GORELEASER_CHANNEL"` in all three templates. - `.github/workflows/release.yaml`: set `GORELEASER_CHANNEL: release` explicitly. - `hack/main_publish_test.go`: `TestReleaseAndImageChannels` renders the release and both `dockers_v2` disable templates with `missingkey=error` for the `main`, empty, `release` and unset channels, and checks which pipes run on each (release and the release image off only on `main`; the `:main` image on only on `main`). ## Validation - The new test fails on the v0.1.1 config with the same `map has no entry` error, and passes on this PR. - `make verify-vendor`, `make build`, `make lint`, `make test` and actionlint pass. - A local `goreleaser release --clean --skip=announce,publish` cannot reproduce the failure: the release and image pipes it fails in are skipped when publishing is skipped. The unit test is the gate for those templates. The real check is the next release run. ![The channel test passes on this PR and fails with the v0.1.1 config](https://github.com/user-attachments/assets/3726ad51-d271-4127-bad3-ddbfabb15909) Terminal recording (vhs capture; timing approximate): https://github.com/user-attachments/assets/8c3c135a-cf06-4b60-b457-3610cc7daffa ## After this lands Cut v0.1.2 from `main`. The v0.1.1 tag stays: its source already contains #136, but it has no release artifacts. --- _Generated with [`xum`](https://github.com/coder/xum) • Model: `anthropic:claude-opus-5-5` • Thinking: `medium` • Cost: `$1754.57`_
1 parent 78a2eca commit c9ffd94

3 files changed

Lines changed: 65 additions & 3 deletions

File tree

‎.github/workflows/release.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
args: release --clean
4444
env:
4545
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46+
GORELEASER_CHANNEL: release
4647

4748
- name: Compute release image tag
4849
id: release_image_tag

‎.goreleaser.yaml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ archives:
3131
- README.md
3232

3333
release:
34-
disable: '{{ eq .Env.GORELEASER_CHANNEL "main" }}'
34+
disable: '{{ eq (index .Env "GORELEASER_CHANNEL") "main" }}'
3535

3636
dockers_v2:
3737
- id: coder-k8s-image-main
38-
disable: '{{ ne .Env.GORELEASER_CHANNEL "main" }}'
38+
disable: '{{ ne (index .Env "GORELEASER_CHANNEL") "main" }}'
3939
dockerfile: Dockerfile.goreleaser
4040
ids:
4141
- coder-k8s
@@ -64,7 +64,7 @@ dockers_v2:
6464
- "--provenance=false"
6565

6666
- id: coder-k8s-image-release
67-
disable: '{{ eq .Env.GORELEASER_CHANNEL "main" }}'
67+
disable: '{{ eq (index .Env "GORELEASER_CHANNEL") "main" }}'
6868
dockerfile: Dockerfile.goreleaser
6969
ids:
7070
- coder-k8s

‎hack/main_publish_test.go‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,67 @@ func TestChangelogChannels(t *testing.T) {
5151
}
5252
}
5353

54+
// The release workflow does not set GORELEASER_CHANNEL, and GoReleaser fails a template that reads a missing
55+
// .Env key ("map has no entry"). Every channel-dependent disable template must render for an unset channel,
56+
// and pick the right pipes per channel.
57+
func TestReleaseAndImageChannels(t *testing.T) {
58+
data, err := os.ReadFile("../.goreleaser.yaml")
59+
if err != nil {
60+
t.Fatal(err)
61+
}
62+
var config struct {
63+
Release struct {
64+
Disable string `json:"disable"`
65+
} `json:"release"`
66+
DockersV2 []struct {
67+
ID string `json:"id"`
68+
Disable string `json:"disable"`
69+
} `json:"dockers_v2"`
70+
}
71+
if err := yaml.Unmarshal(data, &config); err != nil {
72+
t.Fatal(err)
73+
}
74+
// want maps each template to whether it must be disabled on the main channel (and enabled otherwise).
75+
type check struct {
76+
name, text string
77+
disabledOnMain bool
78+
}
79+
checks := []check{{name: "release", text: config.Release.Disable, disabledOnMain: true}}
80+
for _, d := range config.DockersV2 {
81+
switch d.ID {
82+
case "coder-k8s-image-main":
83+
checks = append(checks, check{name: d.ID, text: d.Disable, disabledOnMain: false})
84+
case "coder-k8s-image-release":
85+
checks = append(checks, check{name: d.ID, text: d.Disable, disabledOnMain: true})
86+
default:
87+
t.Fatalf("unexpected dockers_v2 id %q; add it to this test", d.ID)
88+
}
89+
}
90+
if len(checks) != 3 {
91+
t.Fatalf("expected release plus two dockers_v2 entries, got %d checks", len(checks))
92+
}
93+
for _, c := range checks {
94+
tmpl, err := template.New(c.name).Option("missingkey=error").Parse(c.text)
95+
if err != nil {
96+
t.Fatalf("%s: %v", c.name, err)
97+
}
98+
for _, channel := range []string{"main", "", "release", "unset"} {
99+
env := map[string]string{}
100+
if channel != "unset" {
101+
env["GORELEASER_CHANNEL"] = channel
102+
}
103+
var result strings.Builder
104+
if err := tmpl.Execute(&result, struct{ Env map[string]string }{Env: env}); err != nil {
105+
t.Fatalf("%s, channel %q: %v", c.name, channel, err)
106+
}
107+
wantDisabled := (channel == "main") == c.disabledOnMain
108+
if (result.String() == "true") != wantDisabled {
109+
t.Fatalf("%s disabled = %q for channel %q", c.name, result.String(), channel)
110+
}
111+
}
112+
}
113+
}
114+
54115
// `goreleaser release --clean` deletes its output directory. dist/ holds the tracked install bundle, so
55116
// GoReleaser writes to .goreleaser-dist instead, and .gitignore must ignore that whole directory to keep the
56117
// release worktree clean.

0 commit comments

Comments
 (0)