Guide · 12 min

Déployer depuis le dépôt

Le dépôt est la source d'une application Archestack, comme le code source est la source d'un programme. Un déploiement traite Archestack comme le compilateur : un pipeline construit un Archestack jetable à partir des fichiers du dépôt, exécute les tests dessus, et ce n'est que lorsqu'ils réussissent qu'il planifie la modification par rapport à l'environnement hébergé et l'y applique. L'environnement hébergé continue de servir ses utilisateurs pendant tout ce temps.

État : l'Archestack CLI exécute chacune des étapes ci-dessous, depuis une étape de script dans n'importe quel pipeline. Des tâches de pipeline prêtes à l'emploi pour Azure DevOps et GitHub Actions qui l'encapsulent sont en cours de développement ; Ce qui fonctionne aujourd'hui indique ce que chaque étape exécute.

Votre système de CI

Le pipeline

merge to main
  build     a throwaway Archestack made from the repository's files
  test      every package's test cases, each in a sandbox
  plan      against tst: artifacts and SQL, with a plan hash
  deploy    tst: schema, then files, then the release
  approve   the plan against acc, then deploy acc
  approve   the plan against prd, then deploy prd

Une pull request exécute le build, les tests et le plan par rapport à l'environnement de test, pour qu'un relecteur voie ce qui changerait avant que quoi que ce soit ne soit fusionné. Une fusion dans la branche principale exécute toutes les étapes, et la recette comme la production attendent chacune qu'une personne approuve leur plan.

1. Build : Archestack comme compilateur

Le pipeline démarre un Archestack vide sur l'agent de build, dans Docker à partir de la même image d'API que celle des environnements, ou à partir d'un dossier de runtime comme celui avec lequel l'extension VS Code fait tourner les projets, et y charge le dépôt : les tables de tous les packages en un seul déploiement, puis les artefacts de chaque package, les dépendances avant les packages qui en ont besoin. C'est là qu'une erreur apparaît en premier, comme une erreur de compilation : une référence à un Business Entity, une table ou un script qui n'existe pas, ou un nom qu'un autre package utilise déjà, arrête le chargement. Le résultat est un environnement construit à partir des seuls fichiers, sans rien qui reste de la machine de qui que ce soit.

2. Tests

Les cas de test de chaque package s'exécutent sur le build, chacun dans une base de données sandbox qui lui est propre, et les mails et les notifications sont enregistrés au lieu d'être envoyés. Chaque script qu'un test exécute est d'abord compilé, donc un script qui ne compile plus fait échouer son test. Un seul cas en échec arrête le pipeline, et rien n'est déployé.

3. Plan par rapport à la cible

Les mêmes fichiers sont planifiés par rapport à l'environnement cible : quels artefacts y sont créés, modifiés ou supprimés, et quelles modifications de tables s'exécutent en SQL, avec le risque de chaque opération et les scripts typés qu'elle empêcherait de compiler. Le plan porte un hachage. Le déploiement applique exactement le plan qui a été approuvé : si la cible a changé entre-temps, il est refusé et le plan est refait.

4. Déploiement : schéma, fichiers, release

  1. Schéma. Les modifications de tables s'exécutent comme un déploiement de base de données, listé dans l'historique des déploiements de l'environnement comme n'importe quel autre. Une modification qui perd des données ne s'exécute que si le pipeline autorise explicitement la perte de données.
  2. Fichiers. Les artefacts sont écrits en une seule transaction, donc les utilisateurs voient toute la nouvelle version d'un package ou rien du tout. Un déploiement ne touche qu'à ce que le package contient et crée, et jamais à ce que chaque environnement décide pour lui-même.
  3. Release. Une fois les fichiers en place, le pipeline publie lui-même une release. C'est le moment où les nouvelles pages et les nouveaux layouts d'application atteignent l'application publiée, et personne ne publie à la main. Chaque déploiement est une nouvelle version de l'application, avec sa propre release.

