Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a12bc11
ci: add hourly NVIDIA NIM PR maintenance scheduler
seonghobae Aug 5, 2026
b73fe34
ci: route hourly review repair to NVIDIA NIM autofix
seonghobae Aug 5, 2026
5007a33
ci: add NVIDIA NIM OpenCode review autofix worker
seonghobae Aug 5, 2026
5a653e9
test(ci): lock hourly NVIDIA NIM maintenance contracts
seonghobae Aug 5, 2026
bc56187
fix(ci): restore shared scheduler globals after NIM dispatch
seonghobae Aug 5, 2026
1d309e5
docs(ci): doctor hourly NVIDIA NIM repair architecture
seonghobae Aug 5, 2026
50b5768
docs: add central automation changelog
seonghobae Aug 5, 2026
93ffc8a
refactor(ci): make NIM scheduler import deterministic
seonghobae Aug 5, 2026
6b7c87f
fix(ci): make NIM scheduler runnable as a script
seonghobae Aug 5, 2026
b4ac90c
fix(ci): declare reusable scheduler GitHub write secrets
seonghobae Aug 5, 2026
a2691d1
test(ci): cover reusable secrets and wrapper cleanup
seonghobae Aug 5, 2026
b34834a
docs(ci): add primary TRINITY orchestration citation
seonghobae Aug 5, 2026
278a5f8
fix(ci): exchange OpenCode app token for cross-repository scheduling
seonghobae Aug 5, 2026
2ebda80
test(ci): lock OpenCode app-token scheduler fallback
seonghobae Aug 5, 2026
6c89cb1
merge(fix/trusted-uv-lock-coverage-clean): refresh NVIDIA NIM mainten…
seonghobae Aug 5, 2026
c73832a
fix(ci): minimize central scheduler token permissions
seonghobae Aug 5, 2026
e53efc8
test(ci): enforce central scheduler least privilege
seonghobae Aug 5, 2026
1ea0896
test(ci): define safe conflict-repair staging contract
seonghobae Aug 5, 2026
a2873cd
ci: repair NVIDIA NIM conflict staging once
seonghobae Aug 5, 2026
517a1de
ci: trigger one-shot NVIDIA NIM conflict repair
seonghobae Aug 5, 2026
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
189 changes: 189 additions & 0 deletions .github/workflows/nvidia-nim-pr-maintenance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
name: NVIDIA NIM PR Maintenance

on:
workflow_call:
inputs:
target_repository:
description: Repository to scan in owner/name form
required: false
default: ""
type: string
base_branch:
description: Base branch to scan; defaults to the caller repository default branch
required: false
default: ""
type: string
dry_run:
description: Print actions without dispatching an autofix
required: false
default: false
type: boolean
max_prs:
description: Maximum open pull requests to inspect
required: false
default: "50"
type: string
max_dispatches:
description: Maximum NVIDIA NIM autofix runs to dispatch
required: false
default: "1"
type: string
retry_hours:
description: Minimum hours before redispatching the same head
required: false
default: "1"
type: string
secrets:
PR_REVIEW_MERGE_TOKEN:
description: Optional cross-repository GitHub write token
required: false
OPENCODE_APPROVE_TOKEN:
description: Optional existing OpenCode GitHub write token fallback
required: false
repository_dispatch:
types: [nvidia-nim-pr-maintenance]
schedule:
- cron: "23 * * * *"

concurrency:
group: >-
nvidia-nim-pr-maintenance-${{
github.event.client_payload.target_repository || inputs.target_repository ||
vars.PR_REVIEW_FIX_TARGET_REPOSITORY || github.repository }}
cancel-in-progress: true

permissions: {}

