Przewodnik - 12 min

Wdrażanie z repozytorium

Repozytorium jest źródłem aplikacji Archestack, tak jak kod źródłowy jest źródłem programu. Wdrożenie traktuje Archestack jak kompilator: pipeline buduje z plików repozytorium tymczasowy Archestack, uruchamia na nim testy i dopiero gdy przejdą, planuje zmianę względem hostowanego środowiska i wprowadza ją tam. Hostowane środowisko przez cały ten czas obsługuje swoich użytkowników.

Stan: Archestack CLI uruchamia każdy z poniższych etapów jako krok skryptu dowolnego pipeline'u. Gotowe zadania pipeline'u dla Azure DevOps i GitHub Actions, które go opakowują, są w trakcie tworzenia; sekcja Co działa dziś mówi, co uruchamia każdy etap.

Twój system CI

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

Pull request uruchamia build, testy i plan względem środowiska testowego, więc recenzent widzi, co by się zmieniło, zanim cokolwiek zostanie scalone. Merge do gałęzi głównej uruchamia wszystkie etapy, a środowisko akceptacyjne i produkcyjne czekają, aż ktoś zatwierdzi plan każdego z nich.

1. Build: Archestack jako kompilator

Pipeline uruchamia na agencie builda pusty Archestack, w Dockerze z tego samego obrazu API, na którym działają środowiska, albo z folderu runtime'u takiego jak ten, którym rozszerzenie VS Code uruchamia projekty, i wczytuje do niego repozytorium: tabele wszystkich packages w jednym wdrożeniu, potem artefakty każdego package'a, zależności przed packages, które ich potrzebują. To tutaj błąd wychodzi na jaw najwcześniej, tak jak błąd kompilacji: odwołanie do Business Entity, tabeli albo skryptu, których nie ma, albo nazwa, której używa już inny package, zatrzymuje wczytywanie. Wynikiem jest środowisko zbudowane wyłącznie z plików, bez żadnych pozostałości z czyjejkolwiek maszyny.

2. Testy

Przypadki testowe wszystkich packages działają na tym buildzie, każdy we własnej bazie sandbox, a maile i powiadomienia są rejestrowane, a nie wysyłane. Każdy skrypt, który uruchamia test, jest najpierw kompilowany, więc test ze skryptem, który przestał się kompilować, kończy się niepowodzeniem. Jeden nieudany przypadek zatrzymuje pipeline i nic nie zostaje wdrożone.

3. Plan względem środowiska docelowego

Te same pliki są planowane względem środowiska docelowego: które artefakty zostaną tam utworzone, zmienione lub usunięte i które zmiany tabel zostaną wykonane jako SQL, z ryzykiem każdej operacji i typowanymi skryptami, które po tej zmianie przestałyby się kompilować. Plan ma swój hash. Wdrożenie wprowadza dokładnie ten plan, który został zatwierdzony: jeśli środowisko docelowe w międzyczasie się zmieniło, wdrożenie jest odrzucane, a plan powstaje od nowa.

4. Wdrożenie: schemat, pliki, wydanie

  1. Schemat. Zmiany tabel są wykonywane jako wdrożenie bazy danych, widoczne w historii wdrożeń środowiska jak każde inne. Zmiana, która traci dane, jest wykonywana tylko wtedy, gdy pipeline wprost pozwala na utratę danych.
  2. Pliki. Artefakty są zapisywane w jednej transakcji, więc użytkownicy widzą całą nową wersję package'a albo nic z niej. Wdrożenie dotyka tylko tego, co package zawiera i tworzy, i nigdy tego, o czym każde środowisko decyduje samo.
  3. Wydanie. Gdy pliki są już na miejscu, pipeline sam publikuje wydanie. To moment, w którym nowe strony i układy aplikacji docierają do opublikowanej aplikacji, i nikt nie publikuje ręcznie. Każde wdrożenie to nowa wersja aplikacji z własnym wydaniem.

Środowisko, które nigdy nie opublikowało wydania, pokazuje swoje wersje robocze, więc nowe pliki byłyby widoczne w chwili, gdy trafią na miejsce. Przed pierwszym wdrożeniem na takie środowisko pipeline publikuje więc wydanie tego, co środowisko już zawiera, a od tej pory nowe pliki czekają jako wersje robocze na własne wydanie, tak jak przy każdym kolejnym wdrożeniu.

