chore(go): use vociferate for unreleased parsing

This commit is contained in:
Micheal Wilkinson
2026-03-21 14:25:27 +00:00
parent b7d1760beb
commit e625d475a5
3 changed files with 36 additions and 17 deletions

View File

@@ -13,6 +13,7 @@ func main() {
version := flag.String("version", "", "semantic version to release, with or without leading v") version := flag.String("version", "", "semantic version to release, with or without leading v")
date := flag.String("date", "", "release date in YYYY-MM-DD format") date := flag.String("date", "", "release date in YYYY-MM-DD format")
recommend := flag.Bool("recommend", false, "print the recommended next release tag based on the changelog") recommend := flag.Bool("recommend", false, "print the recommended next release tag based on the changelog")
printUnreleased := flag.Bool("print-unreleased", false, "print the current Unreleased changelog body")
root := flag.String("root", ".", "repository root to update") root := flag.String("root", ".", "repository root to update")
versionFile := flag.String("version-file", "", "path to the version file, relative to --root") versionFile := flag.String("version-file", "", "path to the version file, relative to --root")
versionPattern := flag.String("version-pattern", "", "regexp with one capture group for the version value") versionPattern := flag.String("version-pattern", "", "regexp with one capture group for the version value")
@@ -41,8 +42,18 @@ func main() {
return return
} }
if *printUnreleased {
body, err := vociferate.UnreleasedBody(absRoot, opts)
if err != nil {
fmt.Fprintf(os.Stderr, "print unreleased: %v\n", err)
os.Exit(1)
}
fmt.Print(body)
return
}
if *version == "" || *date == "" { if *version == "" || *date == "" {
fmt.Fprintln(os.Stderr, "usage: vociferate --version <version> --date <YYYY-MM-DD> [--root <dir>] [--version-file <path>] [--version-pattern <regexp>] [--changelog <path>] | --recommend [--root <dir>] [--version-file <path>] [--version-pattern <regexp>] [--changelog <path>]") fmt.Fprintln(os.Stderr, "usage: vociferate --version <version> --date <YYYY-MM-DD> [--root <dir>] [--version-file <path>] [--version-pattern <regexp>] [--changelog <path>] | --recommend [--root <dir>] [--version-file <path>] [--version-pattern <regexp>] [--changelog <path>] | --print-unreleased [--root <dir>] [--changelog <path>]")
os.Exit(2) os.Exit(2)
} }

View File

@@ -147,9 +147,15 @@ runs:
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
"$comments_url" >/dev/null "$comments_url" >/dev/null
- name: Setup Go for vociferate
uses: actions/setup-go@v5
with:
go-version-file: ${{ github.action_path }}/../go.mod
- name: Extract changelog unreleased entries - name: Extract changelog unreleased entries
id: extract-changelog id: extract-changelog
shell: bash shell: bash
working-directory: ${{ github.action_path }}/..
env: env:
CHANGELOG: ${{ inputs.changelog }} CHANGELOG: ${{ inputs.changelog }}
run: | run: |
@@ -160,25 +166,11 @@ runs:
exit 0 exit 0
fi fi
# Extract everything between [Unreleased] header and the next [X.Y.Z] header
unreleased="$(awk '
/^## \[Unreleased\]/ { in_unreleased=1; next }
/^## \[[0-9]+\.[0-9]+\.[0-9]+\]/ { if (in_unreleased) exit }
in_unreleased && NF { print }
' "$CHANGELOG")"
# Use a temporary file to handle multiline content
tmp_file=$(mktemp)
printf '%s' "$unreleased" > "$tmp_file"
# Read it back and set as output
delimiter="EOF_CHANGELOG" delimiter="EOF_CHANGELOG"
printf '%s<<%s\n' "unreleased_entries<<$delimiter" "$delimiter" >> "$GITHUB_OUTPUT" printf 'unreleased_entries<<%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
cat "$tmp_file" >> "$GITHUB_OUTPUT" go run ./cmd/vociferate --print-unreleased --root "$GITHUB_WORKSPACE" --changelog "$CHANGELOG" >> "$GITHUB_OUTPUT"
printf '%s\n' "$delimiter" >> "$GITHUB_OUTPUT" printf '%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
rm -f "$tmp_file"
- name: Validate changelog gate - name: Validate changelog gate
id: changelog-gate id: changelog-gate
shell: bash shell: bash

View File

@@ -209,6 +209,12 @@ func RecommendedTag(rootDir string, options Options) (string, error) {
return defaultService().RecommendedTag(rootDir, options) return defaultService().RecommendedTag(rootDir, options)
} }
// UnreleasedBody returns the current Unreleased changelog body exactly as it
// should appear in downstream tooling.
func UnreleasedBody(rootDir string, options Options) (string, error) {
return defaultService().UnreleasedBody(rootDir, options)
}
// RecommendedTag returns the next semantic release tag based on current changelog state. // RecommendedTag returns the next semantic release tag based on current changelog state.
func (s *Service) RecommendedTag(rootDir string, options Options) (string, error) { func (s *Service) RecommendedTag(rootDir string, options Options) (string, error) {
resolved, err := resolveOptions(options) resolved, err := resolveOptions(options)
@@ -265,6 +271,16 @@ func (s *Service) RecommendedTag(rootDir string, options Options) (string, error
return fmt.Sprintf("v%d.%d.%d", parsed.major, parsed.minor, parsed.patch), nil return fmt.Sprintf("v%d.%d.%d", parsed.major, parsed.minor, parsed.patch), nil
} }
// UnreleasedBody returns the current Unreleased changelog body.
func (s *Service) UnreleasedBody(rootDir string, options Options) (string, error) {
resolved, err := resolveOptions(options)
if err != nil {
return "", err
}
return s.readUnreleasedBody(rootDir, resolved.Changelog)
}
func sectionHasEntries(unreleasedBody, sectionName string) bool { func sectionHasEntries(unreleasedBody, sectionName string) bool {
heading := "### " + sectionName heading := "### " + sectionName
sectionStart := strings.Index(unreleasedBody, heading) sectionStart := strings.Index(unreleasedBody, heading)