jobs:
dispatch-review-fixes:
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
id-token: write
issues: read
pull-requests: read
statuses: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
TARGET_REPOSITORY: >-
${{ github.event.client_payload.target_repository || inputs.target_repository ||
vars.PR_REVIEW_FIX_TARGET_REPOSITORY || github.repository }}
DEFAULT_BRANCH: >-
${{ github.event.client_payload.base_branch || inputs.base_branch ||
vars.PR_REVIEW_FIX_BASE_BRANCH || github.event.repository.default_branch }}
DRY_RUN: >-
${{ github.event.client_payload.dry_run == true ||
github.event.client_payload.dry_run == 'true' || inputs.dry_run == true }}
MAX_PRS: ${{ github.event.client_payload.max_prs || inputs.max_prs || '50' }}
MAX_DISPATCHES: >-
${{ github.event.client_payload.max_dispatches || inputs.max_dispatches || '1' }}
RETRY_HOURS: ${{ github.event.client_payload.retry_hours || inputs.retry_hours || '1' }}
AUTOFIX_REPOSITORY: ContextualWisdomLab/.github
AUTOFIX_WORKFLOW: nvidia-nim-pr-review-autofix.yml
steps:
- name: Resolve immutable called-workflow source
id: trusted_source
env:
OIDC_AUDIENCE: cwl-nvidia-nim-pr-maintenance-source
run: |
set -euo pipefail
request_url="${ACTIONS_ID_TOKEN_REQUEST_URL}"
separator="&"
case "$request_url" in
*\?*) ;;
*) separator="?" ;;
esac
response="$(
curl -fsS \
-H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
"${request_url}${separator}audience=${OIDC_AUDIENCE}"
)"
token="$(jq -r '.value // empty' <<<"$response")"
[ -n "$token" ] || { echo "::error::OIDC token response was empty."; exit 1; }
payload_segment="$(cut -d. -f2 <<<"$token")"
case $((${#payload_segment} % 4)) in
2) payload_segment="${payload_segment}==" ;;
3) payload_segment="${payload_segment}=" ;;
esac
payload="$(printf '%s' "$payload_segment" | tr '_-' '/+' | base64 -d)"
source_sha="$(jq -r '.job_workflow_sha // .workflow_sha // empty' <<<"$payload")"
source_ref="$(jq -r '.job_workflow_ref // .workflow_ref // empty' <<<"$payload")"
if ! [[ "$source_sha" =~ ^[0-9a-fA-F]{40}$ ]]; then
echo "::error::Called workflow source did not resolve to an immutable SHA."
exit 1
fi
case "$source_ref" in
ContextualWisdomLab/.github/.github/workflows/nvidia-nim-pr-maintenance.yml@*) ;;
*) echo "::error::Unexpected called workflow source: ${source_ref:-missing}."; exit 1 ;;
esac
echo "sha=$source_sha" >>"$GITHUB_OUTPUT"

- name: Checkout immutable scheduler source
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: ContextualWisdomLab/.github
ref: ${{ steps.trusted_source.outputs.sha }}
fetch-depth: 1
persist-credentials: false

- name: Exchange OpenCode app token for scheduler writes
id: scheduler_app_token
env:
OIDC_AUDIENCE: opencode-github-action
OPENCODE_API_BASE_URL: https://api.opencode.ai
run: |
set -euo pipefail
mark_unavailable() {
echo "available=false" >>"$GITHUB_OUTPUT"
}
request_url="${ACTIONS_ID_TOKEN_REQUEST_URL}"
separator="&"
case "$request_url" in
*\?*) ;;
*) separator="?" ;;
esac
oidc_response="$(
curl -fsS \
-H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
"${request_url}${separator}audience=${OIDC_AUDIENCE}"
)" || { mark_unavailable; exit 0; }
oidc_token="$(jq -r '.value // empty' <<<"$oidc_response")"
[ -n "$oidc_token" ] || { mark_unavailable; exit 0; }
token_response="$(
curl -fsS \
-X POST \
-H "Authorization: Bearer ${oidc_token}" \
"${OPENCODE_API_BASE_URL}/exchange_github_app_token"
)" || { mark_unavailable; exit 0; }
app_token="$(jq -r '.token // empty' <<<"$token_response")"
[ -n "$app_token" ] || { mark_unavailable; exit 0; }
echo "::add-mask::$app_token"
{
echo "available=true"
echo "token=$app_token"
} >>"$GITHUB_OUTPUT"

- name: Self-test NVIDIA NIM scheduler contract
run: python3 scripts/ci/pr_review_fix_scheduler_nim.py --self-test

- name: Dispatch bounded NVIDIA NIM review repair
env:
GH_TOKEN: >-
${{ steps.scheduler_app_token.outputs.token || secrets.PR_REVIEW_MERGE_TOKEN ||
secrets.OPENCODE_APPROVE_TOKEN || github.token }}
run: |
set -euo pipefail
args=(
--repo "$TARGET_REPOSITORY"
--base-branch "$DEFAULT_BRANCH"
--max-prs "$MAX_PRS"
--max-dispatches "$MAX_DISPATCHES"
--retry-hours "$RETRY_HOURS"
--autofix-repository "$AUTOFIX_REPOSITORY"
--autofix-workflow "$AUTOFIX_WORKFLOW"
)
if [ "$DRY_RUN" = "true" ]; then
args+=(--dry-run)
fi
python3 scripts/ci/pr_review_fix_scheduler_nim.py "${args[@]}"
Loading
Loading