Dlaczego środowisko działa bez przerwy

  • Nic się nie restartuje. Wdrożenie to dane w bazach danych środowiska, a nie nowy build serwera. API przez cały czas odpowiada, a zmieniony skrypt jest kompilowany przy pierwszym uruchomieniu.
  • Pliki trafiają na miejsce naraz. Jedna transakcja na package, więc nikt nie pracuje na połowie package'a.
  • Strony przełączają się w jednym kroku. Opublikowana aplikacja czyta bieżące wydanie. Nowe strony czekają jako wersje robocze, dopóki wydanie nie zostanie opublikowane, co przenosi na nie wszystkich użytkowników w tym samym momencie. Aktywacja poprzedniego wydania wycofuje zmiany; przywraca strony i układy, nigdy dane ani tabele.
  • Zmiany tabel są planowane i przeglądane. Dodanie tabeli albo kolumny dopuszczającej wartości null nikomu nie przeszkadza, a wszystko, co traci dane, wymaga wyraźnej zgody.

Najpierw rozszerz, potem zawęź

Script Modules, Business Events i Business Entities działają od chwili, w której ich pliki trafią na miejsce, a nie od wydania. Zmiana, która zmienia nazwę kolumny albo ją usuwa, trafia więc na środowisko w dwóch wdrożeniach:

  1. Rozszerz. Dodaj nową tabelę albo kolumnę i wdróż skrypty i strony, które z niej korzystają, podczas gdy stara wciąż jest na miejscu.
  2. Zawęź. W późniejszym wdrożeniu, gdy nic już nie czyta starej kolumny, usuń ją. Plan oznacza usunięcie jako utratę danych, a sprawdzenie typowanych skryptów mówi, czy coś nadal jej używa.

Zmiana, która przepisuje dużą tabelę, na przykład nowy typ kolumny, blokuje tę tabelę, dopóki trwa. Zaplanuj takie zmiany na spokojny moment.

Środowiska

Repozytorium wymienia swoje środowiska w archestack.json. Środowisko oznaczone "mode": "pipeline" jest wdrażane wyłącznie przez pipeline, a rozszerzenie VS Code nie pozwala ręcznie wysyłać do niego zmian:

"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" }
}

To, o czym każde środowisko decyduje samo, nie znajduje się w plikach ani w żadnym wdrożeniu: użytkownicy i role, uprawnienia stron, oznaczenia jako publiczne, uprawnienia i klucze Data API, konta pocztowe i połączenia z innymi systemami. Ustawiają je administratorzy każdego środowiska, więc wdrożenie nigdy nie może uczynić niczego publicznym ani nikomu dać dostępu.

Plik pipeline'u

Pipeline znajduje się w repozytorium i z niego wdraża: każde uruchomienie wykonuje checkout jednego commita, i to właśnie te pliki są budowane, testowane i wdrażane. Nic nie jest eksportowane z przestrzeni roboczej. Poniżej jest ten sam pipeline dla trzech systemów CI, a każdy z nich przeprowadza zmianę przez środowisko testowe, akceptacyjne i produkcyjne. Polecenia archestack pochodzą z Archestack CLI, więc każdy inny system CI, który uruchamia .NET i Dockera na Linuksie, wykonuje te same kroki.

  • Etap Build and test uruchamia się dla każdego pull requesta i każdego merge'a do gałęzi main. Buduje z commita tymczasowy Archestack, uruchamia testy wszystkich packages i pakuje repozytorium w jeden artefakt, więc każde środowisko dostaje dokładnie te same pliki.
  • Krok planu i krok wdrożenia dla każdego środowiska. Plan powstaje względem środowiska i jest pokazywany w uruchomieniu; wdrożenie wprowadza potem dokładnie ten plan, po zatwierdzeniu w przypadku środowiska akceptacyjnego i produkcyjnego. Środowiska idą jedno po drugim, więc akceptacyjne jest planowane dopiero po wdrożeniu testowego, a produkcyjne dopiero po wdrożeniu akceptacyjnego. Pull request zatrzymuje się po planie względem środowiska testowego.
  • Tokeny wdrożeniowe. Token każdego środowiska tworzy się w builderze tego środowiska, w Operations, Deploy Tokens. Jest pokazywany tylko raz, działa jako administrator i służy wyłącznie do wdrażania: nigdy nie odczytuje danych środowiska. Adres środowiska pochodzi z archestack.json.
Twój system CI

Azure DevOps

Pipeline to azure-pipelines.yml w katalogu głównym repozytorium:

