Guide CI/CD
Structure du pipeline CI
Le workflow principal est .github/workflows/cicd-main.yml. Il se déclenche sur les push vers les branches correspondant à pull-request/[0-9]+ et deploy-release/*, sur les merge groups, sur un planning quotidien, et sur un envoi manuel.
is-not-external-contributor
└─ pre-flight
└─ configure # détermine scope, container tag, n_repeat
├─ linting
├─ cicd-container-build
│ ├─ cicd-parse-unit-tests → cicd-unit-tests-latest
│ ├─ cicd-parse-integration-tests-h100 → cicd-integration-tests-latest-h100
│ └─ cicd-parse-integration-tests-gb200 → cicd-integration-tests-latest-gb200 (maintainers only)
└─ Nemo_CICD_Test # porte de validation finale pass/fail
Les images sont poussées vers :
- AWS ECR :
766267172432.dkr.ecr.us-east-1.amazonaws.com/… - GCP Artifact Registry :
us-east4-docker.pkg.dev/nv-projdgxchipp-20260113193621/megatron-lm/…
Labels de périmètre des tests CI
Le pipeline CI lit les labels des PR pour décider du périmètre de test, n_repeat et de l'image container.
Arbre de décision (premier match gagne) :
| Condition | scope |
n_repeat |
lightweight |
Notes |
|---|---|---|---|---|
| Merge group | mr-github |
1 | false | Automatique, aucun label requis |
Label : Run tests |
mr-github |
1 | true | Entraîne 4 étapes, pas de comparaison golden-value |
Label : Run functional tests |
mr-github |
5 | false | Entraîne 100 étapes, comparaison golden-value |
| (aucun label) | mr-github-slim |
5 | false | Sous-ensemble slim uniquement |
Label d'image orthogonal :
| Label | Effet |
|---|---|
container::lts |
Utilise l'image de base LTS à la place de dev (combinable avec n'importe quel label de scope) |
Run MBridge tests |
Déclenche également la suite de tests MBridge L1 |
Quel label attacher à l'ouverture d'une PR
| Chemins modifiés / nature du changement | Label à attacher |
|---|---|
Docs uniquement (docs/, *.md, docstrings) |
(aucun) |
CI/tooling uniquement (.github/, tools/, Makefile) |
(aucun) |
Fichiers de test uniquement (tests/) — tests existants, sans nouvelles golden values |
Run tests |
| Nouveaux cas de test ajoutés (pas de golden values existantes) | Run functional tests |
Réactivation d'un test désactivé (scope -broken → actif) |
Run functional tests |
| Code de bibliothèque non-numérique (logging, gestion d'erreurs, flags CLI, refactors) | Run tests |
| Pourrait affecter la numérologie d'entraînement (arch du modèle, attention, optimizer, distribué, MoE routing) | Run functional tests |
Changements de container ou de dépendances (docker/, pyproject.toml, uv.lock) |
Run tests + container::lts |
| Touche l'intégration MBridge | ajouter Run MBridge tests |
Règle d'or : par défaut, utilisez Run tests. Utilisez toujours Run functional tests quand la PR ajoute de nouveaux cas de test (les golden values doivent être générées) ou quand le changement pourrait plausiblement décaler les courbes de loss.
Déclencher le CI interne
Utilisez tools/trigger_internal_ci.py pour pousser la branche actuelle vers le remote GitLab interne et déclencher un pipeline — sans toucher à l'interface GitLab.
Détails complets de configuration et d'utilisation : @tools/trigger_internal_ci.md.
Prérequis (une seule fois) :
# 1. Ajouter le remote GitLab interne
git remote add gitlab git@<gitlab-hostname>:ADLR/Megatron-LM.git
# 2. Créer un personal access token avec le scope 'api' sur votre profil GitLab,
# puis le stocker :
export GITLAB_TOKEN=glpat-<your-token>
Utilisation :
python tools/trigger_internal_ci.py \
--gitlab-origin gitlab \
[--functional-test-scope mr] \
[--functional-test-repeat 5] \
[--functional-test-cases all] \
[--dry-run]
Le script fait un force-push de la branche actuelle sous la forme pull-request/<branch> et affiche l'URL du pipeline résultant.
Investigation des défaillances CI
Les branches CI suivent toujours le pattern pull-request/<number>.
Localiser la PR à partir d'une branche CI
# Extraire le numéro de PR de la branche actuelle
PR_NUMBER=$(git rev-parse --abbrev-ref HEAD | grep -oP '(?<=pull-request/)\d+')
# Récupérer les métadonnées de la PR (titre, labels, auteur, branche de base)
gh pr view "$PR_NUMBER" --repo NVIDIA/Megatron-LM
# Afficher le changeset pour cette PR
gh pr diff "$PR_NUMBER" --repo NVIDIA/Megatron-LM
Lire les logs des jobs CI
# Lister les exécutions de workflow récentes pour la PR
gh run list --repo NVIDIA/Megatron-LM --branch "pull-request/$PR_NUMBER"
# Diffuser la sortie du job en défaillance
gh run view <run-id> --repo NVIDIA/Megatron-LM --log-failed
Les logs complets par rang ne sont pas dans le stdout du runner. Ils sont uploadés comme des artifacts GitHub nommés logs-<test_case>-<run_id>-<uuid>.
# 1. Trouver le nom de l'artifact
gh run view <run-id> --repo NVIDIA/Megatron-LM --json artifacts \
--jq '.artifacts[].name'
# 2. Télécharger le zip de l'artifact
gh run download <run-id> --repo NVIDIA/Megatron-LM \
--name "logs-<artifact-name>" -D ./ci-logs
# 3. Localiser quels logs de rang contiennent des erreurs
grep -r -l "ERROR\|Traceback\|FAILED\|fatal" ./ci-logs/
# 4. Les fichiers logs peuvent dépasser 10 000 lignes — ne jamais lire un log complet en une seule fois.
wc -l ./ci-logs/<test>/<attempt>/attempt_0/<rank>/stderr.log
sed -n '1,200p' ./ci-logs/.../stderr.log # lire par chunks
Identifier la cause racine de la défaillance
- Défaillance de linting — réexécutez
tools/autoformat.shlocalement ; le diff montre exactement ce qui doit changer. - Défaillance de build de container — inspectez le log du job
cicd-container-build. - Défaillance de test unitaire — le bucket en défaillance se trouve dans la matrice du job
cicd-unit-tests-latest. - Défaillance de test fonctionnel — regardez le job
cicd-integration-tests-*. Commencez parstdout.logpour le rang 0. - Test instable — le runner réessaie automatiquement jusqu'à 3 fois. Si tous les tentatives sont épuisées et que le pattern correspond à un transitoire connu (NCCL, ECC, segfault), c'est du bruit d'infrastructure.
Corréler une défaillance avec le changeset de la PR
# Trouver les tests unitaires qui couvrent un fichier source modifié
grep -r "from megatron.core.transformer.attention" tests/unit_tests/ -l
# Vérifier CODEOWNERS pour l'assignation du revieweur
cat .github/CODEOWNERS | grep "<changed-path>"