Installer via un pipeline Aetheus

Dès que vous exploitez un Aetheus, il peut installer le suivant. Cette page décrit le plus petit pipeline qui y parvient : construire, déployer, enregistrer une release. Pas de QA, pas de porte qualité, pas d'analyse de sécurité.

C'est une seconde installation, pas la première

Il vous faut un Aetheus en service pour exécuter le pipeline. Installez le premier avec Docker ou depuis les binaires.

Ce qu'il faut avant d'écrire le moindre YAML

  1. Un projet

    Tout le reste s'y rattache : le dépôt, le pipeline, les releases et les artefacts.

  2. Un dépôt Git lié à ce projet

    La définition du pipeline est lue depuis le dépôt à chaque lancement, et l'exécution y récupère une révision épinglée. Un pipeline nécessitant un espace de travail est refusé avant même la création de l'exécution si son dépôt source est absent ou ambigu : liez-le donc explicitement quand le projet en contient plusieurs.

  3. Un agent en ligne sur l'hôte cible

    Le pipeline s'exécute sur la machine que vous déployez. Enregistrez cette machine en tant que serveur et attendez que son agent soit en ligne. Chaque étape ci-dessous la désigne avec agent: : ce sélecteur correspond exactement au nom du serveur dans Aetheus (ou à une étiquette), il est fermé par défaut, et une étape dont le serveur nommé est hors ligne attend au lieu de s'exécuter ailleurs. Sans lui, une étape part sur le runner Linux en ligne le moins chargé de l'organisation, et les étapes suivantes restent sur ce runner par affinité : avec plusieurs runners Linux, le build et l'étape Compose pourraient tomber sur un autre hôte. group: ne choisit aucun serveur ; il borne seulement le nombre d'étapes du groupe exécutées en même temps.

    L'hôte a aussi besoin de ce qu'utilise le build. Pour la configuration ci-dessous, c'est Docker avec le greffon Compose.

  4. Une bibliothèque de variables pour les valeurs non secrètes

    Noms d'hôte, ports, racines web, chemins de déploiement. Un pipeline ne voit qu'une bibliothèque qu'il liste explicitement : la déclarer dans le YAML fait partie de la mise en place, pas des finitions.

  5. Un coffre pour les secrets

    Mot de passe de la base, clé JWT, clé et sel de chiffrement, mot de passe administrateur initial. Un coffre que le pipeline ne peut pas résoudre échoue l'exécution, ce qui est le comportement souhaitable : l'alternative serait de déployer avec des secrets vides.

Le pipeline minimal

Commitez ceci en tant que .pipeline/aetheus-install.yaml dans le dépôt lié. Trois étapes : construire les images, transmettre la charge utile à l'étape de déploiement, puis enregistrer ce qui a été publié.

name: aetheus-install
trigger: manual

variable_libraries:
  - aetheus-target-host

vaults:
  - aetheus-target-secrets

variables:
  APP_VERSION: "1.0.$(BUILD_PIPELINE_RUNNUMBER)"
  COMPOSE_PROJECT: "aetheus"
  DEPLOY_DIR: "/srv/aetheus"

