Explorar el Código

fix(triage): respect manual game/engine labels and skip closed issues (#5097)

The triage bot re-added game and engine labels a maintainer removed by
hand, because removing a label triggers the job again and it re-derives
them from the issue text. It also ran on closed issues.

Only run the label jobs on open issues, and keep a game/engine label as
a person last left it (removed or added), like the Linux support label
override. The backfill job follows the same rule.
Daniel Gibbs hace 11 horas
padre
commit
abff9471ce
Se han modificado 1 ficheros con 65 adiciones y 6 borrados
  1. 65 6
      .github/workflows/action-issue-triage-automation.yml

+ 65 - 6
.github/workflows/action-issue-triage-automation.yml

@@ -69,7 +69,7 @@ env:
 
 jobs:
   issue-regex-labeler:
-    if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' && (github.event.action == 'opened' || github.event.action == 'edited')
+    if: github.repository_owner == 'GameServerManagers' && github.event_name == 'issues' && github.event.issue.state == 'open' && (github.event.action == 'opened' || github.event.action == 'edited')
     runs-on: ubuntu-latest
     steps:
       - name: Issue Labeler
@@ -82,7 +82,7 @@ jobs:
           sync-labels: 0
 
   issue-ai-maintenance:
-    if: github.repository_owner == 'GameServerManagers' && (github.event_name == 'issues' || github.event_name == 'issue_comment')
+    if: github.repository_owner == 'GameServerManagers' && (github.event_name == 'issues' || github.event_name == 'issue_comment') && github.event.issue.state == 'open'
     runs-on: ubuntu-latest
     steps:
       - name: Reconcile issue labels and AI triage
@@ -819,8 +819,37 @@ jobs:
             }
 
             // Avoid pointless API calls.
-            const finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
-            const finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+            let finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
+            let finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+
+            const isGameOrEngineLabel = (label) => label.startsWith('game: ') || label.startsWith('engine: ');
+            if ([...finalAdds, ...finalRemoves].some(isGameOrEngineLabel)) {
+              try {
+                const issueEvents = await github.paginate(github.rest.issues.listEvents, {
+                  owner,
+                  repo,
+                  issue_number: issueNumber,
+                  per_page: 100,
+                });
+                const lastManualLabelEvent = new Map();
+                for (const e of issueEvents) {
+                  if (!['labeled', 'unlabeled'].includes(e.event) || !e.label?.name) continue;
+                  lastManualLabelEvent.set(e.label.name, e.actor?.type === 'Bot' ? null : e.event);
+                }
+                finalAdds = finalAdds.filter((label) => {
+                  if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'unlabeled') return true;
+                  console.log(`Label "${label}" was removed manually; not adding it back.`);
+                  return false;
+                });
+                finalRemoves = finalRemoves.filter((label) => {
+                  if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'labeled') return true;
+                  console.log(`Label "${label}" was added manually; keeping it.`);
+                  return false;
+                });
+              } catch (err) {
+                console.log(`Could not read issue events: ${err.message}`);
+              }
+            }
 
             for (const label of finalRemoves) {
               try {
@@ -2199,8 +2228,38 @@ jobs:
                 }
 
                 // Apply changes
-                const finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
-                const finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+                let finalAdds = [...labelsToAdd].filter((label) => !existingLabels.has(label));
+                let finalRemoves = [...labelsToRemove].filter((label) => existingLabels.has(label));
+
+                const isGameOrEngineLabel = (label) => label.startsWith('game: ') || label.startsWith('engine: ');
+                if ([...finalAdds, ...finalRemoves].some(isGameOrEngineLabel)) {
+                  try {
+                    const issueEvents = await github.paginate(github.rest.issues.listEvents, {
+                      owner,
+                      repo,
+                      issue_number: rawIssue.number,
+                      per_page: 100,
+                    });
+                    const lastManualLabelEvent = new Map();
+                    for (const e of issueEvents) {
+                      if (!['labeled', 'unlabeled'].includes(e.event) || !e.label?.name) continue;
+                      lastManualLabelEvent.set(e.label.name, e.actor?.type === 'Bot' ? null : e.event);
+                    }
+                    finalAdds = finalAdds.filter((label) => {
+                      if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'unlabeled') return true;
+                      console.log(`#${rawIssue.number}: "${label}" was removed manually; not adding it back`);
+                      return false;
+                    });
+                    finalRemoves = finalRemoves.filter((label) => {
+                      if (!isGameOrEngineLabel(label) || lastManualLabelEvent.get(label) !== 'labeled') return true;
+                      console.log(`#${rawIssue.number}: "${label}" was added manually; keeping it`);
+                      return false;
+                    });
+                  } catch (err) {
+                    if (isApiRateLimitError(err)) throw err;
+                    console.log(`#${rawIssue.number}: could not read issue events: ${err.message}`);
+                  }
+                }
 
                 let labelAdded = 0;
                 let labelRemoved = 0;