Construire et tester
- Leçon 5
- 45 min
- Module 2 : Créer un pipeline CI reproductible
Leçon 5 sur 15 · CI/CD, tests et mises en production sûresConstruire et tester
1. Comprendre le chemin de livraison
2. Créer un pipeline CI reproductible
3. Gérer les environnements et les secrets
4. Mettre en production les changements d'IA et de base de données
5. Rétablir et maintenir le processus de mise en production
Ce que vous saurez faire
Une exécution verte doit signifier quelque chose : les tests ont réussi, les paquets n’ont aucune vulnérabilité connue et l’image démarre et répond. Construisez cette image une seule fois, testez-la et conservez exactement celle-là.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- L’exécuteur propre, le cache et la première tâche, dans Configurer l’exécuteur : exemple détaillé : le premier flux de travail.
- pytest et les tests de l’API de billets de soutien, dans Tests automatisés des points de terminaison : testClient : des requêtes sans serveur du cours Vérifier et nettoyer : une vérification rapide.
- Une vérification de bon fonctionnement, dans Vérifier et nettoyer : une vérification de bon fonctionnement, du cours sur les API.
- Les noms d’images, les étiquettes et les empreintes, dans Registre et déploiement : Registre, dépôt et étiquette du cours L’essentiel de Docker et du nuage pour les développeurs en IA.
- Pourquoi le nuage exige
linux/amd64, dans Registre et déploiement : construire pour le processeur du nuage du cours sur Docker.
Ce qu’il vous faut sur votre ordinateur
- Votre dépôt
ticket-api-ciavec la première tâche et une exécution verte, dans Configurer l’exécuteur : exercice guidé. - Docker Desktop (ou Docker Engine sous Linux), dans Installer et vérifier : installer Docker du cours sur Docker, pour
scripts/check.sh. - Si votre projet manque ou ne fonctionne plus, copiez l’instantané
end-of-m01. Refaites ensuite Configurer l’exécuteur : exemple détaillé : le premier flux de travail. L’instantané n’a pas encore de flux de travail.
Exécuté avec GitHub Actions (exécuteurs ubuntu-24.04) dans le dépôt public Nextia-Intelligence/ticket-api-ci, et Docker Desktop 4.81.0 sous macOS (Apple silicon). Les étapes pour Windows et Linux n’ont pas été testées.
Les versions exactes, sur chaque exécuteur
Section intitulée « Les versions exactes, sur chaque exécuteur »La tâche installe les paquets depuis requirements-lock.txt, et non depuis requirements.txt :
- name: Install the exact versions run: python -m pip install -r requirements-lock.txtrequirements.txt indique ce dont le projet a besoin. Le fichier de verrouillage indique la version exacte de chaque paquet, y compris les paquets dont ceux-ci dépendent. Le journal de l’exécution verte énumère ce qui a été installé (extrait abrégé) :
Successfully installed CacheControl-0.14.4 ... fastapi-0.142.2 ... pip_audit-2.10.1 ... pytest-9.1.1 ... ruff-0.16.10 ... uvicorn-0.54.0 ...Chaque exécution installe ces mêmes versions jusqu’à ce que quelqu’un modifie le fichier de verrouillage dans un commit (enregistrement des changements). Une exécution rouge indique donc que le code ou le fichier de verrouillage a changé. Elle ne signale jamais qu’un paquet a publié une nouvelle version pendant la nuit. La nouvelle version arrive seulement quand vous la choisissez, dans un commit que le pipeline vérifie.
Des vérifications qui ont du sens
Section intitulée « Des vérifications qui ont du sens »Une vérification est utile quand elle peut échouer pour une raison importante pour les utilisateurs. L’analyse statique a trouvé deux vrais problèmes dans Configurer l’exécuteur. Ajoutez maintenant deux autres vérifications à la première tâche, après Lint (analyse statique) :
- name: Unit and contract tests run: python -m pytest --junitxml=reports/junit.xml - name: Security - known vulnerabilities in the image's packages run: pip-audit -r requirements-run.txt --progress-spinner offTests. pytest exécute les 25 tests des cours sur les API et sur Docker. Ils testent les points de terminaison, les entrées non valides et le classificateur qui échoue. Un test de contrat compare l’API à contract/openapi.json. --junitxml=reports/junit.xml écrit aussi les résultats dans un fichier au format JUnit XML, que de nombreux outils peuvent lire. Publier les preuves conserve ce fichier. Ajoutez reports/ à .gitignore, car ce fichier est une sortie, pas du code source.
Vérification de sécurité. pip-audit compare les paquets à une base de données publique de vulnérabilités connues. Il lit requirements-run.txt, les paquets que l’image installe, car ce sont ceux que les utilisateurs rencontrent. Les outils de développement, comme pytest, ne vont jamais dans l’image.
La sortie des deux étapes de l’exécution verte :
collected 25 items
tests/test_classify.py ............... [ 60%]tests/test_contract.py .. [ 68%]tests/test_history.py ........ [100%]
- generated xml file: /home/runner/work/ticket-api-ci/ticket-api-ci/reports/junit.xml -============================== 25 passed in 0.42s ==============================No known vulnerabilities foundConnaissez aussi les limites. pip-audit voit seulement les paquets Python, pas les paquets Debian de l’image de base. Il trouve seulement les vulnérabilités déjà connues et publiées. Une réussite signifie « rien de connu aujourd’hui ». Exécutez-le donc à chaque changement.
Construire une seule fois, puis conserver cette construction
Section intitulée « Construire une seule fois, puis conserver cette construction »Les vérifications testent le code. Les utilisateurs reçoivent une image. Le pipeline doit donc aussi tester l’image, puis livrer cette image, pas une nouvelle.
Pourquoi ne pas reconstruire plus tard, par exemple une fois pour la préproduction et une fois pour la production? Amira fait le test sur son Mac. Elle construit deux fois le même commit, sans cache :
docker build -q --no-cache -t c19m02-ticket-api:a .docker build -q --no-cache -t c19m02-ticket-api:b .La sortie :
sha256:9f93ccc6caaab583c4b1b9dc8e4e892f86ee0d7e7bd0ca6b5bea94904e833618sha256:3a4656c8cadaab5acd3a8509580d9005626ac47a8f1385c6282c9645fd514256Même commit, même Dockerfile, deux images différentes. Chaque construction enregistre son heure. Une construction sans cache peut aussi télécharger un paquet ou une image de base plus récente. Une deuxième construction produit un nouvel artefact que personne n’a testé.
Description textuelle du diagramme
Dans le flux supérieur, une seule construction est testée et poussée. Chaque environnement suivant exécute exactement cette empreinte. Dans le flux inférieur, chaque environnement reçoit sa propre construction. L’image de production n’a jamais été testée. Personne ne peut prouver qu’elle est identique à l’image de préproduction, car son identifiant diffère. Les identifiants du bas proviennent des deux constructions locales ci-dessus. L’empreinte du haut correspond à la vraie image poussée par le pipeline de référence. Le module 3 la promeut.
La tâche d’image
Section intitulée « La tâche d’image »La deuxième tâche construit l’image, la teste sur l’exécuteur et la pousse vers le GitHub Container Registry (GHCR, ghcr.io). Elle s’exécute seulement après la réussite des vérifications :
image: name: Build, smoke-test and push the image needs: checks runs-on: ubuntu-24.04 timeout-minutes: 15 permissions: contents: read packages: write env: IMAGE: ghcr.io/${{ github.repository }} PUSH: ${{ github.event_name != 'pull_request' }} steps: - uses: actions/checkout@v7 - uses: docker/setup-buildx-action@v4 - name: Read the version from pyproject.toml id: version run: python3 -c "import tomllib; print('version=' + tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])" >> "$GITHUB_OUTPUT" - name: Image names and labels id: meta uses: docker/metadata-action@v6 with: images: ${{ env.IMAGE }} tags: | type=sha,prefix=sha- type=semver,pattern={{version}} - name: Build (and keep it here for the smoke test) uses: docker/build-push-action@v7 with: context: . platforms: linux/amd64 load: true tags: ticket-api:candidate build-args: | VERSION=${{ steps.version.outputs.version }} REVISION=${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max - name: Smoke-test the image before it leaves this runner run: | docker run -d --name candidate -p 127.0.0.1:8000:8000 -e API_KEY=ci-smoke-key ticket-api:candidate for _ in $(seq 1 30); do curl -fs http://127.0.0.1:8000/health && break; sleep 1; done scripts/smoke.sh http://127.0.0.1:8000 ci-smoke-key - name: Sign in to GitHub Container Registry if: env.PUSH == 'true' uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Push the same build if: env.PUSH == 'true' id: push uses: docker/build-push-action@v7 with: context: . platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | VERSION=${{ steps.version.outputs.version }} REVISION=${{ github.sha }} cache-from: type=ghaLes parties, depuis le haut :
needs: checks: la tâche d’image attend la tâche dont l’identifiant estchecks. Si les vérifications échouent, GitHub saute cette tâche, comme dans la première exécution rouge.permissions: seule cette tâche peut écrire des paquets. SonGITHUB_TOKENpeut donc pousser vers GHCR. La tâche de vérification garde seulementcontents: read.PUSHvauttruepour chaque déclencheur sauf une demande de tirage (pull request). Une demande de tirage construit l’image et vérifie son bon fonctionnement, mais ne pousse rien. Une branche ne peut donc jamais placer d’image dans le registre. Les lignesif: env.PUSH == 'true'sautent les dernières étapes pour une demande de tirage.- La version vient de
pyproject.toml(1.1.0). Elle a donc une seule source. docker/metadata-actioncrée les noms d’images.type=sha,prefix=sha-donne l’étiquettesha-suivie des 7 premiers caractères du commit, commesha-c862935. L’étiquette indique le commit, donc elle ne pointe jamais vers un autre code.type=semverajoute une étiquette comme1.1.0seulement quand le déclencheur est une étiquette de versionv1.1.0. L’étape crée aussi des étiquettes de métadonnées (des renseignements dans l’image). Publier les preuves les lit.- La première construction produit
linux/amd64, le type de processeur du nuage (voir le cours sur Docker).load: trueconserve l’image dans Docker sur l’exécuteur sous le nomticket-api:candidate. C’est une version candidate : une image qui peut devenir une version publiée si elle réussit toutes les vérifications.cache-to: type=ghaenregistre les couches dans le cache de GitHub Actions. Le Dockerfile n’utilise pas encoreVERSIONetREVISION. Les arguments de construction sont là pour plus tard. - La vérification de bon fonctionnement démarre la version candidate sur l’exécuteur et lance
scripts/smoke.shcontre elle. - L’étape de poussée reconstruit l’image avec
cache-from: type=gha. Les étapes du Dockerfile sont identiques, donc chaque étape vient du cache. BuildKit ne fait qu’emballer et envoyer les mêmes couches.
scripts/smoke.sh reprend la vérification de bon fonctionnement du cours sur les API. Ce script termine avec le code de sortie 1 si une vérification échoue :
#!/usr/bin/env bash# Smoke check of a running ticket API: the main paths, and one failure path.# scripts/smoke.sh <base URL> <API key># Exits with 1 when a check fails. Prints no secret.set -uo pipefail
url=${1:?Give the base URL, for example https://ticket-api-staging...}key=${2:?Give the API key}failed=0
check() { # name, expected status, curl arguments... local name=$1 expected=$2; shift 2 local status status=$(curl -s -o /dev/null -w '%{http_code}' --max-time 30 "$@") if [ "$status" = "$expected" ]; then echo "ok $name ($status)" else echo "FAIL $name: expected $expected, got $status" failed=1 fi}
check "health" 200 "$url/health"check "ready" 200 "$url/ready"check "classify with the key" 200 -X POST "$url/v1/classify" \ -H 'Content-Type: application/json' -H "X-API-Key: $key" -d '{"subject":"Parcel lost"}'check "classify without a key" 401 -X POST "$url/v1/classify" \ -H 'Content-Type: application/json' -d '{"subject":"Parcel lost"}'
exit $failedRendez-le exécutable avant de créer son commit : chmod +x scripts/smoke.sh. Git conserve cette permission, et l’exécuteur en a besoin.
Le fichier complet à cette étape se trouve dans le dépôt de référence : ci.yml à c862935. Il contient trois étapes de plus, que la prochaine leçon ajoute.
Ce que l’exécution a fait
Section intitulée « Ce que l’exécution a fait »Description textuelle du diagramme
La tâche 1 exécute les quatre vérifications. Quoi qu’il arrive, elle téléverse ensuite le rapport de test comme artefact reports. Si une vérification échoue, l’exécution est rouge et la tâche 2 ne démarre jamais. Si tout réussit, la tâche 2 construit l’image et vérifie son bon fonctionnement sur son exécuteur. Pour une demande de tirage, l’exécution s’arrête là, et rien ne va dans le registre. Pour une poussée vers main, une branche de correctif urgent ou une étiquette de version, la tâche 2 pousse la même construction vers GHCR. Elle enregistre ensuite la provenance de l’image et téléverse build-info.json comme artefact build-info. Cette leçon ajoute tout sauf les deux artefacts et la provenance. Publier les preuves les ajoute.
L’exécution de référence 37663364319 montre le même graphe :

Le journal de la tâche d’image montre chaque partie. La première construction a exécuté chaque étape, car le cache était encore vide (extrait abrégé) :
#11 [5/7] RUN pip install -r requirements-run.txt#11 DONE 10.4s#13 [7/7] COPY ticket_api ./ticket_api#13 DONE 0.0s#16 exporting to GitHub Actions Cache#16 DONE 10.3sLa vérification de bon fonctionnement sur l’exécuteur :
{"status":"ok"}ok health (200)ok ready (200)ok classify with the key (200)ok classify without a key (401)La première ligne semble étrange. Dans la boucle d’attente, curl -fs …/health a affiché le corps {"status":"ok"} sans saut de ligne. La première ligne ok (réussite) le suit donc directement. C’est sans conséquence. Le dépôt de référence a ensuite ajouté -o /dev/null à ce curl pour ne pas afficher le corps.
Ensuite, la poussée. Chaque étape venait du cache, et la poussée a envoyé les couches testées par la vérification de bon fonctionnement :
#7 [2/7] RUN useradd --create-home --uid 10001 app#7 CACHED...#10 [5/7] RUN pip install -r requirements-run.txt#10 CACHED...#12 [7/7] COPY ticket_api ./ticket_api#12 CACHED#14 pushing manifest for ghcr.io/usmanahmed99/ticket-api-ci:sha-c862935@sha256:6c9bb4ed7c7cffc27f0c5489ba867d4d5db16def1c59c8bcbaeb3d26c45ce2e1sha256:6c9bb4ed… est l’empreinte de ce que le registre contient maintenant. Le module 3 déploie exactement cette empreinte. Un détail à préciser : l’image poussée contient aussi des étiquettes de métadonnées, contrairement à la copie testée. L’empreinte poussée n’est donc pas identique à l’identifiant de la copie testée. Le code, les paquets et chaque couche sont identiques : chaque étape indique CACHED (en cache).
Cette exécution va-t-elle pousser l’image?
Section intitulée « Cette exécution va-t-elle pousser l’image? »| Déclencheur | Vérifications | Construction et vérification de bon fonctionnement | Poussée | Étiquettes d’image |
|---|---|---|---|---|
Demande de tirage, de n’importe quelle branche vers main |
oui | oui | non | aucune |
Poussée vers main |
oui | oui | oui | sha-<7> |
Poussée vers hotfix/1.2.1 |
oui | oui | oui | sha-<7> |
Poussée de l’étiquette v1.1.0 |
oui | oui | oui | sha-<7> et 1.1.0 |
Dans la dernière ligne, l’étiquette 1.1.0 pointe vers une nouvelle construction d’un ancien commit. Le module 3 retire ce déclencheur et étiquette l’image que main a déjà construite. La première demande de tirage du dépôt de référence (exécution 37664331105) prouve la première ligne. Sa tâche d’image a pris 32 secondes, avec chaque étape du Dockerfile à CACHED et aucune poussée.
Les mêmes vérifications sur votre ordinateur
Section intitulée « Les mêmes vérifications sur votre ordinateur »Attendre 2 minutes pour que l’exécuteur trouve une erreur d’analyse statique, c’est long. scripts/check.sh fait les mêmes vérifications, dans le même ordre, sur votre ordinateur :
#!/usr/bin/env bash# Run the same checks as the CI pipeline, on your computer, in the same order.# Use it before you push. Needs the virtual environment (requirements-lock.txt)# and Docker. Database tests run only when TEST_DATABASE_URL is set.set -euo pipefail
step() { printf '\n== %s\n' "$1"; }
step "Lint"ruff check .
step "Tests"python -m pytest -q --junitxml=reports/junit.xml
step "Security: known vulnerabilities in the image's packages"pip-audit -r requirements-run.txt --progress-spinner off
step "Build the image"docker build -q -t ticket-api:check . >/dev/null
step "Smoke check of the image"docker run -d --rm --name ticket-api-check -p 127.0.0.1:8099:8000 -e API_KEY=check-key ticket-api:check >/dev/nulltrap 'docker stop ticket-api-check >/dev/null' EXITfor _ in $(seq 1 20); do curl -fs http://127.0.0.1:8099/health >/dev/null && break; sleep 0.5; donescripts/smoke.sh http://127.0.0.1:8099 check-key
printf '\nAll checks passed.\n'set -e arrête le script au premier échec, comme une étape échouée arrête une tâche. L’image utilise le port 8099, pour éviter un conflit avec une API sur le port 8000. La ligne trap arrête le conteneur à la fin du script, même après un échec. Le script construit pour le processeur de votre ordinateur (sur un Mac avec Apple silicon : arm64). Cela suffit pour détecter une image défectueuse avant de pousser. L’exécuteur construit linux/amd64. (Le commentaire mentionne les tests de base de données, qui arrivent au module 4.)
chmod +x scripts/check.shscripts/check.shLa sortie du Mac de test. (Le test utilisait les noms c19m02-ticket-api:check et c19m02-ticket-api-check.)
== LintAll checks passed!
== Tests......................... [100%]25 passed in 0.25s
== Security: known vulnerabilities in the image's packagesNo known vulnerabilities found
== Build the image
== Smoke check of the imageok health (200)ok ready (200)ok classify with the key (200)ok classify without a key (401)
All checks passed.Cela a pris 14 secondes, avec les couches de l’image déjà dans le cache local.
Exercice guidé : ajouter les vérifications et la tâche d’image
Section intitulée « Exercice guidé : ajouter les vérifications et la tâche d’image »- Ajoutez les deux étapes Unit and contract tests (tests unitaires et de contrat) et Security (sécurité) à la tâche de vérification.
- Ajoutez
reports/à.gitignore. - Ajoutez
scripts/smoke.shetscripts/check.sh, puis rendez les deux exécutables avecchmod +x. - Exécutez
scripts/check.sh. Continuez seulement quand il afficheAll checks passed.(toutes les vérifications ont réussi). - Ajoutez la tâche
image. - Vérifiez le fichier avec actionlint.
- Créez un commit et poussez vers
main. - Ouvrez l’exécution. Vérifiez que la tâche d’image a démarré seulement après la tâche de vérification.
- Dans le journal de la tâche d’image, trouvez les lignes de vérification de bon fonctionnement, les lignes
CACHEDde la poussée et l’empreinte. - Ouvrez la page du paquet,
https://github.com/<you>/ticket-api-ci/pkgs/container/ticket-api-ci. Trouvez l’étiquettesha-suivie des 7 premiers caractères de votre commit.
Afficher le résultat attendu
scripts/check.sh termine avec All checks passed. Sur GitHub, l’exécution contient deux tâches vertes. Lint, test, audit prend environ 45 secondes. Build, smoke-test and push the image prend environ une minute. L’étape de test indique 25 passed (25 tests réussis), et l’étape de sécurité indique No known vulnerabilities found (aucune vulnérabilité connue trouvée). La vérification de bon fonctionnement affiche quatre lignes ok. La poussée indique CACHED pour les six étapes du Dockerfile après FROM. Elle affiche ensuite pushing manifest for ghcr.io/<you>/ticket-api-ci:sha-…@sha256:… (poussée du manifeste de l’image). La page du paquet montre l’étiquette sha-….
La documentation de GitHub indique qu’un nouveau paquet est privé par défaut. Mais un paquet publié par un flux de travail avec GITHUB_TOKEN reçoit la visibilité de son dépôt. Dans le dépôt de référence, le paquet était immédiatement public : une requête anonyme pour le manifeste a reçu 200. Vérifiez le vôtre. S’il indique Private (privé), ouvrez le paquet, puis Package settings (paramètres du paquet) → Change visibility (changer la visibilité). Cette option est en bas, sous « Danger Zone » (zone de danger). Un paquet public ne peut plus redevenir privé.
À vous de jouer : faites échouer une vérification et trouvez-la en une seconde
Section intitulée « À vous de jouer : faites échouer une vérification et trouvez-la en une seconde »Faites ceci sur votre ordinateur seulement. Dans ticket_api/config.py, retirez encore from None de la ligne 28. La ligne sera comme lors de la première exécution en échec. Prédisez : quelles étapes scripts/check.sh exécute-t-il, combien de temps prend-il et quel est son code de sortie? Exécutez-le. Annulez ensuite le changement avec git restore ticket_api/config.py.
Afficher la réponse
Il exécute seulement Lint (analyse statique). La sortie :
== LintB904 Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling --> ticket_api/config.py:28:13...Found 1 error.Le code de sortie est 1, et l’exécution a pris moins d’une seconde sur le Mac de test. set -e a arrêté le script au premier échec. Aucun test n’a donc été exécuté et aucune image n’a été construite. L’exécuteur fait la même chose : la tâche de l’image est ignorée. Vous avez trouvé en une seconde ce que l’exécuteur a trouvé en 25 secondes, sans envoi au dépôt. C’est la première moitié de la vérification de fin de ce module : reproduire une vérification en échec sur votre ordinateur.
Erreur courante
Le test de bon fonctionnement réussit dans le cas normal, et l'API est ouverte
Symptôme : quelqu’un raccourcit l’étape de test de bon fonctionnement et démarre l’image candidate sans -e API_KEY=ci-smoke-key. L’image démarre, /health répond et la classification fonctionne. Le Mac de test a exécuté l’image ainsi et appelé scripts/smoke.sh :
docker run -d --name c19m02-candidate -p 127.0.0.1:8098:8000 c19m02-ticket-api:ascripts/smoke.sh http://127.0.0.1:8098 ci-smoke-keyLa sortie :
ok health (200)ok ready (200)ok classify with the key (200)FAIL classify without a key: expected 401, got 200Le code de sortie était 1. Dans le pipeline CI, cette étape échoue, et les étapes d’envoi ne s’exécutent jamais.
Cause : sans API_KEY ni REQUIRE_API_KEY, l’API de billets démarre sans restriction, comme dans le cours L’essentiel de Docker et du nuage pour les développeurs en IA. Toute requête permet une classification, avec ou sans clé. Trois vérifications ont réussi. Seule la vérification qui doit échouer a révélé le problème.
Solution : démarrez l’image candidate comme en production : avec une clé. Dans le nuage, REQUIRE_API_KEY=true empêche l’application de démarrer si la clé manque, comme dans le cours L’essentiel de Docker et du nuage pour les développeurs en IA. Gardez le cas d’échec dans le test de bon fonctionnement. Supprimez ensuite le conteneur : docker rm -f c19m02-candidate.
Pour un vrai service d’IA : une API de modèle qui répond sans clé coûte de l’argent à chaque requête et peut divulguer des données. Un test de bon fonctionnement qui teste seulement ce qui devrait fonctionner ne peut pas détecter cela. Chaque test de bon fonctionnement exige au moins une requête qui doit être refusée.
Vérifiez votre compréhension
La tâche de l'image construit deux fois : d'abord avec load : true, puis avec push : true. Pourquoi n'est-ce pas l'erreur de reconstruction du diagramme?
Afficher la réponse
La deuxième construction utilise le même commit (enregistrement des changements), le même Dockerfile et le cache des couches de la première (cache-from: type=gha). Chaque étape affichait CACHED (en cache), donc aucune étape n’a été exécutée de nouveau. BuildKit a assemblé les mêmes couches que le test de bon fonctionnement avait testées et les a envoyées à GHCR. L’erreur est une deuxième construction qui exécute les étapes de nouveau, par exemple un autre jour ou pour un autre environnement. Les paquets ou l’image de base peuvent alors différer, et le résultat est une image que personne n’a testée. Ici, la seule différence concerne les étiquettes que porte l’image envoyée.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Prédisez : Sam ouvre une demande de tirage de feature/x vers main. Quelles tâches et étapes s'exécutent, et que contient GHCR ensuite?
Afficher la réponse
Les deux tâches s’exécutent. La tâche de vérification exécute l’analyse statique, les tests et pip-audit. Si ces vérifications réussissent, la tâche de l’image construit linux/amd64 et teste le bon fonctionnement de l’image candidate sur son exécuteur. Ensuite, PUSH vaut false (faux), car le déclencheur est pull_request (demande de tirage). Les étapes de connexion et d’envoi sont donc ignorées. GHCR ne contient rien de nouveau. L’image est envoyée seulement après l’arrivée du changement dans main. L’envoi vers main exécute alors le pipeline de nouveau sur le code fusionné.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Exercice pratique : montrez une exécution réussie de votre pipeline avec deux tâches. Où trouvez-vous l'empreinte de votre image, et quelle étiquette indique son commit?
Afficher la réponse
L’exécution présente Lint, test, audit (analyse statique, tests, audit), puis Build, smoke-test and push the image (construction, test de bon fonctionnement et envoi de l’image), reliées dans le graphique. L’étape Push the same build (envoyer la même construction) de la tâche de l’image contient la ligne pushing manifest for ghcr.io/<you>/ticket-api-ci:sha-<7>@sha256:…, avec l’empreinte. La sortie Digest (empreinte) de l’étape l’affiche de nouveau. L’étiquette sha- suivie des 7 premiers caractères du commit indique le commit. La page du paquet de votre dépôt affiche la même étiquette.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Installez à partir du fichier de verrouillage. Une exécution en échec indique alors que votre changement a brisé quelque chose, pas qu’un paquet a changé pendant la nuit.
- Vérifications utiles : l’analyse statique, les tests (avec un rapport JUnit) et pip-audit sur les paquets de l’image. Sachez ce que chacune ne peut pas détecter.
- Construisez une seule fois. Testez le bon fonctionnement de l’image candidate sur l’exécuteur, puis envoyez cette même construction avec l’étiquette
sha-<7>. Une deuxième construction est un nouvel artefact non testé. - Une demande de tirage construit et teste, mais n’envoie jamais l’image.
scripts/check.shexécute les mêmes vérifications sur votre ordinateur avant votre envoi au dépôt.
Ensuite, conservez les preuves. Ce sont le rapport de test, un relevé du commit et de l’exécution ayant produit chaque empreinte, et une preuve signée de la source de l’image. Protégez ensuite main avec un ensemble de règles.
Leçon suivante : Publier les preuves