feat: generate compare links for changelog references
This commit is contained in:
@@ -9,6 +9,7 @@ package vociferate
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -246,7 +247,7 @@ func updateChangelog(rootDir, version, releaseDate, changelogPath string) error
|
|||||||
updated := text[:afterHeader] + "\n" + defaultUnreleasedTemplate + "\n" + newSection + text[nextSectionStart:]
|
updated := text[:afterHeader] + "\n" + defaultUnreleasedTemplate + "\n" + newSection + text[nextSectionStart:]
|
||||||
repoURL, ok := deriveRepositoryURL(rootDir)
|
repoURL, ok := deriveRepositoryURL(rootDir)
|
||||||
if ok {
|
if ok {
|
||||||
updated = addChangelogLinks(updated, repoURL)
|
updated = addChangelogLinks(updated, repoURL, rootDir)
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(path, []byte(updated), 0o644); err != nil {
|
if err := os.WriteFile(path, []byte(updated), 0o644); err != nil {
|
||||||
return fmt.Errorf("write changelog: %w", err)
|
return fmt.Errorf("write changelog: %w", err)
|
||||||
@@ -426,7 +427,7 @@ func normalizeRepoURL(remoteURL string) (string, bool) {
|
|||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
func addChangelogLinks(text, repoURL string) string {
|
func addChangelogLinks(text, repoURL, rootDir string) string {
|
||||||
repoURL = strings.TrimSuffix(strings.TrimSpace(repoURL), "/")
|
repoURL = strings.TrimSuffix(strings.TrimSpace(repoURL), "/")
|
||||||
if repoURL == "" {
|
if repoURL == "" {
|
||||||
return text
|
return text
|
||||||
@@ -456,16 +457,60 @@ func addChangelogLinks(text, repoURL string) string {
|
|||||||
text = strings.Join(lines[:cutAt], "\n") + "\n"
|
text = strings.Join(lines[:cutAt], "\n") + "\n"
|
||||||
|
|
||||||
// Build and append reference link definitions.
|
// Build and append reference link definitions.
|
||||||
linkDefs := []string{fmt.Sprintf("[Unreleased]: %s/src/branch/main", repoURL)}
|
releasedMatches := releasedSectionRe.FindAllStringSubmatch(text, -1)
|
||||||
for _, match := range releasedSectionRe.FindAllStringSubmatch(text, -1) {
|
releasedVersions := make([]string, 0, len(releasedMatches))
|
||||||
|
for _, match := range releasedMatches {
|
||||||
if len(match) >= 2 {
|
if len(match) >= 2 {
|
||||||
linkDefs = append(linkDefs, fmt.Sprintf("[%s]: %s/releases/tag/v%s", match[1], repoURL, match[1]))
|
releasedVersions = append(releasedVersions, match[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
linkDefs := make([]string, 0, len(releasedVersions)+1)
|
||||||
|
if len(releasedVersions) > 0 {
|
||||||
|
latest := releasedVersions[0]
|
||||||
|
linkDefs = append(linkDefs, fmt.Sprintf("[Unreleased]: %s/compare/v%s...main", repoURL, latest))
|
||||||
|
} else {
|
||||||
|
linkDefs = append(linkDefs, fmt.Sprintf("[Unreleased]: %s/src/branch/main", repoURL))
|
||||||
|
}
|
||||||
|
|
||||||
|
firstCommitShort, hasFirstCommit := firstCommitShortHash(rootDir)
|
||||||
|
for i, version := range releasedVersions {
|
||||||
|
if i+1 < len(releasedVersions) {
|
||||||
|
previousVersion := releasedVersions[i+1]
|
||||||
|
linkDefs = append(linkDefs, fmt.Sprintf("[%s]: %s/compare/v%s...v%s", version, repoURL, previousVersion, version))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasFirstCommit {
|
||||||
|
linkDefs = append(linkDefs, fmt.Sprintf("[%s]: %s/compare/%s...v%s", version, repoURL, firstCommitShort, version))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
linkDefs = append(linkDefs, fmt.Sprintf("[%s]: %s/compare/v%s...main", version, repoURL, version))
|
||||||
|
}
|
||||||
|
|
||||||
return strings.TrimRight(text, "\n") + "\n\n" + strings.Join(linkDefs, "\n") + "\n"
|
return strings.TrimRight(text, "\n") + "\n\n" + strings.Join(linkDefs, "\n") + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func firstCommitShortHash(rootDir string) (string, bool) {
|
||||||
|
command := exec.Command("git", "-C", rootDir, "rev-list", "--max-parents=0", "--abbrev-commit", "HEAD")
|
||||||
|
output, err := command.Output()
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
commit := strings.TrimSpace(string(output))
|
||||||
|
if commit == "" {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(commit, "\n") {
|
||||||
|
commit = strings.SplitN(commit, "\n", 2)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return commit, true
|
||||||
|
}
|
||||||
|
|
||||||
func parseSemver(version string) (semver, error) {
|
func parseSemver(version string) (semver, error) {
|
||||||
parts := strings.Split(strings.TrimSpace(version), ".")
|
parts := strings.Split(strings.TrimSpace(version), ".")
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
|
|||||||
Reference in New Issue
Block a user