Skip to content

PR #1056 · internal CI dispatch #911

PR #1056 · internal CI dispatch

PR #1056 · internal CI dispatch #911

# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
name: TensorRT-Model-Connect Internal CI Bridge
run-name: >-
PR #${{ github.event.pull_request.number || inputs.pr_number }} · internal CI dispatch
on:
pull_request_target:
branches:
- main
types: [labeled]
workflow_dispatch:
inputs:
pr_number:
description: Open pull request number to test
required: true
type: string
permissions: {}
concurrency:
group: >-
trtmc-private-dispatch-${{ github.event.pull_request.number || inputs.pr_number }}
cancel-in-progress: false
jobs:
authorize:
name: Authorize trusted trigger
if: >-
github.repository == 'NVIDIA/TensorRT-Model-Connect' &&
(
github.event_name == 'workflow_dispatch' ||
(
github.event_name == 'pull_request_target' &&
github.ref == 'refs/heads/main' &&
github.event.label.name == 'run-internal-ci'
)
)
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
actions: read
contents: read
pull-requests: write
outputs:
pr_number: ${{ steps.snapshot.outputs.pr_number }}
head_sha: ${{ steps.snapshot.outputs.head_sha }}
steps:
# This trusted workflow reads PR metadata only. It never checks out or
# executes the pull-request head.
- name: Capture the exact pull-request head
id: snapshot
env:
GH_TOKEN: ${{ github.token }}
ACTOR: ${{ github.actor }}
PR_NUMBER: ${{ github.event.pull_request.number || inputs.pr_number }}
EVENT_NAME: ${{ github.event_name }}
EVENT_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail
[[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]]
# The legacy .permission field maps maintain to write. Use
# .role_name so maintainers remain distinct from write users.
actor_role="$(
gh api --method GET \
"/repos/$GITHUB_REPOSITORY/collaborators/$ACTOR/permission" \
--jq '.role_name'
)"
case "$actor_role" in
maintain|admin) ;;
*)
echo "::error::Only actors with maintain or admin access may dispatch CI."
exit 1
;;
esac
if [ "$EVENT_NAME" = "pull_request_target" ]; then
[[ "$EVENT_HEAD_SHA" =~ ^[0-9a-f]{40}$ ]]
fi
pull="$(gh api --method GET "/repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER")"
state="$(jq -er '.state' <<<"$pull")"
base_repo="$(jq -er '.base.repo.full_name' <<<"$pull")"
base_ref="$(jq -er '.base.ref' <<<"$pull")"
head_sha="$(jq -er '.head.sha' <<<"$pull")"
test "$state" = "open"
test "$base_repo" = "$GITHUB_REPOSITORY"
test "$base_ref" = "main"
[[ "$head_sha" =~ ^[0-9a-f]{40}$ ]]
if [ "$EVENT_NAME" = "pull_request_target" ] \
&& [ "$head_sha" != "$EVENT_HEAD_SHA" ]; then
echo "::error::The CI trigger was superseded by a newer PR head."
exit 1
fi
# This contributor-visible result is a readiness prerequisite. The
# maintainer-owned label and this default-branch workflow remain the
# authorization boundary for protected resources.
community_cpu_run="$(
gh api --method GET \
"/repos/$GITHUB_REPOSITORY/actions/workflows/community-cpu.yml/runs?event=pull_request&head_sha=$head_sha&per_page=100" \
--jq '.workflow_runs | map(select(.conclusion == "success")) | sort_by(.updated_at) | last | .id // empty'
)"
if ! [[ "$community_cpu_run" =~ ^[1-9][0-9]*$ ]]; then
echo "::error::Community CPU / Required must pass on the current PR head before internal CI can run."
exit 1
fi
{
echo "pr_number=$PR_NUMBER"
echo "head_sha=$head_sha"
} >> "$GITHUB_OUTPUT"
- name: Consume the trusted trigger label
if: ${{ success() && github.event_name == 'pull_request_target' }}
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
gh api --silent --method DELETE \
"/repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/labels/run-internal-ci"
dispatch:
name: Internal CI dispatch
needs: authorize
runs-on: ubuntu-24.04
environment:
name: ci-dispatch
deployment: false
timeout-minutes: 5
permissions: {}
steps:
- name: Dispatch internal premerge CI
env:
# Fine-grained PAT scoped only to the internal CI repository with
# Actions: write. The protected environment owns this secret.
GH_TOKEN: ${{ secrets.TRTMC_CI_DISPATCH_TOKEN }}
PRIVATE_CI_OWNER: ${{ secrets.TRTMC_PRIVATE_CI_OWNER }}
PRIVATE_CI_REPOSITORY: ${{ secrets.TRTMC_PRIVATE_CI_REPOSITORY }}
PR_NUMBER: ${{ needs.authorize.outputs.pr_number }}
HEAD_SHA: ${{ needs.authorize.outputs.head_sha }}
run: |
set -euo pipefail
[[ "$PRIVATE_CI_OWNER" =~ ^[A-Za-z0-9]([A-Za-z0-9-]{0,37}[A-Za-z0-9])?$ ]]
[[ "$PRIVATE_CI_REPOSITORY" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]{0,98}[A-Za-z0-9])?$ ]]
umask 077
payload="$RUNNER_TEMP/internal-ci-dispatch.json"
trap 'rm -f "$payload"' EXIT
jq -n \
--arg pr_number "$PR_NUMBER" \
--arg head_sha "$HEAD_SHA" \
'{
ref: "main",
inputs: {
pr_number: $pr_number,
head_sha: $head_sha
}
}' > "$payload"
gh api --silent --method POST \
"/repos/$PRIVATE_CI_OWNER/$PRIVATE_CI_REPOSITORY/actions/workflows/premerge.yml/dispatches" \
--input "$payload"