feat: add staging namespace module for validation pipeline #218

Merged
forgejo_admin merged 1 commit from 213-staging-namespace-and-network-policies into main 2026-03-28 05:47:33 +00:00

Summary

Adds the staging Kubernetes namespace as a new Terraform module with default-deny network policy, root orchestrator wiring, and output exposure. This is the pal-e-platform foundation for the dev-staging-prod validation pipeline.

Changes

  • terraform/modules/staging/main.tf — New module creating the staging namespace with environment=staging label
  • terraform/modules/staging/outputs.tf — Exposes staging_namespace for downstream consumers
  • terraform/modules/staging/variables.tf — Empty (namespace is self-contained; ArgoCD deploys workloads)
  • terraform/modules/staging/versions.tf — Kubernetes provider requirement
  • terraform/main.tf — Wires module.staging into the root orchestrator
  • terraform/network-policies.tf — Adds netpol_staging default-deny policy allowing ingress from tailscale, staging (intra-ns), monitoring, argocd, and woodpecker
  • terraform/outputs.tf — Exposes staging_namespace at root level
  • scripts/woodpecker-update-tag-step.yaml — Documents OVERLAY_ENV tiers (prod/staging) and adds commented staging deploy step template

tofu plan Output

Cannot run tofu plan from worktree (no backend access). tofu validate and tofu fmt -check both pass clean. Expected plan output:

+ kubernetes_namespace_v1.staging (module.staging)
+ kubernetes_manifest.netpol_staging (network-policies.tf)

No existing resources modified or destroyed.

Test Plan

  • tofu validate passes
  • tofu fmt -recursive -check passes (no formatting drift)
  • scripts/test-update-kustomize-tag.sh passes (7/7)
  • After tofu apply: verify kubectl get ns staging exists with correct labels
  • Verify kubectl get networkpolicy -n staging shows default-deny-ingress
  • Downstream: pal-e-deployments can create staging overlays targeting this namespace

Review Checklist

  • tofu fmt -recursive clean
  • tofu validate passes
  • No new secrets required (no variables added)
  • Network policy follows existing default-deny pattern
  • Module follows existing conventions (main.tf, outputs.tf, variables.tf, versions.tf)
  • Existing tests pass (7/7 kustomize tag tests)
  • This PR is the platform foundation only. Staging overlays, ArgoCD apps, and Woodpecker pipeline steps are downstream work in other repos.
  • Closes #213
  • Discovered scope for other repos:
    • pal-e-deployments: staging overlays per service
    • pal-e-services: staging ArgoCD Applications
    • claude-custom: /validate-ticket tier awareness
    • Per-repo: .woodpecker.yaml staging deploy steps
