Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 79 additions & 13 deletions .github/workflows/pr-title-tags.yaml
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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 }}
Expand Down Expand Up @@ -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) ----
Comment thread
Boss2002n marked this conversation as resolved.
Resolved
// 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,
Comment thread
Boss2002n marked this conversation as resolved.
Resolved
});
}
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,
});
4 changes: 2 additions & 2 deletions .github/workflows/pr-welcome-comment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <label>\`

**PR title tags:**
Component tags (\`[Triton/Gluon]\`, \`[HIP]\`, \`[CK]\`, \`[ASM]\`, ...) are added to the PR title automatically from the changed files and re-synced on every push — change-type tags like \`[fix]\`/\`[Perf]\` and op tags like \`[MLA]\` are left untouched. Add the \`no-auto-title\` label to opt this PR out of title tagging.`
**PR title tags & labels:**
Component tags (\`[Triton/Gluon]\`, \`[HIP]\`, \`[CK]\`, \`[ASM]\`, ...) are added to the PR title and as PR labels automatically from the changed files and re-synced on every push — change-type tags like \`[fix]\`/\`[Perf]\`, op tags like \`[MLA]\`, and human labels (\`ci:*\`) are left untouched. Add the \`no-auto-title\` label to opt this PR out.`
});
6 changes: 4 additions & 2 deletions CONTRIBUTE.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,10 @@ PR titles carry two kinds of bracket tags.
**Component tags — applied automatically.** A GitHub Action
(`.github/workflows/pr-title-tags.yaml`) derives these from the files the PR
changes and keeps them in sync on every push, so you don't need to add them
yourself. Hand-written variants (`[TRITON]`, `[Gluon]`, `[CK_TILE]`, `[Doc]`,
...) are normalized to the canonical forms:
yourself. The same components are also applied as PR labels (the title shows
at most three; the labels carry the full set). Hand-written variants
(`[TRITON]`, `[Gluon]`, `[CK_TILE]`, `[Doc]`, ...) are normalized to the
canonical forms:

* `[Triton/Gluon]` - Triton/Gluon kernels (`aiter/ops/triton/`, `aiter/aot/triton/`, triton tests and benchmarks)
* `[ASM]` - assembly kernels (`hsa/`, `*_asm.py`)
Expand Down
Loading