Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
65 changes: 65 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copyright 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

# Pilot configuration (verification on this repository only; fleet rollout
# is decided after evaluation). Requires the CodeRabbit GitHub App to be
# installed on the organization.
language: "en-US"

reviews:
profile: "chill"
request_changes_workflow: false
high_level_summary: true
poem: false
review_status: true
auto_review:
enabled: true
# Drafts included during the pilot so the open TRI-1100 PR gets
# reviewed; revisit (likely false) before any fleet rollout.
drafts: true
path_instructions:
- path: ".github/workflows/*.yml"
instructions: |
These workflows are consumed org-wide (reusable workflows pinned by
tag). Review github-script blocks for correctness and injection
safety, and flag any behavior change that would require a new tag
and consumer rev bumps.
- path: "tools/*.py"
instructions: |
This tooling runs as a centralized pre-commit hook in consumer
repositories with cwd set to the consumer repo root. It must never
modify LICENSE files and must keep license headers out of .github/
templates.
- path: "ISSUE_TEMPLATE/**"
instructions: |
Org-wide inherited defaults. Issue reporting must keep routing to
the server repository; frontmatter must stay the first line of any
template file.

chat:
auto_reply: true
42 changes: 42 additions & 0 deletions .github/workflows/conventional-pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Self-check: run this repository's own reusable conventional-pr workflow
# on its own pull requests (local path reference uses the PR's version).

name: conventional-pr-check

on:
pull_request:
types: [opened, edited, synchronize, reopened]

jobs:
conventional-pr:
permissions:
pull-requests: write
issues: write
contents: read
uses: ./.github/workflows/conventional-pr.yml
181 changes: 181 additions & 0 deletions .github/workflows/conventional-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Reusable workflow: validates the PR title against the Conventional Commits
# format (<type>: <Title>), labels the PR with its commit type (org-wide
# color scheme enforced), and labels cherry-pick PRs (detected via the
# `git cherry-pick -x` commit trailer or a title/branch hint).
# Call from a repo with:
#
# jobs:
# conventional-pr:
# uses: triton-inference-server/.github/.github/workflows/conventional-pr.yml@v1.1.0
#
# The caller must grant `permissions: pull-requests: write`.

name: conventional-pr

on:
workflow_call:

jobs:
validate-and-label:
runs-on: ubuntu-latest
permissions:
pull-requests: write
issues: write
contents: read
steps:
- name: Validate PR title and apply type label
uses: actions/github-script@v7
with:
script: |
// Conventional-commit type -> human-readable label, org-wide color,
// and description. Titles are validated against the type tokens;
// the friendlier label is what gets applied.
const TYPES = {
build: { label: 'build', color: 'c5def5',
description: 'Build system or external dependencies (build: PRs)' },
chore: { label: 'chore', color: 'fef2c0',
description: 'Maintenance work, no production code change (chore: PRs)' },
ci: { label: 'CI/CD', color: 'bfd4f2',
description: 'Continuous integration and workflow changes (ci: PRs)' },
docs: { label: 'documentation', color: '0075ca',
description: 'Improvements or additions to documentation (docs: PRs)' },
feat: { label: 'feature', color: 'a2eeef',
description: 'New feature or capability (feat: PRs)' },
fix: { label: 'fix', color: 'd73a4a',
description: 'Bug fix (fix: PRs)' },
perf: { label: 'performance', color: 'fbca04',
description: 'Performance improvement (perf: PRs)' },
refactor: { label: 'refactor', color: '5319e7',
description: 'Code change that neither fixes a bug nor adds a feature (refactor: PRs)' },
revert: { label: 'revert', color: 'b60205',
description: 'Reverts a previous change (revert: PRs)' },
style: { label: 'code style', color: 'f9d0c4',
description: 'Formatting and style-only changes (style: PRs)' },
test: { label: 'testing', color: '1d76db',
description: 'Adding or correcting tests (test: PRs)' },
};
const CHERRY = { label: 'cherry-pick', color: '006b75',
description: 'Cherry-picked from another branch' };
const types = Object.keys(TYPES);
const typeLabels = Object.values(TYPES).map((t) => t.label);
const { owner, repo } = context.repo;
const number = context.payload.pull_request.number;

// Create the label if missing, otherwise enforce the org color and
// description.
async function ensureLabel({ label: name, color, description }) {
try {
await github.rest.issues.createLabel(
{ owner, repo, name, color, description });
} catch (e) {
if (e.status !== 422) throw e; // 422 = already exists
const { data } = await github.rest.issues.getLabel({ owner, repo, name });
if (data.color.toLowerCase() !== color ||
(data.description || '') !== description) {
await github.rest.issues.updateLabel(
{ owner, repo, name, color, description });
}
}
}

