Skip to content

Commit

Permalink
feat: support multiline commit messages within changelog (#373)
Browse files Browse the repository at this point in the history
  • Loading branch information
ga-paul-t authored Aug 28, 2023
1 parent af8eb91 commit 571466e
Show file tree
Hide file tree
Showing 15 changed files with 297 additions and 83 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*.dll
*.so
*.dylib
/uplift

# Test binary, built with `go test -c`
*.test
Expand Down
25 changes: 8 additions & 17 deletions cmd/uplift/bump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,10 @@ docs: update docs
feat: a new feature
fix: a bug fix
(tag: 0.1.0) feat: this was the last feature`
gittest.InitRepository(t, gittest.WithLog(log))

// TODO:
// gittest.StagedFile(t, "", "") > TempFile and StageFile under the covers
// gittest.WithCommittedFiles("", "", "", "") > file is automatically committed at the end

gittest.TempFile(t, "test.txt", bumpFile)
gittest.StageFile(t, "test.txt")
gittest.TempFile(t, ".uplift.yml", bumpConfig)
gittest.StageFile(t, ".uplift.yml")
gittest.Commit(t, "chore: added files")
gittest.InitRepository(t,
gittest.WithLog(log),
gittest.WithCommittedFiles("test.txt", ".uplift.yml"),
gittest.WithFileContent("test.txt", bumpFile, ".uplift.yml", bumpConfig))

bmpCmd := newBumpCmd(noChangesPushed(), os.Stdout)

Expand All @@ -77,12 +70,10 @@ func TestBump_PrereleaseFlag(t *testing.T) {
fix: fix bug
feat!: breaking change
feat: this is a new feature`
gittest.InitRepository(t, gittest.WithLog(log))
gittest.TempFile(t, "test.txt", bumpFile)
gittest.StageFile(t, "test.txt")
gittest.TempFile(t, ".uplift.yml", bumpConfig)
gittest.StageFile(t, ".uplift.yml")
gittest.Commit(t, "chore: added files")
gittest.InitRepository(t,
gittest.WithLog(log),
gittest.WithCommittedFiles("test.txt", ".uplift.yml"),
gittest.WithFileContent("test.txt", bumpFile, ".uplift.yml", bumpConfig))

bmpCmd := newBumpCmd(&globalOptions{}, os.Stdout)
bmpCmd.Cmd.SetArgs([]string{"--prerelease", "-beta.1+12345"})
Expand Down
21 changes: 15 additions & 6 deletions cmd/uplift/changelog.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,19 @@ uplift changelog --include "^.*\(scope\)"
# Generate the next changelog entry but do not stage or push any changes
# back to the git remote
uplift changelog --no-stage`
uplift changelog --no-stage
# Generate a changelog with multiline commit messages
uplift changelog --multiline`
)

type changelogOptions struct {
DiffOnly bool
Exclude []string
Include []string
All bool
Sort string
DiffOnly bool
Exclude []string
Include []string
All bool
Sort string
Multiline bool
*globalOptions
}

