From 18edad9e45e763c3cc190e1ad4fc111162331175 Mon Sep 17 00:00:00 2001 From: Severin Rudie Date: Mon, 25 Nov 2019 19:03:40 -0800 Subject: [PATCH] No issue: add script for compiling closed issues from commit history (#6509) --- .github/ISSUE_TEMPLATE/release_checklist.md | 5 +- .../PrintMentionedIssuesAndPrs.kts | 102 ++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 automation/releasetools/PrintMentionedIssuesAndPrs.kts diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md index d54b7b1b2..8ce82027a 100644 --- a/.github/ISSUE_TEMPLATE/release_checklist.md +++ b/.github/ISSUE_TEMPLATE/release_checklist.md @@ -34,8 +34,9 @@ We will refer to the release that is going out as the *current* release. - [ ] Merge any remaining [automated L10N string PRs](https://github.com/mozilla-mobile/fenix/pull/6156). - [ ] Create a branch off of master (DO NOT PUSH YET) for the *current* milestone of format `releases/v2.3` (where 2.3 is the *current* milestone). After that, anything landing in master will be part of the next milestone. - [ ] On the Release branch, pin the AC version to the stable version ([example](https://github.com/mozilla-mobile/fenix/commit/e413da29f6a7a7d4a765817a9cd5687abbf27619)) with commit message "Issue #``: Pin to stable AC `` for release v2.3" (replacing 2.3 with the version) -- [ ] Go through the list of issues closed during this sprint and make sure they all have the correct milestone. -- [ ] Add `eng:qa:needed` flags on each issue that still needs it. +- For each issue closed since the last release (run `kotlinc -script automation/releasetools/PrintMentionedIssuesAndPrs.kts` to get a list [see script for details]): + - [ ] Ensure it has the correct milestone. + - [ ] Add `eng:qa:needed` flags on each issue that still needs it. - Note: You will need code review to make changes to the release branch after this point, because it is a protected branch. - [ ] Push the branch. diff --git a/automation/releasetools/PrintMentionedIssuesAndPrs.kts b/automation/releasetools/PrintMentionedIssuesAndPrs.kts new file mode 100644 index 000000000..10129316c --- /dev/null +++ b/automation/releasetools/PrintMentionedIssuesAndPrs.kts @@ -0,0 +1,102 @@ + +import java.io.File +import java.io.IOException +import java.util.concurrent.TimeUnit +import java.util.stream.Stream + +/** + * Script for use when compiling a changelog. It will find all GH mentions in commit + * messages newer than the HEAD of the passed git tag. If no tag is passed, it will + * default to the highest versioned tag, as defined by gits `--sort=version:refname`. + * + * @param (optional) git tag of the earliest commit through which to search. If null, + * this will default to the tag on origin with the highest version name. + * + * To run this script: + * - Update local master + * - From project root, run `kotlinc -script automation/releasetools/PrintMentionedIssuesAndPrs.kts` + * + * TODO + * - Use origin/master, instead of local master + * - Interface with the GitHub API to filter out references to PRs + * - Pull down issue names for each, to make constructing the changelog easier + */ + +val origin = "https://github.com/mozilla-mobile/fenix.git" +val DEBUG = false + +println("Starting PrintMentionedIssuesAndPrs.kts") + +val tag = try { args[0] } catch(e: IndexOutOfBoundsException) { getHighestVersionedTag() } +debug { "Last tag: $tag" } + +val commonCommit = getMostRecentCommonAncestorWithMaster(tag) +debug { "common commit: $commonCommit" } + +val log = gitLogSince(commonCommit) +debug { "Log: $log" } + +val numbers = getNumbersFromLog(log) +debug { "Numbers: ${numbers.joinToString()}" } + +println(numbers) + +fun getHighestVersionedTag(): String { + val originTags = runCommand("git ls-remote --tags --sort=version:refname $origin") + + // Tags are sorted in ascending order, so this returns the name of the newest tag + return originTags.substringAfterLast("refs/tags/") + // Trim the trailing line break + .trim() +} + +fun getMostRecentCommonAncestorWithMaster(tag: String): String { + runCommand("git fetch --tags") + // TODO use origin master + return runCommand("git merge-base master $tag").trim() +} + +fun gitLogSince(sha: String): String { + val returnAsString = "--no-pager" + val maxCount = "-500" + // There is no plumbing version of 'git log', but pretty formatting provides a + // mostly consistent return value + // See: https://stackoverflow.com/a/53584289/9307461 + val formatSubjectOnly = "--pretty=format:%s" + + return runCommand("git $returnAsString log $sha..HEAD $maxCount $formatSubjectOnly") +} + +fun getNumbersFromLog(log: String): List { + val pattern = "#\\d+".toRegex() + return pattern.findAll(log) + .map { it.value } + .distinct() + .toList() +} + +// Function adapted from: +// https://stackoverflow.com/questions/35421699/how-to-invoke-external-command-from-within-kotlin-code +fun runCommand(cmd: String, workingDir: File = File(".")): String { + try { + val parts = cmd.split(" ".toRegex()) + debug { "Parts: $parts" } + val proc = ProcessBuilder(*parts.toTypedArray()) + .directory(workingDir) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectError(ProcessBuilder.Redirect.PIPE) + .start() + proc.waitFor(10, TimeUnit.SECONDS) + + debug { "Err: ${proc.errorStream.bufferedReader().use { it.readText() }}" } + + return proc.inputStream.bufferedReader().use { it.readText() } + } catch(e: IOException) { + e.printStackTrace() + throw(e) + } +} + +fun debug(block: () -> String) { + if (DEBUG) println(block()) +}