-
Notifications
You must be signed in to change notification settings - Fork 2
ci: org-wide defaults - templates, issue routing, hooks, and reusable workflows #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
cc977ce
ci: add org-wide defaults and reusable conventional-pr workflow
mc-nv de133b0
ci: consolidate centralized hooks into this repository
mc-nv 85ab521
ci: enforce org-wide label colors and detect cherry-pick PRs
mc-nv 355dd17
ci: apply human-readable type labels with descriptions
mc-nv 054fc99
ci: keep the fix type label literal and clean up legacy type labels
mc-nv 6cc271f
ci: label feat PRs as 'feature'
mc-nv ea73a0f
docs: keep the Commit Type checklist in the external PR template
mc-nv 80887c1
ci: label PRs from all conforming commit types
mc-nv e08e347
ci: detect cherry-picks of squash-merged commits
mc-nv 4489ed7
chore: add BSD-3-Clause LICENSE and enable the add-license hook on th…
mc-nv 898e8cc
ci: add CodeRabbit pilot configuration
mc-nv 1a8388b
ci: fail add-license when the LICENSE copyright year is stale
mc-nv 6698584
ci: license-process .github/workflows, exclude only templates
mc-nv cd67f38
ci: grant issues:write to the conventional-pr labeling job
mc-nv 76ff555
ci: address fleet-wide review findings
mc-nv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } | ||
|
|
||
| // 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".'); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
derivedis initialised on line 121 asnew Set([match[1]]), and the early return on lines 109–115 guarantees thatmatch[1]is always a valid type token before execution reaches this point. Consequentlyderived.sizeis always ≥ 1 here and thederived.size === 0branch 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 thenew 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!
There was a problem hiding this comment.
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.