# 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)
  • Zatwierdzenia. Utwórz środowiska archestack-tst, archestack-acc i archestack-prd w Pipelines, Environments i dodaj do akceptacyjnego i produkcyjnego sprawdzenie Approvals. Azure DevOps czeka wtedy na osobę zatwierdzającą, zanim ruszą te etapy wdrożenia, a plan widać w podsumowaniu uruchomienia. Wyniki testów są publikowane w uruchomieniu.
  • Poświadczenia. Token wdrożeniowy każdego środowiska to sekret ARCHESTACK_TOKEN w grupie zmiennych o tej samej nazwie co środowisko, na przykład archestack-prd.
  • Utrata danych. Allow changes that lose data to pole wyboru przy ręcznym uruchomieniu, domyślnie odznaczone. Bez jego zaznaczenia plan, który usuwa tabelę albo kolumnę, zatrzymuje pipeline.
  • Pull requesty w Azure Repos. Azure Repos ignoruje sekcję pr:; zamiast tego dodaj pipeline jako build validation branch policy na gałęzi main.
  • Pipeline utworzony w edytorze webowym jest zapisywany jako nowy plik nazwany tak jak pipeline. Wskaż w ustawieniach pipeline'u plik azure-pipelines.yml, bo inaczej plik, który edytujesz, nie jest tym, który się uruchamia.

GitHub Actions

Workflow to .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 }}

Każde środowisko jest planowane i wdrażane przez ten sam reusable workflow obok niego:

# .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 }}
  • Zatwierdzenia. Utwórz środowiska archestack-tst, archestack-acc i archestack-prd w Settings, Environments i dodaj do akceptacyjnego i produkcyjnego required reviewers. Job wdrożenia czeka na recenzenta, a plan jest już w podsumowaniu uruchomienia. W prywatnym repozytorium środowiska wymagają GitHub Pro, Team albo Enterprise.
  • Poświadczenia. Tokeny wdrożeniowe to sekrety repozytorium ARCHESTACK_TOKEN_TST, ARCHESTACK_TOKEN_ACC i ARCHESTACK_TOKEN_PRD, więc plan może się wykonać przed zatwierdzeniem. Workflow na dowolnej gałęzi repozytorium może odczytać sekret repozytorium; żeby token produkcyjny był dostępny tylko dla zatwierdzonych uruchomień, zrób z niego zamiast tego sekret środowiska archestack-prd, a jego plan wykona się wtedy po zatwierdzeniu.
  • Utrata danych. Allow changes that lose data to pole wyboru pod Run workflow, domyślnie odznaczone.
  • Pull requesty z forków nie dostają sekretów, więc ich plan względem środowiska testowego się nie powiedzie; pull requesty z gałęzi samego repozytorium są planowane jak zwykle.
  • concurrency nie pozwala dwóm uruchomieniom wdrażać na to samo środowisko w tym samym czasie. Wyniki testów są zachowywane jako artefakt tests uruchomienia.

GitLab CI

Pipeline to .gitlab-ci.yml w katalogu głównym repozytorium:

# .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. Build uruchamia tymczasowy Archestack w usłudze docker:dind obok joba, co wymaga runnera pozwalającego na kontenery uprzywilejowane, tak jak własne runnery GitLab.com. DOCKER_HOST mówi CLI, gdzie jest Docker, i tam CLI łączy się z Archestack.
  • Zatwierdzenia. Wdrożenie na środowisko akceptacyjne i produkcyjne to ręczne joby, które blokują pipeline, a każdy z nich uruchamia się po przeczytaniu jego planu. Każdy plan jest zachowywany przy swoim jobie, a plan względem środowiska testowego jest też podlinkowany w merge requeście. W GitLab Premium dodatkowo zabezpiecz te środowiska i wymagaj zatwierdzeń.
  • Poświadczenia. Tokeny wdrożeniowe to maskowane zmienne CI/CD ARCHESTACK_TOKEN_TST, ARCHESTACK_TOKEN_ACC i ARCHESTACK_TOKEN_PRD. Oznacz zmienne akceptacyjnego i produkcyjnego jako chronione, żeby odczytywała je tylko gałąź main. Chroniona zmienna nie trafia do pipeline'u merge requesta, więc zostaw zmienną testowego niechronioną, żeby merge requesty mogły planować względem środowiska testowego.
  • Utrata danych. Uruchom pipeline ręcznie z ALLOW_DATA_LOSS ustawionym na true. Wyniki testów widać w merge requeście.
  • resource_group nie pozwala dwóm pipeline'om wdrażać na to samo środowisko w tym samym czasie.

Archestack CLI

