Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/cd-cleanup.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Cloud env safety net: nightly scale dev/ppe container apps to min=0/max=3 so a misconfigured
# Cloud env safety net: nightly scale ci/ppe container apps to min=0/max=3 so a misconfigured
# bicepparam (or manual `az` poke) can't keep instances pinned overnight and rack up bills.
# Idempotent. Skips prod intentionally.
name: cd-cleanup
Expand All @@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
# Per-matrix-env GitHub Environment so each iteration uses its own
# AZURE_CLIENT_ID / AZURE_SUBSCRIPTION_ID vars + secrets. Without this,
# both dev and ppe would resolve from whatever single environment was
# both ci and ppe would resolve from whatever single environment was
# hard-coded here, defeating the per-env credential separation that
# the rest of CD relies on.
environment: ${{ matrix.env }}
Expand All @@ -26,7 +26,7 @@ jobs:
strategy:
fail-fast: false
matrix:
env: [dev, ppe]
env: [ci, ppe]
steps:
- uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0
with:
Expand Down
26 changes: 13 additions & 13 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Cloud CD pipeline: builds the FTGO service images, pushes to GHCR, and deploys.
#
# TRIGGERS:
# - push to main → build + deploy-dev only
# - push to main → build + deploy-ci only
# - workflow_dispatch → build + deploy through to chosen env:
# environment=dev → dev
# environment=ppe → dev → ppe
# environment=prod → dev → ppe → prod (requires reviewer on prod environment)
# environment=ci → ci
# environment=ppe → ci → ppe
# environment=prod → ci → ppe → prod (requires reviewer on prod environment)
#
# ppe and prod NEVER run on push — they require an explicit dispatch with the env input.
#
# Per-env deploy logic lives in the reusable workflow .github/workflows/deploy-env.yml
# so dev/ppe/prod stay in lock-step. To change deploy behaviour for ALL envs,
# so ci/ppe/prod stay in lock-step. To change deploy behaviour for ALL envs,
# edit deploy-env.yml once.
#
# Environment GitHub vars expected per env: AZURE_CLIENT_ID, AZURE_SUBSCRIPTION_ID
Expand All @@ -24,11 +24,11 @@ on:
workflow_dispatch:
inputs:
environment:
description: Target environment (dev|ppe|prod). Defaults to full dev→ppe→prod chain.
description: Target environment (ci|ppe|prod). Defaults to full ci→ppe→prod chain.
required: false
default: dev
default: ci
type: choice
options: [dev, ppe, prod]
options: [ci, ppe, prod]
imageTag:
description: Existing image tag (e.g. sha-abc1234) to redeploy. Leave blank to build a fresh one from HEAD.
required: false
Expand Down Expand Up @@ -169,27 +169,27 @@ jobs:
fi
echo "imageTag=${TAG}" >> "$GITHUB_OUTPUT"

deploy-dev:
deploy-ci:
needs: resolve-image-tag
if: |
always() && needs.resolve-image-tag.result == 'success' &&
(github.event_name == 'push' ||
github.event.inputs.environment == 'dev' ||
github.event.inputs.environment == 'ci' ||
github.event.inputs.environment == 'ppe' ||
github.event.inputs.environment == 'prod')
permissions:
id-token: write
contents: read
uses: ./.github/workflows/deploy-env.yml
with:
environment: dev
environment: ci
image_tag: ${{ needs.resolve-image-tag.outputs.imageTag }}
secrets: inherit

deploy-ppe:
needs: [resolve-image-tag, deploy-dev]
needs: [resolve-image-tag, deploy-ci]
if: |
always() && needs.deploy-dev.result == 'success' &&
always() && needs.deploy-ci.result == 'success' &&
github.event_name == 'workflow_dispatch' &&
(github.event.inputs.environment == 'ppe' ||
github.event.inputs.environment == 'prod')
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ jobs:
run: |
set -euo pipefail
fail=0
for env in dev ppe prod; do
for env in ci ppe prod; do
for stem in main bootstrap azure; do
file="infra/bicep/${stem}.${env}.bicepparam"
[ -f "$file" ] || continue
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/deploy-env.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Reusable CD workflow: deploy infra/bicep/azure.bicep to a single environment.
#
# Called once per env (dev / ppe / prod) from cd.yml. The caller is responsible
# for ordering (deploy-dev → deploy-ppe → deploy-prod) and for opting an env
# Called once per env (ci / ppe / prod) from cd.yml. The caller is responsible
# for ordering (deploy-ci → deploy-ppe → deploy-prod) and for opting an env
# in/out via `if:`. This workflow assumes:
#
# - GitHub Environment named ${{ inputs.environment }} exists with vars
Expand All @@ -18,7 +18,7 @@ on:
workflow_call:
inputs:
environment:
description: Target environment name (dev|ppe|prod). Used for the GitHub Environment, RG name suffix, and bicepparam file.
description: Target deployment-tier name (ci|ppe|prod). Used for the GitHub Environment, RG name suffix, and bicepparam file.
required: true
type: string
image_tag:
Expand Down
48 changes: 24 additions & 24 deletions DOCTRINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,29 @@ The rule is one-way: this repo **cites** the upstream guides; the upstream guide

