Skip to content

Commit c3ed725

Browse files
committed
feat: add dry-run
adds ability to output candidate releases, and candidate PRs without actually releasing or updating PRs
1 parent 1155c2c commit c3ed725

File tree

3 files changed

+73
-16
lines changed

3 files changed

+73
-16
lines changed

README.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ steps:
8383
| `proxy-server` | Configure a proxy servier in the form of `<host>:<port>` e.g. `proxy-host.com:8080` |
8484
| `skip-github-release` | If `true`, do not attempt to create releases. This is useful if splitting release tagging from PR creation. |
8585
| `skip-github-pull-request` | If `true`, do not attempt to create release pull requests. This is useful if splitting release tagging from PR creation. |
86-
| `skip-labeling` | If `true`, do not attempt to label the PR. |
86+
| `skip-labeling` | If `true`, do not attempt to label the PR. |
87+
| `dry-run` | If `true`, the action outputs pending releases and/or pending pull requests, but does not create them. |
8788

8889
## GitHub Credentials
8990

@@ -93,7 +94,7 @@ the `token` configuration option.
9394
If your repository is in an organization, you may need to
9495
[permit github actions to create an approve PRs](https://stackoverflow.com/questions/72376229).
9596

96-
> [!WARNING]
97+
> [!WARNING]
9798
> If using GitHub Actions, you will need to specify a `token` for your workflows to run on
9899
> Release Please's releases and PRs. See [the heading below](#other-actions-on-release-please-prs).
99100

@@ -165,13 +166,16 @@ New types of releases can be [added here](https://github.com/googleapis/release-
165166

166167
> Properties that are available after the action executed.
167168

168-
| output | description |
169-
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
170-
| `releases_created` | `true` if any release was created, `false` otherwise |
171-
| `paths_released` | A JSON string of the array of paths that had releases created (`[]` if nothing was released) |
172-
| `prs_created` | `true` if any pull request was created or updated |
173-
| `pr` | A JSON string of the [PullRequest object](https://github.com/googleapis/release-please/blob/main/src/pull-request.ts#L15) (unset if no release created) |
174-
| `prs` | A JSON string of the array of [PullRequest objects](https://github.com/googleapis/release-please/blob/main/src/pull-request.ts#L15) (unset if no release created) |
169+
| output | description |
170+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
171+
| `releases_created` | `true` if any release was created, `false` otherwise. |
172+
| `paths_released` | A JSON string of the array of paths that had releases created (`[]` if nothing was released). |
173+
| `releases_pending` | `true` if any candidate release is pending (when running in dry-run mode). |
174+
| `paths_to_release` | A JSON string of the array of paths that have pending candidate releases (when running in dry-run mode). |
175+
| `prs_created` | `true` if any pull request was created or updated. |
176+
| `prs_pending` | `true` if any candidate pull request is pending (when running in dry-run mode). |
177+
| `pr` | A JSON string of the [PullRequest object](https://github.com/googleapis/release-please/blob/main/src/pull-request.ts#L15) (in dry-run [ReleasePullRequest object](https://github.com/googleapis/release-please/blob/main/src/release-pull-request.ts#L20), unset otherwise) |
178+
| `prs` | A JSON string of the array of [PullRequest objects](https://github.com/googleapis/release-please/blob/main/src/pull-request.ts#L15) (in dry-run [ReleasePullRequest object](https://github.com/googleapis/release-please/blob/main/src/release-pull-request.ts#L20), unset otherwise) |
175179

176180
### Root component outputs
177181

action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ inputs:
6666
description: 'The proto://host where commits live. Default `https://github.com`'
6767
required: false
6868
default: ${{ github.server_url }}
69+
dry-run:
70+
description: 'if set to true, the action lists build releases and/or PRs but does not create them'
71+
required: false
72+
default: false
6973
runs:
7074
using: 'node20'
7175
main: 'dist/index.js'

src/index.ts

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// limitations under the License.
1414

1515
import * as core from '@actions/core';
16-
import {GitHub, Manifest, CreatedRelease, PullRequest, VERSION} from 'release-please';
16+
import {GitHub, Manifest, CreatedRelease, PullRequest, VERSION, CandidateRelease, ReleasePullRequest} from 'release-please';
1717

1818
const DEFAULT_CONFIG_FILE = 'release-please-config.json';
1919
const DEFAULT_MANIFEST_FILE = '.release-please-manifest.json';
@@ -43,6 +43,7 @@ interface ActionInputs {
4343
fork?: boolean;
4444
includeComponentInTag?: boolean;
4545
changelogHost: string;
46+
dryRun?: boolean;
4647
}
4748

4849
function parseInputs(): ActionInputs {
@@ -65,6 +66,7 @@ function parseInputs(): ActionInputs {
6566
fork: getOptionalBooleanInput('fork'),
6667
includeComponentInTag: getOptionalBooleanInput('include-component-in-tag'),
6768
changelogHost: core.getInput('changelog-host') || DEFAULT_GITHUB_SERVER_URL,
69+
dryRun: getOptionalBooleanInput('dry-run'),
6870
};
6971
return inputs;
7072
}
@@ -122,17 +124,26 @@ export async function main() {
122124
core.info(`Running release-please version: ${VERSION}`)
123125
const inputs = parseInputs();
124126
const github = await getGitHubInstance(inputs);
127+
const manifest = await loadOrBuildManifest(github, inputs);
125128

126129
if (!inputs.skipGitHubRelease) {
127-
const manifest = await loadOrBuildManifest(github, inputs);
128-
core.debug('Creating releases');
129-
outputReleases(await manifest.createReleases());
130+
if (inputs.dryRun) {
131+
core.debug('Listing pending releases');
132+
outputCandidateReleases(await manifest.buildReleases());
133+
} else {
134+
core.debug('Creating releases');
135+
outputReleases(await manifest.createReleases());
136+
}
130137
}
131138

132139
if (!inputs.skipGitHubPullRequest) {
133-
const manifest = await loadOrBuildManifest(github, inputs);
134-
core.debug('Creating pull requests');
135-
outputPRs(await manifest.createPullRequests());
140+
if (inputs.dryRun) {
141+
core.debug('Listing pending pull requests');
142+
outputCandidatePRs(await manifest.buildPullRequests());
143+
} else {
144+
core.debug('Creating pull requests');
145+
outputPRs(await manifest.createPullRequests());
146+
}
136147
}
137148
}
138149

@@ -200,6 +211,35 @@ function outputReleases(releases: (CreatedRelease | undefined)[]) {
200211
core.setOutput('paths_released', JSON.stringify(pathsReleased));
201212
}
202213

214+
function outputCandidateReleases(releases: CandidateRelease[]) {
215+
releases = releases.filter(release => release !== undefined);
216+
const pathsReleased = [];
217+
core.setOutput('releases_pending', releases.length > 0);
218+
if (releases.length) {
219+
for (const release of releases) {
220+
if (!release) {
221+
continue;
222+
}
223+
const path = release.path || '.';
224+
if (path) {
225+
pathsReleased.push(path);
226+
// If the special root release is set (representing project root)
227+
// and this is explicitly a manifest release, set the release_created boolean.
228+
setPathOutput(path, 'release_pending', true);
229+
}
230+
if (release.tag) {
231+
// Historically tagName was output as tag_name, keep this
232+
// consistent to avoid breaking change:
233+
setPathOutput(path, 'tag_name', release.tag.toString());
234+
setPathOutput(path, 'body', release.notes)
235+
}
236+
}
237+
}
238+
// Paths of all releases that were created, so that they can be passed
239+
// to matrix in next step:
240+
core.setOutput('paths_to_release', JSON.stringify(pathsReleased));
241+
}
242+
203243
function outputPRs(prs: (PullRequest | undefined)[]) {
204244
prs = prs.filter(pr => pr !== undefined);
205245
core.setOutput('prs_created', prs.length > 0);
@@ -209,6 +249,15 @@ function outputPRs(prs: (PullRequest | undefined)[]) {
209249
}
210250
}
211251

252+
function outputCandidatePRs(prs: ReleasePullRequest[]) {
253+
prs = prs.filter(pr => pr !== undefined);
254+
core.setOutput('prs_pending', prs.length > 0);
255+
if (prs.length) {
256+
core.setOutput('pr', prs[0]);
257+
core.setOutput('prs', JSON.stringify(prs));
258+
}
259+
}
260+
212261
if (require.main === module) {
213262
main().catch(err => {
214263
core.setFailed(`release-please failed: ${err.message}`)

0 commit comments

Comments
 (0)