Skip to content

declarative-deployment-boundary

recognized control-plane commands bypass Terraform resource ownership

Why

Imperative control-plane commands split deployment ownership between Terraform and repository-specific orchestration, so drift and safety depend on execution order. Publishing an application artifact is a release operation and remains outside this rule.

Fix

Model the resource, identity, and lifecycle in Terraform; let CI select inputs and apply the saved plan without maintaining a second mutation path.

Examples

Before — flagged A Cloud Run configuration update owns infrastructure
.github/workflows/deploy.yml
jobs:
deploy:
steps:
- run: gcloud run deploy api --image $IMAGE --memory 1Gi
After — preferred CI publishes a Cloud Run application artifact
.github/workflows/deploy.yml
jobs:
deploy:
steps:
- run: gcloud run deploy api --image $IMAGE --region us
Before — flagged Keep Cloud Run infrastructure in Terraform
.github/workflows/deploy.yml
jobs:
deploy:
steps:
- run: gcloud run deploy api --image $IMAGE --memory 1Gi
After — preferred CI applies the reviewed Terraform plan
.github/workflows/deploy.yml
jobs:
deploy:
steps:
- run: terraform apply saved.tfplan
Before — flagged Provider resources own API enablement
main.tf
resource "terraform_data" "enable_api" {
provisioner "local-exec" {
command = "gcloud services enable example.googleapis.com"
}
}
After — preferred Read-only local commands do not create drift
main.tf
resource "terraform_data" "inspect_api" {
provisioner "local-exec" {
command = "gcloud services list --enabled"
}
}
Before — flagged Keep Worker resource creation in Terraform
.github/workflows/deploy.yml
jobs:
deploy:
steps:
- run: pnpm exec wrangler d1 create app
After — preferred CI publishes a Worker application artifact
.github/workflows/deploy.yml
jobs:
deploy:
steps:
- run: pnpm exec wrangler deploy --tag $GITHUB_SHA

Files

.github/workflows/*.{yaml,yml}{cloudbuild,deploy,deployments,iac,infra,k8s,scripts,terraform,tools}/****/*.tf