Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow configuring release-search-depth and commit-search-depth #1396

Merged
merged 5 commits into from
Apr 15, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/manifest-releaser.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,21 @@ documented in comments)
// absence defaults to "chore: release ${branch}"
"group-pull-request-title-pattern": "chore: release ${branch}",

// When searching for the latest release SHAs, only consider the last N releases.
// This option prevents paginating through all releases in history when we
// expect to find the release within the last N releases. For repositories with
// a large number of individual packages, you may want to consider raising this
// value, but it will increase the number of API calls used.
"release-search-depth": 400,

// When fetching the list of commits to consider, only consider the last N commits.
// This option limits paginating through every commit in history when we may not
// find the release SHA of the last release (there may not be one). We expect to
// only need to consider the last 500 commits on a branch. For repositories with
// a large number of individual packages, you may want to consider raising this
// value, but it will increase the number of API calls used.
"commit-search-depth": 500,

// per package configuration: at least one entry required.
// the key is the relative path from the repo root to the folder that contains
// all the files for that package.
Expand Down
20 changes: 18 additions & 2 deletions src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ export interface ManifestOptions {
prerelease?: boolean;
draftPullRequest?: boolean;
groupPullRequestTitlePattern?: string;
releaseSearchDepth?: number;
commitSearchDepth?: number;
}

