import groovy.json.* import java.text.SimpleDateFormat JIRA_BASE_URL = 'https://issues.redhat.com/rest/api/2' JIRA_PROJECT = 'DBZ' RELEASE_NOTES_LABEL = 'add-to-upgrade-guide' ISSUE_BUG = ['Bug'] as Set ISSUE_ENHANCEMENT = ['Enhancement', 'Feature Request'] as Set ISSUE_TASK = ['Task', 'Sub-task'] ISSUE_BASE_URL = 'https://issues.redhat.com/browse/' if (args.length != 4) { println "Usage: generate-release-notes.groovy " return -1 } version = args[0] previousVersion = args[1] kafkaVersion = args[2] jiraPat = args[3] def today() { def currentDate = new Date() def format switch (currentDate.date % 10) { case 1: case 21: case 31: format = new SimpleDateFormat("MMMM d'st' yyyy", Locale.ENGLISH) break case 2: case 22: format = new SimpleDateFormat("MMMM d'nd' yyyy", Locale.ENGLISH) break case 3: case 23: format = new SimpleDateFormat("MMMM d'rd' yyyy", Locale.ENGLISH) break default: format = new SimpleDateFormat("MMMM d'th' yyyy", Locale.ENGLISH) } format.format(currentDate) } def jiraURL(path, params = [:]) { def url = "$JIRA_BASE_URL/$path" if (params) { url <<= '?' << params.collect {k, v -> "$k=${URLEncoder.encode(v, 'US-ASCII')}"}.join('&') } return url.toString().toURL() } def jiraGET(path, params = [:]) { jiraURL(path, params).openConnection().with { doOutput = true requestMethod = 'GET' setRequestProperty('Content-Type', 'application/json') setRequestProperty('Authorization', "Bearer $jiraPat") new JsonSlurper().parse(new StringReader(content.text)) } } def unresolvedIssuesFromJira() { jiraGET('search', [ 'jql': "project=$JIRA_PROJECT AND fixVersion=$version ORDER BY key ASC", 'maxResults': '500' ]).issues.collect { ['key': it.key, 'title': it.fields.summary, 'type': it.fields.issuetype.name, 'labels': it.fields.labels] } } def findVersion() { jiraGET('project/DBZ/versions').find { it.name == version } } def markdownSection(section, issues) { println """### $section since $previousVersion """ if (!issues) { println 'None' } else { issues.each { issue -> println "* ${issue.title} [$issue.key](${ISSUE_BASE_URL}${issue.key})" } } println "\n" } def asciidocSection(section, issues) { println "=== $section\n" if (!issues) { println "There are no ${section.toLowerCase()} in this release." } else { issues.each { issue -> println "* ${issue.title} ${ISSUE_BASE_URL}${issue.key}[$issue.key]" } } println '\n' } def asciidocPlaceholderSection(section, issues) { println "=== $section\n" if (!issues) { println "There are no ${section.toLowerCase()} in this release." } else { issues.each { issue -> println "[Placeholder for $section text] (${ISSUE_BASE_URL}${issue.key}[$issue.key]).\n" } } println '\n' } def versionId = findVersion().id def issues = unresolvedIssuesFromJira() def newFeatures = issues.findAll { it.type in ISSUE_ENHANCEMENT && !(RELEASE_NOTES_LABEL in it.labels) } def fixes = issues.findAll { it.type in ISSUE_BUG && !(RELEASE_NOTES_LABEL in it.labels) } def otherChanges = issues.findAll { it.type in ISSUE_TASK && !(RELEASE_NOTES_LABEL in it.labels) } def breakingChanges = issues.findAll { RELEASE_NOTES_LABEL in it.labels } println """ ================================================================================ CHANGELOG.md ================================================================================ ## $version ${today()} [Detailed release notes](https://issues.redhat.com/secure/ReleaseNote.jspa?projectId=12317320&version=$versionId) """ markdownSection('New features', newFeatures) markdownSection('Breaking changes', breakingChanges) markdownSection('Fixes', fixes) markdownSection('Other changes', otherChanges) println """ ================================================================================ ================================================================================ release-notes.asciidoc ================================================================================ [[release-${version.toLowerCase().reverse().replaceFirst('\\.', '-').reverse()}]] == *Release $version* _(${today()})_ See the https://issues.redhat.com/secure/ReleaseNote.jspa?projectId=12317320&version=$versionId[complete list of issues]. === Kafka compatibility This release has been built against Kafka Connect $kafkaVersion and has been tested with version $kafkaVersion of the Kafka brokers. See the https://kafka.apache.org/documentation/#upgrade[Kafka documentation] for compatibility with other versions of Kafka brokers. === Upgrading Before upgrading any connector, be sure to check the backward-incompatible changes that have been made since the release you were using. When you decide to upgrade one of these connectors to $version from any earlier versions, first check the migration notes for the version you're using. Gracefully stop the running connector, remove the old plugin files, install the $version plugin files, and restart the connector using the same configuration. Upon restart, the $version connectors will continue where the previous connector left off. As one might expect, all change events previously written to Kafka by the old connector will not be modified. If you are using our container images, then please do not forget to pull them fresh from https://quay.io/organization/debezium[Quay.io]. """ asciidocPlaceholderSection('Breaking changes', breakingChanges) asciidocSection('New features', newFeatures) asciidocSection('Fixes', fixes) asciidocSection('Other changes', otherChanges) println '\n================================================================================'