-
Notifications
You must be signed in to change notification settings - Fork 0
Add sovereign landing zone deployment workflow (validate → what-if → deploy) #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,264 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Sovereign Cloud Platform Landing Zone - Deployment Pipeline | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Three-stage pipeline: validate -> what-if -> deploy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Uses OIDC federation for Azure authentication (no client secrets). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # See REUSE_CATALOG.md for the full mapping of repository assets to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # sovereign landing zone modules. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Deploy Sovereign Landing Zone | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: [main] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| push: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| branches: [main] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workflow_dispatch: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| environment: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: 'Target environment (dev or prod)' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: choice | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| options: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - dev | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - prod | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: dev | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dry_run: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: 'Dry run -- run validate and what-if only, skip deploy' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: boolean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # OIDC federation requires id-token: write. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # pull-requests: write is needed to post what-if results as PR comments. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id-token: write | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pull-requests: write | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| env: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEPLOYMENT_LOCATION: westeurope | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DEPLOYMENT_NAME: sovereign-lz-${{ github.run_number }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # -------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # VALIDATE -- compile, lint, and validate the Bicep template | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # -------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| validate: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Validate | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Checkout repository | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Log in to Azure with OIDC | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uses: azure/login@v2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+54
to
+59
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Lint Bicep template | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Catches style and best-practice issues before compilation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: az bicep lint --file deployments/sovereign-baseline/main.bicep | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Compile Bicep to ARM template | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p dist | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| az bicep build \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --file deployments/sovereign-baseline/main.bicep \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --outfile dist/sovereign-lz.json | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Determine parameter file | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: params | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PARAMS_FILE="deployments/sovereign-baseline/${{ github.event.inputs.environment }}.parameters.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PARAMS_FILE="deployments/sovereign-baseline/prod.parameters.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PARAMS_FILE="deployments/sovereign-baseline/dev.parameters.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+63
to
+80
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: az bicep lint --file deployments/sovereign-baseline/main.bicep | |
| - name: Compile Bicep to ARM template | |
| run: | | |
| mkdir -p dist | |
| az bicep build \ | |
| --file deployments/sovereign-baseline/main.bicep \ | |
| --outfile dist/sovereign-lz.json | |
| - name: Determine parameter file | |
| id: params | |
| run: | | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| PARAMS_FILE="deployments/sovereign-baseline/${{ github.event.inputs.environment }}.parameters.json" | |
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| PARAMS_FILE="deployments/sovereign-baseline/prod.parameters.json" | |
| else | |
| PARAMS_FILE="deployments/sovereign-baseline/dev.parameters.json" | |
| run: az bicep lint --file main.bicep | |
| - name: Compile Bicep to ARM template | |
| run: | | |
| mkdir -p dist | |
| az bicep build \ | |
| --file main.bicep \ | |
| --outfile dist/sovereign-lz.json | |
| - name: Determine parameter file | |
| id: params | |
| run: | | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| PARAMS_FILE="${{ github.event.inputs.environment }}.parameters.json" | |
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| PARAMS_FILE="prod.parameters.json" | |
| else | |
| PARAMS_FILE="dev.parameters.json" |
Copilot
AI
Mar 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter file selection writes paths like deployments/sovereign-baseline/dev.parameters.json / prod.parameters.json, but there are no matching *.parameters.json files in the repo. This will cause az deployment sub validate/what-if/create to fail when it tries to load --parameters @...; either commit these parameter files (in this PR) or adjust the workflow to use the existing parameter file locations.
| PARAMS_FILE="deployments/sovereign-baseline/${{ github.event.inputs.environment }}.parameters.json" | |
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| PARAMS_FILE="deployments/sovereign-baseline/prod.parameters.json" | |
| else | |
| PARAMS_FILE="deployments/sovereign-baseline/dev.parameters.json" | |
| fi | |
| echo "file=$PARAMS_FILE" >> "$GITHUB_OUTPUT" | |
| - name: Validate deployment at subscription scope | |
| run: | | |
| az deployment sub validate \ | |
| --location "${{ env.DEPLOYMENT_LOCATION }}" \ | |
| --name "${{ env.DEPLOYMENT_NAME }}" \ | |
| --template-file dist/sovereign-lz.json \ | |
| --parameters @${{ steps.params.outputs.file }} | |
| CANDIDATE_PARAMS_FILE="deployments/sovereign-baseline/${{ github.event.inputs.environment }}.parameters.json" | |
| elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
| CANDIDATE_PARAMS_FILE="deployments/sovereign-baseline/prod.parameters.json" | |
| else | |
| CANDIDATE_PARAMS_FILE="deployments/sovereign-baseline/dev.parameters.json" | |
| fi | |
| if [[ -f "$CANDIDATE_PARAMS_FILE" ]]; then | |
| PARAMS_FILE="$CANDIDATE_PARAMS_FILE" | |
| else | |
| echo "Warning: parameter file '$CANDIDATE_PARAMS_FILE' not found; proceeding without explicit parameters." >&2 | |
| PARAMS_FILE="" | |
| fi | |
| echo "file=$PARAMS_FILE" >> "$GITHUB_OUTPUT" | |
| - name: Validate deployment at subscription scope | |
| run: | | |
| PARAMS_FILE='${{ steps.params.outputs.file }}' | |
| if [[ -n "$PARAMS_FILE" ]]; then | |
| az deployment sub validate \ | |
| --location "${{ env.DEPLOYMENT_LOCATION }}" \ | |
| --name "${{ env.DEPLOYMENT_NAME }}" \ | |
| --template-file dist/sovereign-lz.json \ | |
| --parameters @"$PARAMS_FILE" | |
| else | |
| az deployment sub validate \ | |
| --location "${{ env.DEPLOYMENT_LOCATION }}" \ | |
| --name "${{ env.DEPLOYMENT_NAME }}" \ | |
| --template-file dist/sovereign-lz.json | |
| fi |
Copilot
AI
Mar 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issues.listComments is called without pagination/per_page handling, so it only scans the first page of comments (default 30). On PRs with more comments, older workflow comments may not be found/deleted, resulting in duplicates. Consider requesting a higher per_page and/or paginating until the matching comment is found.
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number | |
| }); | |
| for (const comment of comments.data) { | |
| const comments = await github.paginate( | |
| github.rest.issues.listComments, | |
| { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100 | |
| } | |
| ); | |
| for (const comment of comments) { |
Copilot
AI
Mar 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deploy job always runs under the sovereign-production protected environment regardless of the workflow_dispatch environment input, and it always logs into the same subscription via AZURE_SUBSCRIPTION_ID. This makes it possible to deploy a “dev” parameter set through the production gate into the production subscription. Consider mapping dev/prod to different GitHub environments and/or subscription IDs, or explicitly disallow environment: dev when running the deploy job.
Copilot
AI
Mar 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The module paths listed in the deploy-step comment don’t match the repository layout. The sovereign modules currently live directly under 03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/modules/ (e.g., sovereign-policy-initiative.bicep), not under modules/sovereign/.... Please update these paths to avoid misleading operators/debugging the wrong files.
| # - modules/sovereign/policy/sovereign-policy-initiative.bicep | |
| # - modules/sovereign/encryption/sovereign-keyvault-cmk.bicep | |
| # - modules/sovereign/encryption/sovereign-tls-enforcement.bicep | |
| # - modules/sovereign/confidential-compute/sovereign-confidential-vm.bicep | |
| # - modules/sovereign/confidential-compute/sovereign-confidential-aks-nodepool.bicep | |
| # - modules/sovereign/hybrid-arc/sovereign-arc-governance.bicep | |
| # - modules/sovereign/identity/sovereign-rbac-assignments.bicep | |
| # - modules/sovereign-policy-initiative.bicep | |
| # - modules/sovereign-keyvault-cmk.bicep | |
| # - modules/sovereign-tls-enforcement.bicep | |
| # - modules/sovereign-confidential-vm.bicep | |
| # - modules/sovereign-confidential-aks-nodepool.bicep | |
| # - modules/sovereign-arc-governance.bicep | |
| # - modules/sovereign-rbac-assignments.bicep |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
workflow_dispatchdefines anenvironmentinput (dev/prod), but this name is easy to confuse with the GitHub Actions jobenvironmentthat provides deployment protection. If this input is only meant to select a parameters file, consider renaming it (e.g.,parameters_profile) to avoid accidental assumptions about where the deployment is going.