Aus dem Repository deployen
Das Repository ist die Quelle einer Archestack-App, so wie Quellcode die Quelle eines Programms ist. Ein Deployment behandelt Archestack als Compiler: Eine Pipeline baut aus den Dateien des Repositorys ein Wegwerf-Archestack, führt die Tests dagegen aus, und nur wenn sie bestehen, plant sie die Änderung gegen die gehostete Umgebung und wendet sie dort an. Die gehostete Umgebung bedient ihre Benutzer dabei die ganze Zeit weiter.
Status: Die Archestack CLI führt jede der folgenden Stufen aus, aus einem Skriptschritt in jeder beliebigen Pipeline. Fertige Pipeline-Tasks für Azure DevOps und GitHub Actions, die sie kapseln, sind in Entwicklung; Was heute läuft sagt, was jede Stufe ausführt.
Die 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 Ein Pull Request führt den Build, die Tests und den Plan gegen die Testumgebung aus, sodass ein Reviewer sieht, was sich ändern würde, bevor etwas gemergt wird. Ein Merge in den Main-Branch führt jede Stufe aus, und Abnahme und Produktion warten jeweils darauf, dass eine Person ihren Plan genehmigt.
1. Build: Archestack als Compiler
Die Pipeline startet auf dem Build-Agent ein leeres Archestack, in Docker aus demselben API-Image, das die Umgebungen ausführen, oder aus einem Laufzeitordner wie dem, mit dem die VS Code-Erweiterung Projekte ausführt, und lädt das Repository hinein: die Tabellen aller Packages in einem Deployment, dann die Artefakte jedes Packages, Abhängigkeiten vor den Packages, die sie brauchen. Hier zeigt sich ein Fehler zuerst, so wie ein Compilerfehler: Ein Verweis auf eine Business Entity, eine Tabelle oder ein Skript, die es nicht gibt, oder ein Name, den schon ein anderes Package verwendet, stoppt das Laden. Das Ergebnis ist eine Umgebung, die allein aus den Dateien entstanden ist, ohne Überbleibsel von irgendjemandes Rechner.
2. Test
Die Testfälle jedes Packages laufen gegen den Build, jeder in einer eigenen Sandbox-Datenbank, und Mails und Benachrichtigungen werden aufgezeichnet statt verschickt. Jedes Skript, das ein Test ausführt, wird zuerst kompiliert, ein Skript, das nicht mehr kompiliert, lässt seinen Test also fehlschlagen. Ein einziger fehlgeschlagener Fall stoppt die Pipeline, und nichts wird deployt.
3. Gegen das Ziel planen
Dieselben Dateien werden gegen die Zielumgebung geplant: welche Artefakte dort angelegt, geändert oder entfernt werden und welche Tabellenänderungen als SQL laufen, mit dem Risiko jeder Operation und den typisierten Skripten, die dadurch nicht mehr kompilieren würden. Der Plan trägt einen Hash. Das Deployment wendet genau den Plan an, der genehmigt wurde: Hat sich das Ziel in der Zwischenzeit geändert, wird es abgelehnt und der Plan neu erstellt.
4. Deployen: Schema, Dateien, Release
- Schema. Die Tabellenänderungen laufen als Datenbank-Deployment und stehen wie jedes andere in der Deployment-Historie der Umgebung. Eine Änderung, die Daten verliert, läuft nur, wenn die Pipeline Datenverlust ausdrücklich erlaubt.
- Dateien. Die Artefakte werden in einer Transaktion geschrieben, die Benutzer sehen also die ganze neue Version eines Packages oder nichts davon. Ein Deployment berührt nur, was das Package enthält und anlegt, und nie, was jede Umgebung selbst entscheidet.
- Release. Sobald die Dateien angekommen sind, veröffentlicht die Pipeline selbst ein Release. Das ist der Moment, in dem die neuen Pages und App Layouts die veröffentlichte App erreichen, und niemand veröffentlicht von Hand. Jedes Deployment ist eine neue Version der App mit einem eigenen Release.
Eine Umgebung, die noch nie ein Release veröffentlicht hat, zeigt ihre Entwürfe, die neuen Dateien wären also in dem Moment sichtbar, in dem sie ankommen. Vor ihrem ersten Deployment in eine solche Umgebung veröffentlicht die Pipeline deshalb ein Release dessen, was die Umgebung bereits enthält, und von da an warten die neuen Dateien als Entwürfe auf ihr eigenes Release, wie bei jedem späteren Deployment.
Warum die Umgebung weiterläuft
- Nichts startet neu. Ein Deployment sind Daten in den Datenbanken der Umgebung, kein neuer Build des Servers. Die API antwortet die ganze Zeit weiter, und ein geändertes Skript wird kompiliert, wenn es zum ersten Mal läuft.
- Dateien kommen auf einmal an. Eine Transaktion pro Package, sodass niemand gegen ein halbes Package arbeitet.
- Pages wechseln in einem Schritt. Die veröffentlichte App liest das aktuelle Release. Neue Pages warten als Entwürfe, bis das Release veröffentlicht wird, was alle Benutzer im selben Moment auf sie umstellt. Wer das vorherige Release aktiviert, rollt zurück; das stellt die Pages und Layouts wieder her, nie Daten oder Tabellen.
- Tabellenänderungen werden geplant und geprüft. Eine Tabelle oder eine Spalte, die NULL zulässt, hinzuzufügen, stört niemanden, und alles, was Daten verliert, braucht ein ausdrückliches Ja.
Erst erweitern, dann zurückbauen
Script Modules, Business Events und Business Entities sind live, sobald ihre Dateien ankommen, nicht erst mit dem Release. Eine Änderung, die eine Spalte umbenennt oder entfernt, geht deshalb in zwei Deployments raus:
- Erweitern. Füge die neue Tabelle oder Spalte hinzu und deploye die Skripte und Pages, die sie verwenden, während die alte noch da ist.
- Zurückbauen. Entferne die alte Spalte in einem späteren Deployment, sobald nichts sie mehr liest. Der Plan markiert das Entfernen als Datenverlust, und die Prüfung der typisierten Skripte sagt, ob noch irgendetwas sie verwendet.
Eine Änderung, die eine große Tabelle neu schreibt, etwa ein neuer Typ für eine Spalte, hält eine Sperre auf dieser Tabelle, solange sie läuft. Plane solche Änderungen für einen ruhigen Moment ein.
Umgebungen
Das Repository führt seine Umgebungen in archestack.json auf. Eine Umgebung mit
"mode": "pipeline" wird nur von der Pipeline deployt, und die VS Code-Erweiterung
weigert sich, von Hand dorthin zu pushen:
"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" }
} Was jede Umgebung selbst entscheidet, steht weder in den Dateien noch in irgendeinem Deployment: Benutzer und Rollen, Page-Berechtigungen, was öffentlich ist, Data-API-Freigaben und -Schlüssel, Mail-Konten und Verbindungen zu anderen Systemen. Die Administratoren jeder Umgebung legen sie fest, ein Deployment kann also nie etwas öffentlich machen oder jemandem Zugriff geben.
Die Pipeline-Datei
Die Pipeline liegt im Repository und deployt von dort: Jeder Lauf checkt einen Commit aus, und
genau diese Dateien werden gebaut, getestet und deployt. Aus einem Workspace wird nichts
exportiert. Unten steht dieselbe Pipeline für drei CI-Systeme, jede bringt eine Änderung in die
Test-, Abnahme- und Produktionsumgebung. Die archestack-Befehle sind die der
Archestack CLI, jedes andere CI-System, das .NET und Docker unter Linux
ausführt, führt also dieselben Schritte aus.
- Build und Test läuft bei jedem Pull Request und jedem Merge in den Main-Branch. Diese Stufe baut aus dem Commit ein Wegwerf-Archestack, führt die Tests aller Packages aus und packt das Repository in ein einziges Artefakt, sodass jede Umgebung genau dieselben Dateien bekommt.
- Ein Plan- und ein Deploy-Schritt pro Umgebung. Der Plan wird gegen die Umgebung erstellt und im Lauf angezeigt; das Deployment wendet dann genau diesen Plan an, bei Abnahme und Produktion nach einer Genehmigung. Die Umgebungen kommen nacheinander dran, Abnahme wird also erst geplant, wenn Test deployt ist, und Produktion erst, wenn Abnahme deployt ist. Ein Pull Request stoppt nach dem Plan gegen die Testumgebung.
- Deploy-Tokens. Das Token jeder Umgebung wird im Builder dieser Umgebung
erstellt, unter Operations, Deploy Tokens. Es wird nur einmal angezeigt,
handelt als Administrator und dient nur dem Deployment: Die Daten der Umgebung liest es nie. Die
Adresse der Umgebung kommt aus
archestack.json.
Azure DevOps
Die Pipeline ist azure-pipelines.yml im Stammverzeichnis des Repositorys:
# 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) - Genehmigungen. Lege unter Pipelines, Environments die Umgebungen
archestack-tst,archestack-accundarchestack-prdan und füge Abnahme und Produktion einen Approvals-Check hinzu. Azure DevOps wartet dann auf eine genehmigende Person, bevor diese Deploy-Stufen starten, mit dem Plan in der Zusammenfassung des Laufs. Die Testergebnisse werden im Lauf veröffentlicht. - Zugangsdaten. Das Deploy-Token jeder Umgebung ist das Secret
ARCHESTACK_TOKENin einer Variablengruppe mit demselben Namen wie die Umgebung, etwaarchestack-prd. - Datenverlust. Allow changes that lose data ist ein Kontrollkästchen, wenn ein Lauf von Hand gestartet wird, standardmäßig aus. Ohne diese Option stoppt ein Plan, der eine Tabelle oder eine Spalte entfernt, die Pipeline.
- Pull Requests auf Azure Repos. Azure Repos ignoriert den Abschnitt
pr:; füge die Pipeline stattdessen als build validation branch policy auf dem Main-Branch hinzu. - Eine im Web-Editor angelegte Pipeline wird als neue Datei gespeichert, die nach
der Pipeline benannt ist. Richte die Pipeline in ihren Einstellungen auf
azure-pipelines.ymlaus, sonst ist die Datei, die du bearbeitest, nicht die, die läuft.
GitHub Actions
Der Workflow ist .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 }} Jede Umgebung wird vom selben wiederverwendbaren Workflow daneben geplant und deployt:
# .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 }} - Genehmigungen. Lege unter Settings, Environments die Umgebungen
archestack-tst,archestack-accundarchestack-prdan und füge Abnahme und Produktion required reviewers hinzu. Der Deploy-Job wartet auf eine prüfende Person, mit dem Plan schon in der Zusammenfassung des Laufs. In einem privaten Repository brauchen Environments GitHub Pro, Team oder Enterprise. - Zugangsdaten. Die Deploy-Tokens sind die Repository-Secrets
ARCHESTACK_TOKEN_TST,ARCHESTACK_TOKEN_ACCundARCHESTACK_TOKEN_PRD, damit der Plan vor der Genehmigung laufen kann. Ein Workflow auf jedem Branch des Repositorys kann ein Repository-Secret lesen; um das Token der Produktion genehmigten Läufen vorzubehalten, mache es stattdessen zu einem Environment-Secret vonarchestack-prd, dann läuft sein Plan nach der Genehmigung. - Datenverlust. Allow changes that lose data ist ein Kontrollkästchen unter Run workflow, standardmäßig aus.
- Pull Requests aus Forks bekommen keine Secrets, ihr Plan gegen die Testumgebung schlägt also fehl; Pull Requests aus Branches des Repositorys selbst planen wie gewohnt.
-
concurrencyverhindert, dass zwei Läufe gleichzeitig in dieselbe Umgebung deployen. Die Testergebnisse werden als Artefakttestsdes Laufs aufbewahrt.
GitLab CI
Die Pipeline ist .gitlab-ci.yml im Stammverzeichnis des Repositorys:
# .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. Der Build führt das Wegwerf-Archestack auf einem
docker:dind-Service neben dem Job aus, was einen Runner braucht, der privilegierte Container erlaubt, wie es die eigenen Runner von GitLab.com tun.DOCKER_HOSTsagt der CLI, wo Docker ist, und sie erreicht das Archestack dort. - Genehmigungen. Das Deployment in Abnahme und Produktion sind manuelle Jobs, die die Pipeline blockieren und jeweils gestartet werden, sobald ihr Plan gelesen wurde. Jeder Plan wird bei seinem Job aufbewahrt, und der Plan gegen die Testumgebung ist auch im Merge Request verlinkt. Mit GitLab Premium schütze diese Umgebungen zusätzlich und verlange Genehmigungen.
- Zugangsdaten. Die Deploy-Tokens sind die maskierten CI/CD-Variablen
ARCHESTACK_TOKEN_TST,ARCHESTACK_TOKEN_ACCundARCHESTACK_TOKEN_PRD. Schütze die von Abnahme und Produktion, sodass nur der Main-Branch sie liest. Eine geschützte Variable erreicht keine Merge-Request-Pipeline, lass die der Testumgebung also ungeschützt, damit Merge Requests gegen die Testumgebung planen können. - Datenverlust. Starte die Pipeline von Hand mit
ALLOW_DATA_LOSSauftrue. Testergebnisse erscheinen im Merge Request. -
resource_groupverhindert, dass zwei Pipelines gleichzeitig in dieselbe Umgebung deployen.
Die Archestack CLI
Die CLI ist das .NET-Tool Archestack.Cli, installiert mit
dotnet tool install --global Archestack.Cli auf jedem Agent mit .NET 8 oder neuer. Ihre
Befehle laufen im Stammverzeichnis des Repositorys oder nehmen mit --from einen Ordner
oder ein gepacktes ZIP:
-
archestack buildstartet das Wegwerf-Archestack und lädt das Repository hinein. Es läuft in Docker aus dem Image, das der Abschnittprojectvonarchestack.jsonnennt, sonst aus dem neuesten veröffentlichten;--imagewählt ein anderes, und--runtimeführt einen Laufzeitordner ohne Docker aus. Es ist fertig, sobald die NuGet-Pakete, die das Repository nennt, wiederhergestellt sind, und läuft für den nächsten Schritt weiter, bisarchestack stopes beendet.--nuget-cache <folder>behält diese Downloads für den nächsten Build, der sie sonst erneut herunterlädt; zwei Builds, die gleichzeitig laufen, brauchen je einen eigenen Ordner. -
archestack testführt die Testfälle aller Packages dagegen aus, vier gleichzeitig, und schreibt mit--junitJUnit. -
archestack pack --out app.zippacktarchestack.json,packages/undworkspace/. Dieselben Dateien ergeben immer dieselben Bytes, und der Plan hält ihren Hash fest, ein Deployment lehnt also andere Dateien als die geplanten ab. -
archestack planundarchestack deployfunktionieren nur bei einer Umgebung mit"mode": "pipeline", mit ihrem Deploy-Token inARCHESTACK_TOKEN_<ENV>(etwaARCHESTACK_TOKEN_PRD) oderARCHESTACK_TOKEN. Ein Artefakt, das aus dem Repository gelöscht wurde, wird aus seinem Package genommen und bleibt in der Umgebung; plane mit--delete-removed true, um es auch dort zu löschen. Ein Package in der Umgebung, das das Repository nicht enthält, bleibt unangetastet und wird im Plan genannt. Nennt das Repository NuGet-Pakete, fragen beide zuerst die Umgebung, ob sie sich dort wiederherstellen lassen, unddeploywartet nach dem letzten Push bis zu fünf Minuten, bis die Umgebung sie wiederhergestellt hat, bevor es das Release veröffentlicht. Schlägt dieses Warten fehl, sind die Dateien deployt, aber es wird kein Release veröffentlicht.
Der Exit-Code sagt, was einen Schritt gestoppt hat: 3 das Token wurde abgelehnt, 4 die Umgebung
hat sich seit dem Plan geändert (neu planen), 5 die Dateien lassen sich so, wie sie sind, nicht
anwenden, 6 der Plan verliert Daten und das war nicht erlaubt, 7 ein Test ist fehlgeschlagen, 9
der Server oder das Netzwerk hat versagt, 10 die Umgebung läuft mit einer anderen Hauptversion
von Archestack als die CLI oder mit einer ohne NuGet-Unterstützung. NuGet-Pakete, die sich mit
den Dateien nicht wiederherstellen lassen, ergeben 5, ebenso eine Umgebung, in der NuGet-Pakete
oder der typisierte Datenzugriff ausgeschaltet sind. Bei plan und deploy
ergibt ein NuGet-Fehler, den die Dateien nicht beheben können, 9: etwa ein Server mit zu wenig
Speicherplatz, ein Feed, den er nicht erreicht, oder eine Wiederherstellung nach dem letzten
Push, die fehlschlug oder nicht in fünf Minuten fertig wurde. Derselbe Schritt kann dann beim
nächsten Lauf gelingen.
Was heute läuft
- Build, Test, Planen und Deployen laufen über die CLI, aus Skriptschritten wie in den Pipelines oben. Auf dem Rechner eines Entwicklers ist das Projekt der VS Code-Erweiterung derselbe Build: Reset Project Database erstellt es von Grund auf, und Run Tests führt die Tests aller Packages dagegen aus.
- Pipeline-Tasks für Azure DevOps und GitHub Actions, die die CLI kapseln: in Entwicklung.
Stolperfallen
- Ein Rollback macht Tabellen und Daten nicht rückgängig. Jedes Deployment ist ein Release, jede Version, die die Pipeline deployt hat, lässt sich also wieder aktivieren, aber das stellt nur Pages und Layouts wieder her. Tabellen zurückzuholen ist ein eigenes Deployment, geplant und geprüft wie jedes andere.
- Script Modules und Business Events warten nicht auf das Release. Sie sind live, sobald ihre Dateien ankommen, weshalb eine Änderung, die etwas entfernt, in zwei Deployments rausgeht.
- Jede Umgebung lädt ihre NuGet-Pakete selbst herunter. Die
NuGet-Pakete, die die
nuget.jsoneines Packages deklariert, werden von jeder Umgebung heruntergeladen, die das Package bekommt, der Build eingeschlossen, jede muss also nuget.org oder den Feed erreichen, mit dem ihre Server konfiguriert sind. Der Build nimmtScripting__NuGet__Sourcesund die EinstellungenScripting__NuGet__Feeds__*aus den Umgebungsvariablen, mit denen die CLI läuft. Ein Push, dessen NuGet-Pakete sich nicht wiederherstellen lassen, wird abgelehnt und ändert nichts: Der Befehlplander CLI prüft das, bevor irgendetwas deployt wird, undbuildunddeploywarten, bis sie wiederhergestellt sind.
Wie es weitergeht
Im Team arbeiten beschreibt, wie sich Entwickler das Repository teilen, das die Pipeline deployt. Workspaces und Hosting erklärt die Umgebungen, in die sie deployt, und Database Deployments den Schema-Schritt.