Expand Down Expand Up @@ -126,6 +130,7 @@ func newChangelogCmd(gopts *globalOptions, out io.Writer) *changelogCommand {
f.StringSliceVar(&chglogCmd.Opts.Exclude, "exclude", []string{}, "a list of regexes for excluding conventional commits from the changelog")
f.StringSliceVar(&chglogCmd.Opts.Include, "include", []string{}, "a list of regexes to cherry-pick conventional commits for the changelog")
f.StringVar(&chglogCmd.Opts.Sort, "sort", "", "the sort order of commits within each changelog entry")
f.BoolVar(&chglogCmd.Opts.Multiline, "multiline", false, "include multiline commit messages within changelog (skips truncation)")

chglogCmd.Cmd = cmd
return chglogCmd
Expand Down Expand Up @@ -185,6 +190,10 @@ func setupChangelogContext(opts changelogOptions, out io.Writer) (*context.Conte
ctx.NoStage = opts.NoStage
ctx.Changelog.DiffOnly = opts.DiffOnly
ctx.Changelog.All = opts.All
ctx.Changelog.Multiline = opts.Multiline
if !ctx.Changelog.Multiline && ctx.Config.Changelog != nil {
ctx.Changelog.Multiline = ctx.Config.Changelog.Multiline
}

// Sort order provided as a command-line flag takes precedence
ctx.Changelog.Sort = opts.Sort
Expand Down
28 changes: 28 additions & 0 deletions cmd/uplift/changelog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,31 @@ func TestChangelog_Hooks(t *testing.T) {
assert.FileExists(t, AfterChangelogFile)
assert.FileExists(t, AfterFile)
}

func TestChangelog_WithMultiline(t *testing.T) {
log := `> (tag: 2.0.0) feat: this is a multiline commit
The entire contents of this commit should exist in the changelog.
Multiline formatting should be correct for rendering in markdown
> fix: this is a bug fix
> docs: update documentation
this now includes code examples`
gittest.InitRepository(t, gittest.WithLog(log))

chglogCmd := newChangelogCmd(noChangesPushed(), os.Stdout)
chglogCmd.Cmd.SetArgs([]string{"--multiline"})

err := chglogCmd.Cmd.Execute()
require.NoError(t, err)

assert.True(t, changelogExists(t))

cl := readChangelog(t)
assert.Contains(t, cl, `feat: this is a multiline commit
The entire contents of this commit should exist in the changelog.
Multiline formatting should be correct for rendering in markdown`)
assert.Contains(t, cl, "fix: this is a bug fix")
assert.Contains(t, cl, `docs: update documentation
this now includes code examples`)
}
6 changes: 6 additions & 0 deletions cmd/uplift/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ type releaseOptions struct {
Exclude []string
Include []string
Sort string
Multiline bool
*globalOptions
}

Expand Down Expand Up @@ -133,6 +134,7 @@ func newReleaseCmd(gopts *globalOptions, out io.Writer) *releaseCommand {
f.StringSliceVar(&relCmd.Opts.Exclude, "exclude", []string{}, "a list of regexes for excluding conventional commits from the changelog")
f.StringSliceVar(&relCmd.Opts.Include, "include", []string{}, "a list of regexes to cherry-pick conventional commits for the changelog")
f.StringVar(&relCmd.Opts.Sort, "sort", "", "the sort order of commits within each changelog entry")
f.BoolVar(&relCmd.Opts.Multiline, "multiline", false, "include multiline commit messages within changelog (skips truncation)")

relCmd.Cmd = cmd
return relCmd
Expand Down Expand Up @@ -191,6 +193,10 @@ func setupReleaseContext(opts releaseOptions, out io.Writer) (*context.Context,
ctx.Changelog.PreTag = true

// Merge config and command line arguments together
ctx.Changelog.Multiline = opts.Multiline
if !ctx.Changelog.Multiline && ctx.Config.Changelog != nil {
ctx.Changelog.Multiline = ctx.Config.Changelog.Multiline
}
ctx.Changelog.Include = opts.Include
ctx.Changelog.Exclude = opts.Exclude
if ctx.Config.Changelog != nil {
Expand Down
61 changes: 40 additions & 21 deletions cmd/uplift/release_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,10 @@ func TestRelease(t *testing.T) {
fix: bug fix
docs: update docs
ci: update pipeline`
gittest.InitRepository(t, gittest.WithLog(log))

gittest.TempFile(t, "test.txt", bumpFile)
gittest.StageFile(t, "test.txt")
gittest.TempFile(t, ".uplift.yml", bumpConfig)
gittest.StageFile(t, ".uplift.yml")
gittest.Commit(t, "chore: added files")
gittest.InitRepository(t,
gittest.WithLog(log),
gittest.WithCommittedFiles("test.txt", ".uplift.yml"),
gittest.WithFileContent("test.txt", bumpFile, ".uplift.yml", bumpConfig))

relCmd := newReleaseCmd(noChangesPushed(), os.Stdout)

Expand Down Expand Up @@ -120,13 +117,10 @@ func TestRelease_PrereleaseFlag(t *testing.T) {
log := `refactor: make changes
feat: new feature
docs: update docs`
gittest.InitRepository(t, gittest.WithLog(log))

gittest.TempFile(t, "test.txt", bumpFile)
gittest.StageFile(t, "test.txt")
gittest.TempFile(t, ".uplift.yml", bumpConfig)
gittest.StageFile(t, ".uplift.yml")
gittest.Commit(t, "chore: added files")
gittest.InitRepository(t,
gittest.WithLog(log),
gittest.WithCommittedFiles("test.txt", ".uplift.yml"),
gittest.WithFileContent("test.txt", bumpFile, ".uplift.yml", bumpConfig))

relCmd := newReleaseCmd(noChangesPushed(), os.Stdout)
relCmd.Cmd.SetArgs([]string{"--prerelease", "-beta.1+12345"})
Expand Down Expand Up @@ -166,13 +160,10 @@ func TestRelease_SkipBumps(t *testing.T) {
fix: bug fix
ci: updated workflow
(tag: 1.0.0) feat: first feature`
gittest.InitRepository(t, gittest.WithLog(log))

gittest.TempFile(t, "test.txt", bumpFile)
gittest.StageFile(t, "test.txt")
gittest.TempFile(t, ".uplift.yml", bumpConfig)
gittest.StageFile(t, ".uplift.yml")
gittest.Commit(t, "chore: added files")
gittest.InitRepository(t,
gittest.WithLog(log),
gittest.WithCommittedFiles("test.txt", ".uplift.yml"),
gittest.WithFileContent("test.txt", bumpFile, ".uplift.yml", bumpConfig))

relCmd := newReleaseCmd(noChangesPushed(), os.Stdout)
relCmd.Cmd.SetArgs([]string{"--skip-bumps"})
Expand Down Expand Up @@ -270,3 +261,31 @@ feat: a new feat`
assert.NotContains(t, cl, "ci: a ci task")
assert.NotContains(t, cl, "docs: some new docs")
}

func TestRelease_WithMultiline(t *testing.T) {
log := `> feat: this is a multiline commit
The entire contents of this commit should exist in the changelog.
Multiline formatting should be correct for rendering in markdown
> fix: this is a bug fix
> docs: update documentation
this now includes code examples`
gittest.InitRepository(t, gittest.WithLog(log))

relCmd := newReleaseCmd(noChangesPushed(), os.Stdout)
relCmd.Cmd.SetArgs([]string{"--multiline"})

err := relCmd.Cmd.Execute()
require.NoError(t, err)

assert.True(t, changelogExists(t))

cl := readChangelog(t)
assert.Contains(t, cl, `feat: this is a multiline commit
The entire contents of this commit should exist in the changelog.
Multiline formatting should be correct for rendering in markdown`)
assert.Contains(t, cl, "fix: this is a bug fix")
assert.Contains(t, cl, `docs: update documentation
this now includes code examples`)
}
10 changes: 8 additions & 2 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ uplift changelog --diff-only

## Migrate an Existing Repository

:octicons-beaker-24: Experimental

If your repository does not contain a `CHANGELOG.md` file, you can generate one that spans its entire history. A word of warning, this does require a tagging structure to be in place.

```sh
uplift changelog --all
```

## Supporting Multiline Commits

You can configure `uplift` to include multiline commit messages within your changelog by changing its default behaviour to truncate them to a single line.

```sh
uplift changelog --multiline
```
5 changes: 5 additions & 0 deletions docs/reference/cli/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ uplift changelog --include "^.*\(scope\)"
# Generate the next changelog entry but do not stage or push any changes
# back to the git remote
uplift changelog --no-stage
# Generate a changelog with multiline commit messages
uplift changelog --multiline
```

## Flags
Expand All @@ -58,6 +61,8 @@ uplift changelog --no-stage
-h, --help help for changelog
--include strings a list of regexes to cherry-pick conventional commits
for the changelog
--multiline include multiline commit messages within changelog
(skips truncation)
--sort string the sort order of commits within each changelog entry
```

Expand Down
2 changes: 2 additions & 0 deletions docs/reference/cli/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ uplift release --no-prefix
-h, --help help for release
--include strings a list of regexes to cherry-pick conventional commits
for the changelog
--multiline include multiline commit messages within changelog
(skips truncation)
--no-prefix strip the default 'v' prefix from the next calculated
semantic version
--prerelease string append a prerelease suffix to next calculated semantic
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ changelog:
# commits that are to be included
include:
- '^.*\(scope\)'
# Include multiline commit messages within the changelog. Disables
# default behaviour of truncating a commit message to its first line
multiline: true
```

## commitAuthor
Expand Down
Loading

0 comments on commit 571466e

Please sign in to comment.