Skip to content

Commit ae2b8fa

Browse files
authored
Merge pull request #202 from github/sticky_locks_for_noop
Sticky Locks for `noop` deployments
2 parents 7b824da + 0285658 commit ae2b8fa

File tree

8 files changed

+118
-6
lines changed

8 files changed

+118
-6
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ As seen above, we have two steps. One for a noop deploy, and one for a regular d
282282
| `skip_completing` | `false` | `"false"` | If set to "true", skip the process of completing a deployment. You must manually create a deployment status after the deployment is complete. Default is "false" |
283283
| `deploy_message_path` | `false` | `".github/deployment_message.md"` | The path to a markdown file which is used as a template for custom deployment messages. Example: `".github/deployment_message.md"` |
284284
| `sticky_locks` | `false` | `"false"` | If set to `"true"`, locks will not be released after a deployment run completes. This applies to both successful, and failed deployments.Sticky locks are also known as ["hubot style deployment locks"](./docs/hubot-style-deployment-locks.md). They will persist until they are manually released by a user, or if you configure [another workflow with the "unlock on merge" mode](./docs/unlock-on-merge.md) to remove them automatically on PR merge. |
285+
| `sticky_locks_for_noop` | `false` | `"false"` | If set to `"true"`, then sticky_locks will also be used for noop deployments. This can be useful in some cases but it often leads to locks being left behind when users test noop deployments. |
285286

286287
## Outputs 📤
287288

__tests__/main.test.js

