Skip to content

Commit a40c82b

Browse files
authored
Merge pull request #299 from github/lock-branch-validation
Lock Branch Validation
2 parents 7d3b7d8 + bada9d6 commit a40c82b

File tree

9 files changed

+118
-9
lines changed

9 files changed

+118
-9
lines changed

Diff for: __tests__/functions/valid-branch-name.test.js

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import {constructValidBranchName} from '../../src/functions/valid-branch-name'
2+
import * as core from '@actions/core'
3+
4+
const debugMock = jest.spyOn(core, 'debug')
5+
6+
const branchName = 'production'
7+
8+
beforeEach(() => {
9+
jest.clearAllMocks()
10+
jest.spyOn(core, 'debug').mockImplementation(() => {})
11+
})
12+
13+
test('does not make any modifications to a valid branch name', async () => {
14+
expect(constructValidBranchName(branchName)).toBe(branchName)
15+
expect(debugMock).toHaveBeenCalledWith(
16+
`constructing valid branch name: ${branchName}`
17+
)
18+
expect(debugMock).toHaveBeenCalledWith(
19+
`constructed valid branch name: ${branchName}`
20+
)
21+
})
22+
23+
test('replaces spaces with hyphens', async () => {
24+
expect(constructValidBranchName(`super ${branchName}`)).toBe(
25+
`super-${branchName}`
26+
)
27+
expect(debugMock).toHaveBeenCalledWith(
28+
`constructing valid branch name: super ${branchName}`
29+
)
30+
expect(debugMock).toHaveBeenCalledWith(
31+
`constructed valid branch name: super-${branchName}`
32+
)
33+
})
34+
35+
test('replaces multiple spaces with hyphens', async () => {
36+
expect(constructValidBranchName(`super duper ${branchName}`)).toBe(
37+
`super-duper-${branchName}`
38+
)
39+
expect(debugMock).toHaveBeenCalledWith(
40+
`constructing valid branch name: super duper ${branchName}`
41+
)
42+
expect(debugMock).toHaveBeenCalledWith(
43+
`constructed valid branch name: super-duper-${branchName}`
44+
)
45+
})
46+
47+
test('returns null if the branch is null', async () => {
48+
expect(constructValidBranchName(null)).toBe(null)
49+
})
50+
51+
test('returns undefined if the branch is undefined', async () => {
52+
expect(constructValidBranchName(undefined)).toBe(undefined)
53+
})

Diff for: dist/index.js

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

Diff for: dist/index.js.map

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

Diff for: src/functions/check-lock-file.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {LOCK_METADATA} from './lock-metadata'
22
import {COLORS} from './colors'
3+
import {constructValidBranchName} from './valid-branch-name'
34
import * as core from '@actions/core'
45

56
const LOCK_FILE = LOCK_METADATA.lockFile
@@ -10,6 +11,8 @@ const LOCK_FILE = LOCK_METADATA.lockFile
1011
// :param branchName: The name of the branch to check
1112
// :return: The lock file contents if it exists, false if not
1213
export async function checkLockFile(octokit, context, branchName) {
14+
branchName = constructValidBranchName(branchName)
15+
1316
core.debug(`checking if lock file exists on branch: ${branchName}`)
1417
// If the lock branch exists, check if a lock file exists
1518
try {

Diff for: src/functions/lock.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as core from '@actions/core'
22
import dedent from 'dedent-js'
33
import {checkLockFile} from './check-lock-file'
44
import {actionStatus} from './action-status'
5+
import {constructValidBranchName} from './valid-branch-name'
56
import {timeDiff} from './time-diff'
67
import {LOCK_METADATA} from './lock-metadata'
78
import {COLORS} from './colors'
@@ -23,7 +24,7 @@ async function constructBranchName(environment, global) {
2324
}
2425

2526
// If the lock is not global, return the environment-specific lock branch name
26-
return `${environment}-${LOCK_BRANCH_SUFFIX}`
27+
return `${constructValidBranchName(environment)}-${LOCK_BRANCH_SUFFIX}`
2728
}
2829

2930
// Helper function for creating a lock file for branch-deployment locks

Diff for: src/functions/unlock-on-merge.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as core from '@actions/core'
22
import {unlock} from './unlock'
33
import {LOCK_METADATA} from './lock-metadata'
44
import {checkLockFile} from './check-lock-file'
5+
import {constructValidBranchName} from './valid-branch-name'
56

67
// Helper function to automatically find, and release a deployment lock when a pull request is merged
78
// :param octokit: the authenticated octokit instance
@@ -28,7 +29,7 @@ export async function unlockOnMerge(octokit, context, environment_targets) {
2829
var releasedEnvironments = []
2930
for (const environment of environment_targets.split(',')) {
3031
// construct the lock branch name for this environment
31-
var lockBranch = `${environment}-${LOCK_METADATA.lockBranchSuffix}`
32+
var lockBranch = `${constructValidBranchName(environment)}-${LOCK_METADATA.lockBranchSuffix}`
3233

3334
// attempt to fetch the lockFile for this branch
3435
var lockFile = await checkLockFile(octokit, context, lockBranch)

Diff for: src/functions/unlock.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as core from '@actions/core'
22
import {actionStatus} from './action-status'
33
import dedent from 'dedent-js'
44
import {LOCK_METADATA} from './lock-metadata'
5+
import {constructValidBranchName} from './valid-branch-name'
56
import {COLORS} from './colors'
67

78
// Constants for the lock file
@@ -90,7 +91,7 @@ export async function unlock(
9091
branchName = GLOBAL_LOCK_BRANCH
9192
successText = '`global`'
9293
} else {
93-
branchName = `${environment}-${LOCK_BRANCH_SUFFIX}`
94+
branchName = `${constructValidBranchName(environment)}-${LOCK_BRANCH_SUFFIX}`
9495
successText = `\`${environment}\``
9596
}
9697

Diff for: src/functions/valid-branch-name.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import * as core from '@actions/core'
2+
3+
// Helper function to create a valid branch name that will pass GitHub's API ref validation
4+
// :param branch: The branch name
5+
// :returns: A string of the branch name with proper formatting
6+
export function constructValidBranchName(branch) {
7+
core.debug(`constructing valid branch name: ${branch}`)
8+
9+
if (branch === null) {
10+
return null
11+
} else if (branch === undefined) {
12+
return undefined
13+
}
14+
15+
// If environment contains any spaces, replace all of them with a hyphen
16+
branch = branch.replace(/\s/g, '-')
17+
18+
core.debug(`constructed valid branch name: ${branch}`)
19+
return branch
20+
}

Diff for: src/main.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {help} from './functions/help'
2424
import {LOCK_METADATA} from './functions/lock-metadata'
2525
import {COLORS} from './functions/colors'
2626
import {getInputs} from './functions/inputs'
27+
import {constructValidBranchName} from './functions/valid-branch-name'
2728

2829
// :returns: 'success', 'success - noop', 'success - merge deploy mode', 'failure', 'safe-exit', 'success - unlock on merge mode' or raises an error
2930
export async function run() {
@@ -255,7 +256,7 @@ export async function run() {
255256
// special comment for global deploy locks
256257
let globalMsg = ''
257258
let environmentMsg = `- __Environment__: \`${lockData.environment}\``
258-
let lockBranchName = `${lockData.environment}-${LOCK_METADATA.lockBranchSuffix}`
259+
let lockBranchName = `${constructValidBranchName(lockData.environment)}-${LOCK_METADATA.lockBranchSuffix}`
259260
if (lockData.global === true) {
260261
globalMsg = dedent(`
261262

0 commit comments

Comments
 (0)