Un environnement qui n'a jamais publié de release affiche ses brouillons, donc les nouveaux fichiers y seraient visibles dès leur arrivée. Avant son premier déploiement vers un tel environnement, le pipeline publie donc une release de ce que l'environnement contient déjà, et à partir de là les nouveaux fichiers attendent sous forme de brouillons jusqu'à leur propre release, comme dans chaque déploiement suivant.

Pourquoi l'environnement reste disponible

  • Rien ne redémarre. Un déploiement, ce sont des données dans les bases de données de l'environnement, pas un nouveau build du serveur. L'API continue de répondre pendant tout ce temps, et un script modifié est compilé la première fois qu'il s'exécute.
  • Les fichiers arrivent d'un coup. Une transaction par package, donc personne ne travaille sur la moitié d'un package.
  • Les pages basculent en une seule étape. L'application publiée lit la release courante. Les nouvelles pages attendent sous forme de brouillons jusqu'à ce que la release soit publiée, ce qui fait passer tous les utilisateurs sur elles au même moment. Activer la release précédente fait un retour arrière ; il restaure les pages et les layouts, jamais les données ni les tables.
  • Les modifications de tables sont planifiées et relues. Ajouter une table ou une colonne nullable ne gêne personne, et tout ce qui perd des données demande un oui explicite.

Étendre, puis réduire

Les Script Modules, les Business Events et les Business Entities sont actifs dès que leurs fichiers arrivent, pas à la release. Une modification qui renomme ou supprime une colonne part donc en deux déploiements :

  1. Étendre. Ajoutez la nouvelle table ou colonne, et déployez les scripts et les pages qui l'utilisent, en laissant l'ancienne en place.
  2. Réduire. Dans un déploiement ultérieur, une fois que plus rien ne lit l'ancienne colonne, supprimez-la. Le plan marque la suppression comme une perte de données, et la vérification des scripts typés indique si quelque chose l'utilise encore.

Une modification qui réécrit une grande table, comme un nouveau type pour une colonne, pose un verrou sur cette table pendant son exécution. Programmez-les à un moment calme.

Environnements

Le dépôt liste ses environnements dans archestack.json. Un environnement marqué "mode": "pipeline" n'est déployé que par le pipeline, et l'extension VS Code refuse d'y pousser quoi que ce soit à la main :

"environments": {
  "tst": { "url": "https://acme-tst.example.com", "apiUrl": "https://api.example.com", "workspace": "acme-tst.example.com", "mode": "pipeline" },
  "acc": { "url": "https://acme-acc.example.com", "apiUrl": "https://api.example.com", "workspace": "acme-acc.example.com", "mode": "pipeline" },
  "prd": { "url": "https://acme.example.com", "apiUrl": "https://api.example.com", "workspace": "acme.example.com", "mode": "pipeline" }
}

Ce que chaque environnement décide pour lui-même ne figure ni dans les fichiers ni dans aucun déploiement : les utilisateurs et les rôles, les permissions des pages, ce qui est marqué public, les autorisations et les clés de la Data API, les comptes mail et les connexions à d'autres systèmes. Les administrateurs de chaque environnement les règlent, donc un déploiement ne peut jamais rendre quelque chose public ni donner accès à qui que ce soit.

Le fichier de pipeline

