From 17f89e35641c2cfae5c416aa0f53d393502b2cf7 Mon Sep 17 00:00:00 2001 From: Satya Nikhil Kodukula Date: Thu, 27 Aug 2026 13:23:20 -0400 Subject: [PATCH 1/3] [CI] Mirror PR title component tags as auto-managed labels --- .github/workflows/pr-title-tags.yaml | 92 +++++++++++++++++++---- .github/workflows/pr-welcome-comment.yaml | 4 +- CONTRIBUTE.md | 6 +- 3 files changed, 85 insertions(+), 17 deletions(-) diff --git a/.github/workflows/pr-title-tags.yaml b/.github/workflows/pr-title-tags.yaml index b1df88e710a..471ad2a3c01 100644 --- a/.github/workflows/pr-title-tags.yaml +++ b/.github/workflows/pr-title-tags.yaml @@ -1,15 +1,19 @@ -name: PR Title Tags +name: PR Title Tags & Labels -# Keeps PR-title component tags uniform ([Triton/Gluon], [HIP], [ASM], [CK], -# ...) and always in sync with the PR's changed files. +# Keeps PR-title component tags ([Triton/Gluon], [HIP], [ASM], [CK], ...) and +# the matching PR labels uniform and always in sync with the PR's changed +# files. The title is capped at 3 tags for readability; the labels carry the +# full component set. # # The diff is the source of truth: on every push, bracket tags in the # component namespace (any variant — [TRITON], [Gluon], [CK_TILE], # [Triton-Gluon-MLA-GFX950], ...) are recomputed from the changed files, so # dropped components disappear and new ones appear. Tags outside the # component namespace ([fix], [Perf], [MLA], [gfx1250], ...) are never -# touched. To opt a PR out entirely, add the 'no-auto-title' label — it takes -# effect immediately, and removing it re-syncs the title on the spot. +# touched. The same rule applies to labels: only the component labels listed +# in COMPONENT_LABELS are ever added or removed — human labels (ci:*, ...) +# are left alone. To opt a PR out entirely, add the 'no-auto-title' label — +# it takes effect immediately, and removing it re-syncs the PR on the spot. # # The tag set is documented in CONTRIBUTE.md ("PR Title Format") — keep the # two in sync when adding or renaming tags. @@ -25,6 +29,7 @@ on: permissions: pull-requests: write + issues: write # labels on PRs go through the issues API concurrency: group: pr-title-tags-${{ github.event.pull_request.number }} @@ -127,12 +132,73 @@ jobs: const newTitle = (add.map(t => `[${t}]`).join(' ') + ' ' + stripped).trim(); if (newTitle === original) { core.info(`Title already in sync (computed: ${JSON.stringify(tags)})`); - return; + } else { + core.info(`Retitling: "${original}" -> "${newTitle}"`); + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + title: newTitle, + }); + } + + // ---- labels: mirror the FULL computed component set (uncapped) ---- + // Only these labels are ever added or removed; anything else on + // the PR (ci:*, no-auto-title, ...) belongs to humans. + const COMPONENT_LABELS = { + 'Triton/Gluon': '1d76db', + 'ASM': '5319e7', + 'HIP': 'b60205', + 'CK': '0e8a16', + 'OPUS': 'fbca04', + 'FlyDSL': 'd93f0b', + 'CI': 'bfdadc', + 'JIT': 'c5def5', + 'Build': 'bfd4f2', + 'Config': 'f9d0c4', + 'Docs': '0075ca', + }; + const current = pr.labels + .map(l => l.name) + .filter(name => name in COMPONENT_LABELS); + const labelsToAdd = tags.filter(t => !current.includes(t)); + const labelsToRemove = current.filter(name => !tags.includes(name)); + + for (const name of labelsToAdd) { + // Make sure the label exists with our color; 422 = already exists. + try { + await github.rest.issues.createLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name, + color: COMPONENT_LABELS[name], + }); + } catch (e) { + if (e.status !== 422) throw e; + } + } + if (labelsToAdd.length) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + labels: labelsToAdd, + }); + } + for (const name of labelsToRemove) { + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + name, + }); + } catch (e) { + if (e.status !== 404) throw e; // already gone is fine + } + } + if (labelsToAdd.length || labelsToRemove.length) { + core.info(`Labels: +[${labelsToAdd}] -[${labelsToRemove}]`); + } else { + core.info('Labels already in sync.'); } - core.info(`Retitling: "${original}" -> "${newTitle}"`); - await github.rest.pulls.update({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: pr.number, - title: newTitle, - }); diff --git a/.github/workflows/pr-welcome-comment.yaml b/.github/workflows/pr-welcome-comment.yaml index 6c50995c099..2fd9e37d6ce 100644 --- a/.github/workflows/pr-welcome-comment.yaml +++ b/.github/workflows/pr-welcome-comment.yaml @@ -42,6 +42,6 @@ jobs: > Only add \`ci:atom_full\` for FlyDSL or Triton upgrades. > Add labels via the sidebar or \`gh pr edit ${context.issue.number} --add-label