Nieuwe functionaliteit bouwen¶
Nieuwe functionaliteit is een wijziging in de coderepository. Een wijziging die alleen andere waarden nodig heeft, is een configuratiewijziging; zie Config. Elke nieuwe feature volgt de regels voor achterwaartse compatibiliteit: opt-in, standaard uit.
flowchart LR
a["1. Module"] --> b["2. Koppel aan een layer<br/>+ feature flag"]
b --> c["3. Test"]
c --> d["4. Deploy naar dev<br/>(lokaal / Demo canary)"]
d --> e["5. PR + CI"]
e --> f["Release"]
0. Je omgeving inrichten¶
- Clone
xms-cloud-platform-codeen open het in de dev container (VS Code: Reopen in Container). Daarin zitten PowerShell 7, Terraform, de Azure CLI en Pester. - De dev container mount
../config, relatief aan de coderepository, op/workspaces/config. Clone een configuratierepository naast de code alsconfig, of gebruik de Demo-configuratie inconfig/Demo/canary. - Kopieer
.env.examplenaar.enven stelMCP_CONFIGin, bijvoorbeeldMCP_CONFIG=/workspaces/xms-cloud-platform-code/config/Demo/canary/mcp.json. - Installeer de git hooks:
lefthook install. - Maak een branch vanaf
main.feature/<name>krijgt een GitVersion-label (-<name>);users/<initials>/<name>is de gebruikelijke conventie voor persoonlijk werk.
1. Modules¶
Terraform is georganiseerd in drie niveaus:
| Level | Map | Regel |
|---|---|---|
| Module | infra/modules/<name>/ |
Eén resourcetype of een nauw samenhangende groep. Geen kennis van layers of configbestanden. Bestanden: main.tf, variables.tf, output.tf/outputs.tf, versions.tf, optioneel tests/. |
| Template | infra/templates/<name>/ |
Combineert modules tot een feature (bijvoorbeeld application_gateway, virtual_hub). Berekent namen uit de scaffold_* variabelen. |
| Layer | infra/deploy/<layer>/ |
Root module met backend, providers en variabelen. Roept templates aan achter feature flags. Variabelen zijn per feature opgesplitst: variables_<feature>.tf. |
Richtlijnen (zie ook .agents/skills/terraform-style-guide in de coderepository):
- Draai
terraform fmt. Gebruikcreate_*/use_*_modulebooleans voor optionele features en*_idinputs voor afhankelijkheden. - Gebruik
dynamicblocks voor optionele geneste configuratie. - Bouw namen op uit
scaffold_company_short_name,scaffold_environmentenscaffold_location_short_name, en voeg eenoverwrite_*_namevariabele toe zodat klanten met bestaande namen die kunnen behouden. - Als de feature JSON uit de configuratierepository leest, neem dan een
*_relative_pathvariabele en bouw het pad op als"${var.config_path}/${var.<x>_relative_path}". Onthoud datfileset()op een verkeerd pad niets teruggeeft. - Pin providers in root modules op een exacte versie. Anders faalt de pin check.
Spoke-features¶
Spoke Terraform staat in src/Xebia.Mcp/Files/terraform/spoke-canvas/ (deploy/subscription, deploy/spoke,
modules/). Een nieuwe spoke-property vraagt om:
- de Terraform die de property leest, met een default als de property ontbreekt;
- een optionele property in
src/Xebia.Mcp/Files/json/spokeschema.json; - een rij in de spoke-JSON-referentie.
2. Koppel het aan een layer, achter een flag¶
# infra/deploy/connectivity/variables_my_feature.tf
variable "use_my_feature_module" {
description = "Deploy my feature. Default false keeps existing deployments unchanged."
type = bool
default = false
}
# infra/deploy/connectivity/main.tf
module "my_feature" {
source = "../../templates/my_feature"
count = var.use_my_feature_module ? 1 : 0
# ...
}
Daarna:
- voeg de flag en de bijbehorende variabelen toe aan de Demo-configuratie (
config/Demo/canary/<region>/<layer>.auto.tfvars); - voeg de flag toe aan de feature flags-referentie;
- als consumenten of operators erom gaan vragen, voeg dan een runbook toe of breid er een uit onder Veelvoorkomende aanvragen;
- als de beslissing architecturaal is, schrijf dan een ADR (
docs/adr/, templateadr-template.md).
Wijzigingen in de orkestratie¶
Logica die bepaalt wat er draait (if/else, loops, matrices, parsing) hoort in een PowerShell-functie in
src/Xebia.Mcp/Functions/, niet in YAML (ADR-0011, CONTRIBUTING.md):
- Publieke functies in
Functions/Public/<Domain>/, interne inFunctions/Private/<Domain>/. - Comment-based help met
.SYNOPSIS,.DESCRIPTION,.PARAMETER,.EXAMPLE,.NOTES. begin/cleanblocks diebegin.ps1/clean.ps1dot-sourcen.- Wijzig het Azure DevOps-template en de GitHub workflow in dezelfde pull request.
3. Testen¶
| Test | Waar | Hoe te draaien | Draait in |
|---|---|---|---|
| Terraform validate + docs | elke layer | automatisch bij commit | lefthook pre-commit |
| Terraform moduletests | infra/modules/<name>/tests/*.tftest.hcl (met mock_provider) |
terraform -chdir=infra/modules/<name> test, of automatisch voor gestagede modules (scripts/Run-TerraformTest.ps1) |
lefthook pre-commit |
| Provider pin check | infra/deploy/** |
pwsh scripts/Test-TerraformRootProviderPins.ps1 |
lefthook + GitHub CI |
| PowerShell unit tests | Functions/**/Tests/<Function>.Unit.Tests.ps1 |
pwsh ./dev/dev.ps1 -Action Test |
Prepare-stap van elke pipeline |
| Pariteitscontroles | module-breed (bestandsnaam = functienaam, elke publieke functie heeft een unit test, …) | pwsh ./dev/dev.ps1 -Action Test |
Prepare-stap |
| Config tests | src/Xebia.Mcp/Tests/{Config,SpokeConfig,Smoke} |
pwsh ./dev/dev.ps1 -Action Test (gebruikt MCP_CONFIG) |
Prepare-stap van elke pipeline |
Elke publieke functie heeft een unit test nodig; Assert-XebiaPublicFunctionUnitTestParity faalt anders. Mock aanroepen van de Azure CLI en
Terraform.
4. Deployen naar dev¶
Het ontwikkeldoel is de Demo tenant, configuratie config/Demo/canary in de coderepository.
Lokaal (snelle feedback, je eigen Azure-login):
Import-Module ./src/Xebia.Mcp/Xebia.Mcp.psd1 -Force
Initialize-XebiaDotEnv
Sync-XebiaInfraToMcpModule -Mappings @(@{ Description = 'cloud-platform'; Source = './infra'; Target = 'terraform/cloud-platform/' }) -WhatIf:$false
$config = Resolve-XebiaMcpConfiguration -Path $env:MCP_CONFIG
# Plan one layer (WhatIf on: plan, no apply) — same as dev.ps1 does by default
$global:WhatIfPreference = $true
Deploy-XebiaLocal -Config $config -DeployName connectivity -Region weu
# Plan and apply
$global:WhatIfPreference = $false
Deploy-XebiaLocal -Config $config -DeployName connectivity -Region weu
(dev/dev.ps1 -Action HubDeploy is de bedoelde shortcut, maar werkt niet op main, zie
Bekende problemen.)
Via workflow/pipeline (zoals klanten): draai de eigen entry pipelines van de coderepository (hub.yaml, spoke.yaml)
vanaf je branch tegen de Demo-configuratie. Gebruik mode: Plan of ApproveModifications.
Controleer twee dingen:
- Met de flag uit: het plan toont geen wijzigingen. Dit bewijst achterwaartse compatibiliteit.
- Met de flag aan: het plan toont alleen de nieuwe resources, en de apply werkt.
5. Pull request en CI¶
- Commit met Conventional Commits (
feat(connectivity): add …,fix(ps): …), in Amerikaans Engels (docs/coding-standards/). - Open een pull request naar
main. Beschrijf de wijziging en de flag, en koppel het work item. - Zet de versieverhoging in de merge message:
+semver: minorvoor een feature,+semver: patchvoor een fix,+semver: majorvoor een breaking change,+semver: nonevoor alleen docs. Zie Releasen. -
CI draait:
Platform Pipeline Wat het doet Azure DevOps pull-request.yaml(PR naarmain)Bouwt de container vanaf de PR-branch en draait daarna de hub-stages (deploy en destroy) en spoke-stages (deploy en destroy, glob **/*str*.json) in Plan / WhatIf tegen canaryGitHub ci.yml(PR dieinfra/deploy/**raakt)Provider pin check -
Een reviewer controleert: flag standaard uit,
movedblocks voor hernoemingen, unit tests, zowel ADO als GitHub aangepast, docs bijgewerkt. - Merge. Moet de fix ook naar een ondersteunde versie, cherry-pick hem dan naar de
release/vX.Ybranch (zie Releasen).