Skip to content

Commit dce5977

Browse files
committed
fix: normalize branch protection restrictions and preserve existing settings
1 parent 9d141d8 commit dce5977

2 files changed

Lines changed: 51 additions & 13 deletions

File tree

lib/plugins/branches.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ module.exports = class Branches extends ErrorStash {
8181
resArray.push(new NopCommand(this.constructor.name, this.repo, null, results))
8282
}
8383

84-
Object.assign(params, requiredBranchProtectionDefaults, branch.protection, { headers: previewHeaders })
84+
Object.assign(params, requiredBranchProtectionDefaults, this.reformatAndReturnBranchProtection(structuredClone(result.data)), branch.protection, { headers: previewHeaders })
8585

8686
if (this.nop) {
8787
resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.repos.updateBranchProtection.endpoint(params), 'Add Branch Protection'))
@@ -131,6 +131,18 @@ module.exports = class Branches extends ErrorStash {
131131
protection.required_linear_history = protection.required_linear_history && protection.required_linear_history.enabled
132132
protection.enforce_admins = protection.enforce_admins && protection.enforce_admins.enabled
133133
protection.required_signatures = protection.required_signatures && protection.required_signatures.enabled
134+
if (protection.restrictions) {
135+
delete protection.restrictions.url
136+
protection.restrictions.users = Array.isArray(protection.restrictions.users)
137+
? protection.restrictions.users.map(user => user.login || user)
138+
: []
139+
protection.restrictions.teams = Array.isArray(protection.restrictions.teams)
140+
? protection.restrictions.teams.map(team => team.slug || team)
141+
: []
142+
protection.restrictions.apps = Array.isArray(protection.restrictions.apps)
143+
? protection.restrictions.apps.map(app => app.slug || app)
144+
: []
145+
}
134146
if (protection.required_pull_request_reviews && !protection.required_pull_request_reviews.bypass_pull_request_allowances) {
135147
protection.required_pull_request_reviews.bypass_pull_request_allowances = { apps: [], teams: [], users: [] }
136148
}

test/unit/lib/plugins/branches.test.js

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -181,20 +181,19 @@ describe('Branches', () => {
181181
)
182182

183183
return plugin.sync().then(() => {
184-
expect(github.repos.updateBranchProtection).toHaveBeenCalledWith({
184+
expect(github.repos.updateBranchProtection).toHaveBeenCalledWith(expect.objectContaining({
185185
owner: 'bkeepers',
186186
repo: 'test',
187187
branch: 'main',
188188
required_status_checks: {
189189
strict: true,
190190
contexts: []
191191
},
192-
// When override processing clears {{EXTERNALLY_DEFINED}} contexts,
193-
// enforce_admins defaults to null since config doesn't specify it
194-
enforce_admins: null,
192+
// Existing enforce_admins should be preserved from GitHub
193+
enforce_admins: false,
195194
restrictions: null,
196195
headers: { accept: 'application/vnd.github.hellcat-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.zzzax-preview+json' }
197-
})
196+
}))
198197
})
199198
})
200199
})
@@ -249,17 +248,44 @@ describe('Branches', () => {
249248
)
250249
})
251250
})
251+
252+
it('normalizes restrictions and defaults missing arrays when preserving from GitHub', () => {
253+
github.repos.getBranchProtection = jest.fn().mockResolvedValue({
254+
data: {
255+
enforce_admins: { enabled: true },
256+
restrictions: {
257+
url: 'https://api.github.com/...',
258+
users: [{ login: 'user1' }]
259+
}
260+
}
261+
})
262+
263+
const plugin = configure([{
264+
name: 'main',
265+
protection: {
266+
enforce_admins: false
267+
}
268+
}])
269+
270+
return plugin.sync().then(() => {
271+
const payload = github.repos.updateBranchProtection.mock.calls[0][0]
272+
expect(payload.restrictions).toEqual({
273+
users: ['user1'],
274+
teams: [],
275+
apps: []
276+
})
277+
expect(payload.restrictions.url).toBeUndefined()
278+
})
279+
})
252280
})
253281

254282
describe('when {{EXTERNALLY_DEFINED}} is present in "required_status_checks" and status checks exist in GitHub', () => {
255283
it('it retains the status checks from GitHub', () => {
256284
github.repos.getBranchProtection = jest.fn().mockResolvedValue({
257285
data: {
258286
enforce_admins: { enabled: false },
259-
protection: {
260-
required_status_checks: {
261-
contexts: ['check-1', 'check-2']
262-
}
287+
required_status_checks: {
288+
contexts: ['check-1', 'check-2']
263289
}
264290
}
265291
})
@@ -276,18 +302,18 @@ describe('Branches', () => {
276302
)
277303

278304
return plugin.sync().then(() => {
279-
expect(github.repos.updateBranchProtection).toHaveBeenCalledWith({
305+
expect(github.repos.updateBranchProtection).toHaveBeenCalledWith(expect.objectContaining({
280306
owner: 'bkeepers',
281307
repo: 'test',
282308
branch: 'main',
283309
required_status_checks: {
284310
strict: true,
285311
contexts: ['check-1', 'check-2']
286312
},
287-
enforce_admins: null,
313+
enforce_admins: false,
288314
restrictions: null,
289315
headers: { accept: 'application/vnd.github.hellcat-preview+json,application/vnd.github.luke-cage-preview+json,application/vnd.github.zzzax-preview+json' }
290-
})
316+
}))
291317
})
292318
})
293319
})

0 commit comments

Comments
 (0)