Le pipeline se trouve dans le dépôt et déploie à partir de celui-ci : chaque exécution extrait un seul commit, et ce sont ces fichiers-là qui sont construits, testés et déployés. Rien n'est exporté d'un espace de travail. Voici ci-dessous le même pipeline pour trois systèmes de CI, chacun faisant passer une modification par le test, la recette et la production. Les commandes archestack sont celles de l'Archestack CLI, donc tout autre système de CI qui fait tourner .NET et Docker sous Linux exécute les mêmes étapes.

  • L'étape Build et tests s'exécute pour chaque pull request et chaque fusion dans la branche principale. Elle construit un Archestack jetable à partir du commit, exécute les tests de tous les packages et empaquette le dépôt en un seul artefact, pour que chaque environnement reçoive exactement les mêmes fichiers.
  • Un plan et un déploiement par environnement. Le plan est établi par rapport à l'environnement et affiché dans l'exécution ; le déploiement applique ensuite exactement ce plan, après une approbation pour la recette et la production. Les environnements se suivent l'un après l'autre, donc la recette n'est planifiée qu'une fois le test déployé, et la production qu'une fois la recette déployée. Une pull request s'arrête après le plan par rapport au test.
  • Jetons de déploiement. Le jeton de chaque environnement se crée dans le builder de cet environnement, sous Operations, Deploy Tokens. Il n'est affiché qu'une fois, agit en administrateur et ne sert qu'au déploiement : il ne lit jamais les données de l'environnement. L'adresse de l'environnement vient de archestack.json.
Votre système de CI

Azure DevOps

Le pipeline est le fichier azure-pipelines.yml à la racine du dépôt :

# azure-pipelines.yml: build and test, then plan and deploy test, acceptance and production
trigger:
  branches:
    include: [main]

pr:
  branches:
    include: [main]

parameters:
  - name: environments
    type: object
    default: [tst, acc, prd]
  - name: allowDataLoss
    displayName: Allow changes that lose data
    type: boolean
    default: false

pool:
  vmImage: ubuntu-latest

stages:
  - stage: build
    displayName: Build and test
    jobs:
      - job: build
        steps:
          - checkout: self
            displayName: The repository at this commit
          - script: |
              dotnet tool install --global Archestack.Cli
              echo "##vso[task.prependpath]$HOME/.dotnet/tools"
            displayName: Install the Archestack CLI
          - script: archestack build
            displayName: Build a throwaway Archestack from the repository
          - script: archestack test --junit $(Agent.TempDirectory)/tests.xml
            displayName: Run every package's tests
          - task: PublishTestResults@2
            condition: succeededOrFailed()
            inputs:
              testResultsFormat: JUnit
              testResultsFiles: $(Agent.TempDirectory)/tests.xml
          - script: archestack pack --out $(Build.ArtifactStagingDirectory)/app.zip
            displayName: Pack the repository
          - publish: $(Build.ArtifactStagingDirectory)
            artifact: app

  - ${{ each env in parameters.environments }}:
    - stage: plan_${{ env }}
      displayName: Plan ${{ env }}
      ${{ if ne(env, 'tst') }}:
        condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
      variables:
        - group: archestack-${{ env }}
      jobs:
        - job: plan
          steps:
            - download: current
              artifact: app
            - script: |
                dotnet tool install --global Archestack.Cli
                echo "##vso[task.prependpath]$HOME/.dotnet/tools"
              displayName: Install the Archestack CLI
            - script: >-
                archestack plan --env ${{ env }}
                --from $(Pipeline.Workspace)/app/app.zip
                --allow-data-loss ${{ parameters.allowDataLoss }}
                --out $(Build.ArtifactStagingDirectory)/plan.json
                --summary $(Build.ArtifactStagingDirectory)/plan.md
              displayName: Plan against ${{ env }}
              env:
                ARCHESTACK_TOKEN: $(ARCHESTACK_TOKEN)
            - script: echo "##vso[task.uploadsummary]$(Build.ArtifactStagingDirectory)/plan.md"
              displayName: Show the plan in the run
            - publish: $(Build.ArtifactStagingDirectory)
              artifact: plan-${{ env }}

    - stage: deploy_${{ env }}
      displayName: Deploy ${{ env }}
      condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
      variables:
        - group: archestack-${{ env }}
      jobs:
        - deployment: deploy
          environment: archestack-${{ env }}
          strategy:
            runOnce:
              deploy:
                steps:
                  - download: current
                    artifact: app
                  - download: current
                    artifact: plan-${{ env }}
                  - script: |
                      dotnet tool install --global Archestack.Cli
                      echo "##vso[task.prependpath]$HOME/.dotnet/tools"
                    displayName: Install the Archestack CLI
                  - script: >-
                      archestack deploy --env ${{ env }}
                      --from $(Pipeline.Workspace)/app/app.zip
                      --plan $(Pipeline.Workspace)/plan-${{ env }}/plan.json
                    displayName: Schema, files and release
                    env:
                      ARCHESTACK_TOKEN: $(ARCHESTACK_TOKEN)
  • Approbations. Créez les environnements archestack-tst, archestack-acc et archestack-prd sous Pipelines, Environments, et ajoutez une vérification Approvals à la recette et à la production. Azure DevOps attend alors un approbateur avant que ces étapes de déploiement ne commencent, avec le plan dans le résumé de l'exécution. Les résultats des tests sont publiés dans l'exécution.
  • Identifiants. Le jeton de déploiement de chaque environnement est le secret ARCHESTACK_TOKEN d'un groupe de variables qui porte le même nom que l'environnement, comme archestack-prd.
  • Perte de données. Allow changes that lose data est une case à cocher lorsqu'une exécution est lancée à la main, décochée par défaut. Sans elle, un plan qui supprime une table ou une colonne arrête le pipeline.
  • Pull requests sur Azure Repos. Azure Repos ignore la section pr: ; ajoutez plutôt le pipeline comme build validation branch policy sur la branche principale.
  • Un pipeline créé dans l'éditeur web est enregistré comme un nouveau fichier portant le nom du pipeline. Faites pointer le pipeline vers azure-pipelines.yml dans ses paramètres, sinon le fichier que vous modifiez n'est pas celui qui s'exécute.

