Du code source à quelque chose qui fonctionne vraiment

Vous venez de terminer d'écrire du code sur votre ordinateur. Tout fonctionne parfaitement. Toutes les fonctionnalités marchent. Aucune erreur. Vous êtes satisfait. Maintenant, vous voulez le montrer à votre équipe ou à un utilisateur. Vous copiez le dossier du projet sur un autre ordinateur et essayez de l'exécuter. Soudain, plus rien ne fonctionne. Des erreurs que vous n'aviez jamais vues apparaissent. Ou peut-être que l'application démarre, mais a un aspect complètement différent.

Même code. Résultat différent.

C'est le moment où de nombreux développeurs réalisent quelque chose d'important : le code source n'est pas quelque chose que l'on peut exécuter n'importe où. Le code source est une matière première. C'est un ensemble de fichiers texte contenant des instructions de programme. Avant qu'un serveur, l'ordinateur d'un utilisateur ou un environnement de production puisse l'utiliser, ce code source doit être transformé en quelque chose d'exécutable.

Ce processus de transformation s'appelle un build.

Pourquoi le code source ne peut pas aller directement en production

Plusieurs raisons expliquent pourquoi le code source brut n'est pas prêt à être exécuté en dehors de votre machine.

Premièrement, la plupart des langages de programmation nécessitent une traduction. Java, Kotlin, Go, Rust et C# doivent être compilés en fichiers binaires ou en bytecode. Des langages comme JavaScript, Python ou Ruby n'ont pas besoin de compilation de la même manière, mais ils nécessitent tout de même que les dépendances et les paquets soient correctement organisés pour fonctionner dans différents environnements.

Deuxièmement, les applications modernes dépendent presque toujours de bibliothèques ou de frameworks externes. Ces bibliothèques doivent être téléchargées, placées aux bons endroits et parfois configurées pour chaque environnement. Votre code seul est inutile sans elles.

Troisièmement, les applications ont souvent besoin de ressources comme des fichiers de configuration, des actifs statiques, des templates ou des images. Ceux-ci doivent être empaquetés avec le code de manière cohérente.

Tout ce travail — traduire le code, télécharger les dépendances, organiser les fichiers et produire une sortie prête à être exécutée — est ce que nous appelons un build. Le résultat d'un build s'appelle un artefact.

À quoi ressemble un artefact

Les artefacts se présentent sous de nombreuses formes selon votre stack technologique.

Pour une application Java, l'artefact est généralement un fichier JAR ou WAR. Pour une application Go, c'est un seul fichier binaire. Pour un frontend web, l'artefact peut être un dossier de fichiers HTML, CSS et JavaScript minifiés. Pour une application Python, il peut s'agir d'un paquet contenant toutes les dépendances regroupées.

Le format spécifique importe moins que ce que l'artefact représente : un paquet unique et autonome prêt à être exécuté. C'est cet artefact qui est envoyé aux serveurs, placé dans les environnements de staging ou déployé en production. Le code source lui-même ne va jamais directement sur un serveur. C'est toujours l'artefact qui y va.

Par exemple, un Dockerfile définit les étapes de build qui transforment votre code source en une image conteneur — un format d'artefact courant :

FROM node:18-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build

FROM node:18-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/server.js"]

Considérez cela comme la cuisine. Le code source, ce sont vos ingrédients — farine, œufs, sucre, beurre. Le processus de build est l'action de mélanger, cuire et dresser. L'artefact est le gâteau fini. Vous n'envoyez pas les ingrédients bruts à la table d'un restaurant. Vous envoyez le gâteau.

Le problème des builds multiples

Une fois que vous comprenez que les builds produisent des artefacts, une nouvelle question apparaît. Vous allez builder votre application de nombreuses fois. Chaque modification de code, chaque correction de bug, chaque nouvelle fonctionnalité déclenche un nouveau build. Comment distinguer un artefact d'un autre ?

Sans moyen de les différencier, vous ne pouvez pas savoir quel artefact a été testé, lequel est en production et lequel est tout nouveau. Cela devient critique quand quelque chose tourne mal. Si la production est cassée, vous devez savoir exactement quel artefact y est déployé et quelle version du code l'a produit.

C'est là que l'identification des artefacts devient essentielle. Chaque sortie de build a besoin d'une identité unique. Cette identité vous permet de retracer n'importe quel artefact jusqu'au code source exact, à la configuration de build et à l'environnement qui l'ont créé.

Ce qui se passe pendant un build

Un processus de build typique comporte plusieurs étapes, bien que la séquence exacte dépende de votre technologie.

Le diagramme suivant montre la séquence typique des étapes qui transforment le code source en un artefact déployable :

