Skip to content

Commit 8cbdd7c

Browse files
dimuoncursoragent
andauthored
Pass CHANGELOG.md to GoReleaser so GitHub releases are not empty (#1054)
* Pass CHANGELOG.md to GoReleaser so GitHub releases are not empty. make release extracts this version's changelog section and passes --release-notes; /release no longer edits the GitHub release after the fact. * Match changelog headings as strings and clean up release-notes temp files. Copilot review: version dots were awk regex, and mktemp files were left behind after goreleaser. Co-authored-by: Cursor <cursoragent@cursor.com> * Keep GoReleaser's changelog pipe enabled so --release-notes is honored. changelog.disable: true ignores the notes file and publishes an empty GitHub body. Also quote the mktemp path and fix a reversed test label. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent aca36f9 commit 8cbdd7c

8 files changed

Lines changed: 199 additions & 7 deletions

File tree

‎.agents/skills/release/SKILL.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Only when the user explicitly asks to tag (typically after the PR is merged):
7171
1. Ensure you're on `master` with the merge commit
7272
2. Run `make tag` — it creates the `vX.Y.Z` tag (the `VERSION` minus its `-dev` suffix) and pushes it to the remote pointing at `elastic/terraform-provider-ec`, which triggers the Buildkite release pipeline.
7373
3. Equivalently, tag and push by hand: `git tag vX.Y.Z` then `git push <remote> vX.Y.Z`, where `<remote>` is the one pointing at `elastic/terraform-provider-ec` (often `upstream`).
74+
4. Do **not** `gh release edit`. `make release` (Buildkite) fills the GitHub release body from this version's `CHANGELOG.md` section (`scripts/extract-release-notes.sh` → GoReleaser `--release-notes`; `changelog.disable` in `.goreleaser.yml` would ignore that file). After the pipeline finishes, confirm `gh release view vX.Y.Z --repo elastic/terraform-provider-ec` shows that section (not an empty body).
7475

7576
## Important rules
7677

@@ -79,3 +80,4 @@ Only when the user explicitly asks to tag (typically after the PR is merged):
7980
- **Keep `-dev` suffix in `Makefile` and `ec/version.go`.**
8081
- **Verify `.changelog/` file contents against upstream.**
8182
- **Check all merged PRs, not just those with `.changelog/` entries.**
83+
- **Do not `gh release edit` for notes.** `make release` copies `CHANGELOG.md` into the GitHub release via `--release-notes` (requires the GoReleaser changelog pipe to stay enabled).

‎.goreleaser.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ release:
5858
name: terraform-provider-ec
5959
# If you want to manually examine the release before its live, uncomment this line:
6060
# draft: true
61-
changelog:
62-
disable: true
61+
# Do not set changelog.disable: true — GoReleaser then ignores --release-notes
62+
# and publishes an empty GitHub body. make release always passes --release-notes.
6363
snapshot:
6464
# Allows you to change the name of the generated snapshot
6565
#

‎build/Makefile.release‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,27 @@ endif
2424
snapshot:
2525
@ go tool goreleaser release --clean --snapshot
2626

27+
# GitHub release body is this version's CHANGELOG.md section, passed via
28+
# --release-notes. Do not set changelog.disable in .goreleaser.yml: that skips
29+
# the changelog pipe and ignores the file. extract-release-notes.sh fails if
30+
# the section is missing, so we never tag-publish a blank body.
31+
RELEASE_VERSION = $(subst -dev,,$(VERSION))
32+
2733
## Releases a new version of the terraform provider with a matching tag.
2834
release:
29-
@ $(MAKE) gen VERSION=$(subst -dev,,$(VERSION))
30-
@ go tool goreleaser release --clean --skip=validate --parallelism=4
35+
@ $(MAKE) gen VERSION=$(RELEASE_VERSION)
36+
@ notes=$$(mktemp) && \
37+
trap 'rm -f "$$notes"' EXIT && \
38+
./scripts/extract-release-notes.sh $(RELEASE_VERSION) > "$$notes" && \
39+
go tool goreleaser release --clean --skip=validate --parallelism=4 --release-notes "$$notes"
3140

3241
## Builds a new version of the terraform provider with a matching tag without publishing it.
3342
release-no-publish:
34-
@ $(MAKE) gen VERSION=$(subst -dev,,$(VERSION))
35-
@ go tool goreleaser release --clean --skip=publish,validate --parallelism=4
43+
@ $(MAKE) gen VERSION=$(RELEASE_VERSION)
44+
@ notes=$$(mktemp) && \
45+
trap 'rm -f "$$notes"' EXIT && \
46+
./scripts/extract-release-notes.sh $(RELEASE_VERSION) > "$$notes" && \
47+
go tool goreleaser release --clean --skip=publish,validate --parallelism=4 --release-notes "$$notes"
3648

3749
.PHONY: changelog
3850
changelog:

‎build/Makefile.test‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ _report_path:
2121
unit: _report_path
2222
@ echo "-> Running unit tests for $(BINARY)..."
2323
@ go test $(TEST) $(TESTARGS) $(TESTUNITARGS)
24+
@ echo "-> Running script tests..."
25+
@ ./scripts/extract-release-notes_test.sh
2426

2527
## Alias to "unit".
2628
tests: unit

‎dev-docs/RELEASE.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,11 @@ make tag
8686
configured). Pushing the tag triggers the Buildkite
8787
[release pipeline](https://buildkite.com/elastic/terraform-provider-ec-release), which runs
8888
[`.buildkite/release.sh`](../.buildkite/release.sh) → `make release` (GoReleaser) to build, sign,
89-
and publish the artifacts.
89+
and publish the artifacts. `make release` extracts this version's section from
90+
[`CHANGELOG.md`](../CHANGELOG.md) via [`scripts/extract-release-notes.sh`](../scripts/extract-release-notes.sh)
91+
and passes it to GoReleaser as `--release-notes`. Do not set `changelog.disable` in
92+
[`.goreleaser.yml`](../.goreleaser.yml): that skips the changelog pipe and ignores the file,
93+
so the GitHub body would stay empty.
9094

9195
Confirm the new version is listed in the
9296
[Terraform registry](https://registry.terraform.io/providers/elastic/ec/latest/docs).

‎scripts/extract-release-notes.sh‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Print the CHANGELOG.md section for a version (GitHub release body).
4+
# Usage: extract-release-notes.sh X.Y.Z [CHANGELOG.md]
5+
#
6+
7+
set -euo pipefail
8+
9+
if [[ $# -lt 1 || $# -gt 2 ]]; then
10+
echo "usage: $0 X.Y.Z [CHANGELOG.md]" >&2
11+
exit 2
12+
fi
13+
14+
version="${1#v}"
15+
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16+
changelog="${2:-$(dirname "${__dir}")/CHANGELOG.md}"
17+
18+
if [[ ! -f "$changelog" ]]; then
19+
echo "changelog not found: $changelog" >&2
20+
exit 1
21+
fi
22+
23+
awk -v ver="$version" '
24+
$1 == "#" {
25+
if ($2 == ver) { found = 1; next }
26+
if (found) exit
27+
}
28+
found {
29+
if (!started) {
30+
if ($0 ~ /^[[:space:]]*$/) next
31+
started = 1
32+
}
33+
lines[++n] = $0
34+
}
35+
END {
36+
if (!started) {
37+
print "no changelog section for " ver " in " FILENAME > "/dev/stderr"
38+
exit 1
39+
}
40+
while (n > 0 && lines[n] ~ /^[[:space:]]*$/) n--
41+
for (i = 1; i <= n; i++) print lines[i]
42+
}
43+
' "$changelog"
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env bash
2+
# Self-check for extract-release-notes.sh. Does not tag, push, or publish.
3+
4+
set -euo pipefail
5+
6+
dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
root="$(dirname "$dir")"
8+
extract="$dir/extract-release-notes.sh"
9+
fixture="$dir/testdata/changelog-extract.md"
10+
fail=0
11+
12+
assert_eq() {
13+
local name="$1" got="$2" want="$3"
14+
if [[ "$got" != "$want" ]]; then
15+
echo "FAIL: $name" >&2
16+
printf 'got:\n%s\nwant:\n%s\n' "$got" "$want" >&2
17+
fail=1
18+
else
19+
echo "ok: $name"
20+
fi
21+
}
22+
23+
assert_fails() {
24+
local name="$1"
25+
shift
26+
if "$@" >/dev/null 2>&1; then
27+
echo "FAIL: $name (expected non-zero exit)" >&2
28+
fail=1
29+
else
30+
echo "ok: $name"
31+
fi
32+
}
33+
34+
got="$("$extract" 0.13.1 "$fixture")"
35+
want=$'FEATURES:\n\n* first line of 0.13.1\n\nENHANCEMENTS:\n\n* second line of 0.13.1'
36+
assert_eq "fixture 0.13.1 body" "$got" "$want"
37+
38+
got="$("$extract" v0.13.0 "$fixture")"
39+
want=$'FEATURES:\n\n* only 0.13.0'
40+
assert_eq "fixture 0.13.0 strips v prefix" "$got" "$want"
41+
42+
got="$("$extract" 0.13.10 "$fixture")"
43+
want=$'FEATURES:\n\n* should not leak into 0.13.1'
44+
assert_eq "fixture 0.13.10 matches its own heading, not 0.13.1" "$got" "$want"
45+
46+
got="$("$extract" 0x13y1 "$fixture")"
47+
want=$'FEATURES:\n\n* must not match 0.13.1 via regex dots'
48+
assert_eq "fixture 0x13y1 is not 0.13.1 (dots are not regex)" "$got" "$want"
49+
50+
assert_fails "missing version" "$extract" 9.9.9 "$fixture"
51+
assert_fails "empty section" "$extract" 0.0.1 "$fixture"
52+
assert_fails "usage: no args" "$extract"
53+
assert_fails "changelog missing" "$extract" 0.13.1 "$dir/testdata/does-not-exist.md"
54+
55+
# Live CHANGELOG.md: same shape as GitHub notes for already-shipped versions.
56+
assert_live() {
57+
local version="$1" must_have="$2" must_not="$3"
58+
local got
59+
got="$("$extract" "$version" "$root/CHANGELOG.md")"
60+
if printf '%s\n' "$got" | grep -q '^# '; then
61+
echo "FAIL: live $version included a markdown heading" >&2
62+
printf 'got:\n%s\n' "$got" >&2
63+
fail=1
64+
return
65+
fi
66+
if [[ "$got" != FEATURES:* && "$got" != ENHANCEMENTS:* && "$got" != "BUG FIXES:"* && "$got" != NOTES:* && "$got" != "BREAKING CHANGES:"* ]]; then
67+
echo "FAIL: live $version did not start at a changelog category" >&2
68+
printf 'got:\n%s\n' "$got" >&2
69+
fail=1
70+
return
71+
fi
72+
if [[ "$got" != *"$must_have"* ]]; then
73+
echo "FAIL: live $version missing expected text: $must_have" >&2
74+
printf 'got:\n%s\n' "$got" >&2
75+
fail=1
76+
return
77+
fi
78+
if [[ "$got" == *"$must_not"* ]]; then
79+
echo "FAIL: live $version leaked: $must_not" >&2
80+
printf 'got:\n%s\n' "$got" >&2
81+
fail=1
82+
return
83+
fi
84+
echo "ok: live CHANGELOG $version"
85+
}
86+
87+
assert_live 0.13.0 "encryption_key_path" "linked"
88+
assert_live 0.13.1 "linked" "encryption_key_path"
89+
90+
if [[ "$fail" -ne 0 ]]; then
91+
exit 1
92+
fi
93+
echo "extract-release-notes_test.sh: all ok"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# 0x13y1 (January 1, 2028)
2+
3+
FEATURES:
4+
5+
* must not match 0.13.1 via regex dots
6+
7+
# 0.13.10 (January 1, 2027)
8+
9+
FEATURES:
10+
11+
* should not leak into 0.13.1
12+
13+
# 0.13.1 (September 14, 2026)
14+
15+
FEATURES:
16+
17+
* first line of 0.13.1
18+
19+
ENHANCEMENTS:
20+
21+
* second line of 0.13.1
22+
23+
# 0.13.0 (May 20, 2026)
24+
25+
FEATURES:
26+
27+
* only 0.13.0
28+
29+
# 0.0.1 (January 1, 2020)
30+
31+
32+
# 0.0.0 (January 1, 2019)
33+
34+
BUG FIXES:
35+
36+
* oldest

0 commit comments

Comments
 (0)