GitHub Actions

Le workflow est le fichier .github/workflows/archestack.yml :

# .github/workflows/archestack.yml: build and test, then plan and deploy test, acceptance and production
name: Archestack

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_dispatch:
    inputs:
      allow-data-loss:
        description: Allow changes that lose data
        type: boolean
        default: false

permissions:
  contents: read

jobs:
  build:
    name: Build and test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: 8.0.x
      - name: Install the Archestack CLI
        run: dotnet tool install --global Archestack.Cli
      - name: Build a throwaway Archestack from the repository
        run: archestack build
      - name: Run every package's tests
        run: archestack test --junit "$RUNNER_TEMP/tests.xml"
      - uses: actions/upload-artifact@v4
        if: ${{ !cancelled() }}
        with:
          name: tests
          path: ${{ runner.temp }}/tests.xml
      - name: Pack the repository
        run: archestack pack --out "$RUNNER_TEMP/app/app.zip"
      - uses: actions/upload-artifact@v4
        with:
          name: app
          path: ${{ runner.temp }}/app

  # A pull request stops after the plan against test.
  tst:
    needs: build
    uses: ./.github/workflows/archestack-deploy.yml
    with:
      environment: tst
      deploy: ${{ github.event_name != 'pull_request' }}
      allow-data-loss: ${{ inputs.allow-data-loss == true }}
    secrets:
      token: ${{ secrets.ARCHESTACK_TOKEN_TST }}

  acc:
    if: github.event_name != 'pull_request'
    needs: tst
    uses: ./.github/workflows/archestack-deploy.yml
    with:
      environment: acc
      allow-data-loss: ${{ inputs.allow-data-loss == true }}
    secrets:
      token: ${{ secrets.ARCHESTACK_TOKEN_ACC }}

  prd:
    if: github.event_name != 'pull_request'
    needs: acc
    uses: ./.github/workflows/archestack-deploy.yml
    with:
      environment: prd
      allow-data-loss: ${{ inputs.allow-data-loss == true }}
    secrets:
      token: ${{ secrets.ARCHESTACK_TOKEN_PRD }}

Chaque environnement est planifié et déployé par le même workflow réutilisable placé à côté :

# .github/workflows/archestack-deploy.yml: plans the packed files against one environment, then deploys that plan
name: Archestack environment

