Skip to content
Draft
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
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ Automate releases with Conventional Commit Messages.
# this is a built-in strategy in release-please, see "Action Inputs"
# for more options
release-type: simple
```
# optional. create a prerelease.
# prerelease: true
# optional. prerelease type (e.g. beta).
# prerelease-type: beta
```

Specifying a `release-type` configuration is the most straight-forward
configuration option, but allows for no further customization. For advanced
Expand Down Expand Up @@ -88,6 +92,8 @@ steps:
| `changelog-host` | The proto://host where commits live. Defaults to `${{ github.server_url }}` (usually `https://github.com`) |
| `versioning-strategy` | The versioning strategy to use. Defaults to `default` |
| `release-as` | The version to release as. |
| `prerelease` | If `true`, create a prerelease. Defaults to `false` |
| `prerelease-type` | The prerelease type (e.g. `beta`). Defaults to `beta` |

## GitHub Credentials

Expand Down Expand Up @@ -273,6 +279,10 @@ jobs:
- uses: googleapis/release-please-action@v4
with:
release-type: node
# optional. create a prerelease.
# prerelease: true
# optional. prerelease type (e.g. beta).
# prerelease-type: beta
# The short ref name of the branch or tag that triggered
# the workflow run. For example, `main` or `1.x`
target-branch: ${{ github.ref_name }}
Expand Down
8 changes: 8 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ inputs:
description: 'The version to release as.'
required: false
default: ''
prerelease:
description: 'If true, create a prerelease.'
required: false
default: false
prerelease-type:
description: 'The prerelease type (e.g. beta).'
required: false
default: 'beta'
runs:
using: 'node20'
main: 'dist/index.js'
17 changes: 9 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"homepage": "https://github.com/googleapis/release-please-action#readme",
"dependencies": {
"@actions/core": "^1.10.0",
"release-please": "^17.1.3"
"release-please": "^17.2.0"
},
"devDependencies": {
"@types/mocha": "^9.0.0",
Expand Down
27 changes: 22 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const DEFAULT_MANIFEST_FILE = '.release-please-manifest.json';
const DEFAULT_GITHUB_API_URL = 'https://api.github.com';
const DEFAULT_GITHUB_GRAPHQL_URL = 'https://api.github.com';
const DEFAULT_GITHUB_SERVER_URL = 'https://github.com';
const DEFAULT_PRERELEASE = false;

interface Proxy {
host: string;
Expand All @@ -45,6 +46,8 @@ interface ActionInputs {
changelogHost: string;
versioningStrategy?: string;
releaseAs?: string;
prerelease?: boolean;
prereleaseType?: string;
}

function parseInputs(): ActionInputs {
Expand All @@ -69,6 +72,8 @@ function parseInputs(): ActionInputs {
changelogHost: core.getInput('changelog-host') || DEFAULT_GITHUB_SERVER_URL,
versioningStrategy: getOptionalInput('versioning-strategy'),
releaseAs: getOptionalInput('release-as'),
prerelease: getOptionalBooleanInput('prerelease'),
prereleaseType: getOptionalInput('prerelease-type'),
};
return inputs;
}
Expand Down Expand Up @@ -100,6 +105,8 @@ function loadOrBuildManifest(
changelogHost: inputs.changelogHost,
versioning: inputs.versioningStrategy,
releaseAs: inputs.releaseAs,
prerelease: inputs.prerelease,
prereleaseType: inputs.prereleaseType,
},
{
fork: inputs.fork,
Expand All @@ -108,10 +115,12 @@ function loadOrBuildManifest(
inputs.path
);
}
const manifestOverrides = inputs.fork || inputs.skipLabeling
const manifestOverrides: any = inputs.fork || inputs.skipLabeling || inputs.prerelease !== undefined || inputs.prereleaseType
? {
fork: inputs.fork,
skipLabeling: inputs.skipLabeling,
prerelease: inputs.prerelease,
prereleaseType: inputs.prereleaseType,
}
: {};
core.debug('Loading manifest from config file');
Expand All @@ -122,12 +131,20 @@ function loadOrBuildManifest(
inputs.manifestFile,
manifestOverrides
).then(manifest => {
// Override changelogHost for all paths if provided as action input and different from default
if (inputs.changelogHost && inputs.changelogHost !== DEFAULT_GITHUB_SERVER_URL) {
core.debug(`Overriding changelogHost to: ${inputs.changelogHost}`);
for (const path in manifest.repositoryConfig) {
// Override changelogHost, prerelease and prereleaseType for all paths if provided as action input and maybe also different from default
for (const path in manifest.repositoryConfig) {
if (inputs.changelogHost && inputs.changelogHost !== DEFAULT_GITHUB_SERVER_URL) {
core.debug(`Overriding changelogHost to: ${inputs.changelogHost}`);
manifest.repositoryConfig[path].changelogHost = inputs.changelogHost;
}
if (inputs.prerelease !== undefined) {
core.debug(`Overriding prerelease to: ${inputs.prerelease}`);
manifest.repositoryConfig[path].prerelease = inputs.prerelease;
}
if (inputs.prereleaseType) {
core.debug(`Overriding prereleaseType to: ${inputs.prereleaseType}`);
manifest.repositoryConfig[path].prereleaseType = inputs.prereleaseType;
}
}
return manifest;
});
Expand Down
118 changes: 118 additions & 0 deletions test/release-please.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,54 @@ describe('release-please-action', () => {
sinon.match.any,
);
});

it('allows specifying prerelease', async () => {
restoreEnv = mockInputs({
'release-type': 'simple',
'prerelease': 'true',
});
fakeManifest.createReleases.resolves([]);
fakeManifest.createPullRequests.resolves([]);
await action.main(fetch);
sinon.assert.calledOnce(fakeManifest.createReleases);
sinon.assert.calledOnce(fakeManifest.createPullRequests);

sinon.assert.calledWith(
fromConfigStub,
sinon.match.any,
sinon.match.string,
sinon.match({
releaseType: 'simple',
prerelease: true,
}),
sinon.match.object,
sinon.match.any,
);
});

it('allows specifying prerelease-type', async () => {
restoreEnv = mockInputs({
'release-type': 'simple',
'prerelease-type': 'alpha',
});
fakeManifest.createReleases.resolves([]);
fakeManifest.createPullRequests.resolves([]);
await action.main(fetch);
sinon.assert.calledOnce(fakeManifest.createReleases);
sinon.assert.calledOnce(fakeManifest.createPullRequests);

sinon.assert.calledWith(
fromConfigStub,
sinon.match.any,
sinon.match.string,
sinon.match({
releaseType: 'simple',
prereleaseType: 'alpha',
}),
sinon.match.object,
sinon.match.any,
);
});
});

describe('with manifest', () => {
Expand Down Expand Up @@ -364,6 +412,76 @@ describe('release-please-action', () => {
assert.strictEqual(fakeManifest.repositoryConfig['.'].changelogHost, undefined);
assert.strictEqual(fakeManifest.repositoryConfig['packages/foo'].changelogHost, undefined);
});

it('allows specifying prerelease', async () => {
restoreEnv = mockInputs({
'prerelease': 'true',
});
// Create a mock repositoryConfig on the existing fakeManifest
const mockRepositoryConfig = {
'.': { releaseType: 'node' },
'packages/foo': { releaseType: 'node' }
};
// Use Object.defineProperty to set the readonly property
Object.defineProperty(fakeManifest, 'repositoryConfig', {
value: mockRepositoryConfig,
writable: true,
configurable: true
});
fakeManifest.createReleases.resolves([]);
fakeManifest.createPullRequests.resolves([]);
await action.main(fetch);
sinon.assert.calledOnce(fakeManifest.createReleases);
sinon.assert.calledOnce(fakeManifest.createPullRequests);

// Verify that fromManifest is called WITHOUT prerelease in overrides
sinon.assert.calledWith(
fromManifestStub,
sinon.match.any,
sinon.match.string,
sinon.match.string,
sinon.match.string,
sinon.match(arg => !arg.hasOwnProperty('prerelease')),
);
// Verify that prerelease was added to all paths in repositoryConfig
assert.strictEqual(fakeManifest.repositoryConfig['.'].prerelease, true);
assert.strictEqual(fakeManifest.repositoryConfig['packages/foo'].prerelease, true);
});

it('allows specifying prerelease-type', async () => {
restoreEnv = mockInputs({
'prerelease-type': 'alpha',
});
// Create a mock repositoryConfig on the existing fakeManifest
const mockRepositoryConfig = {
'.': { releaseType: 'node' },
'packages/foo': { releaseType: 'node' }
};
// Use Object.defineProperty to set the readonly property
Object.defineProperty(fakeManifest, 'repositoryConfig', {
value: mockRepositoryConfig,
writable: true,
configurable: true
});
fakeManifest.createReleases.resolves([]);
fakeManifest.createPullRequests.resolves([]);
await action.main(fetch);
sinon.assert.calledOnce(fakeManifest.createReleases);
sinon.assert.calledOnce(fakeManifest.createPullRequests);

// Verify that fromManifest is called WITHOUT prereleaseType in overrides
sinon.assert.calledWith(
fromManifestStub,
sinon.match.any,
sinon.match.string,
sinon.match.string,
sinon.match.string,
sinon.match(arg => !arg.hasOwnProperty('prereleaseType')),
);
// Verify that prereleaseType was added to all paths in repositoryConfig
assert.strictEqual(fakeManifest.repositoryConfig['.'].prereleaseType, 'alpha');
assert.strictEqual(fakeManifest.repositoryConfig['packages/foo'].prereleaseType, 'alpha');
});
});

it('allows specifying manifest config paths', async () => {
Expand Down