From 27d3b024c506ef00bccd82aa783555a268828589 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Thu, 20 Dec 2018 22:45:09 +0100 Subject: [PATCH] build: publish release script should add release notes to tag (#14599) --- tools/release/extract-release-notes.ts | 17 +++++++++++++++++ tools/release/publish-release.ts | 17 ++++++++++++++--- tools/release/stage-release.ts | 2 +- 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 tools/release/extract-release-notes.ts diff --git a/tools/release/extract-release-notes.ts b/tools/release/extract-release-notes.ts new file mode 100644 index 00000000000..99ffad5a6a4 --- /dev/null +++ b/tools/release/extract-release-notes.ts @@ -0,0 +1,17 @@ +import {readFileSync} from 'fs'; + +/** Extracts the release notes for a specific release from a given changelog file. */ +export function extractReleaseNotes(changelogPath: string, versionName: string) { + const changelogContent = readFileSync(changelogPath, 'utf8'); + const escapedVersion = versionName.replace('.', '\\.'); + + // Regular expression that matches the release notes for the given version. Note that we specify + // the "s" RegExp flag so that the line breaks will be ignored within our regex. We determine the + // section of a version by starting with the release header which can either use the markdown + // "h1" or "h2" syntax. The end of the section will be matched by just looking for the first + // subsequent release header. + const releaseNotesRegex = new RegExp(`(##? ${escapedVersion}.*?)##? 7\\.`, 's'); + const matches = releaseNotesRegex.exec(changelogContent); + + return matches ? matches[1].trim() : null; +} diff --git a/tools/release/publish-release.ts b/tools/release/publish-release.ts index da4d400b1c9..15fe05c9bb2 100644 --- a/tools/release/publish-release.ts +++ b/tools/release/publish-release.ts @@ -3,12 +3,14 @@ import {execSync} from 'child_process'; import {readFileSync} from 'fs'; import {join} from 'path'; import {BaseReleaseTask} from './base-release-task'; +import {extractReleaseNotes} from './extract-release-notes'; import {GitClient} from './git/git-client'; import {getGithubReleasesUrl} from './git/github-urls'; import {isNpmAuthenticated, runInteractiveNpmLogin, runNpmPublish} from './npm/npm-client'; import {promptForNpmDistTag} from './prompt/npm-dist-tag-prompt'; import {checkReleasePackage} from './release-output/check-packages'; import {releasePackages} from './release-output/release-packages'; +import {CHANGELOG_FILE_NAME} from './stage-release'; import {parseVersionName, Version} from './version-name/parse-version'; /** Maximum allowed tries to authenticate NPM. */ @@ -88,8 +90,17 @@ class PublishReleaseTask extends BaseReleaseTask { this.checkReleaseOutput(); console.info(green(` ✓ Release output passed validation checks.`)); + // Extract the release notes for the new version from the changelog file. + const releaseNotes = extractReleaseNotes( + join(this.projectDir, CHANGELOG_FILE_NAME), newVersionName); + + if (!releaseNotes) { + console.error(red(` ✘ Could not find release notes in the changelog.`)); + process.exit(1); + } + // Create and push the release tag before publishing to NPM. - this.createAndPushReleaseTag(newVersionName); + this.createAndPushReleaseTag(newVersionName, releaseNotes); // Ensure that we are authenticated before running "npm publish" for each package. this.checkNpmAuthentication(); @@ -230,9 +241,9 @@ class PublishReleaseTask extends BaseReleaseTask { } /** Creates a specified tag and pushes it to the remote repository */ - private createAndPushReleaseTag(tagName: string) { + private createAndPushReleaseTag(tagName: string, releaseNotes: string) { // TODO(devversion): find a way to extract the changelog part just for this version. - if (!this.git.createTag('HEAD', tagName, '')) { + if (!this.git.createTag('HEAD', tagName, releaseNotes)) { console.error(red(` ✘ Could not create the "${tagName}" tag.`)); console.error(red(` Please make sure there is no existing tag with the same name.`)); process.exit(1); diff --git a/tools/release/stage-release.ts b/tools/release/stage-release.ts index 964b001914a..73857ce0030 100644 --- a/tools/release/stage-release.ts +++ b/tools/release/stage-release.ts @@ -10,7 +10,7 @@ import {promptForNewVersion} from './prompt/new-version-prompt'; import {parseVersionName, Version} from './version-name/parse-version'; /** Default filename for the changelog. */ -const CHANGELOG_FILE_NAME = 'CHANGELOG.md'; +export const CHANGELOG_FILE_NAME = 'CHANGELOG.md'; /** * Class that can be instantiated in order to stage a new release. The tasks requires user