CLI to narzędzie .NET Archestack.Cli, instalowane poleceniem dotnet tool install --global Archestack.Cli na dowolnym agencie z .NET 8 lub nowszym. Jego polecenia uruchamia się z katalogu głównego repozytorium albo z opcją --from wskazującą folder lub spakowany plik ZIP:

  • archestack build uruchamia tymczasowy Archestack i wczytuje do niego repozytorium. Działa w Dockerze z obrazu, który wskazuje sekcja project w archestack.json, a w przeciwnym razie z najnowszego opublikowanego; --image wybiera inny, a --runtime uruchamia folder runtime'u bez Dockera. Jest gotowy, gdy pakiety NuGet wskazane w repozytorium zostaną przywrócone, i działa dalej na potrzeby kolejnego kroku, aż do archestack stop. --nuget-cache <folder> zachowuje te pobrane pliki dla następnego buildu, który inaczej pobiera je od nowa; dwa buildy działające jednocześnie potrzebują każdy własnego folderu.
  • archestack test uruchamia na nim przypadki testowe wszystkich packages, po cztery naraz, i zapisuje wyniki JUnit z opcją --junit.
  • archestack pack --out app.zip pakuje archestack.json, packages/ i workspace/. Te same pliki zawsze dają te same bajty, a plan zapisuje ich hash, więc wdrożenie odrzuca pliki inne niż te, które zostały zaplanowane.
  • archestack plan i archestack deploy działają tylko na środowisku oznaczonym "mode": "pipeline", z jego tokenem wdrożeniowym w ARCHESTACK_TOKEN_<ENV> (na przykład ARCHESTACK_TOKEN_PRD) albo ARCHESTACK_TOKEN. Artefakt usunięty z repozytorium zostaje wyjęty ze swojego package'a i pozostaje w środowisku; zaplanuj z --delete-removed true, żeby usunąć go także tam. Package w środowisku, którego repozytorium nie zawiera, zostaje nietknięty i jest wymieniony w planie. Gdy repozytorium wskazuje pakiety NuGet, oba polecenia najpierw pytają środowisko, czy da się je tam przywrócić, a deploy po ostatnim wysłaniu zmian czeka do pięciu minut, aż środowisko je przywróci, zanim opublikuje wydanie. Jeśli to czekanie się nie powiedzie, pliki są wdrożone, ale żadne wydanie nie zostaje opublikowane.

Kod wyjścia mówi, co zatrzymało krok: 3 token został odrzucony, 4 środowisko zmieniło się od czasu planu (zaplanuj ponownie), 5 plików nie da się wprowadzić w obecnej postaci, 6 plan traci dane, a nie było na to zgody, 7 test się nie powiódł, 9 zawiódł serwer albo sieć, 10 środowisko działa na innej wersji głównej Archestack niż CLI albo na wersji bez obsługi NuGet. Pakiety NuGet, których nie da się przywrócić razem z plikami, dają 5, tak samo jak środowisko, w którym pakiety NuGet albo typowany dostęp do danych są wyłączone. W plan i deploy błąd NuGet, którego pliki nie mogą naprawić, daje 9: na przykład serwer z za małą ilością miejsca na dysku, feed, do którego nie ma dostępu, albo przywracanie po ostatnim wysłaniu zmian, które się nie powiodło lub nie skończyło w ciągu pięciu minut. Ten sam krok może się wtedy udać przy następnym uruchomieniu.

Co działa dziś

  • Build, testy, plan i wdrożenie działają na CLI, jako kroki skryptu, jak w pipeline'ach powyżej. Na maszynie programisty projekt rozszerzenia VS Code to ten sam build: Reset Project Database buduje go od zera, a Run Tests uruchamia na nim testy wszystkich packages.
  • Zadania pipeline'u dla Azure DevOps i GitHub Actions, które opakowują CLI: w trakcie tworzenia.

Pułapki

  • Wycofanie nie cofa tabel ani danych. Każde wdrożenie jest wydaniem, więc każdą wersję wdrożoną przez pipeline można aktywować ponownie, ale przywraca to tylko strony i układy. Przywrócenie tabel to osobne wdrożenie, planowane i przeglądane jak każde inne.
  • Script Modules i Business Events nie czekają na wydanie. Działają od chwili, w której ich pliki trafią na miejsce, dlatego zmiana, która coś usuwa, trafia na środowisko w dwóch wdrożeniach.
  • Każde środowisko pobiera własne pakiety NuGet. Pakiety NuGet deklarowane w nuget.json package'a pobiera każde środowisko, które go otrzymuje, łącznie z buildem, więc każde musi mieć dostęp do nuget.org albo do feedu, z którym skonfigurowano jego serwery. Build bierze Scripting__NuGet__Sources i ustawienia Scripting__NuGet__Feeds__* ze środowiska, w którym działa CLI. Gdy pakietów NuGet nie da się przywrócić, wysłanie zmian jest odrzucane i niczego nie zmienia: plan w CLI sprawdza to, zanim cokolwiek zostanie wdrożone, a build i deploy czekają, aż zostaną przywrócone.

Co dalej

Sekcja Praca w zespole opisuje, jak programiści dzielą repozytorium, które wdraża pipeline. Strona Przestrzenie robocze i hosting wyjaśnia, na jakie środowiska wdraża, a sekcja Database Deployments opisuje etap schematu.