flowchart TD A[Code Source] --> B[Récupération depuis le VCS] B --> C[Résolution des dépendances] C --> D[Compilation / Transpilation] D --> E[Assemblage des ressources] E --> F[Packaging de l'artefact] F --> G[Artefact : JAR, ZIP, Binaire, etc.] G --> H[Prêt pour le déploiement] I[Environnement de build cohérent] -.-> B I -.-> C I -.-> D I -.-> E I -.-> F

La première étape consiste généralement à récupérer le dernier code source depuis votre système de gestion de versions. Cela garantit que vous buildiez exactement ce qui se trouve dans le dépôt, et non une modification locale que vous avez oublié de commit.

Vient ensuite la résolution des dépendances. L'outil de build télécharge toutes les bibliothèques et frameworks requis. Cette étape peut être lente la première fois, mais les builds suivants mettent souvent en cache les dépendances pour gagner du temps.

Puis la compilation ou la transformation proprement dite a lieu. Le code est compilé, les actifs sont minifiés, les templates sont traités. L'outil de build applique toutes les transformations définies dans votre configuration de build.

Après cela, les ressources sont assemblées. Les fichiers de configuration, les fichiers statiques et autres actifs sont collectés et placés aux bons endroits dans la structure de sortie.

Enfin, l'outil de build empaquette le tout dans le format d'artefact approprié pour votre application. Cela peut être une archive compressée, un fichier binaire ou une image conteneur.

L'importance de l'environnement de build

Un détail crucial qui piège de nombreuses équipes : les builds doivent se dérouler dans un environnement cohérent. Si vous buildez sur votre machine, le résultat peut différer d'un build sur la machine d'un collègue ou sur un serveur de build. Des systèmes d'exploitation différents, des versions d'outils différentes, des bibliothèques installées différentes — tout cela peut produire des artefacts différents à partir du même code source.

C'est pourquoi les équipes professionnelles utilisent des serveurs de build dédiés ou des conteneurs de build. L'environnement de build est standardisé et contrôlé. Chaque build s'exécute dans les mêmes conditions, produisant des artefacts reproductibles. Votre machine n'est pas un serveur de build, aussi soigneusement que vous l'ayez configurée.

L'artefact est ce qui est déployé

Voici un principe qui semble évident mais qui est fréquemment violé : l'artefact que vous testez en staging doit être exactement le même artefact que vous déployez en production. Pas reconstruit à partir du même code. Pas une configuration légèrement différente. Le fichier exactement identique.

Si vous reconstruisez pour la production, vous introduisez un risque. Peut-être que le serveur de build était dans un état différent. Peut-être qu'une version de dépendance a changé entre les builds. Peut-être que l'outil de build s'est comporté différemment. La seule façon d'être certain que ce que vous avez testé est ce qui s'exécute en production est d'utiliser l'artefact identique.

Cela signifie que votre processus de build doit produire un artefact par version de votre code. Cet artefact est promu à travers les environnements — du développement au test, au staging, puis à la production — sans être reconstruit. L'artefact porte son identité avec lui, et vous pouvez toujours retracer d'où il vient.

Liste de contrôle pratique pour votre processus de build

  • Définissez le format d'artefact que votre application produit (JAR, binaire, image conteneur, etc.)
  • Mettez en place un environnement de build dédié et cohérent pour tous les builds
  • Configurez votre outil de build pour produire des identifiants de version uniques pour chaque build
  • Stockez chaque artefact dans un dépôt central où il peut être récupéré ultérieurement
  • Ne reconstruisez jamais le même code pour différents environnements — promouvez le même artefact
  • Documentez les étapes de votre processus de build pour que toute l'équipe puisse les comprendre

Ce que cela signifie pour votre travail quotidien

La prochaine fois que vous exécuterez votre application sur votre machine et qu'elle fonctionnera, rappelez-vous que ce n'est que le début. Ce code doit passer par un processus de build avant de pouvoir s'exécuter ailleurs. Le build transforme votre code source brut en un artefact — un paquet prêt à être exécuté dans n'importe quel environnement correctement configuré.

Comprendre cette distinction entre code source et artefacts change votre façon de penser la livraison. Le code source est ce que vous écrivez. Les artefacts sont ce que vous déployez. Ce n'est pas la même chose, et les traiter comme interchangeables conduit à ce genre de problèmes "ça marche sur ma machine" qui font perdre des heures de débogage.

Construisez vos artefacts de manière cohérente. Identifiez-les clairement. Promouvez-les à travers les environnements sans les reconstruire. Cette simple discipline élimine toute une catégorie de problèmes de déploiement avant même qu'ils n'atteignent la production.