Skip to content

Commit d6946cc

Browse files
committed
Allow ruleset settings to be overridden outside of safe settings.
1 parent b8a153a commit d6946cc

File tree

2 files changed

+56
-3
lines changed

2 files changed

+56
-3
lines changed

lib/plugins/branches.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,18 +129,19 @@ module.exports = class Branches extends ErrorStash {
129129
getLastKey (obj, property) {
130130
const keys = property.split('.')
131131
for (let i = 0; i < keys.length - 1; i++) {
132-
if (!obj[keys[i]]) return [obj, keys[i]]
132+
if (!obj[keys[i]]) return [null, null]
133133
obj = obj[keys[i]]
134134
}
135135
return [obj, keys[keys.length - 1]]
136136
}
137137

138-
removeOverrides (source, target) {
138+
removeOverrides (source, existing) {
139139
if (source) {
140140
overrides.forEach(override => {
141141
let [obj, lastKey] = this.getLastKey(source, override)
142+
if (!obj) return
142143
if ((Array.isArray(obj[lastKey]) || typeof obj[lastKey] === 'string') && obj[lastKey].includes('{{EXTERNALLY_DEFINED}}')) {
143-
let [obj2, lastKey2] = this.getLastKey(target, override)
144+
let [obj2, lastKey2] = this.getLastKey(existing, override)
144145
if (obj2[lastKey2]) {
145146
obj[lastKey] = obj2[lastKey2]
146147
} else if (Array.isArray(obj[lastKey])) {

lib/plugins/rulesets.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const Diffable = require('./diffable')
22
const NopCommand = require('../nopcommand')
33
const MergeDeep = require('../mergeDeep')
44
const ignorableFields = []
5+
const overrides = [
6+
'required_status_checks',
7+
]
58

69
const version = {
710
'X-GitHub-Api-Version': '2022-11-28'
@@ -92,6 +95,51 @@ module.exports = class Rulesets extends Diffable {
9295
return merged.hasChanges
9396
}
9497

98+
getObjectRef (data, dataKey) {
99+
const results = []
100+
const traverse = (obj) => {
101+
for (const key in obj) {
102+
if (key === dataKey) {
103+
results.push(obj)
104+
} else if (Array.isArray(obj[key])) {
105+
obj[key].forEach(element => traverse(element))
106+
} else if (typeof obj[key] === 'object' && obj[key]) {
107+
traverse(obj[key])
108+
}
109+
}
110+
}
111+
traverse(data)
112+
return results
113+
}
114+
115+
// When {{EXTERNALLY_DEFINED}} is found in the override value, retain the
116+
// existing value from GitHub.
117+
// Note:
118+
// - The admin settings could define multiple overrides, but the GitHub API
119+
// retains one only.
120+
// - The PUT method for rulesets (update) allows for multiple overrides.
121+
// - The POST method for rulesets (create) allows for one override only.
122+
removeOverrides (source, existing) {
123+
overrides.forEach(override => {
124+
let sourceRefs = this.getObjectRef(source, override)
125+
let data = JSON.stringify(sourceRefs, null, 2)
126+
if (data.includes('{{EXTERNALLY_DEFINED}}')) {
127+
let existingRefs = this.getObjectRef(existing, override)
128+
sourceRefs.forEach(sourceRef => {
129+
if (existingRefs[0]) {
130+
sourceRef[override] = existingRefs[0][override]
131+
} else if (Array.isArray(sourceRef[override])) {
132+
sourceRef[override] = []
133+
} else if (typeof sourceRef[override] === 'object' && sourceRef[override]) {
134+
sourceRef[override] = {}
135+
} else {
136+
sourceRef[override] = ''
137+
}
138+
})
139+
}
140+
})
141+
}
142+
95143
update (existing, attrs) {
96144
const parms = this.wrapAttrs(Object.assign({ id: existing.id }, attrs))
97145
if (this.scope === 'org') {
@@ -100,6 +148,7 @@ module.exports = class Rulesets extends Diffable {
100148
new NopCommand(this.constructor.name, this.repo, this.github.request.endpoint('PUT /orgs/{org}/rulesets/{id}', parms), 'Update Ruleset')
101149
])
102150
}
151+
this.removeOverrides(parms, existing)
103152
this.log.debug(`Updating Ruleset with the following values ${JSON.stringify(parms, null, 2)}`)
104153
return this.github.request('PUT /orgs/{org}/rulesets/{id}', parms).then(res => {
105154
this.log(`Ruleset updated successfully ${JSON.stringify(res.url)}`)
@@ -113,6 +162,7 @@ module.exports = class Rulesets extends Diffable {
113162
new NopCommand(this.constructor.name, this.repo, this.github.request.endpoint('PUT /repos/{owner}/{repo}/rulesets/{id}', parms), 'Update Ruleset')
114163
])
115164
}
165+
this.removeOverrides(parms, existing)
116166
this.log.debug(`Updating Ruleset with the following values ${JSON.stringify(parms, null, 2)}`)
117167
return this.github.request('PUT /repos/{owner}/{repo}/rulesets/{id}', parms).then(res => {
118168
this.log(`Ruleset updated successfully ${JSON.stringify(res.url)}`)
@@ -130,6 +180,7 @@ module.exports = class Rulesets extends Diffable {
130180
new NopCommand(this.constructor.name, this.repo, this.github.request.endpoint('POST /orgs/{org}/rulesets', this.wrapAttrs(attrs)), 'Create Ruleset')
131181
])
132182
}
183+
this.removeOverrides(attrs, {})
133184
this.log.debug(`Creating Rulesets with the following values ${JSON.stringify(attrs, null, 2)}`)
134185
return this.github.request('POST /orgs/{org}/rulesets', this.wrapAttrs(attrs)).then(res => {
135186
this.log(`Ruleset created successfully ${JSON.stringify(res.url)}`)
@@ -143,6 +194,7 @@ module.exports = class Rulesets extends Diffable {
143194
new NopCommand(this.constructor.name, this.repo, this.github.request.endpoint('POST /repos/{owner}/{repo}/rulesets', this.wrapAttrs(attrs)), 'Create Ruleset')
144195
])
145196
}
197+
this.removeOverrides(attrs, {})
146198
this.log.debug(`Creating Rulesets with the following values ${JSON.stringify(attrs, null, 2)}`)
147199
return this.github.request('POST /repos/{owner}/{repo}/rulesets', this.wrapAttrs(attrs)).then(res => {
148200
this.log(`Ruleset created successfully ${JSON.stringify(res.url)}`)

0 commit comments

Comments
 (0)