stages:
  - name: Build
    os: linux
    agent: target-host   # le nom du serveur cible dans Aetheus
    group: Deploy
    steps:
      - name: Construire les images de production
        checkout: true
        working_directory: "$(WORKSPACE)"
        timeout_seconds: 3600
        shell: |
          set -eu
          SOURCE_COMMIT="$(git rev-parse HEAD)"
          # Les Dockerfile copient une publication faite sur l'hôte dans .pipeline-publish/ ; ils ne compilent pas.
          DOTNET="$(sh deploy/scripts/ensure-dotnet-sdk.sh)"
          export DOTNET
          APP_VERSION="$(APP_VERSION)" \
            sh deploy/scripts/publish-application.sh .pipeline-publish
          docker build \
            --load \
            --build-arg "APP_VERSION=$(APP_VERSION)" \
            --build-arg "SOURCE_COMMIT=${SOURCE_COMMIT}" \
            --file deploy/docker/Dockerfile.back \
            --tag "aetheus-back:${SOURCE_COMMIT}" .
          docker build \
            --load \
            --file deploy/docker/Dockerfile.front \
            --tag "aetheus-front:${SOURCE_COMMIT}" .
          docker image inspect \
            "aetheus-back:${SOURCE_COMMIT}" \
            "aetheus-front:${SOURCE_COMMIT}" >/dev/null
          mkdir -p .pipeline-artifacts
          printf '%s' "${SOURCE_COMMIT}" > .pipeline-artifacts/source-commit

  - name: Deploy
    os: linux
    agent: target-host
    group: Deploy
    depends_on:
      - Build
    steps:
      - name: Démarrer la pile
        checkout: true
        working_directory: "$(WORKSPACE)"
        timeout_seconds: 1800
        shell: |
          set -eu
          SOURCE_COMMIT="$(git rev-parse HEAD)"
          export AETHEUS_BACK_IMAGE="aetheus-back:${SOURCE_COMMIT}"
          export AETHEUS_FRONT_IMAGE="aetheus-front:${SOURCE_COMMIT}"
          export APP_VERSION="$(APP_VERSION)"
          cd "$(DEPLOY_DIR)"
          docker compose up -d
          # Ne pas appeler cela un succès tant que la base n'est pas réellement joignable.
          for attempt in $(seq 1 30); do
            if curl -sf http://127.0.0.1:10026/health/ready; then exit 0; fi
            sleep 5
          done
          echo "Le backend n'est jamais devenu disponible." >&2
          exit 1

  - name: Release
    os: linux
    agent: target-host
    group: Deploy
    depends_on:
      - Deploy
    steps:
      - name: Enregistrer la release déployée
        type: release
        version: "$(APP_VERSION)"
        changelog: true
        deployed: true
        timeout_seconds: 300

Lire ce pipeline

  • agent: target-host attache chaque étape au serveur cible. Remplacez target-host par le nom de ce serveur ; l'ordre de sélection est pool, puis environment, puis agent, et un sélecteur explicite ne se replie jamais sur un autre runner.
  • Le build publie l'application sur l'hôte avec deploy/scripts/publish-application.sh avant docker build, parce que les deux Dockerfile copient cette publication au lieu de compiler (voir Obtenir les images).
  • checkout: true clone la révision épinglée dans $(WORKSPACE). Sans lui, l'étape s'exécute dans un répertoire vide.
  • depends_on est ce qui sérialise les trois étapes. Sans lui, elles seraient distribuées en parallèle.
  • La tâche de déploiement interroge /health/ready et non /health/live, car le processus répond « vivant » avant que sa connexion à la base soit utilisable. Interroger le mauvais point de santé est la façon classique de déclarer réussi un déploiement cassé.
  • La tâche release est un type natif, pas un script : le backend connaît alors la version, le commit et les artefacts, ce qui donne à un futur retour arrière une cible précise.

Numéros de version

1.0.$(BUILD_PIPELINE_RUNNUMBER) produit 1.0.1, 1.0.2, etc., en comptant chaque lancement de ce pipeline, échecs compris. C'est un compteur de build, pas une version sémantique.

Première exécution

  1. Poussez le YAML sur la branche par défaut du dépôt lié. La définition est lue depuis Git au lancement : rien à synchroniser dans l'interface.

  2. Créez le pipeline dans le projet en le pointant sur ce slug, et rattachez-lui la bibliothèque de variables et le coffre.

  3. Lancez-le, et suivez la chronologie d'exécution. Une étape bloquée en attente signifie presque toujours que le serveur nommé par son agent: est hors ligne ; une étape qui ne nomme aucun serveur enregistré échoue avec la raison au lieu d'attendre.

  4. Une fois au vert, la vue d'ensemble de l'exécution porte la release produite et le commit dont elle est issue.

Ce que ce pipeline laisse volontairement de côté

Les pipelines que le projet applique à lui-même ajoutent beaucoup à ce squelette : artefacts candidats immuables, bascule de couleur blue-green pour que le plan de contrôle ne tombe jamais en se déployant lui-même, étape de retour arrière déclenchée uniquement si la release échoue, et rétention. Ajoutez-les quand vous en aurez besoin ; rien de tout cela n'est nécessaire pour installer une instance.

  • Pipelines : étapes, tâches, artefacts et modèles en détail.
  • Apache : publier les deux noms d'hôte une fois la pile démarrée.