+33
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ beforeEach(() => {
5353
process.env.INPUT_MERGE_DEPLOY_MODE = 'false'
5454
process.env.INPUT_UNLOCK_ON_MERGE_MODE = 'false'
5555
process.env.INPUT_STICKY_LOCKS = 'false'
56+
process.env.INPUT_STICKY_LOCKS_FOR_NOOP = 'false'
5657

5758
github.context.payload = {
5859
issue: {
@@ -188,6 +189,38 @@ test('successfully runs the action in noop mode', async () => {
188189
expect(saveStateMock).toHaveBeenCalledWith('noop', true)
189190
})
190191

192+
test('successfully runs the action in noop mode when using sticky_locks_for_noop set to true', async () => {
193+
process.env.INPUT_STICKY_LOCKS_FOR_NOOP = 'true'
194+
jest.spyOn(prechecks, 'prechecks').mockImplementation(() => {
195+
return {
196+
ref: 'test-ref',
197+
status: true,
198+
message: '✔️ PR is approved and all CI checks passed - OK',
199+
noopMode: true
200+
}
201+
})
202+
203+
github.context.payload.comment.body = '.noop'
204+
205+
expect(await run()).toBe('success - noop')
206+
expect(debugMock).toHaveBeenCalledWith(
207+
`🔒 noop mode detected and using stickyLocks: true`
208+
)
209+
expect(setOutputMock).toHaveBeenCalledWith('comment_body', '.noop')
210+
expect(setOutputMock).toHaveBeenCalledWith('triggered', 'true')
211+
expect(setOutputMock).toHaveBeenCalledWith('comment_id', 123)
212+
expect(setOutputMock).toHaveBeenCalledWith('ref', 'test-ref')
213+
expect(setOutputMock).toHaveBeenCalledWith('noop', true)
214+
expect(setOutputMock).toHaveBeenCalledWith('continue', 'true')
215+
expect(setOutputMock).toHaveBeenCalledWith('type', 'deploy')
216+
expect(saveStateMock).toHaveBeenCalledWith('isPost', 'true')
217+
expect(saveStateMock).toHaveBeenCalledWith('actionsToken', 'faketoken')
218+
expect(saveStateMock).toHaveBeenCalledWith('environment', 'production')
219+
expect(saveStateMock).toHaveBeenCalledWith('comment_id', 123)
220+
expect(saveStateMock).toHaveBeenCalledWith('ref', 'test-ref')
221+
expect(saveStateMock).toHaveBeenCalledWith('noop', true)
222+
})
223+
191224
test('runs the action in lock mode and fails due to bad permissions', async () => {
192225
jest.spyOn(validPermissions, 'validPermissions').mockImplementation(() => {
193226
return permissionsMsg

__tests__/schemas/action.schema.yml

+10
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,16 @@ inputs:
340340
default:
341341
required: true
342342
type: string
343+
sticky_locks_for_noop:
344+
description:
345+
type: string
346+
required: true
347+
required:
348+
type: boolean
349+
required: true
350+
default:
351+
required: true
352+
type: string
343353

344354
# outputs section
345355
outputs:

action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ inputs:
129129
description: 'If set to "true", locks will not be released after a deployment run completes. This applies to both successful, and failed deployments.Sticky locks are also known as "hubot style deployment locks". They will persist until they are manually released by a user, or if you configure another workflow with the "unlock on merge" mode to remove them automatically on PR merge.'
130130
required: false
131131
default: "false"
132+
sticky_locks_for_noop:
133+
description: 'If set to "true", then sticky_locks will also be used for noop deployments. This can be useful in some cases but it often leads to locks being left behind when users test noop deployments.'
134+
required: false
135+
default: "false"
132136
outputs:
133137
continue:
134138
description: 'The string "true" if the deployment should continue, otherwise empty - Use this to conditionally control if your deployment should proceed or not'

dist/index.js

+26-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/hubot-style-deployment-locks.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,29 @@ This behavior is not enabled out of the box and you need to enable it in your Ac
1212

1313
You can still release locks manually with `.unlock` at any time and so can other users. This is helpful if you need to release a lock that is blocking a deployment from another PR or if you were just testing changes and want to release the lock.
1414

15-
## Example
15+
It should be noted that if you want this logic to **also apply to noop deployments** you need to enable another input option called `sticky_locks_for_noop` and also set its value to `"true"`. By default, noop deployments will not claim sticky locks as this often just leads to locks being left behind and never cleaned up.
16+
17+
## Examples
18+
19+
Enabling sticky deployment locks for `.deploy` commands:
20+
21+
```yaml
22+
- name: branch-deploy
23+
id: branch-deploy
24+
uses: github/[email protected]
25+
with:
26+
sticky_locks: "true" # <--- enables sticky deployment lock / hubot style deployment locks
27+
# ... other configuration
28+
```
29+
30+
Enabling sticky deployment locks for `.deploy` and `.noop` commands:
1631

1732
```yaml
1833
- name: branch-deploy
1934
id: branch-deploy
2035
uses: github/[email protected]
2136
with:
2237
sticky_locks: "true" # <--- enables sticky deployment lock / hubot style deployment locks
38+
sticky_locks_for_noop: "true" # <--- enables sticky deployment lock / hubot style deployment locks for noop deployments
2339
# ... other configuration
2440
```

src/main.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export async function run() {
5454
const param_separator = core.getInput('param_separator')
5555
const permissions = core.getInput('permissions')
5656
const sticky_locks = core.getBooleanInput('sticky_locks')
57+
const sticky_locks_for_noop = core.getBooleanInput('sticky_locks_for_noop')
5758

5859
// Create an octokit client with the retry plugin
5960
const octokit = github.getOctokit(token, {
@@ -455,17 +456,40 @@ export async function run() {
455456
core.info(
456457
`🍯 sticky_locks: ${COLORS.highlight}${sticky_locks}${COLORS.reset}`
457458
)
459+
core.info(
460+
`🍯 sticky_locks_for_noop: ${COLORS.highlight}${sticky_locks_for_noop}${COLORS.reset}`
461+
)
462+
463+
// conditionally handle how we want to apply locks on deployments
464+
var stickyLocks
465+
// if sticky_locks is true, then we will use the sticky_locks logic
466+
// if sticky_locks_for_noop is also true, then we will also use the sticky_locks logic for noop deployments
467+
// if sticky_locks is false, then no sticky locks will be applied and only non-sticky locks will be used
468+
// if sticky_locks is true but sticky_locks_for_noop is false, then we will only use sticky locks on non-noop deployments
469+
if (precheckResults.noopMode) {
470+
if (sticky_locks_for_noop) {
471+
stickyLocks = true
472+
} else {
473+
stickyLocks = false
474+
}
475+
core.debug(`🔒 noop mode detected and using stickyLocks: ${stickyLocks}`)
476+
} else {
477+
stickyLocks = sticky_locks
478+
}
458479

459480
// if we are using sticky_locks in deployments, don't leave a comment as this is inferred by the user
460-
const leaveComment = sticky_locks === false ? true : false
481+
const leaveComment = stickyLocks === false ? true : false
482+
483+
core.debug(`🔒 stickyLocks: ${stickyLocks}`)
484+
core.debug(`💬 leaveComment: ${leaveComment}`)
461485

462486
// Aquire the branch-deploy lock
463487
const lockResponse = await lock(
464488
octokit,
465489
context,
466490
precheckResults.ref,
467491
reactRes.data.id,
468-
sticky_locks, // sticky / hubot style locks - true/false depending on the input
492+
stickyLocks, // sticky / hubot style locks - true/false depending on the input
469493
environment, // environment
470494
null, // details only flag
471495
false, // postDeployStep

0 commit comments

Comments
 (0)