2. Compiler et tester .NET et Java
Sections
Réglages de lecture
Voix naturelle enregistrée pour ce cours, la même dans tous les navigateurs.
Aucune voix pour cette langue dans ce navigateur.
Plus de voix
Code et termes techniques en anglais
Désactivé : la voix de la page lit tout, sans pause entre deux voix.
Aucune voix pour cette langue dans ce navigateur.
Plus de voix
D’autres voix : Microsoft Edge propose des voix naturelles en ligne, et Windows (Paramètres › Heure et langue › Voix), macOS et Android en installent d’autres.
Le projet
Section intitulée « Le projet »code/github-actions contient deux fois la même petite fonction — transformer un titre en slug d’URL — avec quatre tests de chaque côté :
| .NET | Java | |
|---|---|---|
| Code | dotnet/Slugs/Slug.cs |
java/src/main/java/com/example/slugs/Slug.java |
| Tests | xUnit v3 [Theory] + [InlineData] |
JUnit 6 @ParameterizedTest + @CsvSource |
| Commande | dotnet test |
mvn -B verify |
| SDK fixé par | global.json |
maven.compiler.release dans pom.xml |
Extrait de dotnet/Slugs.Tests/SlugTests.cs, lignes 8-14 :
[Theory][InlineData("Hello, Wörld!", "hello-world")][InlineData(" GitHub Actions ", "github-actions")][InlineData("C# 14 & .NET 10", "c-14-net-10")][InlineData("", "")]public void From_builds_a_lowercase_ascii_slug(string text, string expected) => Assert.Equal(expected, Slug.From(text));Avant tout YAML : ça doit passer en local, avec les mêmes commandes que la CI. C’est là que sont apparus les deux premiers pièges de cette leçon.
Piège 1 : xUnit v3 et dotnet test avec le SDK .NET 10
Section intitulée « Piège 1 : xUnit v3 et dotnet test avec le SDK .NET 10 »Avec xunit.v3 4.0.1, le premier dotnet test a échoué avant d’exécuter quoi que ce soit :
error : Testing with VSTest target is no longer supported by Microsoft.Testing.Platform on .NET 10 SDK and later. If you use dotnet test, you should opt-in to the new dotnet test experience. For more information, see https://aka.ms/dotnet-test-mtp-errorxUnit v3 s’exécute sur Microsoft.Testing.Platform, et le SDK .NET 10 veut que tu actives explicitement le nouveau dotnet test, dans global.json (dotnet/global.json) :
{ "sdk": { "version": "10.0.100", "rollForward": "latestFeature" }, "test": { "runner": "Microsoft.Testing.Platform" }}Piège 2 : pas de using Xunit implicite
Section intitulée « Piège 2 : pas de using Xunit implicite »Erreur suivante :
CS0246: The type or namespace name 'Theory' could not be found (are you missing a using directive or an assembly reference?)CS0246: The type or namespace name 'InlineData' could not be found (are you missing a using directive or an assembly reference?)Avec ImplicitUsings activé, ce paquet 4.0.1 n’ajoutait pas Xunit aux usings globaux : le fichier de test a besoin de using Xunit;. Ensuite :
Test run summary: Passed! total: 4 failed: 0 succeeded: 4 skipped: 0Le workflow
Section intitulée « Le workflow ».github/workflows/gha-02-build.yml :
# GitHub Actions course, lesson 2: build and test .NET and Java on three OSesname: "GHA 02: build and test"
on: workflow_dispatch: push: branches: [main] paths: ['code/github-actions/**', '.github/workflows/gha-02-build.yml'] pull_request: paths: ['code/github-actions/**', '.github/workflows/gha-02-build.yml']
jobs: dotnet: name: dotnet (${{ matrix.os }}) strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} defaults: run: working-directory: code/github-actions/dotnet steps: - uses: actions/checkout@v7 - uses: actions/setup-dotnet@v6 with: global-json-file: code/github-actions/dotnet/global.json - run: dotnet --version - run: dotnet test
java: name: java (${{ matrix.os }}) strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} defaults: run: working-directory: code/github-actions/java steps: - uses: actions/checkout@v7 - uses: actions/setup-java@v6 with: distribution: temurin java-version: '25' cache: maven - run: java --version - run: mvn -B verify| Élément | Effet |
|---|---|
strategy.matrix.os |
un job par valeur : 3 jobs dotnet et 3 jobs java, tous en parallèle |
fail-fast: false |
un échec sous Windows n’annule pas le job macOS encore en cours (la valeur par défaut, true, l’annule) |
name: dotnet (${{ matrix.os }}) |
le nom du job affiché dans l’exécution ; sans name, GitHub utilise l’id du job et toutes les valeurs de la matrix, par exemple java (ubuntu-latest, 22) |
defaults.run.working-directory |
chaque run: démarre dans ce dossier (les steps uses: ne sont pas concernés) |
actions/setup-dotnet avec global-json-file |
installe le SDK demandé par global.json |
actions/setup-java avec cache: maven |
installe Temurin 25 et met en cache ~/.m2/repository, avec une clé basée sur le hash de pom.xml |
mvn -B |
mode batch : pas de couleurs, pas de barres de progression des téléchargements dans le log |
Ce que montre l’exécution
Section intitulée « Ce que montre l’exécution »Les six jobs sont passés. Extraits :
dotnet (ubuntu-latest) | dotnet-install: Installed version is 10.0.401dotnet (ubuntu-latest) | 10.0.401java (ubuntu-latest) | Resolved Java 25.0.4+1 from tool-cachejava (ubuntu-latest) | openjdk 25.0.4.1 2026-08-18 LTSjava (ubuntu-latest) | [INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0java (ubuntu-latest) | [INFO] BUILD SUCCESSglobal.jsonindique10.0.100avecrollForward: latestFeature:setup-dotneta installé la dernière feature band 10.0, 10.0.401. Fixe"rollForward": "disable"si tu as besoin d’exactement un SDK.- Temurin 25 était déjà dans l’image Ubuntu (
from tool-cache) : aucun téléchargement.
Le shell n’est pas le même partout. Le même step run: dotnet test a journalisé :
dotnet (ubuntu-latest) | shell: /usr/bin/bash -e {0}dotnet (macos-latest) | shell: /bin/bash -e {0}dotnet (windows-latest) | shell: C:\Program Files\PowerShell\7\pwsh.EXE -command ". '{0}'"Sous Windows, run: utilise PowerShell 7 par défaut. dotnet test et mvn -B verify se comportent de la même façon dans les deux, mais pas un script avec $(pwd), export ou des enchaînements &&. Fixe defaults.run.shell: bash pour le job (Git Bash est installé sur les runners Windows) quand un script doit être identique sur les trois OS.
Le cache, mesuré
Section intitulée « Le cache, mesuré »La première exécution n’a trouvé aucun cache Maven et en a enregistré un ; une deuxième exécution (lancée avec gh workflow run gha-02-build.yml) l’a restauré (setup-java/src/cache.ts) :
maven cache is not foundCache saved with the key: setup-java-Linux-x64-maven-4b450ab7781caaed20d3b55ef20c4500aaacb6aad3f54b145929988a7515a1ebCache restored from key: setup-java-Linux-x64-maven-4b450ab7781caaed20d3b55ef20c4500aaacb6aad3f54b145929988a7515a1ebCache hit occurred on the primary key setup-java-Linux-x64-maven-4b450ab7781caaed20d3b55ef20c4500aaacb6aad3f54b145929988a7515a1eb, not saving cache.| Job | 1re exécution (sans cache) | 2e exécution (cache trouvé) |
|---|---|---|
| java (ubuntu-latest) | 16 s | 10 s |
| java (windows-latest) | 43 s | 28 s |
| java (macos-latest) | 20 s | 9 s |
| dotnet (ubuntu-latest) | 21 s | 22 s |
| dotnet (windows-latest) | 60 s | 57 s |
| dotnet (macos-latest) | 20 s | 22 s |
Les jobs .NET ne sont pas devenus plus rapides : rien ne met encore en cache les paquets NuGet. setup-dotnet a une option cache: true basée sur les fichiers packages.lock.json, mesurée dans la leçon 5. La clé contient l’OS (Linux-x64, Windows-x64, macOS-arm64) : chaque OS a son propre cache. Et macos-latest est une machine arm64.
À retenir
Section intitulée « À retenir »- Fais d’abord passer le build en local, avec exactement les commandes de la CI.
- Une
matrixmultiplie un job ;fail-fast: falselaisse chaque combinaison aller au bout. setup-dotnetlitglobal.json;setup-javainstalle un JDK et met en cache Maven ou Gradle.run:utilise bash sous Linux/macOS et PowerShell 7 sous Windows, sauf si tu fixesshell.- Mesure : un cache Maven trouvé a fait gagner ici de 6 à 15 secondes par job ; les jobs Windows sont les plus lents.
Exercices
Section intitulée « Exercices »- Ajoute
22à côté de25pour que le job Java s’exécute aussi sur Java 22, sur les trois OS. Combien de jobs Java vont s’exécuter ?
Solution
name: java ${{ matrix.java }} (${{ matrix.os }}) strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] java: ['25', '22'] steps: - uses: actions/setup-java@v6 with: distribution: temurin java-version: ${{ matrix.java }} cache: maven6 jobs (3 × 2). Mais le build échoue sur 22 : pom.xml fixe maven.compiler.release à 25. Vérifié avec gha-02-exercises.yml :
[INFO] BUILD FAILURE[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.15.0:compile (default-compile) on project slugs: Fatal error compiling: error: release version 25 not supported -> [Help 1]Une matrix teste des combinaisons ; le projet doit les prendre en charge.
- Tu veux que le job Windows exécute
dotnet testdans bash, comme les autres. Où places-tushell: bashpour qu’il s’applique à chaquerun:du job ?
Solution
defaults: run: shell: bash working-directory: code/github-actions/dotnetdefaults.run au niveau du job (ou au niveau du workflow pour tous les jobs). Sous Windows, le log affiche alors :
shell: C:\Program Files\Git\bin\bash.EXE --noprofile --norc -e -o pipefail {0}bash 5.3.15(2)-release, options ehBRemarque -o pipefail : un shell: bash explicite échoue aussi quand une commande au milieu d’un pipe échoue, ce que ne fait pas le bash -e {0} implicite des runners Linux.
- Sans
using Xunit;, quelle erreur la CI afficherait-elle, et sur combien de jobs ?
Solution
CS0246: The type or namespace name 'Theory' could not be found, sur les trois jobs dotnet. Avec fail-fast: false, les trois vont au bout ; avec la valeur par défaut fail-fast: true, le premier échec annule les autres jobs dotnet encore en cours — les jobs java viennent d’une autre définition de job, avec sa propre matrix, et ne sont pas concernés.