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: Support sequential-calls manifest field that disables concurrency when creating multiple pull requests or releases #1401

Merged
merged 1 commit into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ Extra options:
| `--draft-pull-request` | `boolean` | If set, create pull requests as drafts |
| `--label` | `string` | Comma-separated list of labels to apply to the release pull requests. Defaults to `autorelease: pending` |
| `--release-label` | `string` | Comma-separated list of labels to apply to the pull request after the release has been tagged. Defaults to `autorelease: tagged` |
| `--skip-labeling` | `boolean` | If set, labels will not be applied to pull requests |
| `--changelog-path` | `string` | Override the path to the managed CHANGELOG. Defaults to `CHANGELOG.md` |
| `--changelog-type` | [`ChangelogType`](/docs/customizing.md#changelog-types) | Strategy for building the changelog contents. Defaults to `default` |
| `--changelog-sections` | `string` | Comma-separated list of commit scopes to show in changelog headings |
Expand All @@ -83,6 +82,7 @@ Extra options:
| ------ | ---- | ----------- |
| `--config-file` | string | Override the path to the release-please config file. Defaults to `release-please-config.json` |
| `--manifest-file` | string | Override the path to the release-please manifest file. Defaults to `.release-please-manifest.json` |
| `--skip-labeling` | `boolean` | If set, labels will not be applied to pull requests |

### Without a manifest config

Expand All @@ -109,6 +109,7 @@ need to specify your release options:
| `--signoff` | string | Add [`Signed-off-by`](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---signoff) line at the end of the commit log message using the user and email provided. (format "Name \<[email protected]\>") |
| `--extra-files` | `string[]` | Extra file paths for the release strategy to consider |
| `--version-file` | `string` | Ruby only. Path to the `version.rb` file |
| `--skip-labeling` | `boolean` | If set, labels will not be applied to pull requests |

## Creating a release on GitHub

Expand Down
8 changes: 8 additions & 0 deletions docs/manifest-releaser.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ documented in comments)
// value, but it will increase the number of API calls used.
"commit-search-depth": 500,

// when creating multiple pull requests or releases, issue GitHub API requests
// sequentially rather than concurrently, waiting for the previous request to
// complete before issuing the next one.
// This option may reduce failures due to throttling on repositories releasing
// large numbers of packages at once.
// absence defaults to false, causing calls to be issued concurrently.
"sequential-calls": false,

// 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
68 changes: 49 additions & 19 deletions src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,10 @@ export interface ManifestOptions {
signoff?: string;
manifestPath?: string;
labels?: string[];
skipLabeling?: boolean;
releaseLabels?: string[];
snapshotLabels?: string[];
skipLabeling?: boolean;
sequentialCalls?: boolean;
draft?: boolean;
prerelease?: boolean;
draftPullRequest?: boolean;
Expand Down Expand Up @@ -178,6 +179,7 @@ export interface ManifestConfig extends ReleaserConfigJson {
'group-pull-request-title-pattern'?: string;
'release-search-depth'?: number;
'commit-search-depth'?: number;
'sequential-calls'?: boolean;
}
// path => version
export type ReleasedVersions = Record<string, Version>;
Expand Down Expand Up @@ -216,6 +218,7 @@ export class Manifest {
private signoffUser?: string;
private labels: string[];
private skipLabeling?: boolean;
private sequentialCalls?: boolean;
private releaseLabels: string[];
private snapshotLabels: string[];
private plugins: PluginType[];
Expand Down Expand Up @@ -280,6 +283,7 @@ export class Manifest {
manifestOptions?.releaseLabels || DEFAULT_RELEASE_LABELS;
this.labels = manifestOptions?.labels || DEFAULT_LABELS;
this.skipLabeling = manifestOptions?.skipLabeling || false;
this.sequentialCalls = manifestOptions?.sequentialCalls || false;
this.snapshotLabels =
manifestOptions?.snapshotLabels || DEFAULT_SNAPSHOT_LABELS;
this.bootstrapSha = manifestOptions?.bootstrapSha;
Expand Down Expand Up @@ -720,7 +724,7 @@ export class Manifest {
/**
* Opens/updates all candidate release pull requests for this repository.
*
* @returns {number[]} Pull request numbers of release pull requests
* @returns {PullRequest[]} Pull request numbers of release pull requests
*/
async createPullRequests(): Promise<(PullRequest | undefined)[]> {
const candidatePullRequests = await this.buildPullRequests();
Expand All @@ -742,19 +746,32 @@ export class Manifest {
const openPullRequests = await this.findOpenReleasePullRequests();
const snoozedPullRequests = await this.findSnoozedReleasePullRequests();

const promises: Promise<PullRequest | undefined>[] = [];
for (const pullRequest of candidatePullRequests) {
promises.push(
this.createOrUpdatePullRequest(
if (this.sequentialCalls) {
const pullRequests: PullRequest[] = [];
for (const pullRequest of candidatePullRequests) {
const resultPullRequest = await this.createOrUpdatePullRequest(
pullRequest,
openPullRequests,
snoozedPullRequests
)
);
);
if (resultPullRequest) pullRequests.push(resultPullRequest);
}
return pullRequests;
} else {
const promises: Promise<PullRequest | undefined>[] = [];
for (const pullRequest of candidatePullRequests) {
promises.push(
this.createOrUpdatePullRequest(
pullRequest,
openPullRequests,
snoozedPullRequests
)
);
}
const pullNumbers = await Promise.all(promises);
// reject any pull numbers that were not created or updated
return pullNumbers.filter(number => !!number);
}
const pullNumbers = await Promise.all(promises);
// reject any pull numbers that were not created or updated
return pullNumbers.filter(number => !!number);
}

private async findOpenReleasePullRequests(): Promise<PullRequest[]> {
Expand Down Expand Up @@ -968,17 +985,29 @@ export class Manifest {
}
}

const promises: Promise<CreatedRelease[]>[] = [];
for (const pullNumber in releasesByPullRequest) {
promises.push(
this.createReleasesForPullRequest(
if (this.sequentialCalls) {
const resultReleases: CreatedRelease[] = [];
for (const pullNumber in releasesByPullRequest) {
const releases = await this.createReleasesForPullRequest(
releasesByPullRequest[pullNumber],
pullRequestsByNumber[pullNumber]
)
);
);
resultReleases.concat(releases);
}
return resultReleases;
} else {
const promises: Promise<CreatedRelease[]>[] = [];
for (const pullNumber in releasesByPullRequest) {
promises.push(
this.createReleasesForPullRequest(
releasesByPullRequest[pullNumber],
pullRequestsByNumber[pullNumber]
)
);
}
const releases = await Promise.all(promises);
return releases.reduce((collection, r) => collection.concat(r), []);
}
const releases = await Promise.all(promises);
return releases.reduce((collection, r) => collection.concat(r), []);
}

private async createReleasesForPullRequest(
Expand Down Expand Up @@ -1158,6 +1187,7 @@ async function parseConfig(
configSnapshotLabel === undefined ? undefined : [configSnapshotLabel],
releaseSearchDepth: config['release-search-depth'],
commitSearchDepth: config['commit-search-depth'],
sequentialCalls: config['sequential-calls'],
};
return {config: repositoryConfig, options: manifestOptions};
}
Expand Down