mirror of
https://github.com/joaquinjsb/gitea-release-please-action
synced 2026-05-11 16:11:35 +02:00
feat!: v4 release (#871)
Any advanced configuration should be done via a release-please-config.json. Fixes #859 Fixes #858 Fixes #857 Fixes #852 feat!: remove most configuration options in favor of manifest configuration to configure the release-please-action refactor!: rewrite in typescript feat!: remove command option in favor of setting `release-type` and `skip-github-release`/`skip-github-pull-request` feat!: run on node20 deps!: upgrade release-please to v16
This commit is contained in:
@@ -1,572 +0,0 @@
|
||||
const { describe, it, beforeEach, afterEach } = require('mocha')
|
||||
const action = require('../')
|
||||
const assert = require('assert')
|
||||
const core = require('@actions/core')
|
||||
const sinon = require('sinon')
|
||||
const nock = require('nock')
|
||||
const { Manifest } = require('release-please/build/src/manifest')
|
||||
// const { Node } = require('release-please/build/src/strategies/node')
|
||||
// As defined in action.yml
|
||||
|
||||
const defaultInput = {
|
||||
fork: 'false',
|
||||
clean: 'true',
|
||||
'bump-minor-pre-major': 'false',
|
||||
'bump-patch-for-minor-pre-major': 'false',
|
||||
path: '',
|
||||
'monorepo-tags': 'false',
|
||||
'changelog-path': '',
|
||||
'changelog-types': '',
|
||||
command: '',
|
||||
'version-file': '',
|
||||
'default-branch': '',
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
'pull-request-title-pattern': 'chore${scope}: release${component} ${version}',
|
||||
draft: 'false',
|
||||
'draft-pull-request': 'false'
|
||||
}
|
||||
|
||||
const fixturePrs = [
|
||||
{
|
||||
headBranchName: 'release-please--branches--main',
|
||||
baseBranchName: 'main',
|
||||
number: 22,
|
||||
title: 'chore(master): release 1.0.0',
|
||||
body: ':robot: I have created a release *beep* *boop*',
|
||||
labels: ['autorelease: pending'],
|
||||
files: []
|
||||
},
|
||||
{
|
||||
headBranchName: 'release-please--branches--main',
|
||||
baseBranchName: 'main',
|
||||
number: 23,
|
||||
title: 'chore(master): release 1.0.0',
|
||||
body: ':robot: I have created a release *beep* *boop*',
|
||||
labels: ['autorelease: pending'],
|
||||
files: []
|
||||
}
|
||||
]
|
||||
|
||||
let input
|
||||
let output
|
||||
|
||||
const sandbox = sinon.createSandbox()
|
||||
process.env.GITHUB_REPOSITORY = 'google/cloud'
|
||||
|
||||
nock.disableNetConnect()
|
||||
|
||||
describe('release-please-action', () => {
|
||||
beforeEach(() => {
|
||||
input = {}
|
||||
output = {}
|
||||
core.setOutput = (name, value) => {
|
||||
output[name] = value
|
||||
}
|
||||
core.getInput = name => {
|
||||
if (input[name] === undefined || input[name] == null) {
|
||||
return defaultInput[name]
|
||||
} else {
|
||||
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(() => {
|
||||
sandbox.restore()
|
||||
})
|
||||
|
||||
it('opens PR with custom changelogSections', async () => {
|
||||
input = {
|
||||
command: 'release-pr',
|
||||
'release-type': 'node',
|
||||
'changelog-types':
|
||||
'[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false}]',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
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(
|
||||
'changelogSections',
|
||||
JSON.parse(
|
||||
'[{"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',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
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('opens PR with custom header', async () => {
|
||||
input = {
|
||||
command: 'release-pr',
|
||||
'release-type': 'node',
|
||||
'pull-request-header': 'another header',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
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(
|
||||
'pullRequestHeader',
|
||||
'another header'
|
||||
),
|
||||
sinon.match.any
|
||||
)
|
||||
})
|
||||
|
||||
it('both opens PR to the default branch and tags GitHub releases by default', async () => {
|
||||
input = {
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
|
||||
const createReleasesFake = sandbox.fake.returns([
|
||||
{
|
||||
upload_url: 'http://example.com',
|
||||
tagName: 'v1.0.0'
|
||||
}
|
||||
])
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createPullRequests: createPullRequestsFake,
|
||||
createReleases: createReleasesFake
|
||||
})
|
||||
await action.main()
|
||||
|
||||
sinon.assert.calledTwice(createManifestCommand)
|
||||
sinon.assert.calledOnce(createPullRequestsFake)
|
||||
sinon.assert.calledOnce(createReleasesFake)
|
||||
const { prs, ...outputWithoutPrs } = output
|
||||
assert.deepStrictEqual(outputWithoutPrs, {
|
||||
release_created: true,
|
||||
upload_url: 'http://example.com',
|
||||
tag_name: 'v1.0.0',
|
||||
pr: fixturePrs[0],
|
||||
releases_created: true,
|
||||
paths_released: '["."]'
|
||||
})
|
||||
assert.deepStrictEqual(JSON.parse(prs), [fixturePrs[0]])
|
||||
})
|
||||
|
||||
it('both opens PR to a different default branch and tags GitHub releases by default', async () => {
|
||||
input = {
|
||||
'default-branch': 'dev',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
|
||||
const createReleasesFake = sandbox.fake.returns([
|
||||
{
|
||||
upload_url: 'http://example.com',
|
||||
tag_name: 'v1.0.0'
|
||||
}
|
||||
])
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createPullRequests: createPullRequestsFake,
|
||||
createReleases: createReleasesFake
|
||||
})
|
||||
await action.main()
|
||||
|
||||
sinon.assert.calledOnce(createPullRequestsFake)
|
||||
sinon.assert.calledWith(createReleasesFake)
|
||||
sinon.assert.calledWith(
|
||||
createManifestCommand,
|
||||
sinon.match.any,
|
||||
'dev',
|
||||
sinon.match.any,
|
||||
sinon.match.any
|
||||
)
|
||||
const { prs, ...outputWithoutPrs } = output
|
||||
assert.deepStrictEqual(outputWithoutPrs, {
|
||||
release_created: true,
|
||||
upload_url: 'http://example.com',
|
||||
tag_name: 'v1.0.0',
|
||||
pr: fixturePrs[0],
|
||||
releases_created: true,
|
||||
paths_released: '["."]'
|
||||
})
|
||||
assert.deepStrictEqual(JSON.parse(prs), [fixturePrs[0]])
|
||||
})
|
||||
|
||||
it('only opens PR, if command set to release-pr', async () => {
|
||||
input = {
|
||||
command: 'release-pr',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
|
||||
const createReleasesFake = sandbox.fake.returns([
|
||||
{
|
||||
upload_url: 'http://example.com',
|
||||
tag_name: 'v1.0.0'
|
||||
}
|
||||
])
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createPullRequests: createPullRequestsFake,
|
||||
createReleases: createReleasesFake
|
||||
})
|
||||
await action.main()
|
||||
|
||||
sinon.assert.calledOnce(createManifestCommand)
|
||||
sinon.assert.calledOnce(createPullRequestsFake)
|
||||
sinon.assert.notCalled(createReleasesFake)
|
||||
const { prs, ...outputWithoutPrs } = output
|
||||
assert.deepStrictEqual(outputWithoutPrs, {
|
||||
pr: fixturePrs[0]
|
||||
})
|
||||
assert.deepStrictEqual(JSON.parse(prs), [fixturePrs[0]])
|
||||
})
|
||||
|
||||
it('only creates GitHub release, if command set to github-release', async () => {
|
||||
input = {
|
||||
command: 'github-release',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
|
||||
const createReleasesFake = sandbox.fake.returns([
|
||||
{
|
||||
upload_url: 'http://example.com',
|
||||
tag_name: 'v1.0.0'
|
||||
}
|
||||
])
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createPullRequests: createPullRequestsFake,
|
||||
createReleases: createReleasesFake
|
||||
})
|
||||
await action.main()
|
||||
|
||||
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 () => {
|
||||
const release = {
|
||||
id: 123456,
|
||||
name: 'v1.2.3',
|
||||
tagName: 'v1.2.3',
|
||||
sha: 'abc123',
|
||||
notes: 'Some release notes',
|
||||
url: 'http://example2.com',
|
||||
draft: false,
|
||||
uploadUrl: 'http://example.com',
|
||||
path: '.',
|
||||
version: '1.2.3',
|
||||
major: 1,
|
||||
minor: 2,
|
||||
patch: 3
|
||||
}
|
||||
input = {
|
||||
'release-type': 'node',
|
||||
command: 'github-release',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
const createReleasesFake = sandbox.fake.returns([release])
|
||||
sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createReleases: createReleasesFake
|
||||
})
|
||||
await action.main()
|
||||
assert.strictEqual(output.id, 123456)
|
||||
assert.strictEqual(output.release_created, true)
|
||||
assert.strictEqual(output.releases_created, true)
|
||||
assert.strictEqual(output.upload_url, 'http://example.com')
|
||||
assert.strictEqual(output.html_url, 'http://example2.com')
|
||||
assert.strictEqual(output.tag_name, 'v1.2.3')
|
||||
assert.strictEqual(output.major, 1)
|
||||
assert.strictEqual(output.minor, 2)
|
||||
assert.strictEqual(output.patch, 3)
|
||||
assert.strictEqual(output.version, '1.2.3')
|
||||
assert.strictEqual(output.sha, 'abc123')
|
||||
assert.strictEqual(output.paths_released, '["."]')
|
||||
})
|
||||
|
||||
it('sets appropriate outputs when release PR opened', async () => {
|
||||
input = {
|
||||
'release-type': 'node',
|
||||
command: 'release-pr',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createPullRequests: createPullRequestsFake
|
||||
})
|
||||
await action.main()
|
||||
|
||||
sinon.assert.calledOnce(createManifestCommand)
|
||||
sinon.assert.calledOnce(createPullRequestsFake)
|
||||
const { prs, ...outputWithoutPrs } = output
|
||||
assert.deepStrictEqual(outputWithoutPrs, {
|
||||
pr: fixturePrs[0]
|
||||
})
|
||||
assert.deepStrictEqual(JSON.parse(prs), [fixturePrs[0]])
|
||||
})
|
||||
|
||||
it('does not set PR output, when no release PR is returned', async () => {
|
||||
input = {
|
||||
'release-type': 'node',
|
||||
command: 'release-pr',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
const createPullRequestsFake = sandbox.fake.returns([undefined])
|
||||
const createManifestCommand = sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createPullRequests: createPullRequestsFake
|
||||
})
|
||||
await action.main()
|
||||
sinon.assert.calledOnce(createManifestCommand)
|
||||
sinon.assert.calledOnce(createPullRequestsFake)
|
||||
assert.strictEqual(Object.hasOwnProperty.call(output, 'pr'), false)
|
||||
})
|
||||
|
||||
it('does not set release output, when no release is returned', async () => {
|
||||
input = {
|
||||
'release-type': 'node',
|
||||
command: 'github-release',
|
||||
'skip-github-release': 'false',
|
||||
prerelease: 'false',
|
||||
'include-v-in-tag': 'true',
|
||||
'always-link-local': 'true',
|
||||
'separate-pull-requests': 'false',
|
||||
'skip-labeling': 'false',
|
||||
'sequential-calls': 'false'
|
||||
}
|
||||
const createReleasesFake = sandbox.fake.returns([undefined])
|
||||
sandbox.stub(Manifest, 'fromConfig').returns({
|
||||
createReleases: createReleasesFake
|
||||
})
|
||||
await action.main()
|
||||
assert.deepStrictEqual(output, { paths_released: '[]' })
|
||||
})
|
||||
|
||||
it('creates and runs a manifest release', async () => {
|
||||
input = { command: 'manifest' }
|
||||
const createReleasesFake = sandbox.fake.returns([
|
||||
{
|
||||
upload_url: 'http://example.com',
|
||||
tag_name: 'v1.0.0'
|
||||
}
|
||||
])
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
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
|
||||
)
|
||||
const { prs, ...outputWithoutPrs } = output
|
||||
assert.deepStrictEqual(outputWithoutPrs, {
|
||||
release_created: true,
|
||||
upload_url: 'http://example.com',
|
||||
tag_name: 'v1.0.0',
|
||||
pr: fixturePrs[0],
|
||||
releases_created: true,
|
||||
paths_released: '["."]'
|
||||
})
|
||||
assert.deepStrictEqual(JSON.parse(prs), [fixturePrs[0]])
|
||||
})
|
||||
|
||||
it('opens PR only for manifest-pr', async () => {
|
||||
input = { command: 'manifest-pr' }
|
||||
const createPullRequestsFake = sandbox.fake.returns([fixturePrs[0]])
|
||||
const createManifestCommand = sandbox.stub(Manifest, 'fromManifest').returns({
|
||||
createPullRequests: createPullRequestsFake
|
||||
})
|
||||
await action.main()
|
||||
|
||||
sinon.assert.calledOnce(createPullRequestsFake)
|
||||
sinon.assert.calledWith(
|
||||
createManifestCommand,
|
||||
sinon.match.any,
|
||||
'main',
|
||||
sinon.match.any,
|
||||
sinon.match.any
|
||||
)
|
||||
const { prs, ...outputWithoutPrs } = output
|
||||
assert.deepStrictEqual(outputWithoutPrs, {
|
||||
pr: fixturePrs[0]
|
||||
})
|
||||
assert.deepStrictEqual(JSON.parse(prs), [fixturePrs[0]])
|
||||
})
|
||||
|
||||
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(fixturePrs)
|
||||
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
|
||||
)
|
||||
const { prs, ...outputWithoutPrs } = output
|
||||
assert.deepStrictEqual(outputWithoutPrs, {
|
||||
pr: fixturePrs[0],
|
||||
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"]'
|
||||
})
|
||||
assert.deepStrictEqual(JSON.parse(prs), fixturePrs)
|
||||
})
|
||||
})
|
||||
456
test/release-please.ts
Normal file
456
test/release-please.ts
Normal file
@@ -0,0 +1,456 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import {describe, it, beforeEach, afterEach} from 'mocha';
|
||||
import * as action from '../src/index';
|
||||
import * as assert from 'assert';
|
||||
import * as core from '@actions/core';
|
||||
import * as sinon from 'sinon';
|
||||
import * as nock from 'nock';
|
||||
import {RestoreFn} from 'mocked-env';
|
||||
import mockedEnv from 'mocked-env';
|
||||
|
||||
import {Manifest, GitHub} from 'release-please';
|
||||
// As defined in action.yml
|
||||
|
||||
const DEFAULT_INPUTS: Record<string, string> = {
|
||||
token: 'fake-token',
|
||||
};
|
||||
|
||||
const fixturePrs = [
|
||||
{
|
||||
headBranchName: 'release-please--branches--main',
|
||||
baseBranchName: 'main',
|
||||
number: 22,
|
||||
title: 'chore(master): release 1.0.0',
|
||||
body: ':robot: I have created a release *beep* *boop*',
|
||||
labels: ['autorelease: pending'],
|
||||
files: [],
|
||||
},
|
||||
{
|
||||
headBranchName: 'release-please--branches--main',
|
||||
baseBranchName: 'main',
|
||||
number: 23,
|
||||
title: 'chore(master): release 1.0.0',
|
||||
body: ':robot: I have created a release *beep* *boop*',
|
||||
labels: ['autorelease: pending'],
|
||||
files: [],
|
||||
},
|
||||
];
|
||||
|
||||
const sandbox = sinon.createSandbox();
|
||||
process.env.GITHUB_REPOSITORY = 'fakeOwner/fakeRepo';
|
||||
|
||||
function mockInputs(inputs: Record<string, string>): RestoreFn {
|
||||
const envVars: Record<string, string> = {};
|
||||
for (const [name, val] of Object.entries({...DEFAULT_INPUTS, ...inputs})) {
|
||||
envVars[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] = val;
|
||||
}
|
||||
return mockedEnv(envVars);
|
||||
}
|
||||
|
||||
nock.disableNetConnect();
|
||||
|
||||
describe('release-please-action', () => {
|
||||
let output: Record<string, string | boolean> = {};
|
||||
// Save original env varas and restore after each test
|
||||
let restoreEnv: RestoreFn | null;
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
if (restoreEnv) {
|
||||
restoreEnv();
|
||||
restoreEnv = null;
|
||||
}
|
||||
});
|
||||
beforeEach(() => {
|
||||
output = {};
|
||||
sandbox.replace(
|
||||
core,
|
||||
'setOutput',
|
||||
(key: string, value: string | boolean) => {
|
||||
output[key] = value;
|
||||
}
|
||||
);
|
||||
// Default branch lookup:
|
||||
nock('https://api.github.com').get('/repos/fakeOwner/fakeRepo').reply(200, {
|
||||
default_branch: 'main',
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
});
|
||||
describe('configuration', () => {
|
||||
let fakeManifest: sinon.SinonStubbedInstance<Manifest>;
|
||||
describe('with release-type', () => {
|
||||
let fromConfigStub: sinon.SinonStub;
|
||||
beforeEach(() => {
|
||||
fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fromConfigStub = sandbox
|
||||
.stub(Manifest, 'fromConfig')
|
||||
.resolves(fakeManifest);
|
||||
});
|
||||
it('builds a manifest from config', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'release-type': 'simple',
|
||||
});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
});
|
||||
it('skips creating releases if skip-github-release specified', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'skip-github-release': 'true',
|
||||
'release-type': 'simple',
|
||||
});
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.notCalled(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
});
|
||||
it('skips creating pull requests if skip-github-pull-request specified', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'skip-github-pull-request': 'true',
|
||||
'release-type': 'simple',
|
||||
});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.notCalled(fakeManifest.createPullRequests);
|
||||
});
|
||||
it('allows specifying custom target branch', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'target-branch': 'dev',
|
||||
'release-type': 'simple',
|
||||
});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
sinon.assert.calledWith(
|
||||
fromConfigStub,
|
||||
sinon.match.any,
|
||||
'dev',
|
||||
sinon.match.object,
|
||||
sinon.match.object,
|
||||
sinon.match.any,
|
||||
);
|
||||
});
|
||||
it('allows specifying fork', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'fork': 'true',
|
||||
'release-type': 'simple',
|
||||
});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
sinon.assert.calledWith(
|
||||
fromConfigStub,
|
||||
sinon.match.any,
|
||||
sinon.match.string,
|
||||
sinon.match.object,
|
||||
sinon.match({fork: true}),
|
||||
sinon.match.any,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with manifest', () => {
|
||||
let fromManifestStub: sinon.SinonStub;
|
||||
beforeEach(() => {
|
||||
fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fromManifestStub = sandbox
|
||||
.stub(Manifest, 'fromManifest')
|
||||
.resolves(fakeManifest);
|
||||
});
|
||||
it('loads a manifest from the repository', async () => {
|
||||
restoreEnv = mockInputs({});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
});
|
||||
it('skips creating releases if skip-github-release specified', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'skip-github-release': 'true',
|
||||
});
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.notCalled(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
});
|
||||
it('skips creating pull requests if skip-github-pull-request specified', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'skip-github-pull-request': 'true',
|
||||
});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.notCalled(fakeManifest.createPullRequests);
|
||||
});
|
||||
it('allows specifying custom target branch', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'target-branch': 'dev',
|
||||
});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
sinon.assert.calledWith(
|
||||
fromManifestStub,
|
||||
sinon.match.any,
|
||||
'dev',
|
||||
sinon.match.string,
|
||||
sinon.match.string
|
||||
);
|
||||
});
|
||||
it('allows specifying fork', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'fork': 'true',
|
||||
});
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
sinon.assert.calledWith(
|
||||
fromManifestStub,
|
||||
sinon.match.any,
|
||||
sinon.match.string,
|
||||
sinon.match.string,
|
||||
sinon.match.string,
|
||||
sinon.match({fork: true}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('allows specifying manifest config paths', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'config-file': 'path/to/config.json',
|
||||
'manifest-file': 'path/to/manifest.json',
|
||||
});
|
||||
const fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
const fromManifestStub = sandbox
|
||||
.stub(Manifest, 'fromManifest')
|
||||
.resolves(fakeManifest);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
sinon.assert.calledWith(
|
||||
fromManifestStub,
|
||||
sinon.match.any,
|
||||
sinon.match.string,
|
||||
'path/to/config.json',
|
||||
'path/to/manifest.json'
|
||||
);
|
||||
});
|
||||
|
||||
it('allows specifying network options', async () => {
|
||||
restoreEnv = mockInputs({
|
||||
'target-branch': 'dev',
|
||||
'proxy-server': 'some-host:9000',
|
||||
'github-api-url': 'https://my-enterprise-host.local/api',
|
||||
'github-graphql-url': 'https://my-enterprise-host.local/graphql',
|
||||
});
|
||||
const createGithubSpy = sandbox.spy(GitHub, 'create');
|
||||
const fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
sandbox.stub(Manifest, 'fromManifest').resolves(fakeManifest);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
sinon.assert.calledWith(
|
||||
createGithubSpy,
|
||||
sinon.match({
|
||||
apiUrl: 'https://my-enterprise-host.local/api',
|
||||
graphqlUrl: 'https://my-enterprise-host.local',
|
||||
proxy: {
|
||||
host: 'some-host',
|
||||
port: 9000,
|
||||
},
|
||||
defaultBranch: 'dev',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('outputs', () => {
|
||||
it('sets appropriate outputs when GitHub release created', async () => {
|
||||
restoreEnv = mockInputs({});
|
||||
const fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fakeManifest.createReleases.resolves([
|
||||
{
|
||||
id: 123456,
|
||||
name: 'v1.2.3',
|
||||
tagName: 'v1.2.3',
|
||||
sha: 'abc123',
|
||||
notes: 'Some release notes',
|
||||
url: 'http://example2.com',
|
||||
draft: false,
|
||||
uploadUrl: 'http://example.com',
|
||||
path: '.',
|
||||
version: '1.2.3',
|
||||
major: 1,
|
||||
minor: 2,
|
||||
patch: 3,
|
||||
},
|
||||
]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
sandbox.stub(Manifest, 'fromManifest').resolves(fakeManifest);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
assert.strictEqual(output.id, 123456);
|
||||
assert.strictEqual(output.release_created, true);
|
||||
assert.strictEqual(output.releases_created, true);
|
||||
assert.strictEqual(output.upload_url, 'http://example.com');
|
||||
assert.strictEqual(output.html_url, 'http://example2.com');
|
||||
assert.strictEqual(output.tag_name, 'v1.2.3');
|
||||
assert.strictEqual(output.major, 1);
|
||||
assert.strictEqual(output.minor, 2);
|
||||
assert.strictEqual(output.patch, 3);
|
||||
assert.strictEqual(output.version, '1.2.3');
|
||||
assert.strictEqual(output.sha, 'abc123');
|
||||
assert.strictEqual(output.paths_released, '["."]');
|
||||
});
|
||||
|
||||
it('sets appropriate outputs when release PR opened', async () => {
|
||||
restoreEnv = mockInputs({});
|
||||
const fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([fixturePrs[0]]);
|
||||
sandbox.stub(Manifest, 'fromManifest').resolves(fakeManifest);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
const {pr, prs, prs_created} = output;
|
||||
assert.strictEqual(prs_created, true);
|
||||
assert.deepStrictEqual(pr, fixturePrs[0]);
|
||||
assert.deepStrictEqual(prs, JSON.stringify([fixturePrs[0]]));
|
||||
});
|
||||
it('sets appropriate output if multiple releases are created', async () => {
|
||||
restoreEnv = mockInputs({});
|
||||
const fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fakeManifest.createReleases.resolves([
|
||||
{
|
||||
id: 123456,
|
||||
name: 'v1.0.0',
|
||||
tagName: 'v1.0.0',
|
||||
sha: 'abc123',
|
||||
notes: 'Some release notes',
|
||||
url: 'http://example2.com',
|
||||
draft: false,
|
||||
uploadUrl: 'http://example.com',
|
||||
path: 'a',
|
||||
version: '1.0.0',
|
||||
major: 1,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
},
|
||||
{
|
||||
id: 123,
|
||||
name: 'v1.2.0',
|
||||
tagName: 'v1.2.0',
|
||||
sha: 'abc123',
|
||||
notes: 'Some release notes',
|
||||
url: 'http://example2.com',
|
||||
draft: false,
|
||||
uploadUrl: 'http://example.com',
|
||||
path: 'b',
|
||||
version: '1.2.0',
|
||||
major: 1,
|
||||
minor: 2,
|
||||
patch: 0,
|
||||
},
|
||||
]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
sandbox.stub(Manifest, 'fromManifest').resolves(fakeManifest);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
|
||||
assert.strictEqual(output['a--id'], 123456);
|
||||
assert.strictEqual(output['a--release_created'], true);
|
||||
assert.strictEqual(output['a--upload_url'], 'http://example.com');
|
||||
assert.strictEqual(output['a--html_url'], 'http://example2.com');
|
||||
assert.strictEqual(output['a--tag_name'], 'v1.0.0');
|
||||
assert.strictEqual(output['a--major'], 1);
|
||||
assert.strictEqual(output['a--minor'], 0);
|
||||
assert.strictEqual(output['a--patch'], 0);
|
||||
assert.strictEqual(output['a--version'], '1.0.0');
|
||||
assert.strictEqual(output['a--sha'], 'abc123');
|
||||
assert.strictEqual(output['a--path'], 'a');
|
||||
|
||||
assert.strictEqual(output['b--id'], 123);
|
||||
assert.strictEqual(output['b--release_created'], true);
|
||||
assert.strictEqual(output['b--upload_url'], 'http://example.com');
|
||||
assert.strictEqual(output['b--html_url'], 'http://example2.com');
|
||||
assert.strictEqual(output['b--tag_name'], 'v1.2.0');
|
||||
assert.strictEqual(output['b--major'], 1);
|
||||
assert.strictEqual(output['b--minor'], 2);
|
||||
assert.strictEqual(output['b--patch'], 0);
|
||||
assert.strictEqual(output['b--version'], '1.2.0');
|
||||
assert.strictEqual(output['b--sha'], 'abc123');
|
||||
assert.strictEqual(output['b--path'], 'b');
|
||||
|
||||
assert.strictEqual(output.paths_released, '["a","b"]');
|
||||
assert.strictEqual(output.releases_created, true);
|
||||
});
|
||||
it('sets appropriate output if multiple release PR opened', async () => {
|
||||
restoreEnv = mockInputs({});
|
||||
const fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves(fixturePrs);
|
||||
sandbox.stub(Manifest, 'fromManifest').resolves(fakeManifest);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
const {pr, prs} = output;
|
||||
assert.deepStrictEqual(pr, fixturePrs[0]);
|
||||
assert.deepStrictEqual(prs, JSON.stringify(fixturePrs));
|
||||
});
|
||||
it('does not set outputs when no release created or PR returned', async () => {
|
||||
restoreEnv = mockInputs({});
|
||||
const fakeManifest = sandbox.createStubInstance(Manifest);
|
||||
fakeManifest.createReleases.resolves([]);
|
||||
fakeManifest.createPullRequests.resolves([]);
|
||||
sandbox.stub(Manifest, 'fromManifest').resolves(fakeManifest);
|
||||
await action.main();
|
||||
sinon.assert.calledOnce(fakeManifest.createReleases);
|
||||
sinon.assert.calledOnce(fakeManifest.createPullRequests);
|
||||
|
||||
assert.strictEqual(Object.hasOwnProperty.call(output, 'pr'), false);
|
||||
assert.deepStrictEqual(output.paths_released, '[]');
|
||||
assert.deepStrictEqual(output.prs_created, false);
|
||||
assert.deepStrictEqual(output.releases_created, false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user