feat(releaser): release v1.4.0 — GitHub, SSH agent, configurable bumps
- GitHub release support: internal/ghclient (no SDK, minimal HTTP client); GITHUB_TOKEN env var; github.token/github.repo config; GitHub takes precedence over GitLab when both are configured; publisher interface (releasePublisher) in cmd/main.go makes providers interchangeable - SSH agent push: gitutil.Push() now tries gitssh.NewSSHAgentAuth for git@/ssh:// remotes before falling back to the system git binary - --release-env-file flag: override dotenv artifact path; pass "" to disable - git.releasable_types config: filter which commit types trigger a bump (defaults to fix, feat, breaking); useful for maintenance branches - commits.Group(), ExtractSubject(), ReleasableSet() exported helpers: notes.go and changelog.go now delegate to these instead of duplicating - CHANGELOG deduplication guard: changelog.Update() is idempotent — skips write if ## [version] section already exists - Always load config sources: LoadWithSources() called unconditionally; removes the dual config path that previously only tracked sources in --verbose mode - .releaser.gitlab-ci.yml: adds artifacts: reports: dotenv: release.env Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,19 +4,17 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.k3nny.fr/releaser/internal/commits"
|
||||
)
|
||||
|
||||
var headerSubjectRe = regexp.MustCompile(`(?i)^\w+(?:\([^)]*\))?!?\s*:\s*(.+)`)
|
||||
|
||||
// Update inserts a new release section into the CHANGELOG file at path.
|
||||
// If the file does not exist it is created with a standard header.
|
||||
// Only commits with a releasable type (fix, feat, breaking) produce bullets;
|
||||
// if none are found the file is left untouched.
|
||||
// If a section for version already exists the file is left untouched (idempotent).
|
||||
func Update(path, tag, version string, messages []string) error {
|
||||
section := buildSection(version, messages)
|
||||
if section == "" {
|
||||
@@ -31,6 +29,10 @@ func Update(path, tag, version string, messages []string) error {
|
||||
return fmt.Errorf("read %s: %w", path, err)
|
||||
}
|
||||
|
||||
if strings.Contains(existing, "## ["+version+"]") {
|
||||
return nil
|
||||
}
|
||||
|
||||
var out string
|
||||
if existing == "" {
|
||||
out = "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n" +
|
||||
@@ -48,26 +50,7 @@ func Update(path, tag, version string, messages []string) error {
|
||||
}
|
||||
|
||||
func buildSection(version string, messages []string) string {
|
||||
var breaking, feats, fixes []string
|
||||
|
||||
for _, msg := range messages {
|
||||
t := commits.Parse(msg)
|
||||
if t == commits.TypeNone {
|
||||
continue
|
||||
}
|
||||
first := strings.SplitN(strings.TrimSpace(msg), "\n", 2)[0]
|
||||
subject := extractSubject(first)
|
||||
|
||||
switch t {
|
||||
case commits.TypeBreaking:
|
||||
breaking = append(breaking, subject)
|
||||
case commits.TypeFeat:
|
||||
feats = append(feats, subject)
|
||||
case commits.TypeFix:
|
||||
fixes = append(fixes, subject)
|
||||
}
|
||||
}
|
||||
|
||||
breaking, feats, fixes := commits.Group(messages)
|
||||
if len(breaking)+len(feats)+len(fixes) == 0 {
|
||||
return ""
|
||||
}
|
||||
@@ -91,11 +74,3 @@ func writeSection(sb *strings.Builder, title string, items []string) {
|
||||
fmt.Fprintf(sb, "- %s\n", item)
|
||||
}
|
||||
}
|
||||
|
||||
func extractSubject(header string) string {
|
||||
m := headerSubjectRe.FindStringSubmatch(header)
|
||||
if m != nil {
|
||||
return strings.TrimSpace(m[1])
|
||||
}
|
||||
return strings.TrimSpace(header)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user