## Doctrine reference table

| Topic in this repo | Upstream owner | Section / chapter |
| --- | --- | --- |
| ASP.NET Core auth (`scp` vs `roles`+`azp` named policies, JWT defaults, multi-tenant `IssuerValidator`, `tid` allow-list, deny-by-default) | dotnet-engineering-guide | [`docs/02-aspnetcore.md` §10 Authn/Authz](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/02-aspnetcore.md#10-authnauthz) |
| HTTP pipeline order, problem-details, model binding, minimal APIs vs MVC | dotnet-engineering-guide | [`docs/02-aspnetcore.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/02-aspnetcore.md) |
| HttpClient + Polly resilience pipeline, named clients, timeouts | dotnet-engineering-guide | [`docs/02-aspnetcore.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/02-aspnetcore.md), [`docs/05-performance.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/05-performance.md) |
| Testing strategy (unit / integration / WebApplicationFactory / Testcontainers / contract) | dotnet-engineering-guide | [`docs/04-testing.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/04-testing.md) |
| Allocation, async, perf hot-paths | dotnet-engineering-guide | [`docs/05-performance.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/05-performance.md) |
| Cloud-native runtime (containers, health, config, secrets at runtime) | dotnet-engineering-guide | [`docs/06-cloud-native.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/06-cloud-native.md) |
| C# language features, project layout, nullable, analyzers | dotnet-engineering-guide | [`docs/01-foundations.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/01-foundations.md) |
| EF Core, Dapper, transactions, outbox | dotnet-engineering-guide | [`docs/03-data.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/03-data.md) |
| Decision trees a senior .NET architect actually faces | dotnet-engineering-guide | [`docs/decision-trees.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/decision-trees.md) |
| IaC tooling decision (Bicep vs Terraform vs Pulumi), module shape | infra-engineering-guide | [`docs/02-iac-tooling.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/02-iac-tooling.md) |
| CI/CD pipelines, image promotion by SHA, environments, gates | infra-engineering-guide | [`docs/03-ci-cd.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/03-ci-cd.md) |
| Container build (chiseled / distroless / non-root), Kubernetes / ACA defaults | infra-engineering-guide | [`docs/04-containers-k8s.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/04-containers-k8s.md) |
| Observability (OpenTelemetry → Azure Monitor / Loki / Tempo), SLOs | infra-engineering-guide | [`docs/05-observability.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/05-observability.md) |
| Security supply-chain (SLSA, pinact, OpenSSF Scorecard, Dependabot, gitleaks, dependency-review, CodeQL) | infra-engineering-guide | [`docs/06-security-supply-chain.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/06-security-supply-chain.md) |
| Networking (private endpoints, egress, VNet, WAF, mTLS) | infra-engineering-guide | [`docs/07-networking.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/07-networking.md) |
| Data-state (managed DB defaults, backup, residency) | infra-engineering-guide | [`docs/08-data-state.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/08-data-state.md) |
| Reliability (SLI / SLO / error budget, retry / timeout / circuit, blast-radius) | infra-engineering-guide | [`docs/09-reliability.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/09-reliability.md) |
| FinOps (idle cost, scale-to-zero, ACR Basic, daily caps, teardown) | infra-engineering-guide | [`docs/10-finops.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/10-finops.md) — repo-local specialization in [`docs/cost-zero.md`](./docs/cost-zero.md) |
| Platform engineering (golden paths, paved roads, multi-tenant compute) | infra-engineering-guide | [`docs/11-platform-engineering.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/11-platform-engineering.md) |
| Workload identity (Entra workload-id, FIC, MI, OIDC issuer, SPIFFE) — *infra-side* | infra-engineering-guide | [`docs/12-identity.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/12-identity.md) |
| Entra app-side patterns: token acquisition, validation, credential picker, sample registrations | **this repo** | [`docs/`](./docs/) + [`coverage-map.md`](./coverage-map.md) |
| Topic in this repo | Upstream owner | Section / chapter |
| ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ASP.NET Core auth (`scp` vs `roles`+`azp` named policies, JWT defaults, multi-tenant `IssuerValidator`, `tid` allow-list, deny-by-default) | dotnet-engineering-guide | [`docs/02-aspnetcore.md` §10 Authn/Authz](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/02-aspnetcore.md#10-authnauthz) |
| HTTP pipeline order, problem-details, model binding, minimal APIs vs MVC | dotnet-engineering-guide | [`docs/02-aspnetcore.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/02-aspnetcore.md) |
| HttpClient + Polly resilience pipeline, named clients, timeouts | dotnet-engineering-guide | [`docs/02-aspnetcore.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/02-aspnetcore.md), [`docs/05-performance.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/05-performance.md) |
| Testing strategy (unit / integration / WebApplicationFactory / Testcontainers / contract) | dotnet-engineering-guide | [`docs/04-testing.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/04-testing.md) |
| Allocation, async, perf hot-paths | dotnet-engineering-guide | [`docs/05-performance.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/05-performance.md) |
| Cloud-native runtime (containers, health, config, secrets at runtime) | dotnet-engineering-guide | [`docs/06-cloud-native.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/06-cloud-native.md) |
| C# language features, project layout, nullable, analyzers | dotnet-engineering-guide | [`docs/01-foundations.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/01-foundations.md) |
| EF Core, Dapper, transactions, outbox | dotnet-engineering-guide | [`docs/03-data.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/03-data.md) |
| Decision trees a senior .NET architect actually faces | dotnet-engineering-guide | [`docs/decision-trees.md`](https://github.com/mghabin/dotnet-engineering-guide/blob/main/docs/decision-trees.md) |
| IaC tooling decision (Bicep vs Terraform vs Pulumi), module shape | infra-engineering-guide | [`docs/02-iac-tooling.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/02-iac-tooling.md) |
| CI/CD pipelines, image promotion by SHA, environments, gates | infra-engineering-guide | [`docs/03-ci-cd.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/03-ci-cd.md) |
| Container build (chiseled / distroless / non-root), Kubernetes / ACA defaults | infra-engineering-guide | [`docs/04-containers-k8s.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/04-containers-k8s.md) |
| Observability (OpenTelemetry → Azure Monitor / Loki / Tempo), SLOs | infra-engineering-guide | [`docs/05-observability.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/05-observability.md) |
| Security supply-chain (SLSA, pinact, OpenSSF Scorecard, Dependabot, gitleaks, dependency-review, CodeQL) | infra-engineering-guide | [`docs/06-security-supply-chain.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/06-security-supply-chain.md) |
| Networking (private endpoints, egress, VNet, WAF, mTLS) | infra-engineering-guide | [`docs/07-networking.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/07-networking.md) |
| Data-state (managed DB defaults, backup, residency) | infra-engineering-guide | [`docs/08-data-state.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/08-data-state.md) |
| Reliability (SLI / SLO / error budget, retry / timeout / circuit, blast-radius) | infra-engineering-guide | [`docs/09-reliability.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/09-reliability.md) |
| FinOps (idle cost, scale-to-zero, ACR Basic, daily caps, teardown) | infra-engineering-guide | [`docs/10-finops.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/10-finops.md) — repo-local specialization in [`docs/cost-zero.md`](./docs/cost-zero.md) |
| Platform engineering (golden paths, paved roads, multi-tenant compute) | infra-engineering-guide | [`docs/11-platform-engineering.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/11-platform-engineering.md) |
| Workload identity (Entra workload-id, FIC, MI, OIDC issuer, SPIFFE) — *infra-side* | infra-engineering-guide | [`docs/12-identity.md`](https://github.com/mghabin/infra-engineering-guide/blob/main/docs/12-identity.md) |
| Entra app-side patterns: token acquisition, validation, credential picker, sample registrations | **this repo** | [`docs/`](./docs/) + [`coverage-map.md`](./coverage-map.md) |

---

Expand All @@ -55,7 +55,7 @@ This is the **only** layer you should not look upstream for:
- The `OrdersDelegated` / `OrdersApp` named-policy split that operationalizes dotnet-guide ch02 §10.
- The BFF-style `SignedAssertionFromManagedIdentity` pattern (clarified as **not** OIDC-FIC) and its disambiguation.
- The credential-picker for *Entra app-credentials* (MI / FIC / cert / secret) including the three documented exceptions for client secret.
- The per-environment app-registration and FIC creation Bicep modules, parameterized for dev / ppe / prod.
- The per-environment app-registration and FIC creation Bicep modules, parameterized for ci / ppe / prod.
- The end-to-end runnable FTGO demo (ApiGateway, Auth, Auth.Client, Orders.Api, Restaurants.Api, Kitchen.Worker) that exercises all of the above on Azure Container Apps.

Everything else — language, framework, IaC, CI/CD, observability, FinOps, supply-chain — defers upstream. If a doctrine claim in this repo cannot be traced to a row in the table above or a primary source cited in the relevant doc's `## Sources` block, treat it as a bug and open an issue.
Expand Down
Loading
Loading