Add GCP bootstrap workflow for terraform standard
This commit is contained in:
parent
af823faf8c
commit
36b770fe24
180
.github/workflows/terraform-standard-iac-pipeline-gcp-global-bootstrap.yaml
vendored
Normal file
180
.github/workflows/terraform-standard-iac-pipeline-gcp-global-bootstrap.yaml
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
name: Terraform Standard - GCP Project Bootstrap
|
||||
|
||||
concurrency:
|
||||
group: terraform-bootstrap-gcp-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'iac-template/terraform-hcl-standard/gcp-cloud/bootstrap-s3/**'
|
||||
- 'iac-template/terraform-hcl-standard/gcp-cloud/bootstrap-iam/**'
|
||||
- 'iac-template/terraform-hcl-standard/gcp-cloud/bootstrap-dynamodb/**'
|
||||
- '.github/workflows/terraform-standard-iac-pipeline-gcp-global-bootstrap.yaml'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
deploy_action:
|
||||
type: choice
|
||||
options: [plan, apply, destroy]
|
||||
default: plan
|
||||
|
||||
env:
|
||||
TF_WORKDIR: iac-template/terraform-hcl-standard/gcp-cloud
|
||||
DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'plan' }}
|
||||
|
||||
jobs:
|
||||
bootstrap:
|
||||
name: "Bootstrap Modules"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
target: [bootstrap-dynamodb, bootstrap-s3, bootstrap-iam]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Document Bootstrap Scope
|
||||
run: |
|
||||
cat <<'SUMMARY' >> "$GITHUB_STEP_SUMMARY"
|
||||
## Bootstrap scope (GCP)
|
||||
- Cloud Storage: create remote state bucket (versioned + uniform access)
|
||||
- Firestore: enable Datastore mode database for state locking and metadata
|
||||
- IAM: create Terraform bootstrap service account and bind elevated roles
|
||||
|
||||
Resource names and locations follow iac-template/terraform-hcl-standard/gcp-cloud/config/accounts/bootstrap.yaml.
|
||||
SUMMARY
|
||||
|
||||
- uses: hashicorp/setup-terraform@v3
|
||||
with:
|
||||
terraform_version: 1.9.5
|
||||
|
||||
- name: Restore Terraform state
|
||||
uses: actions/download-artifact@v4
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: tfstate-${{ matrix.target }}
|
||||
path: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
|
||||
|
||||
- name: Load bootstrap config
|
||||
run: |
|
||||
python -m pip install --quiet pyyaml
|
||||
python - <<'PY'
|
||||
import json
|
||||
import yaml
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
cfg_path = Path("iac-template/terraform-hcl-standard/gcp-cloud/config/accounts/bootstrap.yaml")
|
||||
cfg = yaml.safe_load(cfg_path.read_text())
|
||||
|
||||
env_path = Path(os.environ["GITHUB_ENV"])
|
||||
current_env = env_path.read_text() if env_path.exists() else ""
|
||||
env_path.write_text(
|
||||
current_env
|
||||
+ f"BOOTSTRAP_PROJECT_ID={cfg['project_id']}\n"
|
||||
+ f"BOOTSTRAP_BUCKET_NAME={cfg['state']['bucket_name']}\n"
|
||||
+ f"BOOTSTRAP_BUCKET_LOCATION={cfg['state'].get('bucket_location', 'US')}\n"
|
||||
+ f"BOOTSTRAP_FIRESTORE_LOCATION={cfg['state'].get('firestore_location', 'us-central')}\n"
|
||||
+ f"BOOTSTRAP_SA_ID={cfg['iam'].get('service_account_id', 'terraform-bootstrap')}\n"
|
||||
+ f"BOOTSTRAP_SA_ROLES={json.dumps(cfg['iam'].get('service_account_roles', []))}\n"
|
||||
)
|
||||
PY
|
||||
|
||||
- name: Authenticate to GCP
|
||||
uses: google-github-actions/auth@v2
|
||||
with:
|
||||
credentials_json: ${{ secrets.GCP_CREDENTIALS_JSON }}
|
||||
project_id: ${{ env.BOOTSTRAP_PROJECT_ID }}
|
||||
create_credentials_file: true
|
||||
export_environment_variables: true
|
||||
|
||||
- name: Set up gcloud CLI
|
||||
uses: google-github-actions/setup-gcloud@v2
|
||||
with:
|
||||
project_id: ${{ env.BOOTSTRAP_PROJECT_ID }}
|
||||
|
||||
- name: Render Terraform variables
|
||||
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
|
||||
run: |
|
||||
cat > bootstrap.auto.tfvars <<EOF
|
||||
project_id = "${BOOTSTRAP_PROJECT_ID}"
|
||||
EOF
|
||||
|
||||
if [ "${{ matrix.target }}" = "bootstrap-s3" ]; then
|
||||
cat >> bootstrap.auto.tfvars <<EOF
|
||||
bucket_name = "${BOOTSTRAP_BUCKET_NAME}"
|
||||
location = "${BOOTSTRAP_BUCKET_LOCATION}"
|
||||
EOF
|
||||
elif [ "${{ matrix.target }}" = "bootstrap-dynamodb" ]; then
|
||||
cat >> bootstrap.auto.tfvars <<EOF
|
||||
location = "${BOOTSTRAP_FIRESTORE_LOCATION}"
|
||||
EOF
|
||||
elif [ "${{ matrix.target }}" = "bootstrap-iam" ]; then
|
||||
cat >> bootstrap.auto.tfvars <<EOF
|
||||
service_account_id = "${BOOTSTRAP_SA_ID}"
|
||||
service_account_roles = ${BOOTSTRAP_SA_ROLES}
|
||||
EOF
|
||||
fi
|
||||
|
||||
- name: Init
|
||||
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
|
||||
run: terraform init -upgrade
|
||||
|
||||
- name: Plan
|
||||
if: env.DEPLOY_ACTION == 'plan'
|
||||
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
|
||||
run: terraform plan -no-color
|
||||
|
||||
- name: Apply
|
||||
if: env.DEPLOY_ACTION == 'apply'
|
||||
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
|
||||
run: terraform apply -auto-approve
|
||||
|
||||
- name: Destroy
|
||||
if: env.DEPLOY_ACTION == 'destroy'
|
||||
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
|
||||
run: terraform destroy -auto-approve
|
||||
|
||||
- name: Save Outputs
|
||||
if: env.DEPLOY_ACTION == 'apply'
|
||||
working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }}
|
||||
run: terraform output -json > ../../outputs_${{ matrix.target }}.json
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: env.DEPLOY_ACTION == 'apply'
|
||||
with:
|
||||
name: outputs-${{ matrix.target }}
|
||||
path: iac-template/terraform-hcl-standard/gcp-cloud/outputs_${{ matrix.target }}.json
|
||||
retention-days: 30
|
||||
|
||||
aggregate:
|
||||
name: "Aggregate Bootstrap Outputs"
|
||||
runs-on: ubuntu-latest
|
||||
needs: bootstrap
|
||||
|
||||
if: ${{ github.event.inputs.deploy_action == 'apply' }}
|
||||
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: ./outputs
|
||||
|
||||
- name: Merge Outputs
|
||||
run: |
|
||||
echo "{" > final_bootstrap_outputs.json
|
||||
f=true
|
||||
for x in outputs/**/outputs_*.json; do
|
||||
k=$(basename $x .json | sed 's/outputs_//')
|
||||
[ "$f" = true ] && f=false || echo "," >> final_bootstrap_outputs.json
|
||||
echo "\"$k\": $(cat $x)" >> final_bootstrap_outputs.json
|
||||
done
|
||||
echo "}" >> final_bootstrap_outputs.json
|
||||
|
||||
- run: cat final_bootstrap_outputs.json
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bootstrap-final-output
|
||||
path: final_bootstrap_outputs.json
|
||||
@ -0,0 +1,14 @@
|
||||
project_id: "modern-app-bootstrap"
|
||||
environment: bootstrap
|
||||
|
||||
state:
|
||||
bucket_name: svc-plus-iac-state
|
||||
bucket_location: US
|
||||
firestore_location: us-central
|
||||
|
||||
iam:
|
||||
service_account_id: terraform-bootstrap
|
||||
service_account_roles:
|
||||
- roles/resourcemanager.projectIamAdmin
|
||||
- roles/storage.admin
|
||||
- roles/compute.admin
|
||||
Loading…
Reference in New Issue
Block a user