diff --git a/.github/workflows/terraform-apply.yml b/.github/workflows/terraform-apply.yml new file mode 100644 index 0000000000..e4cc76cad7 --- /dev/null +++ b/.github/workflows/terraform-apply.yml @@ -0,0 +1,106 @@ +name: Terraform Apply + +on: + push: + branches: + - 'main' + paths: + - 'iac/*' + +permissions: + contents: read + pull-requests: write + +jobs: + targets: + name: Find targets + + runs-on: ubuntu-latest + + outputs: + staging: ${{ steps.staging.outputs.paths }} + production: ${{ steps.production.outputs.paths }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Staging Terraform targets + id: staging + run: echo "paths=$(find iac -name 'provider.tf' | grep cal-itp-data-infra-staging/ | xargs dirname | jq --raw-input --slurp --compact-output 'split("\n")[:-1]')" >> ${GITHUB_OUTPUT} + + - name: Production Terraform targets + id: production + run: echo "paths=$(find iac -name 'provider.tf' | grep cal-itp-data-infra/ | xargs dirname | jq --raw-input --slurp --compact-output 'split("\n")[:-1]')" >> ${GITHUB_OUTPUT} + + staging: + name: Staging + + needs: targets + + runs-on: ubuntu-latest + + permissions: + contents: 'read' + id-token: 'write' + + strategy: + fail-fast: false + matrix: + path: ${{ fromJson(needs.targets.outputs.staging) }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: 'google-github-actions/auth@v2' + with: + create_credentials_file: 'true' + project_id: cal-itp-data-infra-staging + workload_identity_provider: 'projects/473674835135/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'github-actions-terraform@cal-itp-data-infra-staging.iam.gserviceaccount.com' + + - uses: google-github-actions/setup-gcloud@v2 + + - name: Terraform Apply + uses: dflook/terraform-apply@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + path: ${{ matrix.path }} + + production: + name: Production + + needs: targets + + runs-on: ubuntu-latest + + permissions: + contents: 'read' + id-token: 'write' + + strategy: + fail-fast: false + matrix: + path: ${{ fromJson(needs.targets.outputs.production) }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: 'google-github-actions/auth@v2' + with: + create_credentials_file: 'true' + project_id: cal-itp-data-infra + workload_identity_provider: 'projects/1005246706141/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'github-actions-terraform@cal-itp-data-infra.iam.gserviceaccount.com' + + - uses: google-github-actions/setup-gcloud@v2 + + - name: Terraform Apply + uses: dflook/terraform-apply@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + path: ${{ matrix.path }} diff --git a/.github/workflows/terraform-deploy.yml b/.github/workflows/terraform-deploy.yml deleted file mode 100644 index 0a76b1c303..0000000000 --- a/.github/workflows/terraform-deploy.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Deploy to a terraform target - -on: - push: - branches: - - 'main' - - 'targets/*' - paths: - - 'iac/terraform/*' - -jobs: - - deploy: - - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: true - - - uses: google-github-actions/setup-gcloud@v1 - with: - service_account_key: ${{ secrets.GCP_SA_KEY }} - export_default_credentials: true - - - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: 1.1.7 - terraform_wrapper: false - - - name: terraform-deploy - shell: bash - env: - CONTENT_ROOT : ${{ github.workspace }}/iac - ENGINE_ROOT : ${{ github.workspace }}/iac/.engine - run: | - if [[ $GITHUB_REF == refs/heads/main ]]; then - export INFRA_TARGET_NAME=prod - else - export INFRA_TARGET_NAME=${GITHUB_BASE_BRANCH#targets/} - if [[ $INFRA_TARGET_NAME == prod ]]; then - echo "fatal: prod changes must be merged to main branch" >&2 - exit 1 - fi - fi - "$ENGINE_ROOT"/bin/terraform-deploy diff --git a/.github/workflows/terraform-plan.yml b/.github/workflows/terraform-plan.yml new file mode 100644 index 0000000000..8d2de3bffa --- /dev/null +++ b/.github/workflows/terraform-plan.yml @@ -0,0 +1,122 @@ +name: Terraform Plan + +on: + pull_request: + paths: + - 'iac/*' + +jobs: + targets: + name: Find targets + + runs-on: ubuntu-latest + + outputs: + staging: ${{ steps.staging.outputs.paths }} + production: ${{ steps.production.outputs.paths }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Staging Terraform targets + id: staging + run: echo "paths=$(find iac -name 'provider.tf' | grep cal-itp-data-infra-staging/ | xargs dirname | jq --raw-input --slurp --compact-output 'split("\n")[:-1]')" >> ${GITHUB_OUTPUT} + + - name: Production Terraform targets + id: production + run: echo "paths=$(find iac -name 'provider.tf' | grep cal-itp-data-infra/ | xargs dirname | jq --raw-input --slurp --compact-output 'split("\n")[:-1]')" >> ${GITHUB_OUTPUT} + + staging: + name: Staging + + needs: targets + + runs-on: ubuntu-latest + + permissions: + contents: 'read' + id-token: 'write' + + strategy: + fail-fast: false + matrix: + path: ${{ fromJson(needs.targets.outputs.staging) }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: 'google-github-actions/auth@v2' + with: + create_credentials_file: 'true' + project_id: cal-itp-data-infra-staging + workload_identity_provider: 'projects/473674835135/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'github-actions-terraform@cal-itp-data-infra-staging.iam.gserviceaccount.com' + + - uses: google-github-actions/setup-gcloud@v2 + + - name: Terraform Formatting + uses: dflook/terraform-fmt-check@v1 + with: + path: ${{ matrix.path }} + + - name: Terraform Validation + uses: dflook/terraform-validate@v1 + with: + path: ${{ matrix.path }} + + - name: Terraform Plan + uses: dflook/terraform-plan@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + add_github_comment: changes-only + path: ${{ matrix.path }} + + production: + name: Production + + needs: targets + + runs-on: ubuntu-latest + + permissions: + contents: 'read' + id-token: 'write' + + strategy: + fail-fast: false + matrix: + path: ${{ fromJson(needs.targets.outputs.production) }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - uses: 'google-github-actions/auth@v2' + with: + create_credentials_file: 'true' + project_id: cal-itp-data-infra + workload_identity_provider: 'projects/1005246706141/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'github-actions-terraform@cal-itp-data-infra.iam.gserviceaccount.com' + + - uses: google-github-actions/setup-gcloud@v2 + + - name: Terraform Format Check + uses: dflook/terraform-fmt-check@v1 + with: + path: ${{ matrix.path }} + + - name: Terraform Validate + uses: dflook/terraform-validate@v1 + with: + path: ${{ matrix.path }} + + - name: Terraform Plan + uses: dflook/terraform-plan@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + add_github_comment: changes-only + path: ${{ matrix.path }} diff --git a/.github/workflows/terraform-report.yml b/.github/workflows/terraform-report.yml deleted file mode 100644 index c556bae81d..0000000000 --- a/.github/workflows/terraform-report.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Report pending terraform changes - -on: - pull_request: - branches: - - 'main' - - 'targets/*' - paths: - - 'iac/terraform/*' - -jobs: - - changed: - - runs-on: ubuntu-latest - steps: - - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: true - - - uses: 'google-github-actions/auth@v2' - with: - credentials_json: '${{ secrets.GCP_SA_KEY }}' - - - uses: google-github-actions/setup-gcloud@v2 - - - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: 1.1.7 - terraform_wrapper: false - - - name: terraform-report - shell: bash - env: - CONTENT_ROOT : ${{ github.workspace }}/iac - ENGINE_ROOT : ${{ github.workspace }}/iac/.engine - GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} - GITHUB_PR_NUMBER : ${{ github.event.number }} - GITHUB_BASE_BRANCH : ${{ github.event.pull_request.base.ref }} - run: | - - if [[ $GITHUB_BASE_BRANCH == main ]]; then - export INFRA_TARGET_NAME=prod - else - export INFRA_TARGET_NAME=${GITHUB_BASE_BRANCH#targets/} - if [[ $INFRA_TARGET_NAME == prod ]]; then - echo "fatal: prod changes must be merged to main branch" >&2 - exit 1 - fi - fi - - . "$ENGINE_ROOT"/lib/sh/terraform-report.sh - - if [[ ${#target_endpoint_changes[*]} == 0 ]]; then - exit 0 - fi - - gh pr comment $GITHUB_PR_NUMBER --body-file - <