Build : l'étape où le code devient exécutable

Vous venez de pusher vos dernières modifications. Le pipeline les récupère, checkout le code et prépare l'environnement. Et maintenant ? L'étape suivante consiste à s'assurer que ce code peut réellement s'exécuter quelque part. C'est l'étape de build.

Beaucoup de personnes novices en pipelines pensent que le build se résume à la compilation. Si vous écrivez du Java, vous compilez en bytecode. Si vous écrivez du Go, vous compilez en binaire. Cela en fait partie, mais le build est plus large que cela. Chaque type de travail dans la livraison de logiciels nécessite une étape de build, même si le résultat n'est pas un fichier binaire.

Ce que signifie réellement le build

Le code tel que les développeurs l'écrivent n'est généralement pas prêt à être exécuté sur un serveur. Il doit être transformé en quelque chose que le système cible peut exécuter. Pour une application Java, cela signifie compiler le code source en bytecode et l'empaqueter dans un fichier JAR ou WAR. Pour une application Node.js, le build peut impliquer l'exécution d'un bundler, d'un minifier ou d'un transpiler pour que le code soit prêt pour la production. Pour une application Go, le build signifie compiler en un binaire autonome.

Mais le build ne concerne pas uniquement le code applicatif. Les bases de données ont également besoin d'une étape de build. Le code SQL, les procédures stockées et les schémas de base de données doivent être compilés ou validés. Le résultat n'est pas un binaire. C'est un ensemble de fichiers de migration prêts à être exécutés contre une base de données cible dans le bon ordre. Le build pour les bases de données produit généralement des commandes SQL vérifiées, dont la syntaxe et l'ordre des dépendances ont été contrôlés.

Voici à quoi pourrait ressembler une étape de build dans une configuration de pipeline pour deux types d'applications courants :

build-nodejs:
  stage: build
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/

build-go:
  stage: build
  script:
    - go build -o app .
  artifacts:
    paths:
      - app

L'infrastructure passe également par un processus de build. Les fichiers Terraform, les templates CloudFormation et les playbooks Ansible nécessitent une vérification syntaxique, une validation et parfois une compilation en une représentation plus déployable. Le résultat d'un build d'infrastructure peut être un fichier de configuration validé, un template vérifié, ou même une image machine pré-construite.

Le point commun est le suivant : le build transforme la source en quelque chose qui peut être vérifié, puis utilisé par les étapes suivantes.

Le diagramme ci-dessous résume comment le build transforme différents types de code source en artefacts exécutables :

flowchart TD A[Code Source] --> B{Étape de Build} B --> C[Application : Binaire / Package / Image Conteneur] B --> D[Base de données : Scripts de Migration Vérifiés] B --> E[Infrastructure : Configuration / Plan Validé] C --> F[Artefact avec Métadonnées] D --> F E --> F F --> G[Étape Suivante : Test & Scan]

Ce que produit un bon build

Un build doit produire une sortie qui peut être inspectée. Une fois le build terminé, vous devez savoir trois choses : a-t-il réussi, qu'a-t-il produit, et le résultat correspond-il aux attentes.

Une sortie de build bien structurée comprend :

  • Un artefact prêt à l'emploi. Cela peut être un binaire, un package, une image conteneur ou un fichier de migration.
  • Un enregistrement de la version et du commit qui a déclenché ce build.
  • Des métadonnées telles qu'un hash ou une somme de contrôle pour vérifier que l'artefact n'a pas été modifié pendant le transit.
  • Un statut clair de succès ou d'échec.

Sans ces éléments, vous ne pouvez pas faire confiance à ce que le pipeline transmet à l'étape suivante.

Le build doit être reproductible

Si vous exécutez deux fois le même build avec le même code, vous devez obtenir le même résultat. C'est ce qu'on appelle un build déterministe. C'est important car si les builds ne sont pas reproductibles, votre équipe ne peut jamais être sûre que l'artefact provient bien du code que vous pensez.

