diff --git a/__snapshots__/yoshi-go.js b/__snapshots__/yoshi-go.js index 7d6ec0fa5..2fa01ce05 100644 --- a/__snapshots__/yoshi-go.js +++ b/__snapshots__/yoshi-go.js @@ -27,36 +27,36 @@ filename: CHANGES.md exports['YoshiGo run creates a release PR for google-api-go-client 1'] = ` filename: CHANGES.md +# Changelog +## [0.124.0](https://www.github.com/googleapis/google-api-go-client/compare/v0.123.4...v0.124.0) (1983-10-10) +### Features +* **all:** auto-regenerate discovery clients , refs [#1000](https://www.github.com/googleapis/google-api-go-client/issues/1000) [#1001](https://www.github.com/googleapis/google-api-go-client/issues/1001) +* **asset:** added a really cool feature ([d7d1c72](https://www.github.com/googleapis/google-api-go-client/commit/d7d1c720dc1526f4d62ceedad581f498195c8939)) - - -# Changelog -## [0.124.0](https://www.github.com/googleapis/google-api-go-client/compare/v0.123.4...v0.124.0) (1983-10-10) ### Bug Fixes -### Features -* **all:** auto-regenerate discovery clients , refs [#1000](https://www.github.com/googleapis/google-api-go-client/issues/1000) [#1001](https://www.github.com/googleapis/google-api-go-client/issues/1001) -* **asset:** added a really cool feature ([d7d1c72](https://www.github.com/googleapis/google-api-go-client/commit/d7d1c720dc1526f4d62ceedad581f498195c8939)) + * **automl:** fixed a really bad bug ([d7d1c89](https://www.github.com/googleapis/google-api-go-client/commit/d7d1c890dc1526f4d62ceedad581f498195c8939)) * **pubsub/pstest:** this commit should also be included ([dad2c89](https://www.github.com/googleapis/google-api-go-client/commit/dad2c890dc1526f4d62ceedad581f498195c8939)) * **pubsub:** this commit should be included ([dcd1c89](https://www.github.com/googleapis/google-api-go-client/commit/dcd1c890dc1526f4d62ceedad581f498195c8939)) * this commit should be included ([ecd1c89](https://www.github.com/googleapis/google-api-go-client/commit/ecd1c890dc1526f4d62ceedad581f489195c8939)) + ` exports['YoshiGo supports releasing submodule from google-cloud-go 1'] = ` filename: pubsublite/CHANGES.md +# Changelog +### [0.123.5](https://www.github.com/googleapis/google-cloud-go/compare/v0.123.4...v0.123.5) (1983-10-10) - - -# Changelog ### Bug Fixes -### [0.123.5](https://www.github.com/googleapis/google-cloud-go/compare/v0.123.4...v0.123.5) (1983-10-10) + * **pubsublite:** start generating v1 ([1d9662c](https://www.github.com/googleapis/google-cloud-go/commit/1d9662cf08ab1cf3b68d95dee4dc99b7c4aac371)) + ` diff --git a/package.json b/package.json index ccc466547..16daaf4cf 100644 --- a/package.json +++ b/package.json @@ -53,16 +53,15 @@ "typescript": "^3.8.3" }, "dependencies": { + "@conventional-commits/parser": "^0.3.0", "@octokit/graphql": "^4.3.1", "@octokit/request": "^5.3.4", "@octokit/rest": "^18.0.4", "chalk": "^4.0.0", "code-suggester": "^1.4.0", - "concat-stream": "^2.0.0", "conventional-changelog-conventionalcommits": "^4.4.0", - "conventional-changelog-writer": "^4.0.6", + "conventional-changelog-writer": "^5.0.0", "conventional-commits-filter": "^2.0.2", - "conventional-commits-parser": "^3.0.3", "figures": "^3.0.0", "parse-github-repo-url": "^1.4.1", "semver": "^7.0.0", diff --git a/src/conventional-commits.ts b/src/conventional-commits.ts index e3500bce4..f3a3f04e7 100644 --- a/src/conventional-commits.ts +++ b/src/conventional-commits.ts @@ -15,18 +15,22 @@ import chalk = require('chalk'); import * as semver from 'semver'; import {ReleaseType} from 'semver'; -import {Readable} from 'stream'; import {checkpoint, CheckpointType} from './util/checkpoint'; import {Commit} from './graphql-to-commits'; +import { + ConventionalChangelogCommit, + parser, + toConventionalChangelogFormat, +} from '@conventional-commits/parser'; + +interface CommitWithHash extends ConventionalChangelogCommit { + hash: string | null; +} -// eslint-disable-next-line @typescript-eslint/no-var-requires -const concat = require('concat-stream'); // eslint-disable-next-line @typescript-eslint/no-var-requires const conventionalCommitsFilter = require('conventional-commits-filter'); // eslint-disable-next-line @typescript-eslint/no-var-requires -const conventionalCommitsParser = require('conventional-commits-parser'); -// eslint-disable-next-line @typescript-eslint/no-var-requires const conventionalChangelogWriter = require('conventional-changelog-writer'); // eslint-disable-next-line @typescript-eslint/no-var-requires const parseGithubRepoUrl = require('parse-github-repo-url'); @@ -68,52 +72,27 @@ interface Note { text: string; } -interface ParsedConventionalCommit { - type: string; - scope: string | null; - subject: string; - merge: boolean | null; - header: string; - body: string | null; - footer: string | null; - notes: Note[]; - references: object[]; - mentions: string[]; - revert: boolean | null; -} - -// Perform some post processing on the commits parsed by conventional commits: -// 1. don't allow BREAKING CHANGES to have two newlines: -import {Transform} from 'stream'; - -class PostProcessCommits extends Transform { - _transform( - chunk: ParsedConventionalCommit, - _encoding: string, - done: Function - ) { - chunk.notes.forEach(note => { - let text = ''; - let i = 0; - let extendedContext = false; - for (const chunk of note.text.split(/\r?\n/)) { - if (i > 0 && hasExtendedContext(chunk) && !extendedContext) { - text = `${text.trim()}\n`; - extendedContext = true; - } - if (chunk === '') break; - else if (extendedContext) { - text += ` ${chunk}\n`; - } else { - text += `${chunk} `; - } - i++; +function postProcessCommits(commit: ConventionalChangelogCommit) { + commit.notes.forEach(note => { + let text = ''; + let i = 0; + let extendedContext = false; + for (const chunk of note.text.split(/\r?\n/)) { + if (i > 0 && hasExtendedContext(chunk) && !extendedContext) { + text = `${text.trim()}\n`; + extendedContext = true; } - note.text = text.trim(); - }); - this.push(JSON.stringify(chunk, null, 4) + '\n'); - done(); - } + if (chunk === '') break; + else if (extendedContext) { + text += ` ${chunk}\n`; + } else { + text += `${chunk} `; + } + i++; + } + note.text = text.trim(); + }); + return commit; } // If someone wishes to include additional contextual information for a @@ -201,78 +180,62 @@ export class ConventionalCommits { this.headerPartial || preset.writerOpts.headerPartial; preset.writerOpts.mainTemplate = this.mainTemplate || preset.writerOpts.mainTemplate; - - return new Promise((resolve, reject) => { - let content = ''; - const stream = this.commitsReadable() - .pipe(conventionalCommitsParser(preset.parserOpts)) - .pipe(new PostProcessCommits({objectMode: true})) - .pipe(conventionalChangelogWriter(context, preset.writerOpts)); - - stream.on('error', (err: Error) => { - return reject(err); - }); - - stream.on('data', (buffer: Buffer) => { - content += buffer.toString('utf8'); - }); - - stream.on('end', () => { - return resolve(content.trim()); - }); - }); + const parsedCommits = []; + for (const commit of this.commits) { + try { + const parsedCommit = postProcessCommits( + toConventionalChangelogFormat(parser(commit.message)) + ) as CommitWithHash; + parsedCommit.hash = commit.sha; + parsedCommits.push(parsedCommit); + } catch (_err) { + // Commit is not in conventional commit format, it does not + // contribute to the CHANGELOG generation. + } + } + const parsed: string = conventionalChangelogWriter + .parseArray(parsedCommits, context, preset.writerOpts) + .trim(); + return parsed; } private async guessReleaseType(preMajor: boolean): Promise { const VERSIONS = ['major', 'minor', 'patch']; const preset = await presetFactory({preMajor}); - return new Promise((resolve: Function, reject: Function) => { - const stream = this.commitsReadable() - .pipe(conventionalCommitsParser(preset.parserOpts)) - .pipe( - concat((data: ParsedConventionalCommit[]) => { - const commits = conventionalCommitsFilter(data); - - let result = preset.recommendedBumpOpts.whatBump( - commits, - preset.recommendedBumpOpts - ); - - if (result && result.level !== null) { - result.releaseType = VERSIONS[result.level]; - } else if (result === null) { - result = {}; - } + const parsedCommits = []; + for (const commit of this.commits) { + try { + const parsedCommit = toConventionalChangelogFormat( + parser(commit.message) + ); + parsedCommits.push(parsedCommit); + } catch (_err) { + // Commit is not in conventional commit format, it does not + // contribute to the CHANGELOG generation. + } + } + const commits = conventionalCommitsFilter( + parsedCommits + ) as ConventionalChangelogCommit; - // we have slightly different logic than the default of conventional commits, - // the minor should be bumped when features are introduced for pre 1.x.x libs: - if ( - result.reason.indexOf(' 0 features') === -1 && - result.releaseType === 'patch' - ) { - result.releaseType = 'minor'; - } + let result = preset.recommendedBumpOpts.whatBump( + commits, + preset.recommendedBumpOpts + ); - return resolve(result); - }) - ); + if (result && result.level !== null) { + result.releaseType = VERSIONS[result.level]; + } else if (result === null) { + result = {}; + } - stream.on('error', (err: Error) => { - return reject(err); - }); - }); - } - private commitsReadable(): Readable { - // The conventional commits parser expects an array of string commit - // messages terminated by `-hash-` followed by the commit sha. We - // piggyback off of this, and use this sha when choosing a - // point to branch from for PRs. - const commitsReadable = new Readable(); - this.commits.forEach((commit: Commit) => { - commitsReadable.push( - `${commit.message}\n-hash-\n${commit.sha ? commit.sha : ''}` - ); - }); - commitsReadable.push(null); - return commitsReadable; + // we have slightly different logic than the default of conventional commits, + // the minor should be bumped when features are introduced for pre 1.x.x libs: + if ( + result.reason.indexOf(' 0 features') === -1 && + result.releaseType === 'patch' + ) { + result.releaseType = 'minor'; + } + return result; } } diff --git a/test/helpers.ts b/test/helpers.ts index c9b1b0222..07b34cd9b 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -19,21 +19,12 @@ import {resolve} from 'path'; * Given an object of chnages expected to be made by code-suggester API, * stringify content in such a way that it works well for snapshots: */ -export function stringifyExpectedChanges( - expected: [string, object][], - sort = false -): string { +export function stringifyExpectedChanges(expected: [string, object][]): string { let stringified = ''; for (const update of expected) { stringified = `${stringified}\nfilename: ${update[0]}`; const obj = update[1] as {[key: string]: string}; - // TODO(bcoe): dig into issue with Node 10 streams that is forcing us - // to sort content before performing comparison. - // See: https://github.com/googleapis/release-please/issues/601 - const content = sort - ? obj.content.split('\n').sort().join('\n') - : obj.content; - stringified = `${stringified}\n${content}`; + stringified = `${stringified}\n${obj.content}`; } return stringified.replace( /[0-9]{4}-[0-9]{2}-[0-9]{2}/g, diff --git a/test/releasers/yoshi-go.ts b/test/releasers/yoshi-go.ts index c3386726a..1d10b0843 100644 --- a/test/releasers/yoshi-go.ts +++ b/test/releasers/yoshi-go.ts @@ -185,7 +185,7 @@ describe('YoshiGo', () => { req.done(); // eslint-disable-next-line @typescript-eslint/no-explicit-any - snapshot(stringifyExpectedChanges(expectedChanges, true)); + snapshot(stringifyExpectedChanges(expectedChanges)); }); }); it('supports releasing submodule from google-cloud-go', async () => { @@ -261,6 +261,6 @@ describe('YoshiGo', () => { req.done(); // eslint-disable-next-line @typescript-eslint/no-explicit-any - snapshot(stringifyExpectedChanges(expectedChanges, true)); + snapshot(stringifyExpectedChanges(expectedChanges)); }); });