Skip to content

Commit 4b2cec7

Browse files
decyjphrCopilot
andcommitted
Fix delta bugs: org-all precedence + repo config path; update schema
- Delta mode now skips apps configured as repository_selection: all at org level (org 'all' takes precedence — never add/remove repos via delta) - Fix repo config path used to load previous version from baseRef: use CONFIG_PATH/repos/<repo>.yml instead of bare repos/<repo>.yml (the bare path 404'd, so repo-level repository_unselection was never computed) - schema/settings.json: add app_installations top-level property and include it in additive_plugins and disable_plugins enums for editor validation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 24fb684 commit 4b2cec7

2 files changed

Lines changed: 48 additions & 5 deletions

File tree

lib/settings.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1525,8 +1525,24 @@ class Settings {
15251525
}
15261526
}
15271527

1528+
// Apps configured as "all" at the org level take precedence — they must
1529+
// never have repos unselected by suborg/repo deltas, and adding repos is
1530+
// redundant since the app already targets all repos.
1531+
const orgAllApps = new Set()
1532+
const orgAppInstallations = this.config && this.config.app_installations
1533+
if (Array.isArray(orgAppInstallations)) {
1534+
for (const appConfig of orgAppInstallations) {
1535+
if (appConfig && appConfig.app_slug && appConfig.repository_selection === 'all') {
1536+
orgAllApps.add(appConfig.app_slug)
1537+
}
1538+
}
1539+
}
1540+
15281541
// Helper to ensure an entry exists in the change map
15291542
const ensureEntry = (slug) => {
1543+
// Org-level "all" apps are fully managed by full sync; deltas must not
1544+
// add or remove repos for them (org "all" takes precedence).
1545+
if (orgAllApps.has(slug)) return null
15301546
if (!appChangeMap.has(slug)) {
15311547
const installationId = installationMap.get(slug)
15321548
if (!installationId) return null
@@ -1620,7 +1636,7 @@ class Settings {
16201636
// Load previous version of this repo config
16211637
let previousApps = []
16221638
if (baseRef) {
1623-
const repoFilePath = `repos/${repo.repo}.yml`
1639+
const repoFilePath = path.posix.join(CONFIG_PATH, 'repos', `${repo.repo}.yml`)
16241640
try {
16251641
const previousData = await this.loadYamlFromRef(repoFilePath, baseRef)
16261642
previousApps = (previousData && previousData.app_installations) || []

schema/settings.json

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,32 @@
234234
}
235235
}
236236
},
237+
"app_installations": {
238+
"description": "Manage which repositories a GitHub App installation can access. The target is a GitHub App installation rather than a repository. Repo selection follows the config hierarchy: org-level settings.yml selects all repos (repository_selection: all); suborgs/*.yml selects repos by the suborg's targeting criteria; repos/*.yml adds the specific repo. Requires safe-settings to be installed on the enterprise with 'Enterprise organization installations' permission.",
239+
"type": "array",
240+
"items": {
241+
"type": "object",
242+
"required": [
243+
"app_slug"
244+
],
245+
"additionalProperties": false,
246+
"properties": {
247+
"app_slug": {
248+
"type": "string",
249+
"description": "The slug of the GitHub App installation to manage."
250+
},
251+
"repository_selection": {
252+
"type": "string",
253+
"enum": [
254+
"all"
255+
],
256+
"description": "Only valid at the org level (settings.yml). 'all' selects every repository in the org and takes precedence over any suborg/repo-level selections."
257+
}
258+
}
259+
}
260+
},
237261
"additive_plugins": {
238-
"description": "List of Diffable plugins to run in additive mode. In additive mode the plugin will only add and update entries; it will never call remove(), so items that exist on GitHub but are absent from the YAML are preserved. Only Diffable-extending plugins are supported (labels, collaborators, teams, milestones, autolinks, environments, custom_properties, variables, rulesets, custom_repository_roles). Declare only in settings.yml (org level) to keep behavior consistent across all repos.",
262+
"description": "List of Diffable plugins to run in additive mode. In additive mode the plugin will only add and update entries; it will never call remove(), so items that exist on GitHub but are absent from the YAML are preserved. Only Diffable-extending plugins are supported (labels, collaborators, teams, milestones, autolinks, environments, custom_properties, variables, rulesets, custom_repository_roles). The app_installations plugin also honors additive mode (only adds repos to installations, never removes). Declare only in settings.yml (org level) to keep behavior consistent across all repos.",
239263
"type": "array",
240264
"items": {
241265
"type": "string",
@@ -249,7 +273,8 @@
249273
"custom_properties",
250274
"variables",
251275
"rulesets",
252-
"custom_repository_roles"
276+
"custom_repository_roles",
277+
"app_installations"
253278
]
254279
}
255280
},
@@ -274,7 +299,8 @@
274299
"custom_properties",
275300
"custom_repository_roles",
276301
"variables",
277-
"archive"
302+
"archive",
303+
"app_installations"
278304
]
279305
},
280306
{
@@ -300,7 +326,8 @@
300326
"custom_properties",
301327
"custom_repository_roles",
302328
"variables",
303-
"archive"
329+
"archive",
330+
"app_installations"
304331
]
305332
},
306333
"target": {

0 commit comments

Comments
 (0)