Les builds non déterministes surviennent généralement pour deux raisons. Premièrement, le build dépend de bibliothèques externes dont les versions ne sont pas verrouillées. Un jour, la bibliothèque se met à jour, et soudainement votre build produit un artefact différent même si votre code n'a pas changé. Deuxièmement, le build s'exécute dans un environnement incohérent. Peut-être qu'un agent de build a une version d'outil différente d'un autre, ou que des fichiers en cache subsistent d'un build précédent.

Verrouillez vos dépendances. Fixez les versions de vos outils. Utilisez des environnements de build propres. Ces pratiques rendent votre build fiable et votre équipe confiante.

Le build est la première porte

Le build est le premier point du pipeline où une décision est prise : ce changement doit-il continuer ou non ? Si le build échoue, le pipeline doit s'arrêter. Il est inutile d'exécuter des tests ou de déployer si l'artefact lui-même est cassé.

Cela signifie que le build doit être rapide. Les développeurs ont besoin de feedback en minutes, pas en heures. Si un build prend trop de temps, les gens cessent de l'attendre. Ils passent à la tâche suivante, et quand le build échoue enfin, ils ont déjà changé de contexte. La boucle de feedback est rompue.

Gardez votre build léger. Faites uniquement ce qui est nécessaire pour produire un artefact valide. Réservez les vérifications plus approfondies pour les étapes ultérieures. Un build qui s'exécute en moins de cinq minutes donne aux développeurs le signal rapide dont ils ont besoin pour corriger les problèmes pendant que le code est encore frais dans leur esprit.

Build pour différents types de travail

Voyons comment le build fonctionne pour chaque domaine principal.

Applications. Pour les langages compilés, le build signifie compilation et empaquetage. Pour les langages interprétés, le build peut signifier résolution des dépendances, compilation des assets et bundling. Les applications conteneurisées ajoutent une étape supplémentaire : la construction de l'image conteneur elle-même fait partie de l'étape de build.

Bases de données. Le build pour les bases de données signifie valider la syntaxe SQL, vérifier que les fichiers de migration sont ordonnés correctement, et parfois exécuter un dry run contre une copie du schéma. Le résultat est un ensemble de scripts de migration vérifiés, prêts à être exécutés.

Infrastructure. Le build pour l'infrastructure signifie valider les fichiers de configuration, vérifier les erreurs de syntaxe, et parfois générer un plan qui montre ce qui va changer. Pour des outils comme Terraform, l'étape de build peut inclure l'exécution de terraform plan pour produire un aperçu des modifications.

Chaque type de travail a ses propres exigences de build, mais les principes sont les mêmes : transformer la source en un artefact vérifié et reproductible qui peut être transmis à l'étape suivante.

Une checklist rapide pour le build

Avant de considérer votre étape de build comme terminée, vérifiez ces points :

  • Le build produit un artefact vérifiable (binaire, image, fichier de migration, config)
  • Le build est déterministe : même code, même résultat, à chaque fois
  • Le build s'exécute en moins de cinq minutes
  • Le build échoue rapidement et donne des messages d'erreur clairs
  • La sortie du build inclut la version, le commit et les métadonnées de somme de contrôle
  • Les dépendances externes sont verrouillées sur des versions spécifiques
  • L'environnement de build est propre et cohérent entre les exécutions

Et ensuite

Une fois le build terminé et l'artefact prêt, le pipeline passe à l'étape suivante : vérifier si cet artefact fonctionne réellement et peut être déployé en toute sécurité. C'est l'étape de test et de scan. Mais avant d'y arriver, assurez-vous que votre build est solide. Une étape de build faible crée des problèmes que toutes les étapes ultérieures devront gérer.

Le build n'est pas seulement de la compilation. C'est la première véritable vérification que votre code est prêt à devenir quelque chose d'utile. Faites-le correctement, et le reste du pipeline disposera d'une base solide sur laquelle travailler.