diff --git a/src/strategies/go-yoshi.ts b/src/strategies/go-yoshi.ts index 8a9fb3a8c..4f8945962 100644 --- a/src/strategies/go-yoshi.ts +++ b/src/strategies/go-yoshi.ts @@ -21,20 +21,8 @@ import {TagName} from '../util/tag-name'; import {Release} from '../release'; import {VersionGo} from '../updaters/go/version-go'; import {logger} from '../util/logger'; +import {dirname} from 'path'; -// Commits containing a scope prefixed with an item in this array will be -// ignored when generating a release PR for the parent module. -const IGNORED_SUB_MODULES = new Set([ - 'bigtable', - 'bigquery', - 'datastore', - 'firestore', - 'logging', - 'pubsub', - 'pubsublite', - 'spanner', - 'storage', -]); const REGEN_PR_REGEX = /.*auto-regenerate.*/; const REGEN_ISSUE_REGEX = /(?.*)\(#(?.*)\)(\n|$)/; @@ -74,6 +62,7 @@ export class GoYoshi extends BaseStrategy { let regenCommit: ConventionalCommit; const component = await this.getComponent(); logger.debug('Filtering commits'); + const ignoredSubmodules = await this.getIgnoredSubModules(); return commits.filter(commit => { // Only have a single entry of the nightly regen listed in the changelog. // If there are more than one of these commits, append associated PR. @@ -135,7 +124,7 @@ export class GoYoshi extends BaseStrategy { } else { // This is the main module release, so ignore sub modules that // are released independently - for (const submodule of IGNORED_SUB_MODULES) { + for (const submodule of ignoredSubmodules) { if (commitMatchesScope(commit.scope, submodule)) { logger.debug(`Skipping ignored commit scope: ${commit.scope}`); return false; @@ -147,6 +136,28 @@ export class GoYoshi extends BaseStrategy { }); } + async getIgnoredSubModules(): Promise> { + // ignored submodules only applies to the root component of + // googleapis/google-cloud-go + if ( + this.repository.owner !== 'googleapis' || + this.repository.repo !== 'google-cloud-go' || + this.includeComponentInTag + ) { + return new Set(); + } + + logger.info('Looking for go.mod files'); + const paths = ( + await this.github.findFilesByFilenameAndRef('go.mod', this.targetBranch) + ) + .filter(path => !path.includes('internal') && path !== 'go.mod') + .map(path => dirname(path)); + logger.info(`Found ${paths.length} submodules`); + logger.debug(JSON.stringify(paths)); + return new Set(paths); + } + // "closes" is a little presumptuous, let's just indicate that the // PR references these other commits: protected async buildReleaseNotes( diff --git a/test/strategies/go-yoshi.ts b/test/strategies/go-yoshi.ts index eea684d89..589121f2c 100644 --- a/test/strategies/go-yoshi.ts +++ b/test/strategies/go-yoshi.ts @@ -100,6 +100,10 @@ describe('GoYoshi', () => { }); describe('buildReleasePullRequest', () => { it('filters out submodule commits', async () => { + sandbox + .stub(github, 'findFilesByFilenameAndRef') + .withArgs('go.mod', 'main') + .resolves(['go.mod', 'internal/go.mod', 'logging/go.mod']); const strategy = new GoYoshi({ targetBranch: 'main', github, @@ -117,6 +121,10 @@ describe('GoYoshi', () => { snapshot(dateSafe(pullRequestBody)); }); it('filters out touched files not matching submodule commits', async () => { + sandbox + .stub(github, 'findFilesByFilenameAndRef') + .withArgs('go.mod', 'main') + .resolves(['go.mod', 'internal/go.mod', 'logging/go.mod']); const strategy = new GoYoshi({ targetBranch: 'main', github, @@ -158,4 +166,52 @@ describe('GoYoshi', () => { snapshot(dateSafe(pullRequestBody)); }); }); + describe('getIgnoredSubModules', () => { + it('ignores non-google-cloud-go repos', async () => { + github = await GitHub.create({ + owner: 'googleapis', + repo: 'google-cloud-foo', + defaultBranch: 'main', + }); + const strategy = new GoYoshi({ + targetBranch: 'main', + github, + includeComponentInTag: false, + }); + const ignoredSubModules = await strategy.getIgnoredSubModules(); + expect(ignoredSubModules.size).to.eql(0); + }); + it('ignores submodule configurations', async () => { + const strategy = new GoYoshi({ + targetBranch: 'main', + github, + component: 'storage', + includeComponentInTag: true, + }); + const ignoredSubModules = await strategy.getIgnoredSubModules(); + expect(ignoredSubModules.size).to.eql(0); + }); + it('fetches the list of submodules', async () => { + sandbox + .stub(github, 'findFilesByFilenameAndRef') + .withArgs('go.mod', 'main') + .resolves([ + 'storage/go.mod', + 'go.mod', + 'internal/foo/go.mod', + 'internal/go.mod', + 'pubsub/go.mod', + ]); + const strategy = new GoYoshi({ + targetBranch: 'main', + github, + component: 'main', + includeComponentInTag: false, + }); + const ignoredSubModules = await strategy.getIgnoredSubModules(); + expect(ignoredSubModules.size).to.eql(2); + expect(ignoredSubModules.has('storage')).to.be.true; + expect(ignoredSubModules.has('pubsub')).to.be.true; + }); + }); });