diff --git a/__snapshots__/github-release.js b/__snapshots__/github-release.js index 42509eaa4..7ae0f1bcc 100644 --- a/__snapshots__/github-release.js +++ b/__snapshots__/github-release.js @@ -122,3 +122,27 @@ exports['GitHubRelease createRelease creates and labels release on GitHub 2'] = 'autorelease: tagged' ] } + +exports['GitHubRelease createRelease creates releases for submodules in monorepo 1'] = { + 'tag_name': 'bigquery/v1.0.3', + 'body': '\n* entry', + 'name': 'foo bigquery/v1.0.3' +} + +exports['GitHubRelease createRelease creates releases for submodules in monorepo 2'] = { + 'labels': [ + 'autorelease: tagged' + ] +} + +exports['GitHubRelease createRelease creates release for root module in monorepo 1'] = { + 'tag_name': 'v1.0.3', + 'body': '\n* entry', + 'name': 'foo v1.0.3' +} + +exports['GitHubRelease createRelease creates release for root module in monorepo 2'] = { + 'labels': [ + 'autorelease: tagged' + ] +} diff --git a/__snapshots__/yoshi-go.js b/__snapshots__/yoshi-go.js index 505bd1999..044f43c16 100644 --- a/__snapshots__/yoshi-go.js +++ b/__snapshots__/yoshi-go.js @@ -16,7 +16,6 @@ filename: CHANGES.md * **all:** auto-regenerate gapics , refs [#1000](https://www.github.com/googleapis/google-cloud-go/issues/1000) [#1001](https://www.github.com/googleapis/google-cloud-go/issues/1001) * **asset:** added a really cool feature ([d7d1c89](https://www.github.com/googleapis/google-cloud-go/commit/d7d1c890dc1526f4d62ceedad581f498195c8939)) -* **pubsublite:** start generating v1 ([1d9662c](https://www.github.com/googleapis/google-cloud-go/commit/1d9662cf08ab1cf3b68d95dee4dc99b7c4aac371)) ### Bug Fixes diff --git a/src/bin/release-please.ts b/src/bin/release-please.ts index dac297578..b6dd5655b 100644 --- a/src/bin/release-please.ts +++ b/src/bin/release-please.ts @@ -121,6 +121,11 @@ const argv = yargs .option('path', { describe: 'release from path other than root directory', type: 'string', + }) + .option('monorepo-tags', { + describe: 'include library name in tags and release branches', + type: 'boolean', + default: false, }); }, (argv: GitHubReleaseOptions) => { diff --git a/src/github-release.ts b/src/github-release.ts index 3e0adae4c..b8b33329a 100644 --- a/src/github-release.ts +++ b/src/github-release.ts @@ -13,8 +13,6 @@ // limitations under the License. import chalk = require('chalk'); -import {join} from 'path'; - import {checkpoint, CheckpointType} from './util/checkpoint'; import {ReleasePRFactory} from './release-pr-factory'; import { @@ -33,6 +31,7 @@ export interface GitHubReleaseOptions { repoUrl: string; path?: string; packageName?: string; + monorepoTags?: boolean; token?: string; apiUrl: string; proxyKey?: string; @@ -49,6 +48,7 @@ export class GitHubRelease { repoUrl: string; path?: string; packageName?: string; + monorepoTags?: boolean; token?: string; proxyKey?: string; releaseType?: string; @@ -58,6 +58,7 @@ export class GitHubRelease { this.proxyKey = options.proxyKey; this.labels = options.label.split(','); this.repoUrl = options.repoUrl; + this.monorepoTags = options.monorepoTags; this.token = options.token; this.path = options.path; this.packageName = options.packageName; @@ -69,11 +70,44 @@ export class GitHubRelease { } async createRelease(): Promise { - const gitHubReleasePR: - | GitHubReleasePR - | undefined = await this.gh.findMergedReleasePR(this.labels); - if (gitHubReleasePR) { + let gitHubReleasePRs: GitHubReleasePR[] = []; + const rootPath = this.path; + const releases = []; + // In most configurations, createRelease() should be called close to when + // a release PR is merged, e.g., a GitHub action that kicks off this + // workflow on merge. For tis reason, we can pull a fairly small number of PRs: + const pageSize = 25; + if (this.monorepoTags) { + gitHubReleasePRs = await this.gh.findMergedReleasePRs( + this.labels, + pageSize + ); + } else { + const releasePR = await this.gh.findMergedReleasePR( + this.labels, + pageSize + ); + if (releasePR) { + gitHubReleasePRs = [releasePR]; + } + } + if (gitHubReleasePRs.length === 0) { + checkpoint('no recent release PRs found', CheckpointType.Failure); + return undefined; + } + for (const gitHubReleasePR of gitHubReleasePRs) { const version = `v${gitHubReleasePR.version}`; + // If we've enabled monorepoTags, and a prefix was found on release PR + // e.g., release-bigquery-v1.0.0, then assume we are releasing a + // module from within the "bigquery" folder: + if (this.monorepoTags && gitHubReleasePR.packageName) { + this.path = gitHubReleasePR.packageName; + } else { + // As in the case of google-cloud-go, a repo may contain both a + // top level module, and submodules. If no submodule is found in + // the branch name, we use the initial rootPath: + this.path = rootPath; + } checkpoint( `found release branch ${chalk.green(version)} at ${chalk.green( @@ -87,8 +121,7 @@ export class GitHubRelease { ).parsedContent; const latestReleaseNotes = GitHubRelease.extractLatestReleaseNotes( changelogContents, - // For monorepo releases, the library name is prepended to the tag and branch: - version.split('-').pop() || version + version ); checkpoint( `found release notes: \n---\n${chalk.grey(latestReleaseNotes)}\n---\n`, @@ -97,18 +130,27 @@ export class GitHubRelease { // Attempt to lookup the package name from a well known location, such // as package.json, if none is provided: - if (this.packageName === undefined && this.releaseType) { + if (!this.packageName && this.releaseType) { this.packageName = await ReleasePRFactory.class( this.releaseType ).lookupPackageName(this.gh); } + // Go uses '/' for a tag separator, rather than '-': + let tagSeparator = '-'; + if (this.releaseType) { + tagSeparator = ReleasePRFactory.class(this.releaseType).tagSeparator(); + } if (this.packageName === undefined) { - throw Error('could not determine package name for release'); + throw Error( + `could not determine package name for release repo = ${this.repoUrl}` + ); } const release = await this.gh.createRelease( this.packageName, - version, + this.monorepoTags && this.path + ? `${this.path}${tagSeparator}${version}` + : version, gitHubReleasePR.sha, latestReleaseNotes ); @@ -118,18 +160,21 @@ export class GitHubRelease { // Remove 'autorelease: pending' which indicates a GitHub release // has not yet been created. await this.gh.removeLabels(this.labels, gitHubReleasePR.number); - return release; - } else { - checkpoint('no recent release PRs found', CheckpointType.Failure); - return undefined; + releases.push(release); } + // TODO(bcoe): it will be a breaking change, but we should come up with + // an approach to return a list of releases rather than a single + // release (we will need to make this work with the GitHub action). + return releases[0]; } addPath(file: string) { if (this.path === undefined) { return file; } else { - return join(this.path, `./${file}`); + const path = this.path.replace(/[/\\]$/, ''); + file = file.replace(/^[/\\]/, ''); + return `${path}/${file}`; } } diff --git a/src/github.ts b/src/github.ts index 9e132b82f..fa70404b9 100644 --- a/src/github.ts +++ b/src/github.ts @@ -72,13 +72,7 @@ import {Update} from './updaters/update'; // - make sure the branch name starts with "release" // - take everything else // This includes the tag to handle monorepos. -const VERSION_FROM_BRANCH_RE = /^.*:release-(.*)+$/; - -// Takes the output of the above regex and strips it down further -// to a basic semver. -// - skip everything up to the last "-vX.Y.Z" and maybe "-test" -// - take everything after the v as a match group -const SEMVER_FROM_VERSION_RE = /^.*-?(v\d+\.\d+\.\d+[^\d]?(?!.*v\d+\.\d+\.\d+).*)$/; +const VERSION_FROM_BRANCH_RE = /^.*:release-?([\w-.]*)-(v[0-9].*)$/; export interface OctokitAPIs { graphql: Function; @@ -104,6 +98,7 @@ export interface GitHubTag { export interface GitHubReleasePR { number: number; + packageName: string; sha: string; version: string; } @@ -461,17 +456,24 @@ export class GitHub { // the branch we're configured for. async latestTag( prefix?: string, - preRelease = false + preRelease = false, + // Allow a branch prefix to differ from a tag prefix. This was required + // for google-cloud-go, which uses the tag prefix library/vx.y.z. + // this is a requirement in the go community. + branchPrefix?: string ): Promise { - const pull = await this.findMergedReleasePR([], 100, prefix, preRelease); + const pull = await this.findMergedReleasePR( + [], + 100, + branchPrefix ?? prefix, + preRelease + ); if (!pull) return await this.latestTagFallback(prefix, preRelease); - const tag = { name: `v${pull.version}`, sha: pull.sha, version: pull.version, } as GitHubTag; - return tag; } @@ -544,7 +546,6 @@ export class GitHub { preRelease = true ): Promise { const baseLabel = await this.getBaseLabel(); - const pullsResponse = (await this.request( `GET /repos/:owner/:repo/pulls?state=closed&per_page=${perPage}${ this.proxyKey ? `&key=${this.proxyKey}` : '' @@ -554,8 +555,7 @@ export class GitHub { repo: this.repo, } )) as {data: PullsListResponseItems}; - for (let i = 0, pull; i < pullsResponse.data.length; i++) { - pull = pullsResponse.data[i]; + for (const pull of pullsResponse.data) { if ( labels.length === 0 || this.hasAllLabels( @@ -580,22 +580,14 @@ export class GitHub { // [optional-package-name-]v1.2.3[-beta-or-whatever] // Because the package name can contain things like "-v1", // it's easiest/safest to just pull this out by string search. - let version = match[1]; - if (prefix) { - if (!version.startsWith(prefix)) continue; - - // Remove any prefix after validating it. - version = version.substr(prefix.length); + const version = match[2]; + if (!version) continue; + if (prefix && match[1] !== prefix) { + continue; + } else if (!prefix && match[1]) { + continue; } - // Extract the actual version string. - const versionMatch = version.match(SEMVER_FROM_VERSION_RE); - if (!versionMatch) continue; - // If no prefix is provided, and there appears to be a prefix, i.e., - // characters before the version, skip this tag: - if (!prefix && version.indexOf(versionMatch[1]) > 0) continue; - version = versionMatch[1]; - // What's left by now should just be the version string. // Check for pre-releases if needed. if (!preRelease && version.indexOf('-') >= 0) continue; @@ -606,6 +598,7 @@ export class GitHub { return { number: pull.number, + packageName: match[1] ? match[1] : undefined, sha: pull.merge_commit_sha, version: normalizedVersion, } as GitHubReleasePR; @@ -614,6 +607,71 @@ export class GitHub { return undefined; } + // Allows multiple release PRs to be pulled at once, for use by monorepos. + // TODO(bcoe): can we consolidate findMergedRelease and findMergedReleasePRs + // logic? The signficant differences are: findMergedRelease enforces a + // prefix on releases; findMergedReleasePRs returns the entire set of merged + // PRs, vs., a single PR matching a pattern: + async findMergedReleasePRs( + labels: string[], + perPage = 100 + ): Promise { + const prs = []; + const baseLabel = await this.getBaseLabel(); + const pullsResponse = (await this.request( + `GET /repos/:owner/:repo/pulls?state=closed&per_page=${perPage}${ + this.proxyKey ? `&key=${this.proxyKey}` : '' + }&sort=merged_at&direction=desc`, + { + owner: this.owner, + repo: this.repo, + } + )) as {data: PullsListResponseItems}; + for (const pull of pullsResponse.data) { + if ( + labels.length === 0 || + this.hasAllLabels( + labels, + pull.labels.map(l => l.name) + ) + ) { + // it's expected that a release PR will have a + // HEAD matching the format repo:release-v1.0.0. + if (!pull.head) continue; + + // Verify that this PR was based against our base branch of interest. + if (!pull.base || pull.base.label !== baseLabel) continue; + + // The input should look something like: + // user:release-[optional-package-name]-v1.2.3 + // We want the package name and any semver on the end. + const match = pull.head.label.match(VERSION_FROM_BRANCH_RE); + if (!match || !pull.merged_at) { + continue; + } + + // The input here should look something like: + // [optional-package-name-]v1.2.3[-beta-or-whatever] + // Because the package name can contain things like "-v1", + // it's easiest/safest to just pull this out by string search. + const version = match[2]; + if (!version) continue; + + // Make sure we did get a valid semver. + const normalizedVersion = semver.valid(version); + if (!normalizedVersion) continue; + + prs.push({ + number: pull.number, + packageName: match[1] ? match[1] : undefined, + sha: pull.merge_commit_sha, + version: normalizedVersion, + } as GitHubReleasePR); + } + } + return prs; + } + private hasAllLabels(labelsA: string[], labelsB: string[]) { let hasAll = true; labelsA.forEach(label => { @@ -959,11 +1017,11 @@ export class GitHub { async createRelease( packageName: string, - version: string, + tagName: string, sha: string, releaseNotes: string ): Promise { - checkpoint(`creating release ${version}`, CheckpointType.Success); + checkpoint(`creating release ${tagName}`, CheckpointType.Success); return ( await this.request( `POST /repos/:owner/:repo/releases${ @@ -972,10 +1030,10 @@ export class GitHub { { owner: this.owner, repo: this.repo, - tag_name: version, + tag_name: tagName, target_commitish: sha, body: releaseNotes, - name: `${packageName} ${version}`, + name: `${packageName} ${tagName}`, } ) ).data; diff --git a/src/release-pr.ts b/src/release-pr.ts index 6ae1dcce1..1fb24ac17 100644 --- a/src/release-pr.ts +++ b/src/release-pr.ts @@ -195,6 +195,10 @@ export class ReleasePR { return Promise.resolve(undefined); } + static tagSeparator(): string { + return '-'; + } + protected async coerceReleaseCandidate( cc: ConventionalCommits, latestTag: GitHubTag | undefined, @@ -275,7 +279,7 @@ export class ReleasePR { const includePackageName = options.includePackageName; const title = includePackageName - ? `Release ${this.packageName} ${version}` + ? `chore: release ${this.packageName} ${version}` : `chore: release ${version}`; const body = `:robot: I have created a release \\*beep\\* \\*boop\\* \n---\n${changelogEntry}\n\nThis PR was generated with [Release Please](https://github.com/googleapis/release-please).`; const pr: number = await this.gh.openPR({ diff --git a/src/releasers/go-yoshi-submodule.ts b/src/releasers/go-yoshi-submodule.ts new file mode 100644 index 000000000..11b0f1060 --- /dev/null +++ b/src/releasers/go-yoshi-submodule.ts @@ -0,0 +1,106 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {ReleasePR, ReleaseCandidate} from '../release-pr'; +import {ConventionalCommits} from '../conventional-commits'; +import {checkpoint, CheckpointType} from '../util/checkpoint'; +import {Update} from '../updaters/update'; + +import {Changelog} from '../updaters/changelog'; + +const SCOPE_REGEX = /^\w+\((?.*)\):/; + +export class GoYoshiSubmodule extends ReleasePR { + static releaserName = 'go-yoshi-submodule'; + protected async _run() { + if (!this.packageName) { + throw Error('GoYoshiSubmodule requires this.packageName'); + } + // Get tag relative to module/v1.0.0: + const latestTag = await this.gh.latestTag( + `${this.packageName}/`, + false, + `${this.packageName}-` + ); + const commits = ( + await this.commits({ + sha: latestTag?.sha, + path: this.path, + }) + ).filter(commit => { + const scope = commit.message.match(SCOPE_REGEX)?.groups?.scope; + // Filter commits that don't have a scope as we don't know where to put + // them. + if (!scope) { + return false; + } + // Only use commits that match our scope: + if ( + scope === this.packageName || + scope.startsWith(this.packageName + '/') + ) { + return true; + } + return false; + }); + + const cc = new ConventionalCommits({ + commits, + githubRepoUrl: this.repoUrl, + bumpMinorPreMajor: this.bumpMinorPreMajor, + changelogSections: this.changelogSections, + }); + const candidate: ReleaseCandidate = await this.coerceReleaseCandidate( + cc, + latestTag + ); + const changelogEntry: string = await cc.generateChangelogEntry({ + version: candidate.version, + currentTag: `v${candidate.version}`, + previousTag: candidate.previousTag, + }); + + // don't create a release candidate until user facing changes + // (fix, feat, BREAKING CHANGE) have been made; a CHANGELOG that's + // one line is a good indicator that there were no interesting commits. + if (this.changelogEmpty(changelogEntry)) { + checkpoint( + `no user facing commits found since ${ + latestTag ? latestTag.sha : 'beginning of time' + }`, + CheckpointType.Failure + ); + return; + } + + const updates: Update[] = []; + + updates.push( + new Changelog({ + path: this.addPath('CHANGES.md'), + changelogEntry, + version: candidate.version, + packageName: this.packageName, + }) + ); + + return this.openPR({ + sha: commits[0].sha!, + changelogEntry: `${changelogEntry}\n---\n`, + updates, + version: candidate.version, + includePackageName: this.monorepoTags, + }); + } +} diff --git a/src/releasers/go-yoshi.ts b/src/releasers/go-yoshi.ts index 8dc5cf499..69593662c 100644 --- a/src/releasers/go-yoshi.ts +++ b/src/releasers/go-yoshi.ts @@ -25,6 +25,7 @@ import * as semver from 'semver'; // Generic import {Changelog} from '../updaters/changelog'; +import {GoYoshiSubmodule} from './go-yoshi-submodule'; // eslint-disable-next-line @typescript-eslint/no-var-requires const parseGithubRepoUrl = require('parse-github-repo-url'); @@ -38,6 +39,7 @@ const SUB_MODULES = [ 'firestore', 'logging', 'pubsub', + 'pubsublite', 'spanner', 'storage', ]; @@ -47,13 +49,12 @@ const SCOPE_REGEX = /^\w+\((?.*)\):/; export class GoYoshi extends ReleasePR { static releaserName = 'go-yoshi'; protected async _run() { - const latestTag = await this.gh.latestTag( - this.monorepoTags ? `${this.packageName}-` : undefined - ); + const latestTag = await this.gh.latestTag(); // eslint-disable-next-line @typescript-eslint/no-unused-vars const [_owner, repo] = parseGithubRepoUrl(this.repoUrl); let regenPR: Commit | undefined; let sha: null | string = null; + const submodulesToRelease: Set = new Set(); const commits = ( await this.commits({ sha: latestTag?.sha, @@ -71,8 +72,7 @@ export class GoYoshi extends ReleasePR { // parent module. for (const subModule of SUB_MODULES) { if (scope === subModule || scope.startsWith(subModule + '/')) { - // TODO(codyoss): eventually gather these commits into a map so we can - // purpose releases for sub-modules. + submodulesToRelease.add(subModule); return false; } } @@ -108,6 +108,23 @@ export class GoYoshi extends ReleasePR { return true; }); + // If gapic library, and we've noticed commits for submodules, perform + // a release for submodule: + if (this.isGapicRepo(repo)) { + for (const subModule of submodulesToRelease) { + // TODO(codyoss): is there a better way to serialize all these pameters. + checkpoint( + `running release for ${subModule} submodule`, + CheckpointType.Success + ); + await this.submoduleRelease(subModule); + checkpoint( + `finished running release for ${subModule} submodule`, + CheckpointType.Success + ); + } + } + const cc = new ConventionalCommits({ commits: commits, githubRepoUrl: this.repoUrl, @@ -187,4 +204,26 @@ export class GoYoshi extends ReleasePR { protected defaultInitialVersion(): string { return '0.1.0'; } + + static tagSeparator(): string { + return '/'; + } + + async submoduleRelease(subModule: string) { + const releaser = new GoYoshiSubmodule({ + bumpMinorPreMajor: this.bumpMinorPreMajor, + defaultBranch: this.defaultBranch, + fork: this.fork, + token: this.token, + repoUrl: this.repoUrl, + packageName: subModule, + monorepoTags: true, + path: subModule, + apiUrl: this.apiUrl, + snapshot: this.snapshot, + releaseType: 'go-yoshi-submodule', + changelogSections: this.changelogSections, + }); + await releaser.run(); + } } diff --git a/test/github-release.ts b/test/github-release.ts index 5846cb6a2..90f7665df 100644 --- a/test/github-release.ts +++ b/test/github-release.ts @@ -41,7 +41,7 @@ describe('GitHubRelease', () => { .get('/repos/googleapis/foo') .reply(200, repoInfo) .get( - '/repos/googleapis/foo/pulls?state=closed&per_page=100&sort=merged_at&direction=desc' + '/repos/googleapis/foo/pulls?state=closed&per_page=25&sort=merged_at&direction=desc' ) .reply(200, [ { @@ -86,6 +86,128 @@ describe('GitHubRelease', () => { requests.done(); }); + it('creates releases for submodules in monorepo', async () => { + const release = new GitHubRelease({ + label: 'autorelease: pending', + repoUrl: 'googleapis/foo', + packageName: 'foo', + monorepoTags: true, + releaseType: 'go-yoshi', + apiUrl: 'https://api.github.com', + changelogPath: 'CHANGES.md', + }); + const requests = nock('https://api.github.com') + // check for default branch + .get('/repos/googleapis/foo') + .reply(200, repoInfo) + .get( + '/repos/googleapis/foo/pulls?state=closed&per_page=25&sort=merged_at&direction=desc' + ) + .reply(200, [ + { + labels: [{name: 'autorelease: pending'}], + head: { + label: 'head:release-bigquery-v1.0.3', + }, + base: { + label: 'googleapis:main', + }, + number: 1, + merged_at: new Date().toISOString(), + }, + ]) + .get( + '/repos/googleapis/foo/contents/bigquery%2FCHANGES.md?ref=refs/heads/main' + ) + .reply(200, { + content: Buffer.from('#Changelog\n\n## v1.0.3\n\n* entry', 'utf8'), + }) + .post( + '/repos/googleapis/foo/releases', + (body: {[key: string]: string}) => { + snapshot(body); + return true; + } + ) + .reply(200, {tag_name: 'bigquery/v1.0.3'}) + .post( + '/repos/googleapis/foo/issues/1/labels', + (body: {[key: string]: string}) => { + snapshot(body); + return true; + } + ) + .reply(200) + .delete( + '/repos/googleapis/foo/issues/1/labels/autorelease%3A%20pending' + ) + .reply(200); + + const created = await release.createRelease(); + strictEqual(created!.tag_name, 'bigquery/v1.0.3'); + requests.done(); + }); + + it('creates release for root module in monorepo', async () => { + const release = new GitHubRelease({ + label: 'autorelease: pending', + repoUrl: 'googleapis/foo', + packageName: 'foo', + monorepoTags: true, + releaseType: 'go-yoshi', + apiUrl: 'https://api.github.com', + changelogPath: 'CHANGES.md', + }); + const requests = nock('https://api.github.com') + // check for default branch + .get('/repos/googleapis/foo') + .reply(200, repoInfo) + .get( + '/repos/googleapis/foo/pulls?state=closed&per_page=25&sort=merged_at&direction=desc' + ) + .reply(200, [ + { + labels: [{name: 'autorelease: pending'}], + head: { + label: 'head:release-v1.0.3', + }, + base: { + label: 'googleapis:main', + }, + number: 1, + merged_at: new Date().toISOString(), + }, + ]) + .get('/repos/googleapis/foo/contents/CHANGES.md?ref=refs/heads/main') + .reply(200, { + content: Buffer.from('#Changelog\n\n## v1.0.3\n\n* entry', 'utf8'), + }) + .post( + '/repos/googleapis/foo/releases', + (body: {[key: string]: string}) => { + snapshot(body); + return true; + } + ) + .reply(200, {tag_name: 'v1.0.3'}) + .post( + '/repos/googleapis/foo/issues/1/labels', + (body: {[key: string]: string}) => { + snapshot(body); + return true; + } + ) + .reply(200) + .delete( + '/repos/googleapis/foo/issues/1/labels/autorelease%3A%20pending' + ) + .reply(200); + + const created = await release.createRelease(); + strictEqual(created!.tag_name, 'v1.0.3'); + requests.done(); + }); + it('attempts to guess package name for release', async () => { const release = new GitHubRelease({ label: 'autorelease: pending', @@ -98,7 +220,7 @@ describe('GitHubRelease', () => { .get('/repos/googleapis/foo') .reply(200, repoInfo) .get( - '/repos/googleapis/foo/pulls?state=closed&per_page=100&sort=merged_at&direction=desc' + '/repos/googleapis/foo/pulls?state=closed&per_page=25&sort=merged_at&direction=desc' ) .reply(200, [ { diff --git a/test/github.ts b/test/github.ts index adabdce6e..dd0331c20 100644 --- a/test/github.ts +++ b/test/github.ts @@ -219,7 +219,7 @@ describe('GitHub', () => { '/repos/fake/fake/pulls?state=closed&per_page=100&sort=merged_at&direction=desc' ) .reply(200, sampleResults); - const latestTag = await github.latestTag('complex-package_name'); + const latestTag = await github.latestTag('complex-package_name-v1'); expect(latestTag!.version).to.equal('1.1.0'); req.done(); }); diff --git a/test/releasers/yoshi-go.ts b/test/releasers/yoshi-go.ts index f0014cadf..cb386faca 100644 --- a/test/releasers/yoshi-go.ts +++ b/test/releasers/yoshi-go.ts @@ -107,6 +107,11 @@ describe('YoshiGo', () => { packageName: 'yoshi-go', apiUrl: 'https://api.github.com', }); + // Stub the submodule release process, this is tested separately in + // TODO(codyoss): test this separately: + // eslint-disable-next-line @typescript-eslint/no-explicit-any + sandbox.stub(releasePR as any, 'submoduleRelease').resolves(); + await releasePR.run(); req.done(); snapshot(stringifyExpectedChanges(expectedChanges)); @@ -159,6 +164,11 @@ describe('YoshiGo', () => { // Call to add autorelease: pending label: sandbox.stub(releasePR.gh, 'addLabels'); + // Stub the submodule release process, this is tested separately in + // TODO(codyoss): test this separately: + // eslint-disable-next-line @typescript-eslint/no-explicit-any + sandbox.stub(releasePR as any, 'submoduleRelease').resolves(); + const graphql = JSON.parse( readFileSync(resolve(fixturesPath, 'discovery-commits.json'), 'utf8') );