Skip to content
Merged
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
163 changes: 163 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# SPDX-License-Identifier: Apache-2.0 AND CC-BY-4.0
# Copyright (c) 2026 NVIDIA Corporation. All rights reserved.

name: Agent Skills Sync Check

on:
schedule:
- cron: "0 8 * * *" # every day at 08:00 UTC
workflow_dispatch:
pull_request:
branches: [main]

jobs:
check-skills:
name: Verify skill counts match source repos
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
drifted: ${{ steps.sync.outputs.drifted }}
steps:
- uses: actions/checkout@v4

- name: Check skill directories in source repos
id: sync
env:
GH_TOKEN: ${{ secrets.PRIVATE_REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail

DRIFTED=0

# Format: "display_name|owner/repo|ref|skills_path[+extra_path]|expected_count"
REPOS=(
"cuOpt|NVIDIA/cuopt|main|skills|19"
"TensorRT-LLM|NVIDIA/TensorRT-LLM|main|.claude/skills|4"
"Model-Optimizer|NVIDIA/Model-Optimizer|main|.claude/skills|4"
"Megatron-Core|NVIDIA/Megatron-LM|main|.claude/skills|2"
"Megatron-Bridge|NVIDIA-NeMo/Megatron-Bridge|main|skills|8"
"Nemotron Voice Agent|NVIDIA-AI-Blueprints/nemotron-voice-agent|main|.agents/skills|1"
"NeMo Gym|NVIDIA-NeMo/Gym|main|.claude/skills|1"
"NeMo Evaluator|NVIDIA-NeMo/Evaluator|main|packages/nemo-evaluator-launcher/.claude/skills+packages/nemo-evaluator/.claude/skills|4"
)

REPORT="## Skill Catalog Sync Report\n\n"
REPORT+="| Product | Expected | Actual | Status |\n"
REPORT+="|---------|----------|--------|--------|\n"

declare -A UPDATES

count_skills_in_path() {
local repo="$1" ref="$2" path="$3"
local result
result=$(gh api "repos/${repo}/contents/${path}?ref=${ref}" \
--jq '[.[] | select(.type == "dir")] | length' 2>&1)
if [ $? -ne 0 ]; then
echo "ERR:${result}"
else
echo "$result"
fi
}

for entry in "${REPOS[@]}"; do
IFS='|' read -r label owner_repo ref skills_paths expected <<< "$entry"

# Sum skill counts across all paths (split on +)
actual=0
error_msg=""
IFS='+' read -ra PATHS <<< "$skills_paths"
for spath in "${PATHS[@]}"; do
count=$(count_skills_in_path "$owner_repo" "$ref" "$spath")
if [[ "$count" == ERR:* ]]; then
error_msg="${count#ERR:}"
break
fi
actual=$((actual + count))
done

if [ -n "$error_msg" ]; then
REPORT+="| $label | $expected | ERROR | :x: ${error_msg} |\n"
echo "::error::${label}: ${error_msg}"
DRIFTED=1
elif [ "$actual" -eq "$expected" ]; then
REPORT+="| $label | $expected | $actual | :white_check_mark: |\n"
else
REPORT+="| $label | $expected | $actual | :warning: DRIFT |\n"
UPDATES["$label"]="$expected:$actual"
DRIFTED=1
fi
done

echo -e "$REPORT"
echo -e "$REPORT" > /tmp/sync-report.md
echo "drifted=$DRIFTED" >> "$GITHUB_OUTPUT"

if [ "$DRIFTED" -ne 0 ]; then
echo "::error::Skill counts have drifted — update README.md to match source repos."

# Persist updates for the fix job
for label in "${!UPDATES[@]}"; do
echo "${label}=${UPDATES[$label]}"
done > /tmp/updates.txt
fi

- name: Upload sync artifacts
if: steps.sync.outputs.drifted == '1'
uses: actions/upload-artifact@v4
with:
name: sync-data
path: |
/tmp/sync-report.md
/tmp/updates.txt

- name: Fail check on drift
if: steps.sync.outputs.drifted == '1'
run: exit 1

fix-drift:
name: Create PR with corrected skill counts
needs: check-skills
if: needs.check-skills.outputs.drifted == '1' && github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4

- name: Download sync artifacts
uses: actions/download-artifact@v4
with:
name: sync-data
path: /tmp

- name: Update README.md with corrected counts
run: |
set -euo pipefail

while IFS='=' read -r label counts; do
IFS=':' read -r old_count new_count <<< "$counts"
# Escape spaces in label for sed; match bold product name in table row
escaped_label=$(echo "$label" | sed 's/ /[[:space:]]/g')
sed -i -E "s/(\*\*${escaped_label}\*\*[^|]*\|[^|]*\| *)${old_count}( *\|)/\1${new_count}\2/" README.md
done < /tmp/updates.txt

if git diff --quiet README.md; then
echo "::error::No changes to README.md after update — manual fix may be needed."
exit 1
fi

echo "README.md updated:"
git diff README.md

- name: Create pull request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "fix: update skill counts to match source repos"
branch: auto/sync-skill-counts
delete-branch: true
title: "fix: sync skill counts with source repos"
body-path: /tmp/sync-report.md
labels: automated
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ That's it — the skill activates automatically the next time your agent encount
|---------|-------------|:------:|-----------------|
| **cuOpt** | GPU-accelerated optimization — vehicle routing, linear programming, quadratic programming, installation, server deployment, and developer tools. | 19 | [`NVIDIA/cuopt/skills/`](https://github.com/NVIDIA/cuopt/tree/main/skills) |
| **TensorRT-LLM** | LLM inference optimization — model onboarding to AutoDeploy, CI pipeline failure analysis, and test failure diagnostics. | 4 | [`NVIDIA/TensorRT-LLM/.claude/skills/`](https://github.com/NVIDIA/TensorRT-LLM/tree/main/.claude/skills) |
| **Model Optimizer** | Model optimization — quantization, sparsity, and distillation for efficient inference. | 4 | [`NVIDIA/Model-Optimizer/.claude/skills/`](https://github.com/NVIDIA/Model-Optimizer/tree/main/.claude/skills) |
| **Megatron Core** | Large-scale distributed training — model parallelism, pipeline parallelism, and mixed precision. | 2 | [`NVIDIA/Megatron-LM/.claude/skills/`](https://github.com/NVIDIA/Megatron-LM/tree/main/.claude/skills) |
| **Megatron Bridge** | Bridge between NeMo and Megatron — data processing, model conversion, and training utilities. | 8 | [`NVIDIA-NeMo/Megatron-Bridge/skills/`](https://github.com/NVIDIA-NeMo/Megatron-Bridge/tree/main/skills) |
| **Model-Optimizer** | Model optimization — quantization, sparsity, and distillation for efficient inference. | 4 | [`NVIDIA/Model-Optimizer/.claude/skills/`](https://github.com/NVIDIA/Model-Optimizer/tree/main/.claude/skills) |
| **Megatron-Core** | Large-scale distributed training — model parallelism, pipeline parallelism, and mixed precision. | 2 | [`NVIDIA/Megatron-LM/.claude/skills/`](https://github.com/NVIDIA/Megatron-LM/tree/main/.claude/skills) |
| **Megatron-Bridge** | Bridge between NeMo and Megatron — data processing, model conversion, and training utilities. | 8 | [`NVIDIA-NeMo/Megatron-Bridge/skills/`](https://github.com/NVIDIA-NeMo/Megatron-Bridge/tree/main/skills) |
| **Nemotron Voice Agent** | Real-time conversational AI — deploy speech-to-speech voice agents on Workstation, Jetson Thor, or Cloud NIMs. | 1 | [`nemotron-voice-agent/.agents/skills/`](https://github.com/NVIDIA-AI-Blueprints/nemotron-voice-agent/tree/main/.agents/skills) |
| **NeMo Gym** | RL training environments — add benchmarks, resources servers, agent wiring, and reward profiling. | 1 | [`NVIDIA-NeMo/Gym/.claude/skills/`](https://github.com/NVIDIA-NeMo/Gym/tree/main/.claude/skills) |
| **NeMo Evaluator** | LLM evaluation — launch evaluations, access MLflow results, NeMo Evaluator Launcher assistant, and bring-your-own benchmarks. | 4 | [`NVIDIA-NeMo/Evaluator/.claude/skills/`](https://github.com/NVIDIA-NeMo/Evaluator/tree/main/packages/nemo-evaluator-launcher/.claude/skills) ([+1](https://github.com/NVIDIA-NeMo/Evaluator/tree/main/packages/nemo-evaluator/.claude/skills)) |
Expand All @@ -64,9 +64,9 @@ For skill-related issues, feature requests, new skill ideas, discussions, and co
|---------|--------|-------------|--------------|----------|
| **cuOpt** | [Issues](https://github.com/NVIDIA/cuopt/issues) | [Discussions](https://github.com/NVIDIA/cuopt/discussions) | [Contributing](https://github.com/NVIDIA/cuopt/blob/main/CONTRIBUTING.md) | [Security](https://github.com/NVIDIA/cuopt/blob/main/SECURITY.md) |
| **TensorRT-LLM** | [Issues](https://github.com/NVIDIA/TensorRT-LLM/issues) | [Discussions](https://github.com/NVIDIA/TensorRT-LLM/discussions) | [Contributing](https://github.com/NVIDIA/TensorRT-LLM/blob/main/CONTRIBUTING.md) | [Security](https://github.com/NVIDIA/TensorRT-LLM/blob/main/SECURITY.md) |
| **Model Optimizer** | [Issues](https://github.com/NVIDIA/Model-Optimizer/issues) | — | [Contributing](https://github.com/NVIDIA/Model-Optimizer/blob/main/CONTRIBUTING.md) | [Security](https://github.com/NVIDIA/Model-Optimizer/blob/main/SECURITY.md) |
| **Megatron Core** | [Issues](https://github.com/NVIDIA/Megatron-LM/issues) | [Discussions](https://github.com/NVIDIA/Megatron-LM/discussions) | [Contributing](https://github.com/NVIDIA/Megatron-LM/blob/main/CONTRIBUTING.md) | — |
| **Megatron Bridge** | [Issues](https://github.com/NVIDIA-NeMo/Megatron-Bridge/issues) | [Discussions](https://github.com/NVIDIA-NeMo/Megatron-Bridge/discussions) | [Contributing](https://github.com/NVIDIA-NeMo/Megatron-Bridge/blob/main/CONTRIBUTING.md) | — |
| **Model-Optimizer** | [Issues](https://github.com/NVIDIA/Model-Optimizer/issues) | — | [Contributing](https://github.com/NVIDIA/Model-Optimizer/blob/main/CONTRIBUTING.md) | [Security](https://github.com/NVIDIA/Model-Optimizer/blob/main/SECURITY.md) |
| **Megatron-Core** | [Issues](https://github.com/NVIDIA/Megatron-LM/issues) | [Discussions](https://github.com/NVIDIA/Megatron-LM/discussions) | [Contributing](https://github.com/NVIDIA/Megatron-LM/blob/main/CONTRIBUTING.md) | — |
| **Megatron-Bridge** | [Issues](https://github.com/NVIDIA-NeMo/Megatron-Bridge/issues) | [Discussions](https://github.com/NVIDIA-NeMo/Megatron-Bridge/discussions) | [Contributing](https://github.com/NVIDIA-NeMo/Megatron-Bridge/blob/main/CONTRIBUTING.md) | — |
| **Nemotron Voice Agent** | [Issues](https://github.com/NVIDIA-AI-Blueprints/nemotron-voice-agent/issues) | [Discussions](https://github.com/NVIDIA-AI-Blueprints/nemotron-voice-agent/discussions) | [Contributing](https://github.com/NVIDIA-AI-Blueprints/nemotron-voice-agent/blob/main/CONTRIBUTING.md) | [Security](https://github.com/NVIDIA-AI-Blueprints/nemotron-voice-agent/blob/main/SECURITY.md) |
| **NeMo Gym** | [Issues](https://github.com/NVIDIA-NeMo/Gym/issues) | [Discussions](https://github.com/NVIDIA-NeMo/Gym/discussions) | [Contributing](https://github.com/NVIDIA-NeMo/Gym/blob/main/CONTRIBUTING.md) | [Security](https://github.com/NVIDIA-NeMo/Gym/blob/main/SECURITY.md) |
| **NeMo Evaluator** | [Issues](https://github.com/NVIDIA-NeMo/Evaluator/issues) | [Discussions](https://github.com/NVIDIA-NeMo/Evaluator/discussions) | [Contributing](https://github.com/NVIDIA-NeMo/Evaluator/blob/main/CONTRIBUTING.md) | [Security](https://github.com/NVIDIA-NeMo/Evaluator/blob/main/SECURITY.md) |
Expand Down