fix: restore unreleased template behavior

This commit is contained in:
Micheal Wilkinson
2026-03-20 23:24:01 +00:00
parent eb7d2798f1
commit cdfe75f360

View File

@@ -19,6 +19,7 @@ const (
defaultVersionFile = "release-version" defaultVersionFile = "release-version"
defaultVersionExpr = `^\s*([^\r\n]+)\s*$` defaultVersionExpr = `^\s*([^\r\n]+)\s*$`
defaultChangelog = "changelog.md" defaultChangelog = "changelog.md"
defaultUnreleasedBody = "### Breaking\n\n### Added\n\n### Changed\n\n### Removed\n\n### Fixed\n"
) )
var releasedSectionRe = regexp.MustCompile(`(?m)^## \[(\d+\.\d+\.\d+)\] - `) var releasedSectionRe = regexp.MustCompile(`(?m)^## \[(\d+\.\d+\.\d+)\] - `)
@@ -95,8 +96,8 @@ func Prepare(rootDir, version, releaseDate string, options Options) error {
// - minor: Unreleased contains Added entries // - minor: Unreleased contains Added entries
// - patch: all other cases // - patch: all other cases
// //
// When no previous release is present in the changelog, the base version is // When no previous release is present in the changelog, the first
// treated as 0.0.0. // recommendation is always v1.0.0.
func RecommendedTag(rootDir string, options Options) (string, error) { func RecommendedTag(rootDir string, options Options) (string, error) {
resolved, err := resolveOptions(options) resolved, err := resolveOptions(options)
if err != nil { if err != nil {
@@ -104,6 +105,7 @@ func RecommendedTag(rootDir string, options Options) (string, error) {
} }
var currentVersion string var currentVersion string
noPriorRelease := false
if options.VersionFile != "" { if options.VersionFile != "" {
currentVersion, err = readCurrentVersion(rootDir, resolved) currentVersion, err = readCurrentVersion(rootDir, resolved)
if err != nil { if err != nil {
@@ -116,6 +118,7 @@ func RecommendedTag(rootDir string, options Options) (string, error) {
} }
if !found { if !found {
currentVersion = "0.0.0" currentVersion = "0.0.0"
noPriorRelease = true
} else { } else {
currentVersion = version currentVersion = version
} }
@@ -131,8 +134,12 @@ func RecommendedTag(rootDir string, options Options) (string, error) {
return "", err return "", err
} }
if noPriorRelease {
return "v1.0.0", nil
}
switch { switch {
case strings.Contains(unreleasedBody, "### Breaking"), sectionHasEntries(unreleasedBody, "Removed"): case sectionHasEntries(unreleasedBody, "Breaking"), sectionHasEntries(unreleasedBody, "Removed"):
parsed.major++ parsed.major++
parsed.minor = 0 parsed.minor = 0
parsed.patch = 0 parsed.patch = 0
@@ -226,7 +233,7 @@ func updateChangelog(rootDir, version, releaseDate, changelogPath string) error
return err return err
} }
if strings.TrimSpace(unreleasedBody) == "" { if !unreleasedHasEntries(unreleasedBody) {
return fmt.Errorf("unreleased section is empty") return fmt.Errorf("unreleased section is empty")
} }
@@ -236,7 +243,7 @@ func updateChangelog(rootDir, version, releaseDate, changelogPath string) error
newSection += "\n" newSection += "\n"
} }
updated := text[:afterHeader] + "\n" + newSection + text[nextSectionStart:] updated := text[:afterHeader] + "\n" + defaultUnreleasedBody + "\n" + newSection + text[nextSectionStart:]
repoURL, ok := deriveRepositoryURL(rootDir) repoURL, ok := deriveRepositoryURL(rootDir)
if ok { if ok {
updated = addChangelogLinks(updated, repoURL) updated = addChangelogLinks(updated, repoURL)
@@ -269,13 +276,25 @@ func readUnreleasedBody(rootDir, changelogPath string) (string, error) {
return "", err return "", err
} }
if strings.TrimSpace(unreleasedBody) == "" { if !unreleasedHasEntries(unreleasedBody) {
return "", fmt.Errorf("unreleased section is empty") return "", fmt.Errorf("unreleased section is empty")
} }
return unreleasedBody, nil return unreleasedBody, nil
} }
func unreleasedHasEntries(unreleasedBody string) bool {
for _, line := range strings.Split(unreleasedBody, "\n") {
trimmed := strings.TrimSpace(line)
if trimmed == "" || strings.HasPrefix(trimmed, "### ") {
continue
}
return true
}
return false
}
func readChangelogState(rootDir, changelogPath string) (string, string, int, int, string, error) { func readChangelogState(rootDir, changelogPath string) (string, string, int, int, string, error) {
path := filepath.Join(rootDir, changelogPath) path := filepath.Join(rootDir, changelogPath)
contents, err := os.ReadFile(path) contents, err := os.ReadFile(path)