Skip to content

Commit 39b0bdb

Browse files
committed
fix: use slug-aware identity matching in MergeDeep for teams
Teams in YAML use slug format (name: "my-team") while the GitHub API returns display name (name: "My Team") with a separate slug field. This caused phantom diffs in NOP mode. Changes: - GET_NAME_USERNAME_PROPERTY: prefer slug for identity when present - compareDeepIfVisited: strip identity field before value comparison to avoid reporting name casing differences as modifications Backward compatible: items without slug (labels, rulesets) unchanged.
1 parent 46642ce commit 39b0bdb

1 file changed

Lines changed: 14 additions & 5 deletions

File tree

lib/mergeDeep.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ const DeploymentConfig = require('./deploymentConfig')
33

44
const NAME_FIELDS = ['name', 'username', 'actor_id', 'login', 'type', 'key_prefix', 'context']
55
const NAME_USERNAME_PROPERTY = item => NAME_FIELDS.find(prop => Object.prototype.hasOwnProperty.call(item, prop))
6-
const GET_NAME_USERNAME_PROPERTY = item => { if (NAME_USERNAME_PROPERTY(item)) return item[NAME_USERNAME_PROPERTY(item)] }
6+
const GET_NAME_USERNAME_PROPERTY = item => {
7+
if (!item) return undefined
8+
if (item.slug) return item.slug
9+
const prop = NAME_USERNAME_PROPERTY(item)
10+
return prop ? item[prop] : undefined
11+
}
712

813
class MergeDeep {
914
constructor (log, github, ignorableFields = [], configvalidators = {}, overridevalidators = {}) {
@@ -184,7 +189,7 @@ class MergeDeep {
184189
if (source.length < target.length) {
185190
const dels = target.filter(item => {
186191
if (this.isObjectNotArray(item)) {
187-
return !source.some(sourceItem => { const s = GET_NAME_USERNAME_PROPERTY(sourceItem); const t = GET_NAME_USERNAME_PROPERTY(item); if (s === t) return true; if (item.slug && typeof s === "string") return item.slug === s || item.slug === s.toLowerCase(); return false; })
192+
return !source.some(sourceItem => GET_NAME_USERNAME_PROPERTY(item) === GET_NAME_USERNAME_PROPERTY(sourceItem))
188193
} else {
189194
return !source.includes(item)
190195
}
@@ -222,7 +227,7 @@ class MergeDeep {
222227
// Elements that are not in target are additions
223228
additions[key] = combined.filter(item => {
224229
if (this.isObjectNotArray(item)) {
225-
return !target.some(targetItem => { const s = GET_NAME_USERNAME_PROPERTY(item); const t = GET_NAME_USERNAME_PROPERTY(targetItem); if (s === t) return true; if (targetItem.slug && typeof s === "string") return targetItem.slug === s || targetItem.slug === s.toLowerCase(); return false; })
230+
return !target.some(targetItem => GET_NAME_USERNAME_PROPERTY(item) === GET_NAME_USERNAME_PROPERTY(targetItem))
226231
} else {
227232
return !target.includes(item)
228233
}
@@ -233,7 +238,7 @@ class MergeDeep {
233238
// Elements that not in source are deletions
234239
deletions[key] = combined.filter(item => {
235240
if (this.isObjectNotArray(item)) {
236-
return !source.some(sourceItem => { const s = GET_NAME_USERNAME_PROPERTY(sourceItem); const t = GET_NAME_USERNAME_PROPERTY(item); if (s === t) return true; if (item.slug && typeof s === "string") return item.slug === s || item.slug === s.toLowerCase(); return false; })
241+
return !source.some(sourceItem => GET_NAME_USERNAME_PROPERTY(item) === GET_NAME_USERNAME_PROPERTY(sourceItem))
237242
} else {
238243
return !source.includes(item)
239244
}
@@ -249,7 +254,11 @@ class MergeDeep {
249254
additions.push({})
250255
deletions.push({})
251256
if (visited[id]) {
252-
this.compareDeep(a, visited[id], additions[additions.length - 1], modifications[modifications.length - 1], deletions[deletions.length - 1])
257+
// Strip the identity field before comparing — it was already used for matching
258+
const idProp = NAME_USERNAME_PROPERTY(a) || NAME_USERNAME_PROPERTY(visited[id])
259+
const targetObj = idProp ? Object.fromEntries(Object.entries(a).filter(([k]) => k !== idProp)) : a
260+
const sourceObj = idProp ? Object.fromEntries(Object.entries(visited[id]).filter(([k]) => k !== idProp)) : visited[id]
261+
this.compareDeep(targetObj, sourceObj, additions[additions.length - 1], modifications[modifications.length - 1], deletions[deletions.length - 1])
253262
}
254263
// Any addtions for the matching key must be moved to modifications
255264
const lastAddition = additions[additions.length - 1]

0 commit comments

Comments
 (0)