diff --git a/README.md b/README.md index c0043d09..73e35b3e 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 @@ -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 }} diff --git a/action.yml b/action.yml index add125a2..dadc9a2c 100644 --- a/action.yml +++ b/action.yml @@ -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' diff --git a/package-lock.json b/package-lock.json index 40dd6b7f..e4887773 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@actions/core": "^1.10.0", - "release-please": "^17.1.3" + "release-please": "^17.2.0" }, "devDependencies": { "@types/mocha": "^9.0.0", @@ -5128,9 +5128,9 @@ } }, "node_modules/release-please": { - "version": "17.1.3", - "resolved": "https://registry.npmjs.org/release-please/-/release-please-17.1.3.tgz", - "integrity": "sha512-fs4v5318Z3CLqyqw7EueXzjErtL8oXCv6Kc1mMYi72TAyReyBtOuuMB0lwoC2+LtGmvUYoG+RBXnDVU0DsKUIA==", + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/release-please/-/release-please-17.2.0.tgz", + "integrity": "sha512-DIB8gXH+GBwy1MvkJ/xUceVPW+10OOQagNBaOB/V3B8hHbfsVbQjwEL0Hu6zTRsqve9wRvqE48mKtwjaXIxupA==", "license": "Apache-2.0", "dependencies": { "@conventional-commits/parser": "^0.4.1", @@ -5148,7 +5148,7 @@ "conventional-changelog-writer": "^6.0.0", "conventional-commits-filter": "^3.0.0", "detect-indent": "^6.1.0", - "diff": "^7.0.0", + "diff": "^8.0.3", "figures": "^3.0.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", @@ -5186,9 +5186,10 @@ } }, "node_modules/release-please/node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } diff --git a/package.json b/package.json index dec5334c..f7f0ae11 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/index.ts b/src/index.ts index 480dd3e4..a9313974 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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; @@ -45,6 +46,8 @@ interface ActionInputs { changelogHost: string; versioningStrategy?: string; releaseAs?: string; + prerelease?: boolean; + prereleaseType?: string; } function parseInputs(): ActionInputs { @@ -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; } @@ -100,6 +105,8 @@ function loadOrBuildManifest( changelogHost: inputs.changelogHost, versioning: inputs.versioningStrategy, releaseAs: inputs.releaseAs, + prerelease: inputs.prerelease, + prereleaseType: inputs.prereleaseType, }, { fork: inputs.fork, @@ -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'); @@ -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; }); diff --git a/test/release-please.ts b/test/release-please.ts index 16677632..bf4e9d63 100644 --- a/test/release-please.ts +++ b/test/release-please.ts @@ -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', () => { @@ -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 () => {