// 1. Validate the PR title (the squash-merge commit title).
const title = context.payload.pull_request.title;
const match = title.match(/^(\w+)(\([^)]*\))?!?: .+/);
if (!match || !types.includes(match[1])) {
core.setFailed(
`PR title "${title}" does not follow the Conventional Commits ` +
`format "<type>: <Title>" with type one of: ${types.join(', ')}. ` +
'See https://www.conventionalcommits.org/');
return;
}

// 2. Derive the full type set: the title plus every conforming
// commit subject in the PR (merge commits are ignored).
const commits = await github.paginate(github.rest.pulls.listCommits,
{ owner, repo, pull_number: number, per_page: 100 });
const derived = new Set([match[1]]);
for (const c of commits) {
const subject = c.commit.message.split('\n', 1)[0];
if (/^Merge /.test(subject)) continue;
const m = subject.match(/^(\w+)(\([^)]*\))?!?: .+/);
if (m && types.includes(m[1])) derived.add(m[1]);
else core.warning(`Commit ${c.sha.slice(0, 9)} subject is not ` +
`a conventional commit: "${subject}"`);
}

const { data: current } = await github.rest.issues.listLabelsOnIssue(
{ owner, repo, issue_number: number });
// Fail-safe: no derivable type and no manually assigned type label.
if (derived.size === 0 &&
!current.some((l) => typeLabels.includes(l.name))) {
core.setFailed(
'No conventional commit type could be determined from the PR ' +
'title or its commits, and no type label is assigned.');
return;
}
Comment on lines +135 to +141

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Fail-safe condition is unreachable dead code

derived is initialised on line 121 as new Set([match[1]]), and the early return on lines 109–115 guarantees that match[1] is always a valid type token before execution reaches this point. Consequently derived.size is always ≥ 1 here and the derived.size === 0 branch can never fire. The fail-safe described in the PR description ("if no type is derivable … the check fails") is silently a no-op, so any future refactor that removes the new Set([match[1]]) initialiser would produce incorrect labels with no warning.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally defensive: the explicit requirement was 'if no type is derivable and none is manually assigned, fail'. Today the title gate makes the branch unreachable, but the fail-safe is load-bearing the moment the title requirement is ever relaxed (a direction that has been discussed). Keeping it, with this thread as the record of why.


// 3. Apply one label per derived type; drop stale auto-managed
// labels (incl. legacy raw-token names from earlier versions).
const wanted = [...derived].map((t) => TYPES[t].label);
for (const t of derived) await ensureLabel(TYPES[t]);
for (const l of current) {
if ((typeLabels.includes(l.name) || types.includes(l.name)) &&
!wanted.includes(l.name)) {
await github.rest.issues.removeLabel(
{ owner, repo, issue_number: number, name: l.name });
}
}
await github.rest.issues.addLabels(
{ owner, repo, issue_number: number, labels: wanted });
core.info(`Labeled: ${wanted.join(', ')}.`);

// 4. Cherry-pick detection: the standard `git cherry-pick -x`
// trailer in any commit, an explicit hint in the title/branch, or
// a trailing "(#N)" squash-merge reference to a DIFFERENT PR (the
// signature of cherry-picking an already squash-merged commit).
// Additive only - a manually applied label is never removed.
const trailer = /cherry[- ]?picked from commit [0-9a-f]{7,40}/i;
const hint = /cherry[- ]?pick/i;
const prRef = /\(#(\d+)\)$/;
const refersToOtherPr = (subject) => {
const m = subject.trim().match(prRef);
return m !== null && Number(m[1]) !== number;
};
const isCherryPick =
commits.some((c) => trailer.test(c.commit.message)) ||
hint.test(title) ||
hint.test(context.payload.pull_request.head.ref) ||
refersToOtherPr(title) ||
commits.some((c) => refersToOtherPr(c.commit.message.split('\n', 1)[0]));
if (isCherryPick) {
await ensureLabel(CHERRY);
await github.rest.issues.addLabels(
{ owner, repo, issue_number: number, labels: [CHERRY.label] });
core.info('Cherry-pick detected; labeled as "cherry-pick".');
}
54 changes: 54 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of NVIDIA CORPORATION nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

name: pre-commit

on:
pull_request:

jobs:
pre-commit:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v5.0.0
with:
fetch-depth: 2
- uses: actions/setup-python@v6.0.0
- uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
- name: Run pre-commit on the files modified by the PR
# Null-delimited so paths with spaces survive; --no-run-if-empty
# handles deletion-only PRs; deleted paths are filtered out before
# being handed to pre-commit.
run: |
python -m pip install --quiet pre-commit
git diff --name-only -z --diff-filter=d HEAD^1 HEAD \
| xargs -0 --no-run-if-empty \
pre-commit run --show-diff-on-failure --color=always --files
Loading
Loading