1
0
mirror of https://github.com/joaquinjsb/gitea-release-please-action synced 2026-05-13 01:41:34 +02:00

feat(release-please)!: consolidate manifest and individual releasers (#398)

Major update to release-please which consolidates the manifest and single
releaser behavior into a single set of strategies, which can be used
on both split and mono-repos.

feat: adds support for draft pull requests.
feat: adds support for draft releases.
refactor!: if switching to manifest releaser, release_created will only be set if "." path is published.
refactor!: switch to using @actions/core getBooleanInput, accepted values for true = ["true", "True", "TRUE"], accepted values for false = ["false", "False", "FALSE"]
This commit is contained in:
Benjamin E. Coe
2021-12-29 19:54:42 +00:00
committed by GitHub
parent 0091158605
commit 52ffbbe392
7 changed files with 29460 additions and 22224 deletions

View File

@@ -20,7 +20,7 @@ Automate releases with Conventional Commit Messages.
release-please: release-please:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: GoogleCloudPlatform/release-please-action@v2 - uses: GoogleCloudPlatform/release-please-action@v3
with: with:
release-type: node release-type: node
package-name: release-please-action package-name: release-please-action
@@ -37,7 +37,7 @@ Automate releases with Conventional Commit Messages.
```yaml ```yaml
#...(same as above) #...(same as above)
steps: steps:
- uses: GoogleCloudPlatform/release-please-action@v2 - uses: GoogleCloudPlatform/release-please-action@v3
with: with:
command: manifest command: manifest
``` ```
@@ -138,7 +138,7 @@ jobs:
release-please: release-please:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: GoogleCloudPlatform/release-please-action@v2 - uses: GoogleCloudPlatform/release-please-action@v3
with: with:
release-type: node release-type: node
package-name: release-please-action package-name: release-please-action
@@ -161,7 +161,7 @@ jobs:
release-please: release-please:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: GoogleCloudPlatform/release-please-action@v2 - uses: GoogleCloudPlatform/release-please-action@v3
with: with:
release-type: node release-type: node
package-name: release-please-action package-name: release-please-action
@@ -178,7 +178,7 @@ jobs:
release-please: release-please:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: GoogleCloudPlatform/release-please-action@v2 - uses: GoogleCloudPlatform/release-please-action@v3
with: with:
release-type: node release-type: node
package-name: release-please-action package-name: release-please-action
@@ -200,7 +200,7 @@ jobs:
release-please: release-please:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: GoogleCloudPlatform/release-please-action@v2 - uses: GoogleCloudPlatform/release-please-action@v3
id: release id: release
with: with:
release-type: node release-type: node
@@ -248,7 +248,7 @@ jobs:
release-please: release-please:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: GoogleCloudPlatform/release-please-action@v2 - uses: GoogleCloudPlatform/release-please-action@v3
id: release id: release
with: with:
release-type: node release-type: node

View File

@@ -32,18 +32,10 @@ inputs:
description: "create a release from a path other than the repository's root" description: "create a release from a path other than the repository's root"
required: false required: false
default: '' default: ''
monorepo-tags:
description: 'add prefix to tags and branches, allowing multiple libraries to be released from the same repository'
required: false
default: false
changelog-path: changelog-path:
description: 'specify a CHANGELOG path other than the root CHANGELOG.md' description: 'specify a CHANGELOG path other than the root CHANGELOG.md'
required: false required: false
default: '' default: ''
changelog-types:
description: 'changlelog commit types'
required: false
default: ''
command: command:
description: 'release-please command to run, either "github-release", or "release-pr" (defaults to running both)' description: 'release-please command to run, either "github-release", or "release-pr" (defaults to running both)'
required: false required: false
@@ -56,10 +48,10 @@ inputs:
description: 'branch to open pull release PR against (detected by default)' description: 'branch to open pull release PR against (detected by default)'
required: false required: false
default: '' default: ''
pull-request-title-pattern: changelog-types:
description: 'add title pattern to make release PR, defaults to using "chore${scope}: release${component} ${version}".' description: 'changlelog commit types'
required: false required: false
default: 'chore${scope}: release${component} ${version}' default: ''
config-file: config-file:
description: 'where can the config file be found in the project?' description: 'where can the config file be found in the project?'
required: false required: false
@@ -84,6 +76,22 @@ inputs:
description: 'configure github repository URL. Default `process.env.GITHUB_REPOSITORY`' description: 'configure github repository URL. Default `process.env.GITHUB_REPOSITORY`'
required: false required: false
default: '' default: ''
monorepo-tags:
description: 'add prefix to tags and branches, allowing multiple libraries to be released from the same repository'
required: false
default: false
pull-request-title-pattern:
description: 'add title pattern to make release PR, defaults to using "chore${scope}: release${component} ${version}"'
required: false
default: ''
draft:
description: 'mark release as a draft'
required: false
default: false
draft-pull-request:
description: 'mark pull request as a draft'
required: false
default: false
runs: runs:
using: 'node12' using: 'node12'

42961
dist/index.js vendored

File diff suppressed because one or more lines are too long

228
index.js
View File

@@ -1,10 +1,10 @@
const core = require('@actions/core') const core = require('@actions/core')
const { factory } = require('release-please/build/src') const { GitHub } = require('release-please/build/src/github')
const { Manifest } = require('release-please/build/src/manifest')
const CONFIG_FILE = 'release-please-config.json' const CONFIG_FILE = 'release-please-config.json'
const MANIFEST_FILE = '.release-please-manifest.json' const MANIFEST_FILE = '.release-please-manifest.json'
const MANIFEST_COMMANDS = ['manifest', 'manifest-pr'] const MANIFEST_COMMANDS = ['manifest', 'manifest-pr']
const RELEASE_LABEL = 'autorelease: pending'
const GITHUB_RELEASE_COMMAND = 'github-release' const GITHUB_RELEASE_COMMAND = 'github-release'
const GITHUB_RELEASE_PR_COMMAND = 'release-pr' const GITHUB_RELEASE_PR_COMMAND = 'release-pr'
const GITHUB_API_URL = 'https://api.github.com' const GITHUB_API_URL = 'https://api.github.com'
@@ -12,18 +12,9 @@ const GITHUB_GRAPHQL_URL = 'https://api.github.com'
const signoff = core.getInput('signoff') || undefined const signoff = core.getInput('signoff') || undefined
function getBooleanInput (input) {
const trueValue = ['true', 'True', 'TRUE', 'yes', 'Yes', 'YES', 'y', 'Y', 'on', 'On', 'ON']
const falseValue = ['false', 'False', 'FALSE', 'no', 'No', 'NO', 'n', 'N', 'off', 'Off', 'OFF']
const stringInput = core.getInput(input)
if (trueValue.indexOf(stringInput) > -1) return true
if (falseValue.indexOf(stringInput) > -1) return false
throw TypeError(`Wrong boolean value of the input '${input}'`)
}
function getGitHubInput () { function getGitHubInput () {
return { return {
fork: getBooleanInput('fork'), fork: core.getBooleanInput('fork'),
defaultBranch: core.getInput('default-branch') || undefined, defaultBranch: core.getInput('default-branch') || undefined,
repoUrl: core.getInput('repo-url') || process.env.GITHUB_REPOSITORY, repoUrl: core.getInput('repo-url') || process.env.GITHUB_REPOSITORY,
apiUrl: core.getInput('github-api-url') || GITHUB_API_URL, apiUrl: core.getInput('github-api-url') || GITHUB_API_URL,
@@ -41,29 +32,123 @@ function getManifestInput () {
} }
async function runManifest (command) { async function runManifest (command) {
const githubOpts = getGitHubInput() // Create the Manifest and GitHub instance from
const manifestOpts = { ...githubOpts, ...getManifestInput() } // argument provided to GitHub action:
const pr = await factory.runCommand('manifest-pr', manifestOpts) const { fork } = getGitHubInput()
if (pr) { const manifestOpts = getManifestInput()
core.setOutput('pr', pr) const github = await getGitHubInstance()
} const manifest = await Manifest.fromManifest(
github,
github.repository.defaultBranch,
manifestOpts.configFile,
manifestOpts.manifestFile,
{
signoff,
fork
}
)
// Create or update release PRs:
outputPRs(await manifest.createPullRequests())
if (command === 'manifest-pr') return if (command === 'manifest-pr') return
outputReleases(await manifest.createReleases())
}
const releasesCreated = await factory.runCommand('manifest-release', manifestOpts) async function main () {
const command = core.getInput('command') || undefined
if (MANIFEST_COMMANDS.includes(command)) {
return await runManifest(command)
}
const { fork } = getGitHubInput()
const bumpMinorPreMajor = core.getBooleanInput('bump-minor-pre-major')
const bumpPatchForMinorPreMajor = core.getBooleanInput('bump-patch-for-minor-pre-major')
const monorepoTags = core.getBooleanInput('monorepo-tags')
const packageName = core.getInput('package-name')
const path = core.getInput('path') || undefined
const releaseType = core.getInput('release-type', { required: true })
const changelogPath = core.getInput('changelog-path') || undefined
const changelogTypes = core.getInput('changelog-types') || undefined
const changelogSections = changelogTypes && JSON.parse(changelogTypes)
const versionFile = core.getInput('version-file') || undefined
const github = await getGitHubInstance()
const pullRequestTitlePattern = core.getInput('pull-request-title-pattern') || undefined
const draft = core.getBooleanInput('draft')
const draftPullRequest = core.getBooleanInput('draft-pull-request')
const manifest = await Manifest.fromConfig(
github,
github.repository.defaultBranch,
{
bumpMinorPreMajor,
bumpPatchForMinorPreMajor,
packageName,
releaseType,
changelogPath,
changelogSections,
versionFile,
includeComponentInTag: monorepoTags,
pullRequestTitlePattern,
draftPullRequest
},
{
draft,
signoff,
fork
},
path
)
// First we check for any merged release PRs (PRs merged with the label
// "autorelease: pending"):
if (!command || command === GITHUB_RELEASE_COMMAND) {
outputReleases(await manifest.createReleases())
}
// Next we check for PRs merged since the last release, and groom the
// release PR:
if (!command || command === GITHUB_RELEASE_PR_COMMAND) {
outputPRs(await manifest.createPullRequests())
}
}
const releasePlease = {
main
}
function getGitHubInstance () {
const { token, defaultBranch, apiUrl, graphqlUrl, repoUrl } = getGitHubInput()
const [owner, repo] = repoUrl.split('/')
const githubCreateOpts = {
owner,
repo,
apiUrl,
graphqlUrl,
token
}
if (defaultBranch) githubCreateOpts.defaultBranch = defaultBranch
return GitHub.create(githubCreateOpts)
}
function outputReleases (releases) {
releases = releases.filter(release => release !== undefined)
const pathsReleased = [] const pathsReleased = []
if (releasesCreated) { if (releases.length) {
core.setOutput('releases_created', true) core.setOutput('releases_created', true)
for (const [path, release] of Object.entries(releasesCreated)) { for (const release of releases) {
if (!release) { const path = release.path || '.'
continue if (path) {
pathsReleased.push(path)
// If the special root release is set (representing project root)
// and this is explicitly a manifest release, set the release_created boolean.
if (path === '.') {
core.setOutput('release_created', true)
} else {
core.setOutput(`${path}--release_created`, true)
}
} }
pathsReleased.push(path) for (let [key, val] of Object.entries(release)) {
if (path === '.') { // Historically tagName was output as tag_name, keep this
core.setOutput('release_created', true) // consistent to avoid breaking change:
} else { if (key === 'tagName') key = 'tag_name'
core.setOutput(`${path}--release_created`, true)
}
for (const [key, val] of Object.entries(release)) {
if (path === '.') { if (path === '.') {
core.setOutput(key, val) core.setOutput(key, val)
} else { } else {
@@ -77,85 +162,12 @@ async function runManifest (command) {
core.setOutput('paths_released', JSON.stringify(pathsReleased)) core.setOutput('paths_released', JSON.stringify(pathsReleased))
} }
async function main () { function outputPRs (prs) {
const command = core.getInput('command') || undefined prs = prs.filter(pr => pr !== undefined)
if (MANIFEST_COMMANDS.includes(command)) { if (prs.length) {
return await runManifest(command) core.setOutput('pr', prs[0])
core.setOutput('prs', JSON.stringify(prs))
} }
const { token, fork, defaultBranch, apiUrl, graphqlUrl, repoUrl } = getGitHubInput()
const bumpMinorPreMajor = getBooleanInput('bump-minor-pre-major')
const bumpPatchForMinorPreMajor = getBooleanInput('bump-patch-for-minor-pre-major')
const monorepoTags = getBooleanInput('monorepo-tags')
const packageName = core.getInput('package-name')
const path = core.getInput('path') || undefined
const releaseType = core.getInput('release-type', { required: true })
const changelogPath = core.getInput('changelog-path') || undefined
const changelogTypes = core.getInput('changelog-types') || undefined
const changelogSections = changelogTypes && JSON.parse(changelogTypes)
const versionFile = core.getInput('version-file') || undefined
const pullRequestTitlePattern = core.getInput('pull-request-title-pattern') || undefined
// First we check for any merged release PRs (PRs merged with the label
// "autorelease: pending"):
if (!command || command === GITHUB_RELEASE_COMMAND) {
const releaseCreated = await factory.runCommand(GITHUB_RELEASE_COMMAND, {
label: RELEASE_LABEL,
repoUrl,
packageName,
path,
monorepoTags,
token,
changelogPath,
releaseType,
defaultBranch,
pullRequestTitlePattern,
apiUrl,
graphqlUrl
})
if (releaseCreated) {
core.setOutput('release_created', true)
for (const key of Object.keys(releaseCreated)) {
core.setOutput(key, releaseCreated[key])
}
}
}
// Next we check for PRs merged since the last release, and groom the
// release PR:
if (!command || command === GITHUB_RELEASE_PR_COMMAND) {
const pr = await factory.runCommand(GITHUB_RELEASE_PR_COMMAND, {
releaseType,
monorepoTags,
packageName,
path,
apiUrl,
graphqlUrl,
repoUrl,
fork,
token,
label: RELEASE_LABEL,
bumpMinorPreMajor,
bumpPatchForMinorPreMajor,
changelogPath,
changelogSections,
versionFile,
defaultBranch,
pullRequestTitlePattern,
signoff
})
if (pr) {
core.setOutput('pr', pr)
}
}
}
const releasePlease = {
main,
getBooleanInput
} }
/* c8 ignore next 4 */ /* c8 ignore next 4 */

7975
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -25,15 +25,16 @@
}, },
"homepage": "https://github.com/bcoe/release-please-action#readme", "homepage": "https://github.com/bcoe/release-please-action#readme",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.6.0",
"release-please": "^12.6.0" "release-please": "^13.0.1"
}, },
"devDependencies": { "devDependencies": {
"@vercel/ncc": "^0.27.0", "@vercel/ncc": "^0.27.0",
"c8": "^7.5.0", "c8": "^7.5.0",
"mocha": "^8.2.1", "mocha": "^9.1.3",
"nock": "^13.2.1",
"sinon": "^9.2.4", "sinon": "^9.2.4",
"standard": "^16.0.3" "standard": "^16.0.4"
}, },
"standard": { "standard": {
"ignore": "dist/" "ignore": "dist/"

View File

@@ -3,9 +3,9 @@ const action = require('../')
const assert = require('assert') const assert = require('assert')
const core = require('@actions/core') const core = require('@actions/core')
const sinon = require('sinon') const sinon = require('sinon')
const { factory, GitHubRelease } = require('release-please/build/src') const nock = require('nock')
const { Manifest } = require('release-please/build/src/manifest') const { Manifest } = require('release-please/build/src/manifest')
const { Node } = require('release-please/build/src/releasers/node') // const { Node } = require('release-please/build/src/strategies/node')
// As defined in action.yml // As defined in action.yml
const defaultInput = { const defaultInput = {
fork: 'false', fork: 'false',
@@ -20,7 +20,9 @@ const defaultInput = {
'version-file': '', 'version-file': '',
'default-branch': '', 'default-branch': '',
// eslint-disable-next-line no-template-curly-in-string // eslint-disable-next-line no-template-curly-in-string
'pull-request-title-pattern': 'chore${scope}: release${component} ${version}' 'pull-request-title-pattern': 'chore${scope}: release${component} ${version}',
draft: 'false',
'draft-pull-request': 'false'
} }
let input let input
@@ -29,6 +31,8 @@ let output
const sandbox = sinon.createSandbox() const sandbox = sinon.createSandbox()
process.env.GITHUB_REPOSITORY = 'google/cloud' process.env.GITHUB_REPOSITORY = 'google/cloud'
nock.disableNetConnect()
describe('release-please-action', () => { describe('release-please-action', () => {
beforeEach(() => { beforeEach(() => {
input = {} input = {}
@@ -43,230 +47,230 @@ describe('release-please-action', () => {
return input[name] return input[name]
} }
} }
core.getBooleanInput = name => {
// Float our own helper, for mocking purposes:
const trueValue = ['true', 'True', 'TRUE']
const falseValue = ['false', 'False', 'FALSE']
const val = core.getInput(name)
if (trueValue.includes(val)) { return true }
if (falseValue.includes(val)) { return false }
throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` +
'Support boolean input list: `true | True | TRUE | false | False | FALSE`')
}
// Default branch lookup:
nock('https://api.github.com')
.get('/repos/google/cloud')
.reply(200, {
default_branch: 'main'
})
}) })
afterEach(() => { afterEach(() => {
sandbox.restore() sandbox.restore()
}) })
const trueValue = ['true', 'True', 'TRUE', 'yes', 'Yes', 'YES', 'y', 'Y', 'on', 'On', 'ON']
const falseValue = ['false', 'False', 'FALSE', 'no', 'No', 'NO', 'n', 'N', 'off', 'Off', 'OFF']
trueValue.forEach(value => {
it(`get the boolean true with the input of '${value}'`, () => {
input = {
fork: value
}
const actual = action.getBooleanInput('fork')
assert.strictEqual(actual, true)
})
})
falseValue.forEach(value => {
it(`get the boolean with the input of '${value}'`, () => {
input = {
fork: value
}
const actual = action.getBooleanInput('fork')
assert.strictEqual(actual, false)
})
})
it('get an error when inputting the wrong boolean value', () => {
input = {
fork: 'wrong'
}
assert.throws(
() => {
action.getBooleanInput('fork')
},
{ name: 'TypeError', message: "Wrong boolean value of the input 'fork'" }
)
})
it('sets pull pullRequestTitlePattern to undefined, if empty string provided', async () => {
input = {
'release-type': 'node',
// eslint-disable-next-line no-template-curly-in-string
'pull-request-title-pattern': ''
}
const runCommandStub = sandbox.stub(factory, 'runCommand')
const githubReleasePRStub = runCommandStub.withArgs('release-pr').returns(25)
await action.main()
sinon.assert.calledOnce(githubReleasePRStub)
sinon.assert.calledWith(
githubReleasePRStub,
'release-pr',
// eslint-disable-next-line no-template-curly-in-string
sinon.match.hasOwn('pullRequestTitlePattern', undefined)
)
})
it('opens PR with custom changelogSections', async () => { it('opens PR with custom changelogSections', async () => {
input = { input = {
command: 'release-pr',
'release-type': 'node', 'release-type': 'node',
'changelog-types': 'changelog-types':
'[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]' '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]'
} }
const runCommandStub = sandbox.stub(factory, 'runCommand') const createPullRequestsFake = sandbox.fake.returns([22])
const githubReleasePRStub = runCommandStub.withArgs('release-pr').returns(25) const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake
})
await action.main() await action.main()
sinon.assert.calledOnce(githubReleasePRStub) sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.calledWith( sinon.assert.calledWith(
githubReleasePRStub, createManifestCommand,
'release-pr', sinon.match.any,
'main',
sinon.match.hasOwn( sinon.match.hasOwn(
'changelogSections', 'changelogSections',
JSON.parse( JSON.parse(
'[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]' '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]'
) )
) ),
sinon.match.any
)
})
it('opens PR with custom title', async () => {
input = {
command: 'release-pr',
'release-type': 'node',
'pull-request-title-pattern': 'beep boop'
}
const createPullRequestsFake = sandbox.fake.returns([22])
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake
})
await action.main()
sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.calledWith(
createManifestCommand,
sinon.match.any,
'main',
sinon.match.hasOwn(
'pullRequestTitlePattern',
'beep boop'
),
sinon.match.any
) )
}) })
it('both opens PR to the default branch and tags GitHub releases by default', async () => { it('both opens PR to the default branch and tags GitHub releases by default', async () => {
input = { input = {}
'release-type': 'node'
}
const runCommandStub = sandbox.stub(factory, 'runCommand') const createReleasesFake = sandbox.fake.returns([
{
const githubReleaseStub = runCommandStub.withArgs('github-release').returns({ upload_url: 'http://example.com',
upload_url: 'http://example.com', tagName: 'v1.0.0'
tag_name: 'v1.0.0' }
])
const createPullRequestsFake = sandbox.fake.returns([22])
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake,
createReleases: createReleasesFake
}) })
const githubReleasePRStub = runCommandStub.withArgs('release-pr').returns(25)
await action.main() await action.main()
sinon.assert.calledOnce(githubReleaseStub) sinon.assert.calledOnce(createManifestCommand)
sinon.assert.calledOnce(githubReleasePRStub) sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.calledWith( sinon.assert.calledWith(createReleasesFake)
githubReleaseStub,
'github-release',
sinon.match.hasOwn('defaultBranch', undefined)
)
sinon.assert.calledWith(
githubReleasePRStub,
'release-pr',
sinon.match.hasOwn('defaultBranch', undefined)
)
assert.deepStrictEqual(output, { assert.deepStrictEqual(output, {
release_created: true, release_created: true,
upload_url: 'http://example.com', upload_url: 'http://example.com',
tag_name: 'v1.0.0', tag_name: 'v1.0.0',
pr: 25 pr: 22,
prs: '[22]',
releases_created: true,
paths_released: '["."]'
}) })
}) })
it('both opens PR to a different default branch and tags GitHub releases by default', async () => { it('both opens PR to a different default branch and tags GitHub releases by default', async () => {
input = { input = {
'release-type': 'node',
'default-branch': 'dev' 'default-branch': 'dev'
} }
const runCommandStub = sandbox.stub(factory, 'runCommand') const createReleasesFake = sandbox.fake.returns([
{
const githubReleaseStub = runCommandStub.withArgs('github-release').returns({ upload_url: 'http://example.com',
upload_url: 'http://example.com', tag_name: 'v1.0.0'
tag_name: 'v1.0.0' }
])
const createPullRequestsFake = sandbox.fake.returns([22])
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake,
createReleases: createReleasesFake
}) })
const githubReleasePRStub = runCommandStub.withArgs('release-pr').returns(25)
await action.main() await action.main()
sinon.assert.calledOnce(githubReleaseStub) sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.calledWith(createReleasesFake)
sinon.assert.calledWith( sinon.assert.calledWith(
githubReleaseStub, createManifestCommand,
'github-release', sinon.match.any,
sinon.match.hasOwn('defaultBranch', 'dev') 'dev',
sinon.match.any,
sinon.match.any
) )
sinon.assert.calledOnce(githubReleasePRStub)
sinon.assert.calledWith(
githubReleasePRStub,
'release-pr',
sinon.match.hasOwn('defaultBranch', 'dev')
)
assert.deepStrictEqual(output, { assert.deepStrictEqual(output, {
release_created: true, release_created: true,
upload_url: 'http://example.com', upload_url: 'http://example.com',
tag_name: 'v1.0.0', tag_name: 'v1.0.0',
pr: 25 pr: 22,
prs: '[22]',
releases_created: true,
paths_released: '["."]'
}) })
}) })
it('only opens PR, if command set to release-pr', async () => { it('only opens PR, if command set to release-pr', async () => {
input = { input = {
'release-type': 'node',
command: 'release-pr' command: 'release-pr'
} }
const runCommandStub = sandbox.stub(factory, 'runCommand') const createReleasesFake = sandbox.fake.returns([
{
const githubReleaseStub = runCommandStub.withArgs('github-release').returns({ upload_url: 'http://example.com',
upload_url: 'http://example.com', tag_name: 'v1.0.0'
tag_name: 'v1.0.0' }
])
const createPullRequestsFake = sandbox.fake.returns([22])
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake,
createReleases: createReleasesFake
}) })
const githubReleasePRStub = runCommandStub.withArgs('release-pr').returns(25)
await action.main() await action.main()
sinon.assert.notCalled(githubReleaseStub)
sinon.assert.calledOnce(githubReleasePRStub) sinon.assert.calledOnce(createManifestCommand)
sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.notCalled(createReleasesFake)
assert.deepStrictEqual(output, {
pr: 22,
prs: '[22]'
})
}) })
it('only creates GitHub release, if command set to github-release', async () => { it('only creates GitHub release, if command set to github-release', async () => {
input = { input = {
'release-type': 'node',
command: 'github-release' command: 'github-release'
} }
const runCommandStub = sandbox.stub(factory, 'runCommand') const createReleasesFake = sandbox.fake.returns([
{
const githubReleaseStub = runCommandStub.withArgs('github-release').returns({ upload_url: 'http://example.com',
upload_url: 'http://example.com', tag_name: 'v1.0.0'
tag_name: 'v1.0.0' }
])
const createPullRequestsFake = sandbox.fake.returns([22])
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake,
createReleases: createReleasesFake
}) })
const githubReleasePRStub = runCommandStub.withArgs('release-pr').returns(25)
await action.main() await action.main()
sinon.assert.calledOnce(githubReleaseStub)
sinon.assert.notCalled(githubReleasePRStub) sinon.assert.calledOnce(createManifestCommand)
sinon.assert.notCalled(createPullRequestsFake)
sinon.assert.calledOnce(createReleasesFake)
assert.deepStrictEqual(output, {
release_created: true,
upload_url: 'http://example.com',
tag_name: 'v1.0.0',
releases_created: true,
paths_released: '["."]'
})
}) })
it('sets appropriate outputs when GitHub release created', async () => { it('sets appropriate outputs when GitHub release created', async () => {
const expected = { const expected = {
release_created: true, release_created: true,
releases_created: true,
upload_url: 'http://example.com', upload_url: 'http://example.com',
html_url: 'http://example2.com', html_url: 'http://example2.com',
tag_name: 'v1.0.0', tag_name: 'v1.2.3',
major: 1, major: 1,
minor: 2, minor: 2,
patch: 3, patch: 3,
version: 'v1.2.3', version: 'v1.2.3',
sha: 'abc123', sha: 'abc123',
pr: 33 pr: 33,
paths_released: '["."]'
} }
input = { input = {
'release-type': 'node', 'release-type': 'node',
command: 'github-release' command: 'github-release'
} }
const createReleasesFake = sandbox.fake.returns([expected])
const runCommandStub = sandbox.stub(factory, 'runCommand') sandbox.stub(Manifest, 'fromConfig').returns({
createReleases: createReleasesFake
runCommandStub.withArgs('github-release').returns(expected) })
runCommandStub.withArgs('release-pr').returns(25)
await action.main() await action.main()
assert.deepStrictEqual(output, expected) assert.deepStrictEqual(output, expected)
}) })
@@ -276,13 +280,18 @@ describe('release-please-action', () => {
'release-type': 'node', 'release-type': 'node',
command: 'release-pr' command: 'release-pr'
} }
const createPullRequestsFake = sandbox.fake.returns([22])
const runCommandStub = sandbox.stub(factory, 'runCommand') const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake
runCommandStub.withArgs('release-pr').returns(95) })
await action.main() await action.main()
assert.strictEqual(output.pr, 95)
sinon.assert.calledOnce(createManifestCommand)
sinon.assert.calledOnce(createPullRequestsFake)
assert.deepStrictEqual(output, {
pr: 22,
prs: '[22]'
})
}) })
it('does not set PR output, when no release PR is returned', async () => { it('does not set PR output, when no release PR is returned', async () => {
@@ -290,99 +299,129 @@ describe('release-please-action', () => {
'release-type': 'node', 'release-type': 'node',
command: 'release-pr' command: 'release-pr'
} }
const createPullRequestsFake = sandbox.fake.returns([undefined])
const runCommandStub = sandbox.stub(factory, 'runCommand') const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
createPullRequests: createPullRequestsFake
runCommandStub.withArgs('release-pr').returns(undefined) })
await action.main() await action.main()
sinon.assert.calledOnce(createManifestCommand)
sinon.assert.calledOnce(createPullRequestsFake)
assert.strictEqual(Object.hasOwnProperty.call(output, 'pr'), false) assert.strictEqual(Object.hasOwnProperty.call(output, 'pr'), false)
}) })
it('creates and runs a ReleasePR instance, using factory', async () => { it('does not set release output, when no release is returned', async () => {
let maybeReleasePR
sandbox.replace(factory, 'call', runnable => {
maybeReleasePR = runnable
})
input = {
'release-type': 'node',
command: 'release-pr'
}
await action.main()
assert.ok(maybeReleasePR instanceof Node)
})
it('creates and runs a GitHubRelease, using factory', async () => {
let maybeGitHubRelease
sandbox.replace(factory, 'call', runnable => {
maybeGitHubRelease = runnable
})
input = { input = {
'release-type': 'node', 'release-type': 'node',
command: 'github-release' command: 'github-release'
} }
await action.main() const createReleasesFake = sandbox.fake.returns([undefined])
assert.ok(maybeGitHubRelease instanceof GitHubRelease) sandbox.stub(Manifest, 'fromConfig').returns({
}) createReleases: createReleasesFake
it('creates and runs a Manifest, using factory', async () => {
let maybeManifest
sandbox.replace(factory, 'call', runnable => {
maybeManifest = runnable
}) })
input = { command: 'manifest' }
await action.main() await action.main()
assert.ok(maybeManifest instanceof Manifest) assert.deepStrictEqual(output, { paths_released: '[]' })
}) })
it('opens PR creates GitHub releases by default for manifest', async () => { it('creates and runs a manifest release', async () => {
input = { command: 'manifest' } input = { command: 'manifest' }
const createReleasesFake = sandbox.fake.returns([
const runCommandStub = sandbox.stub(factory, 'runCommand')
const manifestReleaseStub = runCommandStub.withArgs('manifest-release').resolves(
{ {
'path/pkgA': upload_url: 'http://example.com',
{ tag_name: 'v1.0.0'
upload_url: 'http://example.com', }
tag_name: 'v1.0.0' ])
}, const createPullRequestsFake = sandbox.fake.returns([22])
'.': { const createManifestCommand = sandbox.stub(Manifest, 'fromManifest').returns({
upload_url: 'http://example.com', createPullRequests: createPullRequestsFake,
tag_name: 'v1.0.0' createReleases: createReleasesFake
} })
})
const manifestReleasePRStub = runCommandStub.withArgs('manifest-pr').returns(25)
await action.main() await action.main()
sinon.assert.calledOnce(manifestReleaseStub) sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.calledOnce(manifestReleasePRStub) sinon.assert.calledWith(createReleasesFake)
sinon.assert.calledWith(
createManifestCommand,
sinon.match.any,
'main',
sinon.match.any,
sinon.match.any
)
assert.deepStrictEqual(output, { assert.deepStrictEqual(output, {
releases_created: true,
release_created: true, release_created: true,
'path/pkgA--upload_url': 'http://example.com',
'path/pkgA--tag_name': 'v1.0.0',
'path/pkgA--release_created': true,
tag_name: 'v1.0.0',
upload_url: 'http://example.com', upload_url: 'http://example.com',
pr: 25, tag_name: 'v1.0.0',
paths_released: '["path/pkgA","."]' pr: 22,
prs: '[22]',
releases_created: true,
paths_released: '["."]'
}) })
}) })
it('opens PR only for manifest-pr', async () => { it('opens PR only for manifest-pr', async () => {
input = { command: 'manifest-pr' } input = { command: 'manifest-pr' }
const createPullRequestsFake = sandbox.fake.returns([22])
const runCommandStub = sandbox.stub(factory, 'runCommand') const createManifestCommand = sandbox.stub(Manifest, 'fromManifest').returns({
const manifestReleasePRStub = runCommandStub.withArgs('manifest-pr').returns(25) createPullRequests: createPullRequestsFake
})
await action.main() await action.main()
sinon.assert.calledOnce(manifestReleasePRStub) sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.calledWith(
createManifestCommand,
sinon.match.any,
'main',
sinon.match.any,
sinon.match.any
)
assert.deepStrictEqual(output, { assert.deepStrictEqual(output, {
pr: 25 pr: 22,
prs: '[22]'
})
})
it('sets appropriate output if multiple releases and prs created', async () => {
input = { command: 'manifest' }
const createReleasesFake = sandbox.fake.returns([
{
upload_url: 'http://example.com',
tag_name: 'v1.0.0',
path: 'a'
},
{
upload_url: 'http://example2.com',
tag_name: 'v1.2.0',
path: 'b'
}
])
const createPullRequestsFake = sandbox.fake.returns([22, 33])
const createManifestCommand = sandbox.stub(Manifest, 'fromManifest').returns({
createPullRequests: createPullRequestsFake,
createReleases: createReleasesFake
})
await action.main()
sinon.assert.calledOnce(createPullRequestsFake)
sinon.assert.calledWith(createReleasesFake)
sinon.assert.calledWith(
createManifestCommand,
sinon.match.any,
'main',
sinon.match.any,
sinon.match.any
)
assert.deepStrictEqual(output, {
pr: 22,
prs: '[22,33]',
releases_created: true,
'a--release_created': true,
'a--upload_url': 'http://example.com',
'a--tag_name': 'v1.0.0',
'a--path': 'a',
'b--release_created': true,
'b--upload_url': 'http://example2.com',
'b--tag_name': 'v1.2.0',
'b--path': 'b',
paths_released: '["a","b"]'
}) })
}) })
}) })