interface ReleaserPackageConfig extends ReleaserConfigJson {
Expand Down Expand Up @@ -173,6 +175,8 @@ export interface ManifestConfig extends ReleaserConfigJson {
plugins?: PluginType[];
'separate-pull-requests'?: boolean;
'group-pull-request-title-pattern'?: string;
'release-search-depth'?: number;
'commit-search-depth'?: number;
}
// path => version
export type ReleasedVersions = Record<string, Version>;
Expand All @@ -187,6 +191,8 @@ export const DEFAULT_LABELS = ['autorelease: pending'];
export const DEFAULT_RELEASE_LABELS = ['autorelease: tagged'];
export const DEFAULT_SNAPSHOT_LABELS = ['autorelease: snapshot'];
export const SNOOZE_LABEL = 'autorelease: snooze';
const DEFAULT_RELEASE_SEARCH_DEPTH = 400;
const DEFAULT_COMMIT_SEARCH_DEPTH = 500;

export const MANIFEST_PULL_REQUEST_TITLE_PATTERN = 'chore: release ${branch}';

Expand Down Expand Up @@ -220,6 +226,8 @@ export class Manifest {
private prerelease?: boolean;
private draftPullRequest?: boolean;
private groupPullRequestTitlePattern?: string;
readonly releaseSearchDepth: number;
readonly commitSearchDepth: number;

/**
* Create a Manifest from explicit config in code. This assumes that the
Expand Down Expand Up @@ -277,6 +285,10 @@ export class Manifest {
this.draftPullRequest = manifestOptions?.draftPullRequest;
this.groupPullRequestTitlePattern =
manifestOptions?.groupPullRequestTitlePattern;
this.releaseSearchDepth =
manifestOptions?.releaseSearchDepth || DEFAULT_RELEASE_SEARCH_DEPTH;
this.commitSearchDepth =
manifestOptions?.commitSearchDepth || DEFAULT_COMMIT_SEARCH_DEPTH;
}

/**
Expand Down Expand Up @@ -403,8 +415,9 @@ export class Manifest {

// Releases by path
const releasesByPath: Record<string, Release> = {};
logger.debug(`release search depth: ${this.releaseSearchDepth}`);
for await (const release of this.github.releaseIterator({
maxResults: 400,
maxResults: this.releaseSearchDepth,
})) {
const tagName = TagName.parse(release.tagName);
if (!tagName) {
Expand Down Expand Up @@ -481,8 +494,9 @@ export class Manifest {
// seen all release commits
logger.info('Collecting commits since all latest releases');
const commits: Commit[] = [];
logger.debug(`commit search depth: ${this.commitSearchDepth}`);
const commitGenerator = this.github.mergeCommitIterator(this.targetBranch, {
maxResults: 500,
maxResults: this.commitSearchDepth,
backfillFiles: true,
});
const releaseShas = new Set(Object.values(releaseShasByPath));
Expand Down Expand Up @@ -1138,6 +1152,8 @@ async function parseConfig(
configReleaseLabel === undefined ? undefined : [configReleaseLabel],
snapshotLabels:
configSnapshotLabel === undefined ? undefined : [configSnapshotLabel],
releaseSearchDepth: config['release-search-depth'],
commitSearchDepth: config['commit-search-depth'],
};
return {config: repositoryConfig, options: manifestOptions};
}
Expand Down
9 changes: 9 additions & 0 deletions test/fixtures/manifest/config/search-depth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"release-search-depth": 10,
"commit-search-depth": 50,
"packages": {
".": {
"release-type": "simple"
}
}
}
12 changes: 6 additions & 6 deletions test/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,37 +330,37 @@ export function mockCommits(
sandbox: sinon.SinonSandbox,
github: GitHub,
commits: Commit[]
) {
): sinon.SinonStub {
async function* fakeGenerator() {
for (const commit of commits) {
yield commit;
}
}
sandbox.stub(github, 'mergeCommitIterator').returns(fakeGenerator());
return sandbox.stub(github, 'mergeCommitIterator').returns(fakeGenerator());
}

export function mockReleases(
sandbox: sinon.SinonSandbox,
github: GitHub,
releases: GitHubRelease[]
) {
): sinon.SinonStub {
async function* fakeGenerator() {
for (const release of releases) {
yield release;
}
}
sandbox.stub(github, 'releaseIterator').returns(fakeGenerator());
return sandbox.stub(github, 'releaseIterator').returns(fakeGenerator());
}

export function mockTags(
sandbox: sinon.SinonSandbox,
github: GitHub,
tags: GitHubTag[]
) {
): sinon.SinonStub {
async function* fakeGenerator() {
for (const tag of tags) {
yield tag;
}
}
sandbox.stub(github, 'tagIterator').returns(fakeGenerator());
return sandbox.stub(github, 'tagIterator').returns(fakeGenerator());
}
170 changes: 170 additions & 0 deletions test/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,33 @@ describe('Manifest', () => {
},
]);
});
it('should configure search depth from manifest', async () => {
const getFileContentsStub = sandbox.stub(
github,
'getFileContentsOnBranch'
);
getFileContentsStub
.withArgs('release-please-config.json', 'main')
.resolves(
buildGitHubFileContent(
fixturesPath,
'manifest/config/search-depth.json'
)
)
.withArgs('.release-please-manifest.json', 'main')
.resolves(
buildGitHubFileContent(
fixturesPath,
'manifest/versions/versions.json'
)
);
const manifest = await Manifest.fromManifest(
github,
github.repository.defaultBranch
);
expect(manifest.releaseSearchDepth).to.eql(10);
expect(manifest.commitSearchDepth).to.eql(50);
});
});

describe('fromConfig', () => {
Expand Down Expand Up @@ -2554,6 +2581,149 @@ describe('Manifest', () => {
expect(pullRequests[0].labels).to.eql(['autorelease: pending']);
snapshot(dateSafe(pullRequests[0].body.toString()));
});

it('should allow customizing release-search-depth', async () => {
const releaseStub = mockReleases(sandbox, github, []);
mockTags(sandbox, github, [
{
name: 'pkg1-v1.0.0',
sha: 'abc123',
},
]);
mockCommits(sandbox, github, [
{
sha: 'def456',
message: 'fix: some bugfix',
files: [],
},
{
sha: 'abc123',
message: 'chore: release 1.0.0',
files: [],
pullRequest: {
headBranchName: 'release-please/branches/main/components/pkg1',
baseBranchName: 'main',
number: 123,
title: 'chore: release 1.0.0',
body: '',
labels: [],
files: [],
sha: 'abc123',
},
},
]);
const getFileContentsStub = sandbox.stub(
github,
'getFileContentsOnBranch'
);
getFileContentsStub
.withArgs('package.json', 'main')
.resolves(
buildGitHubFileContent(
fixturesPath,
'manifest/repo/node/pkg1/package.json'
)
);
const manifest = new Manifest(
github,
'main',
{
'.': {
releaseType: 'node',
},
},
{
'.': Version.parse('1.0.0'),
},
{
releaseSearchDepth: 1,
}
);
expect(manifest.releaseSearchDepth).to.eql(1);
const pullRequests = await manifest.buildPullRequests();
expect(pullRequests).lengthOf(1);
const pullRequest = pullRequests[0];
expect(pullRequest.version?.toString()).to.eql('1.0.1');
expect(pullRequest.headRefName).to.eql(
'release-please--branches--main--components--pkg1'
);
sinon.assert.calledOnceWithMatch(
releaseStub,
sinon.match.has('maxResults', 1)
);
});

it('should allow customizing commit-search-depth', async () => {
mockReleases(sandbox, github, []);
mockTags(sandbox, github, [
{
name: 'pkg1-v1.0.0',
sha: 'abc123',
},
]);
const commitsStub = mockCommits(sandbox, github, [
{
sha: 'def456',
message: 'fix: some bugfix',
files: [],
},
{
sha: 'abc123',
message: 'chore: release 1.0.0',
files: [],
pullRequest: {
headBranchName: 'release-please/branches/main/components/pkg1',
baseBranchName: 'main',
number: 123,
title: 'chore: release 1.0.0',
body: '',
labels: [],
files: [],
sha: 'abc123',
},
},
]);
const getFileContentsStub = sandbox.stub(
github,
'getFileContentsOnBranch'
);
getFileContentsStub
.withArgs('package.json', 'main')
.resolves(
buildGitHubFileContent(
fixturesPath,
'manifest/repo/node/pkg1/package.json'
)
);
const manifest = new Manifest(
github,
'main',
{
'.': {
releaseType: 'node',
},
},
{
'.': Version.parse('1.0.0'),
},
{
commitSearchDepth: 1,
}
);
expect(manifest.commitSearchDepth).to.eql(1);
const pullRequests = await manifest.buildPullRequests();
expect(pullRequests).lengthOf(1);
const pullRequest = pullRequests[0];
expect(pullRequest.version?.toString()).to.eql('1.0.1');
expect(pullRequest.headRefName).to.eql(
'release-please--branches--main--components--pkg1'
);
sinon.assert.calledOnceWithMatch(
commitsStub,
'main',
sinon.match.has('maxResults', 1)
);
});
});

describe('createPullRequests', () => {
Expand Down