mirror of
https://github.com/thegeeklab/git-sv.git
synced 2024-11-21 12:00:40 +00:00
feat: add sections to release-notes config (headers is deprecated)
issue: #40
This commit is contained in:
parent
e64d4ddcc1
commit
e650f64783
@ -77,8 +77,14 @@ func defaultConfig() Config {
|
||||
UpdatePatch: []string{"build", "ci", "chore", "docs", "fix", "perf", "refactor", "style", "test"},
|
||||
IgnoreUnknown: false,
|
||||
},
|
||||
Tag: sv.TagConfig{Pattern: "%d.%d.%d"},
|
||||
ReleaseNotes: sv.ReleaseNotesConfig{Headers: map[string]string{"fix": "Bug Fixes", "feat": "Features", "breaking-change": "Breaking Changes"}},
|
||||
Tag: sv.TagConfig{Pattern: "%d.%d.%d"},
|
||||
ReleaseNotes: sv.ReleaseNotesConfig{
|
||||
Sections: []sv.ReleaseNotesSectionConfig{
|
||||
{Name: "Features", SectionType: "commits", CommitTypes: []string{"feat"}},
|
||||
{Name: "Bug Fixes", SectionType: "commits", CommitTypes: []string{"fix"}},
|
||||
{Name: "Breaking Changes", SectionType: "breaking-change"},
|
||||
},
|
||||
},
|
||||
Branches: sv.BranchesConfig{
|
||||
Prefix: "([a-z]+\\/)?",
|
||||
Suffix: "(-.*)?",
|
||||
@ -129,3 +135,35 @@ func (t *mergeTransformer) Transformer(typ reflect.Type) func(dst, src reflect.V
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func migrateConfig(cfg Config) Config {
|
||||
if cfg.ReleaseNotes.Headers == nil {
|
||||
return cfg
|
||||
}
|
||||
warnf("config 'release-notes.headers' is deprecated, please use 'sections' instead!")
|
||||
|
||||
return Config{
|
||||
Version: cfg.Version,
|
||||
Versioning: cfg.Versioning,
|
||||
Tag: cfg.Tag,
|
||||
ReleaseNotes: sv.ReleaseNotesConfig{
|
||||
Sections: migrateReleaseNotesConfig(cfg.ReleaseNotes.Headers),
|
||||
},
|
||||
Branches: cfg.Branches,
|
||||
CommitMessage: cfg.CommitMessage,
|
||||
}
|
||||
}
|
||||
|
||||
func migrateReleaseNotesConfig(headers map[string]string) []sv.ReleaseNotesSectionConfig {
|
||||
order := []string{"feat", "fix", "refactor", "perf", "test", "build", "ci", "chore", "docs", "style"}
|
||||
var sections []sv.ReleaseNotesSectionConfig
|
||||
for _, key := range order {
|
||||
if name, exists := headers[key]; exists {
|
||||
sections = append(sections, sv.ReleaseNotesSectionConfig{Name: name, SectionType: sv.ReleaseNotesSectionTypeCommits, CommitTypes: []string{key}})
|
||||
}
|
||||
}
|
||||
if name, exists := headers["breaking-change"]; exists {
|
||||
sections = append(sections, sv.ReleaseNotesSectionConfig{Name: name, SectionType: sv.ReleaseNotesSectionTypeBreakingChange})
|
||||
}
|
||||
return sections
|
||||
}
|
||||
|
26
sv/config.go
26
sv/config.go
@ -68,5 +68,29 @@ type TagConfig struct {
|
||||
|
||||
// ReleaseNotesConfig release notes preferences.
|
||||
type ReleaseNotesConfig struct {
|
||||
Headers map[string]string `yaml:"headers"`
|
||||
Headers map[string]string `yaml:"headers"`
|
||||
Sections []ReleaseNotesSectionConfig `yaml:"sections"`
|
||||
}
|
||||
|
||||
func (cfg ReleaseNotesConfig) sectionConfig(sectionType string) *ReleaseNotesSectionConfig {
|
||||
for _, sectionCfg := range cfg.Sections {
|
||||
if sectionCfg.SectionType == sectionType {
|
||||
return §ionCfg
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReleaseNotesSectionConfig preferences for a single section on release notes.
|
||||
type ReleaseNotesSectionConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
SectionType string `yaml:"section-type"`
|
||||
CommitTypes []string `yaml:"commit-types"`
|
||||
}
|
||||
|
||||
const (
|
||||
// ReleaseNotesSectionTypeCommits ReleaseNotesSectionConfig.SectionType value.
|
||||
ReleaseNotesSectionTypeCommits = "commits"
|
||||
// ReleaseNotesSectionTypeBreakingChange ReleaseNotesSectionConfig.SectionType value.
|
||||
ReleaseNotesSectionTypeBreakingChange = "breaking-change"
|
||||
)
|
||||
|
@ -23,18 +23,20 @@ func NewReleaseNoteProcessor(cfg ReleaseNotesConfig) *ReleaseNoteProcessorImpl {
|
||||
|
||||
// Create create a release note based on commits.
|
||||
func (p ReleaseNoteProcessorImpl) Create(version *semver.Version, tag string, date time.Time, commits []GitCommitLog) ReleaseNote {
|
||||
mapping := commitSectionMapping(p.cfg.Sections)
|
||||
|
||||
sections := make(map[string]ReleaseNoteSection)
|
||||
authors := make(map[string]struct{})
|
||||
var breakingChanges []string
|
||||
for _, commit := range commits {
|
||||
authors[commit.AuthorName] = struct{}{}
|
||||
if name, exists := p.cfg.Headers[commit.Message.Type]; exists {
|
||||
section, sexists := sections[commit.Message.Type]
|
||||
if sectionCfg, exists := mapping[commit.Message.Type]; exists {
|
||||
section, sexists := sections[sectionCfg.Name]
|
||||
if !sexists {
|
||||
section = ReleaseNoteSection{Name: name, Types: []string{commit.Message.Type}} //TODO: change to support more than one type per section
|
||||
section = ReleaseNoteSection{Name: sectionCfg.Name, Types: sectionCfg.CommitTypes}
|
||||
}
|
||||
section.Items = append(section.Items, commit)
|
||||
sections[commit.Message.Type] = section
|
||||
sections[sectionCfg.Name] = section
|
||||
}
|
||||
if commit.Message.BreakingMessage() != "" {
|
||||
// TODO: if no message found, should use description instead?
|
||||
@ -43,12 +45,24 @@ func (p ReleaseNoteProcessorImpl) Create(version *semver.Version, tag string, da
|
||||
}
|
||||
|
||||
var breakingChangeSection BreakingChangeSection
|
||||
if name, exists := p.cfg.Headers[breakingChangeMetadataKey]; exists && len(breakingChanges) > 0 {
|
||||
breakingChangeSection = BreakingChangeSection{Name: name, Messages: breakingChanges}
|
||||
if bcCfg := p.cfg.sectionConfig(ReleaseNotesSectionTypeBreakingChange); bcCfg != nil && len(breakingChanges) > 0 {
|
||||
breakingChangeSection = BreakingChangeSection{Name: bcCfg.Name, Messages: breakingChanges}
|
||||
}
|
||||
return ReleaseNote{Version: version, Tag: tag, Date: date.Truncate(time.Minute), Sections: sections, BreakingChanges: breakingChangeSection, AuthorsNames: authors}
|
||||
}
|
||||
|
||||
func commitSectionMapping(sections []ReleaseNotesSectionConfig) map[string]ReleaseNotesSectionConfig {
|
||||
mapping := make(map[string]ReleaseNotesSectionConfig)
|
||||
for _, section := range sections {
|
||||
if section.SectionType == ReleaseNotesSectionTypeCommits {
|
||||
for _, commitType := range section.CommitTypes {
|
||||
mapping[commitType] = section
|
||||
}
|
||||
}
|
||||
}
|
||||
return mapping
|
||||
}
|
||||
|
||||
// ReleaseNote release note.
|
||||
type ReleaseNote struct {
|
||||
Version *semver.Version
|
||||
|
@ -25,7 +25,7 @@ func TestReleaseNoteProcessorImpl_Create(t *testing.T) {
|
||||
tag: "v1.0.0",
|
||||
date: date,
|
||||
commits: []GitCommitLog{commitlog("t1", map[string]string{}, "a")},
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"t1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "a")})}, nil, map[string]struct{}{"a": {}}),
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"Tag 1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "a")})}, nil, map[string]struct{}{"a": {}}),
|
||||
},
|
||||
{
|
||||
name: "unmapped tag",
|
||||
@ -33,7 +33,7 @@ func TestReleaseNoteProcessorImpl_Create(t *testing.T) {
|
||||
tag: "v1.0.0",
|
||||
date: date,
|
||||
commits: []GitCommitLog{commitlog("t1", map[string]string{}, "a"), commitlog("unmapped", map[string]string{}, "a")},
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"t1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "a")})}, nil, map[string]struct{}{"a": {}}),
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"Tag 1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "a")})}, nil, map[string]struct{}{"a": {}}),
|
||||
},
|
||||
{
|
||||
name: "breaking changes tag",
|
||||
@ -41,7 +41,7 @@ func TestReleaseNoteProcessorImpl_Create(t *testing.T) {
|
||||
tag: "v1.0.0",
|
||||
date: date,
|
||||
commits: []GitCommitLog{commitlog("t1", map[string]string{}, "a"), commitlog("unmapped", map[string]string{"breaking-change": "breaks"}, "a")},
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"t1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "a")})}, []string{"breaks"}, map[string]struct{}{"a": {}}),
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"Tag 1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "a")})}, []string{"breaks"}, map[string]struct{}{"a": {}}),
|
||||
},
|
||||
{
|
||||
name: "multiple authors",
|
||||
@ -49,12 +49,14 @@ func TestReleaseNoteProcessorImpl_Create(t *testing.T) {
|
||||
tag: "v1.0.0",
|
||||
date: date,
|
||||
commits: []GitCommitLog{commitlog("t1", map[string]string{}, "author3"), commitlog("t1", map[string]string{}, "author2"), commitlog("t1", map[string]string{}, "author1")},
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"t1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "author3"), commitlog("t1", map[string]string{}, "author2"), commitlog("t1", map[string]string{}, "author1")})}, nil, map[string]struct{}{"author1": {}, "author2": {}, "author3": {}}),
|
||||
want: releaseNote(semver.MustParse("1.0.0"), "v1.0.0", date, map[string]ReleaseNoteSection{"Tag 1": newReleaseNoteSection("Tag 1", []string{"t1"}, []GitCommitLog{commitlog("t1", map[string]string{}, "author3"), commitlog("t1", map[string]string{}, "author2"), commitlog("t1", map[string]string{}, "author1")})}, nil, map[string]struct{}{"author1": {}, "author2": {}, "author3": {}}),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
p := NewReleaseNoteProcessor(ReleaseNotesConfig{Headers: map[string]string{"t1": "Tag 1", "t2": "Tag 2", "breaking-change": "Breaking Changes"}})
|
||||
p := NewReleaseNoteProcessor(ReleaseNotesConfig{Sections: []ReleaseNotesSectionConfig{{Name: "Tag 1", SectionType: "commits", CommitTypes: []string{"t1"}},
|
||||
{Name: "Tag 2", SectionType: "commits", CommitTypes: []string{"t2"}},
|
||||
{Name: "Breaking Changes", SectionType: "breaking-change"}}})
|
||||
if got := p.Create(tt.version, tt.tag, tt.date, tt.commits); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ReleaseNoteProcessorImpl.Create() = %v, want %v", got, tt.want)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user