mockito / shipkit

Toolkit for shipping it used by Mockito library
http://shipkit.org
MIT License
158 stars 35 forks source link

Customized release notes #370

Open wwilk opened 7 years ago

wwilk commented 7 years ago

Problem:

If I want to change even a small detail about release notes (like date format or customize the summary message) it is not possible at the moment.

Solution:

We need some kind of customization of release notes.

First question I asked myself was how flexible it should be. User should be able to customize anything they want, but on the other hand assuming a simple base structure would probably make it easier for us to implement it, and maybe also to use it. We can probably assume that most of users would like to have a file with release notes sorted by date descending, so we can only allow formatting of a single release note.

So we can have a single release-notes.tmpl file which would contain the basic structure: /header.tmpl /release-summary.tmpl /improvements.tmpl

And header.tmpl can be further divided into emphasized-header.tmpl and regular-header.tmpl, etc. On each template user would be able to access "context" which would be a map of all properties related to release note (version, date, contributions etc). This gives user flexibility to change only a small part of the template. On the other hand it makes it a little more complex, because of the multiple files. Also template engine has to support nesting templates.

I first thought about one of the popular templating engines and I read about Mustache and Freemarker. The choice between them was based on the fact that Mustache is much smaller (95 kb vs 795 kb) and also seems to be a little more popular and supports more languages, the latter is not critical.

The problem with Mustache is that there seems to be no simple way to eg. format dates (see https://javarants.com/mustache-is-logic-less-but-the-logic-has-to-go-somewhere-3e976b7a49c8). It is supposed to be logic-free. In our case it drastically limits the abilities of end users.

So I tried much more flexible templating language - Groovy. First advantage is that we already have it on the classpath. It is a fully functional programming language, so it gives the end user a lot of flexibility, and also most users (especially Shipkit/Gradle users) should be familiar with its syntax.

I tried to use SimpleTemplateEngine class. Simple "regular-header.tmpl" would look like that:

**$version (${date.format("yyyy-MM-dd")})** -

As you can see formatting the date is really simple, as would be any other simple operation on text or numbers. The first problem I encountered is lack of support for nesting templates. I have managed to implement it myself by adding a closure "resolveTemplate" to "context" map. We can use it like that:

header.tmpl

${resolveTemplate(binding.variables, emphasize ? 'emphasized-header.tmpl' : 'regular-header.tmpl')}>

Argument "binding.variables" is the "context", we need to pass it every time when we want to nest a template. It is not that beautiful, but seems good enough, not that much code.

@mockito/shipkit-developers At this point I would go with Groovy, but I am interested in the thoughts of others. If you want to see more I can create a pull request with the details of my proof of concept.

mockitoguy commented 7 years ago

Great ideas and a very nice write-up! Some feedback:

//idea: new 'setContent' method:
updateReleaseNotes.setContent { ReleaseNotesData data ->
  return """multiline String that can reach out to $data"""
}