Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a task to create "templatized" release notes #28

Closed
sschuberth opened this issue Sep 18, 2023 · 20 comments
Closed

Add a task to create "templatized" release notes #28

sschuberth opened this issue Sep 18, 2023 · 20 comments
Labels
enhancement New feature or request

Comments

@sschuberth
Copy link
Contributor

I'm not sure if this would be out of scope, but as the commits since the last tag are determined anyway, maybe grouping them by type as part of writing out a release notes files in Markdown format would make sense. Such a Markdown file could then be used for the notes as part of GitHub releases. This would avoid users of this plugin to additionally take something like https://github.com/requarks/changelog-action into use, and ensure that the interpretation of Conventinal Commits is exactly the same for bumping the version and creating the notes.

@sschuberth
Copy link
Contributor Author

Oh, I completely missed that there's now a printChangeLog task! Almost what I want it seems, I need to have a deeper look.

@sschuberth
Copy link
Contributor Author

Do you think the ChangeLog layout could be made configurable, e.g. via Kotlin scripting or FreeMarker?

@jmongard
Copy link
Owner

The change log is somewhat configurable. I have not gotten around to document it as I'm still trying it out in my own projects.
The default configuration is made to generate a change log in markdown similar to Micronauts change log

  • Any text can be changed by replacing the value in the changeLogTexts map.
  • The entire map can be replaced by a new map.
  • Types and scope can be mapped (e.g. fix/feat/deps)
  • Unknown types can be map to a default category
  • Breaking changes will be mapped to a breaking category
  • Categories can be omitted by mapping to empty string
  • More than one category/scope can be mapped to the same category

Output is limited to:
Heading

Subheading
changelist

Subheading
changelist

Footer

import git.semver.plugin.gradle.ChangeLogFormatter

plugins {
    id("com.github.jmongard.git-semver-plugin") version "0.6.4"
}

semver {
    changeLogTexts = mutableMapOf(
        ChangeLogFormatter.OTHER_TYPE to "### Other Changes \uD83D\uDCA1",
        ChangeLogFormatter.MISSING_TYPE to "### Other Changes \uD83D\uDCA1",
        ChangeLogFormatter.BREAKING_CHANGE to "### Breaking Changes \uD83D\uDEE0",
        ChangeLogFormatter.HEADER to "## What's Changed",
        ChangeLogFormatter.CHANGE_PREFIX to "  - ",
        ChangeLogFormatter.CHANGE_LINE_SEPARATOR to "\n    ",
        ChangeLogFormatter.CHANGE_POSTFIX to "",
        "fix" to "### Bug Fixes \uD83D\uDC1E",
        "feat" to "### New Features \uD83C\uDF89",
        "test" to "### Tests ✅",
        "docs" to "### Docs \uD83D\uDCD6",
        "deps" to "### Dependency updates \uD83D\uDE80",
        "build" to "### Build \uD83D\uDC18 & CI ⚙\uFE0F",
        "ci" to "### Build \uD83D\uDC18 & CI ⚙\uFE0F",
        "chore" to "### Chores",
        "perf" to "### Performance Enhancements",
        "refactor" to "### Refactorings",
        "release" to "")
}

It should be possible to change this to output HTML if you like.

How would you like the output to be presented? What would be needed from a template file?

@sschuberth
Copy link
Contributor Author

The default configuration is made to generate a change log in markdown similar to Micronauts change log

That also looks quite nice. So far I was looking at https://github.com/requarks/changelog-action/releases.

It should be possible to change this to output HTML if you like.

No HTML please 😉 Markdown is just fine, as I'm looking for submitting the generated text to GitHub releases.

How would you like the output to be presented? What would be needed from a template file?

What I like about https://github.com/requarks/changelog-action is that it also lists the short commit SHA1 (as a clickable link) and the resolved issue, if any.

And some grouping on scopes (per type) like JReleaser does would maybe also be nice.

@sschuberth

This comment was marked as outdated.

@sschuberth

This comment was marked as resolved.

@sschuberth

This comment was marked as outdated.

@jmongard
Copy link
Owner

jmongard commented Sep 19, 2023

This works for publishing release notes to Github using a linux runner. (I'm still having trouble with the emojis being replaced by "?" when using a windows runner. I think it's some encoding issue in powershell.)

    - name: Create GitHub release
      if: "startsWith(github.ref, 'refs/tags/')"
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
        tag=$(git describe --tags --abbrev=0)
        version=$(./gradlew -q printVersion)
         ./gradlew -q printChangeLog | gh release create $tag -t "MyApp $version" -F -

@sschuberth
Copy link
Contributor Author

This works for publishing release notes to Github using a linux runner.

Yes, thanks, I have something similar in place.

I think it's some encoding issue in powershell.

It's probably easier to debug when omitting some variable pieces and writing to a file (with UTF-8 encoding) instead of going through shell redirection...

Anyway, shall I close this issue, as the task is there, and there's just the open question about if and how the changelog layout should be made more configurable? That could be discussed in a separate issue.

@sschuberth
Copy link
Contributor Author

if and how the changelog layout should be made more configurable?

I just found some inspiration.

@sschuberth sschuberth changed the title Add a task to create release notes in Markdown format Add a task to create "templatized" release notes Sep 20, 2023
@jmongard
Copy link
Owner

