fix: update-discussion labels-only config must not mutate title or body#23273
fix: update-discussion labels-only config must not mutate title or body#23273
Conversation
…e or body Agent-Logs-Url: https://github.com/github/gh-aw/sessions/711a51ea-ad4b-4a70-9560-477629edd7dc Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com>
|
@copilot How are other safe outputs such as |
|
|
@copilot Investigate how labels only are updated and it is ensured title and body are not touched. |
Here's the full trace for a labels-only config ( 1. Compile time ( 2. // These conditions evaluate to false — title/body never enter updateData
if (config.allow_title === true && item.title !== undefined) { ... } // false
if (config.allow_body === true && item.body !== undefined) { ... } // false
// Only this runs
if (config.allow_labels === true && item.labels !== undefined) {
updateData.labels = labelsResult.value;
}
// → updateData = { labels: [...], _includeFooter: true }3. // Guard: skipped entirely because updateData.title and updateData.body are both undefined
if (updateData.title !== undefined || updateData.body !== undefined) {
// ← updateDiscussion GraphQL mutation — NOT called
}
// Only this runs:
if (updateData.labels !== undefined) {
await replaceDiscussionLabels(github, discussion.id, labelIds);
// Uses removeLabelsFromLabelable + addLabelsToLabelable mutations only
}So for a labels-only config, the |
|
@copilot Investigate if there is an issue on how label updates are handled. How are they passed? |
|
Hey One thing would really strengthen this PR before it lands:
If you'd like a hand, you can assign this prompt to your coding agent:
|
…o prevent silent truncation Agent-Logs-Url: https://github.com/github/gh-aw/sessions/ac912316-0d0c-4bd4-b434-a811126e4632 Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com>
Found a real bug in the label update path (commit e9437a7). The issue: Fix in // Before – maxCount defaults to 3, silently truncates 4–10 labels
const labelsResult = validateLabels(item.labels, allowedLabels.length > 0 ? allowedLabels : undefined);
// After – maxCount is MAX_LABELS (10), consistent with tryEnforceArrayLimit
const labelsResult = validateLabels(item.labels, allowedLabels.length > 0 ? allowedLabels : undefined, MAX_LABELS);The full label path for a labels-only config is:
Also added |
|
When
update-discussionis configured with onlylabels:orallowed-labels:, the handler was unconditionally calling theupdateDiscussionGraphQL mutation, sending the current title and body back as-is — an unnecessary write that violates the intended permission boundary.Changes
buildDiscussionUpdateData()— Title and body are now gated behindconfig.allow_title === true/config.allow_body === true, consistent with howupdate_issue.cjshandles body permission (config.allow_body !== false)buildDiscussionUpdateData()—validateLabelsis now called withMAX_LABELS(10) asmaxCount, fixing a bug where 4–10 labels would be silently truncated to 3 due to the defaultmaxCount = 3executeDiscussionUpdate()— TheupdateDiscussionGraphQL mutation is now skipped entirely when neitherupdateData.titlenorupdateData.bodyis set; only the label-replacement calls are madeupdate_discussion.test.cjscovering title/body permission gating, label permission gating,allowed_labelsfiltering,MAX_LABELSenforcement, and a regression test for themaxCounttruncation bugBefore / After
updateDiscussionmutation calledMAX_LABELS)✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.