## Summary Adds the `staging` Kubernetes namespace as a new Terraform module with default-deny network policy, root orchestrator wiring, and output exposure. This is the pal-e-platform foundation for the dev-staging-prod validation pipeline. ## Changes - `terraform/modules/staging/main.tf` — New module creating the `staging` namespace with `environment=staging` label - `terraform/modules/staging/outputs.tf` — Exposes `staging_namespace` for downstream consumers - `terraform/modules/staging/variables.tf` — Empty (namespace is self-contained; ArgoCD deploys workloads) - `terraform/modules/staging/versions.tf` — Kubernetes provider requirement - `terraform/main.tf` — Wires `module.staging` into the root orchestrator - `terraform/network-policies.tf` — Adds `netpol_staging` default-deny policy allowing ingress from tailscale, staging (intra-ns), monitoring, argocd, and woodpecker - `terraform/outputs.tf` — Exposes `staging_namespace` at root level - `scripts/woodpecker-update-tag-step.yaml` — Documents `OVERLAY_ENV` tiers (prod/staging) and adds commented staging deploy step template ## tofu plan Output Cannot run `tofu plan` from worktree (no backend access). `tofu validate` and `tofu fmt -check` both pass clean. Expected plan output: ``` + kubernetes_namespace_v1.staging (module.staging) + kubernetes_manifest.netpol_staging (network-policies.tf) ``` No existing resources modified or destroyed. ## Test Plan - `tofu validate` passes - `tofu fmt -recursive -check` passes (no formatting drift) - `scripts/test-update-kustomize-tag.sh` passes (7/7) - After `tofu apply`: verify `kubectl get ns staging` exists with correct labels - Verify `kubectl get networkpolicy -n staging` shows default-deny-ingress - Downstream: pal-e-deployments can create staging overlays targeting this namespace ## Review Checklist - [x] `tofu fmt -recursive` clean - [x] `tofu validate` passes - [x] No new secrets required (no variables added) - [x] Network policy follows existing default-deny pattern - [x] Module follows existing conventions (main.tf, outputs.tf, variables.tf, versions.tf) - [x] Existing tests pass (7/7 kustomize tag tests) ## Related Notes - This PR is the platform foundation only. Staging overlays, ArgoCD apps, and Woodpecker pipeline steps are downstream work in other repos. ## Related - Closes #213 - Discovered scope for other repos: - pal-e-deployments: staging overlays per service - pal-e-services: staging ArgoCD Applications - claude-custom: /validate-ticket tier awareness - Per-repo: .woodpecker.yaml staging deploy steps
feat: add staging namespace module for validation pipeline
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
58606ad885
Adds the staging k8s namespace as a new Terraform module with
default-deny network policy and root orchestrator wiring. This
is the pal-e-platform foundation for the dev-staging-prod
validation pipeline (Forgejo #213).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

QA Review

Module Structure

  • terraform/modules/staging/ follows the exact 4-file convention (main.tf, outputs.tf, variables.tf, versions.tf) established by all other modules. Clean.
  • Empty variables.tf with explanatory comment is appropriate -- namespace is self-contained, ArgoCD deploys workloads.

Root Orchestrator Wiring

  • module.staging placed after ops, before moved blocks. No dependencies needed since staging is independent of other modules. Correct.

Network Policy

  • Default-deny with field_manager { force_conflicts = true } matches every other netpol in the file.
  • Ingress sources (tailscale, staging self, monitoring, argocd, woodpecker) are the correct set for a staging namespace receiving ArgoCD deployments and Woodpecker smoke tests.
  • No access to postgres or minio from staging -- services in staging should use their own DB connections configured via staging overlays. Correct isolation.

Output

  • staging_namespace exposed at root level for downstream consumers (pal-e-services, pal-e-deployments). Matches pattern of other namespace outputs.

Woodpecker Template

  • Documentation-only change plus commented staging step template. No functional change to the production deploy path.
  • OVERLAY_ENV tier documentation is helpful for downstream adoption.

Validation

  • tofu validate passes
  • tofu fmt -recursive -check clean
  • 7/7 existing tests pass

Nits

None.

VERDICT: APPROVE

## QA Review ### Module Structure - `terraform/modules/staging/` follows the exact 4-file convention (main.tf, outputs.tf, variables.tf, versions.tf) established by all other modules. Clean. - Empty variables.tf with explanatory comment is appropriate -- namespace is self-contained, ArgoCD deploys workloads. ### Root Orchestrator Wiring - `module.staging` placed after ops, before moved blocks. No dependencies needed since staging is independent of other modules. Correct. ### Network Policy - Default-deny with `field_manager { force_conflicts = true }` matches every other netpol in the file. - Ingress sources (tailscale, staging self, monitoring, argocd, woodpecker) are the correct set for a staging namespace receiving ArgoCD deployments and Woodpecker smoke tests. - No access to postgres or minio from staging -- services in staging should use their own DB connections configured via staging overlays. Correct isolation. ### Output - `staging_namespace` exposed at root level for downstream consumers (pal-e-services, pal-e-deployments). Matches pattern of other namespace outputs. ### Woodpecker Template - Documentation-only change plus commented staging step template. No functional change to the production deploy path. - `OVERLAY_ENV` tier documentation is helpful for downstream adoption. ### Validation - `tofu validate` passes - `tofu fmt -recursive -check` clean - 7/7 existing tests pass ### Nits None. **VERDICT: APPROVE**
Author
Owner

PR #218 Review

DOMAIN REVIEW

Tech stack: Terraform/OpenTofu (Kubernetes provider), k8s NetworkPolicy, Woodpecker CI YAML template.

Module structure: The new terraform/modules/staging/ module follows the established four-file convention (main.tf, outputs.tf, variables.tf, versions.tf). The root orchestrator wiring in terraform/main.tf places the module correctly between ops and the moved{} blocks section. The network policy in terraform/network-policies.tf follows the identical kubernetes_manifest pattern used by all other namespace policies (field_manager, default-deny-ingress, namespaceSelector matchLabels). The root terraform/outputs.tf exposes the namespace consistently with other outputs.

Network policy analysis: The staging netpol allows ingress from tailscale (external access), staging (intra-namespace), monitoring (metrics scraping), argocd (deployment sync), and woodpecker (CI pipeline). This is a reasonable initial allowlist for a pre-prod namespace. Notably missing but likely intentional: no postgres/database ingress (staging services will need their own DB access rules once workloads are deployed -- this is correctly deferred as downstream scope).

Woodpecker template: The woodpecker-update-tag-step.yaml changes are documentation-only. The commented staging step template is correct and consistent with the prod step pattern. The OVERLAY_ENV variable is already supported by scripts/update-kustomize-tag.sh (line 30: OVERLAY_ENV="${OVERLAY_ENV:-prod}"), so the template will work when uncommented.

versions.tf discrepancy: The staging module's versions.tf declares source = "hashicorp/kubernetes" but omits the version constraint. Every other module in the codebase pins version = "~> 2.36". Compare:

  • terraform/modules/staging/versions.tf: no version pin
  • terraform/modules/keycloak/versions.tf: version = "~> 2.36"
  • terraform/modules/ops/versions.tf: version = "~> 2.36"
  • terraform/modules/database/versions.tf: version = "~> 2.36"

This is inconsistent but non-blocking since the root module's lock file governs the actual version used. Still, it breaks the established pattern.

BLOCKERS

None. This is a clean, minimal infrastructure PR:

  • No new functionality requiring tests (namespace creation + network policy are declarative infra, validated by tofu validate)
  • No user input to validate
  • No secrets or credentials in code
  • No DRY violations in auth/security paths
  • The existing 7/7 kustomize tag tests continue to pass per the test plan

NITS

  1. Missing version constraint in versions.tf: Add version = "~> 2.36" to the kubernetes provider in terraform/modules/staging/versions.tf to match all other modules. Currently the only module without a version pin.

  2. Staging step placement note: The woodpecker-update-tag-step.yaml comment says "Add this step BEFORE the prod update-kustomize-tag step" but the commented template appears AFTER the prod step in the file. When someone copy-pastes this into a real .woodpecker.yaml, the comment instruction and the file order send mixed signals. Consider reordering the blocks (staging first, prod second) to match the intended execution order, or adjust the comment to say "Copy this step and place it before the prod step in your .woodpecker.yaml."

SOP COMPLIANCE

  • Branch named after issue: 213-staging-namespace-and-network-policies references issue #213
  • PR body follows template: Summary, Changes, Test Plan, Related sections all present
  • Related references: Closes #213 present, discovered scope itemized for downstream repos
  • No secrets committed: no credentials, tokens, or .env files
  • No scope creep: all changes are directly related to the staging namespace story
  • tofu fmt and tofu validate reported as passing
  • tofu plan output: not included (documented as "Cannot run from worktree"). PR conventions require plan output for Terraform changes, but the worktree limitation is a known constraint. The expected plan output (2 new resources, 0 modified/destroyed) is documented.

PROCESS OBSERVATIONS

  • Change failure risk: Low. Two new resources (kubernetes_namespace_v1.staging, kubernetes_manifest.netpol_staging), zero modifications to existing infrastructure. No state migration needed (new module, no moved{} blocks).
  • Deployment frequency: This is a foundation PR that unblocks downstream work across 4+ repos (pal-e-deployments, pal-e-services, claude-custom, per-repo CI configs). Good decomposition -- the platform piece ships independently.
  • Discovered scope: Well-documented in the PR body. Four downstream work items identified and explicitly deferred.

VERDICT: APPROVED

## PR #218 Review ### DOMAIN REVIEW **Tech stack**: Terraform/OpenTofu (Kubernetes provider), k8s NetworkPolicy, Woodpecker CI YAML template. **Module structure**: The new `terraform/modules/staging/` module follows the established four-file convention (`main.tf`, `outputs.tf`, `variables.tf`, `versions.tf`). The root orchestrator wiring in `terraform/main.tf` places the module correctly between `ops` and the `moved{}` blocks section. The network policy in `terraform/network-policies.tf` follows the identical `kubernetes_manifest` pattern used by all other namespace policies (field_manager, default-deny-ingress, namespaceSelector matchLabels). The root `terraform/outputs.tf` exposes the namespace consistently with other outputs. **Network policy analysis**: The staging netpol allows ingress from tailscale (external access), staging (intra-namespace), monitoring (metrics scraping), argocd (deployment sync), and woodpecker (CI pipeline). This is a reasonable initial allowlist for a pre-prod namespace. Notably missing but likely intentional: no postgres/database ingress (staging services will need their own DB access rules once workloads are deployed -- this is correctly deferred as downstream scope). **Woodpecker template**: The `woodpecker-update-tag-step.yaml` changes are documentation-only. The commented staging step template is correct and consistent with the prod step pattern. The `OVERLAY_ENV` variable is already supported by `scripts/update-kustomize-tag.sh` (line 30: `OVERLAY_ENV="${OVERLAY_ENV:-prod}"`), so the template will work when uncommented. **versions.tf discrepancy**: The staging module's `versions.tf` declares `source = "hashicorp/kubernetes"` but **omits the `version` constraint**. Every other module in the codebase pins `version = "~> 2.36"`. Compare: - `terraform/modules/staging/versions.tf`: no version pin - `terraform/modules/keycloak/versions.tf`: `version = "~> 2.36"` - `terraform/modules/ops/versions.tf`: `version = "~> 2.36"` - `terraform/modules/database/versions.tf`: `version = "~> 2.36"` This is inconsistent but non-blocking since the root module's lock file governs the actual version used. Still, it breaks the established pattern. ### BLOCKERS None. This is a clean, minimal infrastructure PR: - No new functionality requiring tests (namespace creation + network policy are declarative infra, validated by `tofu validate`) - No user input to validate - No secrets or credentials in code - No DRY violations in auth/security paths - The existing 7/7 kustomize tag tests continue to pass per the test plan ### NITS 1. **Missing version constraint in `versions.tf`**: Add `version = "~> 2.36"` to the kubernetes provider in `terraform/modules/staging/versions.tf` to match all other modules. Currently the only module without a version pin. 2. **Staging step placement note**: The `woodpecker-update-tag-step.yaml` comment says "Add this step BEFORE the prod update-kustomize-tag step" but the commented template appears AFTER the prod step in the file. When someone copy-pastes this into a real `.woodpecker.yaml`, the comment instruction and the file order send mixed signals. Consider reordering the blocks (staging first, prod second) to match the intended execution order, or adjust the comment to say "Copy this step and place it before the prod step in your .woodpecker.yaml." ### SOP COMPLIANCE - [x] Branch named after issue: `213-staging-namespace-and-network-policies` references issue #213 - [x] PR body follows template: Summary, Changes, Test Plan, Related sections all present - [x] Related references: `Closes #213` present, discovered scope itemized for downstream repos - [x] No secrets committed: no credentials, tokens, or .env files - [x] No scope creep: all changes are directly related to the staging namespace story - [x] `tofu fmt` and `tofu validate` reported as passing - [ ] `tofu plan` output: not included (documented as "Cannot run from worktree"). PR conventions require plan output for Terraform changes, but the worktree limitation is a known constraint. The expected plan output (2 new resources, 0 modified/destroyed) is documented. ### PROCESS OBSERVATIONS - **Change failure risk**: Low. Two new resources (`kubernetes_namespace_v1.staging`, `kubernetes_manifest.netpol_staging`), zero modifications to existing infrastructure. No state migration needed (new module, no `moved{}` blocks). - **Deployment frequency**: This is a foundation PR that unblocks downstream work across 4+ repos (pal-e-deployments, pal-e-services, claude-custom, per-repo CI configs). Good decomposition -- the platform piece ships independently. - **Discovered scope**: Well-documented in the PR body. Four downstream work items identified and explicitly deferred. ### VERDICT: APPROVED
forgejo_admin deleted branch 213-staging-namespace-and-network-policies 2026-03-28 05:47:33 +00:00
Sign in to join this conversation.
No description provided.