Skip to content
Open
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ As seen above, we have two steps. One for a noop deploy, and one for a regular d
| `deployment_order_scope` | `false` | `all` | Controls which deployment history records are considered by enforced deployment order. Use `all` to keep the newest deployment from any system authoritative, or `branch-deploy` to use the newest deployment whose payload identifies it as Branch Deploy. The `branch-deploy` scope ignores newer deployments from other systems and should be used only when Branch Deploy is authoritative for promotion. See the [enforced deployment order docs](./docs/enforced-deployment-order.md) for details. |
| `use_security_warnings` | `false` | `true` | Whether or not to leave security related warnings in log messages during deployments. Default is `true` |
| `allow_non_default_target_branch_deployments` | `false` | `false` | Whether or not to allow deployments of pull requests that target a branch other than the default branch (aka stable branch) as their merge target. By default, this Action would reject the deployment of a branch named `feature-branch` if it was targeting `foo` instead of `main` (or whatever your default branch is). This option allows you to override that behavior and be able to deploy any branch in your repository regardless of the target branch. This option is potentially unsafe and should be used with caution as most default branches contain branch protection rules. Often times non-default branches do not contain these same branch protection rules. Follow along in this [issue thread](https://github.com/github/branch-deploy/issues/340) to learn more. |
| `enable_pr_stacks` | `false` | `false` | Opt in to deployments from native GitHub pull request stacks rooted at `stable_branch`. The selected pull request and all lower unmerged pull requests must pass deployment checks. GitHub stacks are in public preview. See the [PR stacks documentation](docs/pr-stacks.md). |
| `deployment_confirmation` | `false` | `false` | Whether or not to require an additional confirmation before a deployment can continue. Default is `false`. If your project requires elevated security, it is highly recommended to enable this option - especially in open source projects where you might be deploying forks - [Deployment confirmation docs](./docs/deployment-confirmation.md) |
| `deployment_confirmation_timeout` | `false` | `60` | The number of seconds to wait for a deployment confirmation before timing out. Must be a positive integer. Default is `60` seconds (1 minute). |

Expand Down
35 changes: 33 additions & 2 deletions __tests__/action-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import {
CHECKS_MODE_VALUES,
DEPLOYMENT_ORDER_SCOPE_VALUES,
getInputs,
LITERAL_ACTION_INPUT_KEYS,
LITERAL_ACTION_INPUT_VALUES,
OUTDATED_MODE_VALUES,
Expand Down Expand Up @@ -90,6 +91,7 @@ const expectedInputContract = {
default: 'false',
required: false
},
enable_pr_stacks: {default: 'false', required: false},
deployment_confirmation: {default: 'false', required: false},
deployment_confirmation_timeout: {default: '60', required: false}
} as const satisfies Record<string, InputContract>
Expand All @@ -110,6 +112,7 @@ const expectedBooleanInputKeys = [
'skip_successful_deploy_labels_if_approved',
'use_security_warnings',
'allow_non_default_target_branch_deployments',
'enable_pr_stacks',
'deployment_confirmation'
] as const satisfies readonly ActionInputKey[]

Expand Down Expand Up @@ -172,7 +175,7 @@ test('action input and output registries exactly match action.yml', () => {
[...ACTION_OUTPUT_KEYS].sort(),
Object.keys(outputs).sort()
)
assert.strictEqual(ACTION_INPUT_KEYS.length, 51)
assert.strictEqual(ACTION_INPUT_KEYS.length, 52)
assert.strictEqual(ACTION_OUTPUT_KEYS.length, 41)
})

Expand Down Expand Up @@ -204,7 +207,7 @@ test('action input defaults, required flags, and accepted literals stay fixed',

test('typed input registries stay complete and exact', () => {
assert.deepStrictEqual(BOOLEAN_ACTION_INPUT_KEYS, expectedBooleanInputKeys)
assert.strictEqual(BOOLEAN_ACTION_INPUT_KEYS.length, 16)
assert.strictEqual(BOOLEAN_ACTION_INPUT_KEYS.length, 17)
assert.deepStrictEqual(INTEGER_ACTION_INPUT_KEYS, expectedIntegerInputKeys)
assert.deepStrictEqual(LITERAL_ACTION_INPUT_KEYS, expectedLiteralInputKeys)
assert.deepStrictEqual(LITERAL_ACTION_INPUT_VALUES, {
Expand All @@ -224,6 +227,34 @@ test('typed input registries stay complete and exact', () => {
}
})

test('PR stacks remain an opt-in boolean input', () => {
const originalEnvironment = new Map<string, string | undefined>()
try {
for (const [key, definition] of Object.entries(expectedInputContract)) {
const environmentKey = `INPUT_${key.toUpperCase()}`
originalEnvironment.set(environmentKey, process.env[environmentKey])
process.env[environmentKey] = definition.default
}

assert.strictEqual(getInputs().enable_pr_stacks, false)
process.env['INPUT_ENABLE_PR_STACKS'] = 'true'
assert.strictEqual(getInputs().enable_pr_stacks, true)
assert.strictEqual(
getInputs().allow_non_default_target_branch_deployments,
false
)
process.env['INPUT_ENABLE_PR_STACKS'] = 'FALSE'
assert.strictEqual(getInputs().enable_pr_stacks, false)
process.env['INPUT_ENABLE_PR_STACKS'] = 'yes'
assert.throws(() => getInputs(), /specification: enable_pr_stacks/u)
} finally {
for (const [key, value] of originalEnvironment) {
if (value === undefined) delete process.env[key]
else process.env[key] = value
}
}
})

test('runner entrypoints remain the Node 24 committed ESM bundle', () => {
const runs = requireRecord(actionMetadata()['runs'], 'action.yml runs')
assert.deepStrictEqual(
Expand Down
12 changes: 12 additions & 0 deletions __tests__/functions/help.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ test('successfully calls help with defaults', async () => {
assertDebugIncludes(
'`disable_lock: false` - This Action will use deployment locks'
)
assertDebugIncludes(
'`enable_pr_stacks: false` - Enable deployments from native GitHub pull request stacks rooted at the stable branch'
)
})

test('shows the enabled PR stacks setting in help output', async () => {
const inputs = createActionInputs({enable_pr_stacks: true})

assert.strictEqual(await help(octokit, context, 123, inputs), undefined)
assertDebugIncludes(
'`enable_pr_stacks: true` - Enable deployments from native GitHub pull request stacks rooted at the stable branch'
)
})

test('explains disabled locking in help output', async () => {
Expand Down
Loading