on:
  workflow_call:
    inputs:
      environment:
        type: string
        required: true
      deploy:
        type: boolean
        default: true
      allow-data-loss:
        type: boolean
        default: false
    secrets:
      token:
        required: true

jobs:
  plan:
    name: Plan ${{ inputs.environment }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: app
          path: app
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: 8.0.x
      - run: dotnet tool install --global Archestack.Cli
      - name: Plan against ${{ inputs.environment }}
        run: >-
          archestack plan --env ${{ inputs.environment }}
          --from app/app.zip
          --allow-data-loss ${{ inputs.allow-data-loss }}
          --out plan/plan.json
          --summary plan/plan.md
        env:
          ARCHESTACK_TOKEN: ${{ secrets.token }}
      - name: Show the plan in the run
        if: ${{ !cancelled() }}
        run: cat plan/plan.md >> "$GITHUB_STEP_SUMMARY"
      - uses: actions/upload-artifact@v4
        with:
          name: plan-${{ inputs.environment }}
          path: plan

  deploy:
    name: Deploy ${{ inputs.environment }}
    if: inputs.deploy
    needs: plan
    runs-on: ubuntu-latest
    environment: archestack-${{ inputs.environment }}
    concurrency: archestack-${{ inputs.environment }}
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: app
          path: app
      - uses: actions/download-artifact@v4
        with:
          name: plan-${{ inputs.environment }}
          path: plan
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: 8.0.x
      - run: dotnet tool install --global Archestack.Cli
      - name: Schema, files and release
        run: archestack deploy --env ${{ inputs.environment }} --from app/app.zip --plan plan/plan.json
        env:
          ARCHESTACK_TOKEN: ${{ secrets.token }}
  • Approbations. Créez les environnements archestack-tst, archestack-acc et archestack-prd sous Settings, Environments, et ajoutez des required reviewers à la recette et à la production. Le job de déploiement attend un relecteur, avec le plan déjà dans le résumé de l'exécution. Sur un dépôt privé, les environnements nécessitent GitHub Pro, Team ou Enterprise.
  • Identifiants. Les jetons de déploiement sont les secrets de dépôt ARCHESTACK_TOKEN_TST, ARCHESTACK_TOKEN_ACC et ARCHESTACK_TOKEN_PRD, pour que le plan puisse s'exécuter avant l'approbation. Un workflow sur n'importe quelle branche du dépôt peut lire un secret de dépôt ; pour réserver le jeton de la production aux exécutions approuvées, faites-en plutôt un secret d'environnement de archestack-prd, et son plan s'exécute alors après l'approbation.
  • Perte de données. Allow changes that lose data est une case à cocher sous Run workflow, décochée par défaut.
  • Les pull requests venant de forks ne reçoivent aucun secret, donc leur plan par rapport au test échoue ; les pull requests venant de branches du dépôt lui-même planifient normalement.
  • concurrency empêche deux exécutions de déployer vers le même environnement en même temps. Les résultats des tests sont conservés comme artefact tests de l'exécution.

GitLab CI

Le pipeline est le fichier .gitlab-ci.yml à la racine du dépôt :

# .gitlab-ci.yml: build and test, then plan and deploy test, acceptance and production
workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

variables:
  ALLOW_DATA_LOSS:
    value: "false"
    description: Allow changes that lose data (true or false)

stages: [build, tst, acc, prd]

default:
  image: mcr.microsoft.com/dotnet/sdk:8.0
  before_script:
    - dotnet tool install --global Archestack.Cli
    - export PATH="$PATH:$HOME/.dotnet/tools"

build:
  stage: build
  # The throwaway Archestack runs in Docker, here a Docker service beside the job.
  services:
    - docker:27-dind
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
  script:
    - curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz | tar -xz -C /usr/local/bin --strip-components=1 docker/docker
    - archestack build
    - archestack test --junit tests.xml
    - archestack pack --out app.zip
  artifacts:
    when: always
    paths: [app.zip]
    reports:
      junit: tests.xml

.plan:
  script:
    - archestack plan --env "$TARGET" --from app.zip --allow-data-loss "$ALLOW_DATA_LOSS" --out plan.json --summary plan.md
  artifacts:
    when: always
    expose_as: plan
    paths: [plan.md, plan.json]

.deploy:
  script:
    - archestack deploy --env "$TARGET" --from app.zip --plan plan.json

# A merge request stops after the plan against test.
plan-tst:
  extends: .plan
  stage: tst
  needs: [build]
  variables: { TARGET: tst }

deploy-tst:
  extends: .deploy
  stage: tst
  needs: [build, plan-tst]
  environment: archestack-tst
  resource_group: archestack-tst
  variables: { TARGET: tst }
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

plan-acc:
  extends: .plan
  stage: acc
  needs: [build, deploy-tst]
  variables: { TARGET: acc }
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

deploy-acc:
  extends: .deploy
  stage: acc
  needs: [build, plan-acc]
  environment: archestack-acc
  resource_group: archestack-acc
  variables: { TARGET: acc }
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: manual
  allow_failure: false

plan-prd:
  extends: .plan
  stage: prd
  needs: [build, deploy-acc]
  variables: { TARGET: prd }
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

deploy-prd:
  extends: .deploy
  stage: prd
  needs: [build, plan-prd]
  environment: archestack-prd
  resource_group: archestack-prd
  variables: { TARGET: prd }
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: manual
  allow_failure: false
  • Docker. Le build fait tourner l'Archestack jetable sur un service docker:dind à côté du job, ce qui demande un runner qui autorise les conteneurs privilégiés, comme le font les runners de GitLab.com. DOCKER_HOST indique à la CLI où se trouve Docker, et elle y atteint l'Archestack.
  • Approbations. Le déploiement vers la recette et vers la production sont des jobs manuels qui bloquent le pipeline, chacun lancé une fois son plan lu. Chaque plan est conservé avec son job, et le plan par rapport au test est aussi lié depuis la merge request. Avec GitLab Premium, protégez aussi ces environnements et exigez des approbations.
  • Identifiants. Les jetons de déploiement sont les variables CI/CD masquées ARCHESTACK_TOKEN_TST, ARCHESTACK_TOKEN_ACC et ARCHESTACK_TOKEN_PRD. Protégez celles de la recette et de la production, pour que seule la branche principale les lise. Une variable protégée n'atteint pas un pipeline de merge request, laissez donc celle du test non protégée pour que les merge requests puissent planifier par rapport au test.
  • Perte de données. Lancez le pipeline à la main avec ALLOW_DATA_LOSS défini à true. Les résultats des tests s'affichent dans la merge request.
  • resource_group empêche deux pipelines de déployer vers le même environnement en même temps.

L'Archestack CLI

La CLI est l'outil .NET Archestack.Cli, installé avec dotnet tool install --global Archestack.Cli sur tout agent disposant de .NET 8 ou plus récent. Ses commandes s'exécutent à la racine du dépôt, ou prennent --from avec un dossier ou un ZIP empaqueté :

  • archestack build démarre l'Archestack jetable et y charge le dépôt. Il tourne dans Docker à partir de l'image que nomme la section project de archestack.json, sinon de la dernière image publiée ; --image en choisit une autre, et --runtime fait tourner un dossier de runtime sans Docker. Il est prêt une fois restaurés les paquets NuGet que nomme le dépôt, et reste en marche pour l'étape suivante jusqu'à archestack stop. --nuget-cache <folder> garde ces téléchargements pour le build suivant, qui sinon les télécharge à nouveau ; deux builds qui tournent en même temps ont chacun besoin de leur propre dossier.
  • archestack test exécute dessus les cas de test de tous les packages, quatre à la fois, et écrit du JUnit avec --junit.
  • archestack pack --out app.zip empaquette archestack.json, packages/ et workspace/. Les mêmes fichiers donnent toujours les mêmes octets, et le plan enregistre leur hachage, donc un déploiement refuse d'autres fichiers que ceux qui ont été planifiés.
  • archestack plan et archestack deploy ne fonctionnent que sur un environnement marqué "mode": "pipeline", avec son jeton de déploiement dans ARCHESTACK_TOKEN_<ENV> (comme ARCHESTACK_TOKEN_PRD) ou ARCHESTACK_TOKEN. Un artefact supprimé du dépôt est retiré de son package et laissé dans l'environnement ; planifiez avec --delete-removed true pour l'y supprimer aussi. Un package de l'environnement que le dépôt ne contient pas est laissé tel quel et nommé dans le plan. Quand le dépôt nomme des paquets NuGet, les deux demandent d'abord à l'environnement s'ils s'y restaurent, et deploy attend jusqu'à cinq minutes après le dernier push que l'environnement les ait restaurés, avant de publier la release. Si cette attente échoue, les fichiers sont déployés mais aucune release n'est publiée.

Le code de sortie indique ce qui a arrêté une étape : 3 le jeton a été refusé, 4 l'environnement a changé depuis le plan (planifiez à nouveau), 5 les fichiers ne peuvent pas être appliqués en l'état, 6 le plan perd des données et ce n'était pas autorisé, 7 un test a échoué, 9 le serveur ou le réseau a échoué, 10 l'environnement fait tourner une autre version majeure d'Archestack que la CLI, ou une version sans prise en charge de NuGet. Des paquets NuGet qui ne se restaurent pas avec les fichiers donnent un 5, tout comme un environnement où les paquets NuGet ou l'accès typé aux données sont désactivés. Pour plan et deploy, un échec NuGet que les fichiers ne peuvent pas corriger donne un 9 : par exemple un serveur à court d'espace disque, un flux qu'il ne peut pas joindre, ou une restauration après le dernier push qui a échoué ou ne s'est pas terminée en cinq minutes. La même étape peut alors réussir à la prochaine exécution.

Ce qui fonctionne aujourd'hui

  • Build, tests, plan et déploiement passent par la CLI, depuis des étapes de script comme dans les pipelines ci-dessus. Sur la machine d'un développeur, le projet de l'extension VS Code est ce même build : Reset Project Database le construit à partir de rien, et Run Tests exécute dessus les tests de tous les packages.
  • Les tâches de pipeline pour Azure DevOps et GitHub Actions qui encapsulent la CLI : en cours de développement.

Pièges

  • Un retour arrière ne défait ni les tables ni les données. Chaque déploiement est une release, donc toute version que le pipeline a déployée peut être réactivée, mais cela ne restaure que les pages et les layouts. Ramener les tables en arrière est un déploiement à part entière, planifié et relu comme n'importe quel autre.
  • Les Script Modules et les Business Events n'attendent pas la release. Ils sont actifs dès que leurs fichiers arrivent, c'est pourquoi une modification qui supprime quelque chose part en deux déploiements.
  • Chaque environnement télécharge ses propres paquets NuGet. Les paquets NuGet que déclare le nuget.json d'un package sont téléchargés par chaque environnement qui le reçoit, build compris, donc chacun doit pouvoir joindre nuget.org ou le flux avec lequel ses serveurs sont configurés. Le build reprend Scripting__NuGet__Sources et les paramètres Scripting__NuGet__Feeds__* des variables d'environnement de la machine où s'exécute la CLI. Un push dont les paquets NuGet ne peuvent pas être restaurés est refusé et ne change rien : le plan de la CLI le vérifie avant que quoi que ce soit ne soit déployé, et build et deploy attendent qu'ils soient restaurés.

Pour aller plus loin

Travailler en équipe explique comment les développeurs se partagent le dépôt que le pipeline déploie. Espaces de travail et hébergement présente les environnements vers lesquels il déploie, et Database Deployments l'étape du schéma.