Yes, good inspiration but the mustache templates looks scary :-).
I'm thinking perhaps a Kotlin DSL could be created for templates e.g.

semver {
    changeLogSettings {
        template {
            Heading

            BreakingChanges {
               CommitMessage
            }

            ChangeList {
                ChangeHeader
                ChangeItem {
                    CommitHash
                    Scope("%s: ")
                    Text
                }
            }

            Footer
        }
    }
}

I never created a DSL like this so I'm a bit unsure how it could be done

@sschuberth
Copy link
Contributor Author

While I'm a big fan of Kotlin DSLs, for this use-case it could be a bit cumbersome to maintain. As soon as you'd introduce a new property in the data model, you'd need to also create an according DSL. That is, unless you use something like https://github.com/F43nd1r/autodsl or https://github.com/bipokot/Kabu 😆

@jmongard
Copy link
Owner

I'm currently experimenting with a way to configure the change log like this:

semver {
  groupVersionIncrements = false
  createReleaseTag = true
  createReleaseCommit = true
//changeLogFormat = ChangeLogFormat.scopeChangeLog
  changeLogFormat {
		appendLine("# My changelog").appendLine()

		withBreakingChanges {
			appendLine("## Breaking changes")
			format {
				"- ${fullHeader()}"
			}
			appendLine()
		}
		withType("fix") {
			appendLine("## Bug Fixes")
			format {
				"- ${scope()}${header()}"
			}
			appendLine()
		}
		withType("feat") {
			appendLine("## Features")
			format {
				"- ${scope()}${header()}"
			}
			appendLine()
		}
	}
}

and a more advanced example that first groups on type and then scope :

{
            appendLine(defaultHeader).appendLine()

            withType("release") {
                skip()
            }
            withBreakingChanges({
                appendLine(defaultBreakingChangeHeader).appendLine()
                groupByScope {
                    append("#### ").appendLine(key)
                    format {
                        "- ${hash()}${type()}${header()}"
                    }
                    appendLine()
                }
                withoutScope {
                    appendLine("#### Missing scope")
                    format {
                        "- ${hash()}${type()}${header()}"
                    }
                    appendLine()
                }
                appendLine()
            })
            groupBySorted({ defaultHeaderTexts[it.type].orEmpty() }, {
                appendLine(key).appendLine()
                groupByScope {
                    append("#### ").appendLine(key)
                    format {
                        "- ${hash()}${header()}"
                    }
                    appendLine()
                }
                withoutScope {
                    appendLine("#### Missing scope")
                    format {
                        "- ${hash()}${header()}"
                    }
                    appendLine()
                }
                appendLine()
            })
            otherwise({
                appendLine(defaultOtherChangeHeader).appendLine()
                groupByScope {
                    append("#### ").appendLine(key)
                    format {
                        "- ${hash()}${type()}${header()}"
                    }
                    appendLine()
                }
                withoutScope {
                    appendLine("#### Missing scope")
                    format {
                        "- ${hash()}${type()}${header()}"
                    }
                    appendLine()
                }
                appendLine()
            })
        }
        ```
      
The default format produces a change log very similar to the previous version. 
You can group and filter the commits any way you like and the use some predefined formatting methods to create the change log text for the commit. 

It is still missing functionality to access the author and commit time. I guess if you want the GitHub user name you need to access the GitHub API but I don't think I want to make the plugin specific to GitHub. 

@jmongard jmongard added the enhancement New feature or request label Oct 11, 2023
@sschuberth
Copy link
Contributor Author

How do you customize e.g. the top-most "What's Changed" header with the changeLogFormat {} approach?

@jmongard
Copy link
Owner

You either set the constant text

semver {
  ChangeLogFormat.defaultHeaderTexts[ChangeLogFormat.HEADER]="My Changelog Header"
  //Optionally use another predefined format
  changeLogFormat = ChangeLogFormat.scopeChangeLog
}

or if you have your custom format just append whatever you like:

semver {
  changeLogFormat {
      appendLine("# Test changelog").appendLine()
      withType("test") {
          appendLine("## Test")
          formatChanges {
              appendLine("- ${'$'}{scope()}${'$'}{header()}")
          }
          appendLine()
      }
  }
}

There is a bit of documentation to do for the change log feature 😅

@jmongard
Copy link
Owner

Maybe it can changed to something prettier 🤔

@sschuberth
Copy link
Contributor Author

Maybe it can changed to something prettier 🤔

I agree. It doesn't feel right to alter a mutable global map to do this. IMO header etc. should be (nested) properties on the semver / changeLogFormat extension that you can set like

semver {
    changeLogFormat {
        header = "What's New"
    }
}

@jmongard
Copy link
Owner

Changed in 0.9.0 so now you could set the text like this:

semver {
          changeLogTexts {
                   header = "# My Changelog"
                   breakingChange = "## Breaking"
                   otherChange = "## Other changelog"
                   headerTexts["feat"] = "## New Feature"
           }
}

How does it feel?

@sschuberth
Copy link
Contributor Author

How does it feel?

Looks good!

@sschuberth
Copy link
Contributor Author

While what's currently implemented in not the fully templatized approach I had in mind originally, I feel that it's configurable enough, so let me close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants