Skip to content

Instantly share code, notes, and snippets.

@bobvanderlinden
Last active May 18, 2018 12:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bobvanderlinden/bdbf44bf3bda9d6c0a30495e51ff0c97 to your computer and use it in GitHub Desktop.
Save bobvanderlinden/bdbf44bf3bda9d6c0a30495e51ff0c97 to your computer and use it in GitHub Desktop.
Changelog in Markdown/JSON using Gradle

This Gradle script will generate a changelog.json file from a recent_changes.txt. The recent_changes.txt is a Markdown file where a developer can define the changelog and the Gradle task will convert it to JSON, so that it can be used inside a app or in later Gradle tasks. The resulting JSON structure can be found in example.changelog.json.

In addition, the changelog.json is reused for a whatsnew file that can be uploaded to Google Play using Google Play Publisher.

// Generate changelog
android.applicationVariants.all { variant ->
def outputDir = file("${buildDir}/changelog")
def inputFile = file("${rootProject.projectDir}/docs/recent_changes.txt")
def outputFile = file("${outputDir}/changelog.json")
android.sourceSets.main.assets.srcDir outputDir
def generateChangelogTask = task("generate${variant.name.capitalize()}Changelog").doLast {
def versions = []
inputFile.eachLine { line ->
def match
if ((match = (line =~ /^v(\d+\.\d+\.\d+(?:-\w+)?) (\d+)$/)).matches()) {
def versionName = match.group(1)
def versionCode = match.group(2).toInteger()
versions.add([
name: versionName,
code: versionCode,
changes: []
])
} else if ((match = (line =~ /^\* (.*)$/)).matches()) {
versions.last().changes.add(match.group(1))
} else if (line == "") {
// Should be last line of version.
} else {
throw new InvalidUserDataException("Incorrect format")
}
}
outputDir.mkdirs()
outputFile.text = groovy.json.JsonOutput.toJson(versions)
}
generateChangelogTask.inputs.files inputFile
generateChangelogTask.outputs.files outputFile
generateChangelogTask.metaClass.outputFile = outputFile
generateChangelogTask.metaClass.inputFile = inputFile
variant.mergeAssets.dependsOn generateChangelogTask
if (variant.buildType.isDebuggable()) {
return
}
def validateChangelogTask = task("validate${variant.name.capitalize()}Changelog").doLast {
def json = new groovy.json.JsonSlurper().parseText(file(outputFile).getText())
def changelogVersionName = json[0].name
def changelogVersionCode = json[0].code
if (changelogVersionName != variant.versionName) {
throw new InvalidUserDataException("Version name (${variant.versionName}) of ${variant.name} does not match last changelog entry (${changelogVersionName})")
}
if (changelogVersionCode % 100 != 0) {
throw new InvalidUserDataException("Version code of changelog entry (${changelogVersionCode}) is invalid. It should be a multiple of 100.")
}
if ((changelogVersionCode / 100 as long) != (variant.versionCode / 100 as long)) {
throw new InvalidUserDataException("Version code (${variant.versionCode}) of ${variant.name} does not match last changelog entry (${changelogVersionCode})")
}
}
validateChangelogTask.inputs.files outputFile
validateChangelogTask.dependsOn generateChangelogTask
variant.mergeAssets.dependsOn validateChangelogTask
}
// Generate whatsnew to use with https://github.com/Triple-T/gradle-play-publisher
android.applicationVariants.all { variant ->
if (variant.buildType.isDebuggable()) {
return
}
def changelogJsonFile = project.tasks["generate${variant.name.capitalize()}Changelog"].outputFile
def listingDir = file("${buildDir}/listing")
def cultureDir = file("${listingDir}/en-US")
def whatsnewFile = file("${cultureDir}/whatsnew")
def generateWhatsnewTask = task("generate${variant.name.capitalize()}Whatsnew").doLast {
def json = new groovy.json.JsonSlurper().parseText(file(changelogJsonFile).getText())
assert json[0].changes instanceof List
def changes = json[0].changes.collect { "* ${it}" }.join("\n")
// Remove lines that exceed the maximum number of characters in a whatsnew message
if (changes.length() > 500) {
changes = changes.substring(0, changes.lastIndexOf('*', 500) - 1)
}
cultureDir.mkdirs()
whatsnewFile.text = changes
}
generateWhatsnewTask.inputs.files changelogJsonFile
generateWhatsnewTask.outputs.files whatsnewFile
generateWhatsnewTask.dependsOn project.tasks["generate${variant.name.capitalize()}Changelog"]
}
[{"name":"1.0.0","code":1000000,"changes":["This is something that has changed","Another change"]},{"name":"0.9.0","code":90000,"changes":["This was a change for a previous version"]}]
v1.0.0 1000000
* This is something that has changed
* Another change
v0.9.0 90000
* This was a change for a previous version
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment