From c057781ad66c35c254048348c0f999bce5202d80 Mon Sep 17 00:00:00 2001 From: gitea-admin Date: Wed, 29 Oct 2025 07:04:09 +0000 Subject: [PATCH] Add Terraform CI/CD pipeline --- .gitea/workflows/terraform.yml | 248 +++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 .gitea/workflows/terraform.yml diff --git a/.gitea/workflows/terraform.yml b/.gitea/workflows/terraform.yml new file mode 100644 index 0000000..edd26ba --- /dev/null +++ b/.gitea/workflows/terraform.yml @@ -0,0 +1,248 @@ +name: Terraform CI/CD Pipeline + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - main + workflow_dispatch: + inputs: + action: + description: 'Action to perform' + required: true + type: choice + options: + - plan + - apply + - destroy + +env: + TF_VERSION: "1.9.0" + WORKING_DIR: "./terraform" # Adjust to your terraform directory + +jobs: + # Stage 1: Linting and Syntax Checks + lint-and-validate: + name: Lint and Validate + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: https://github.com/hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + + - name: Terraform Format Check + id: fmt + run: terraform fmt -check -recursive + working-directory: ${{ env.WORKING_DIR }} + continue-on-error: true + + - name: Terraform Init (for validation) + run: terraform init -backend=false + working-directory: ${{ env.WORKING_DIR }} + + - name: Terraform Validate + run: terraform validate + working-directory: ${{ env.WORKING_DIR }} + + - name: Check Format Result + if: steps.fmt.outcome == 'failure' + run: | + echo "❌ Terraform formatting check failed. Run 'terraform fmt -recursive' to fix." + exit 1 + + # Stage 2: Security Scanning + security-scan: + name: Security Scan + runs-on: ubuntu-latest + needs: lint-and-validate + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run Checkov (Open Source Security Scanner) + uses: https://github.com/bridgecrewio/checkov-action@v12 + with: + directory: ${{ env.WORKING_DIR }} + framework: terraform + soft_fail: false # Set to true to not fail the pipeline on security issues + output_format: cli + + - name: Run tfsec (Terraform Security Scanner) + uses: https://github.com/aquasecurity/tfsec-action@v1.0.3 + with: + working_directory: ${{ env.WORKING_DIR }} + soft_fail: false + + # Stage 3: Terraform Init and Plan + plan: + name: Terraform Plan + runs-on: ubuntu-latest + needs: security-scan + if: github.event_name == 'push' || github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && (github.event.inputs.action == 'plan' || github.event.inputs.action == 'apply')) + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: https://github.com/hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + terraform_wrapper: false + + - name: Configure Terraform Credentials + run: | + # Add your cloud provider credentials here + # Example for AWS: + # echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}" >> $GITHUB_ENV + # echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> $GITHUB_ENV + + # Example for Azure: + # echo "ARM_CLIENT_ID=${{ secrets.ARM_CLIENT_ID }}" >> $GITHUB_ENV + # echo "ARM_CLIENT_SECRET=${{ secrets.ARM_CLIENT_SECRET }}" >> $GITHUB_ENV + # echo "ARM_SUBSCRIPTION_ID=${{ secrets.ARM_SUBSCRIPTION_ID }}" >> $GITHUB_ENV + # echo "ARM_TENANT_ID=${{ secrets.ARM_TENANT_ID }}" >> $GITHUB_ENV + + # For GCP, you might need to create a credentials file + echo "Configure your provider credentials here" + + - name: Terraform Init + run: terraform init + working-directory: ${{ env.WORKING_DIR }} + env: + # Add backend configuration secrets if needed + TF_CLI_ARGS_init: "-backend-config=access_key=${{ secrets.BACKEND_ACCESS_KEY }}" + + - name: Terraform Plan + run: terraform plan -out=tfplan.binary + working-directory: ${{ env.WORKING_DIR }} + + - name: Convert Plan to JSON + run: terraform show -json tfplan.binary > tfplan.json + working-directory: ${{ env.WORKING_DIR }} + + - name: Upload Terraform Plan + uses: actions/upload-artifact@v4 + with: + name: terraform-plan + path: | + ${{ env.WORKING_DIR }}/tfplan.binary + ${{ env.WORKING_DIR }}/tfplan.json + ${{ env.WORKING_DIR }}/.terraform/ + ${{ env.WORKING_DIR }}/.terraform.lock.hcl + retention-days: 30 + + - name: Comment Plan on PR + if: github.event_name == 'pull_request' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const plan = fs.readFileSync('${{ env.WORKING_DIR }}/tfplan.json', 'utf8'); + const output = `#### Terraform Plan 📖 + +
Show Plan + + \`\`\`json + ${plan} + \`\`\` + +
`; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: output + }); + + # Stage 4: Terraform Apply + apply: + name: Terraform Apply + runs-on: ubuntu-latest + needs: plan + if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'apply') + environment: + name: production + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: https://github.com/hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + terraform_wrapper: false + + - name: Download Terraform Plan + uses: actions/download-artifact@v4 + with: + name: terraform-plan + path: ${{ env.WORKING_DIR }} + + - name: Configure Terraform Credentials + run: | + # Same credentials configuration as in plan stage + echo "Configure your provider credentials here" + + - name: Restore Terraform Init Files + run: | + # The .terraform directory is already restored from artifacts + echo "Terraform initialization files restored" + + - name: Terraform Apply + run: terraform apply -auto-approve tfplan.binary + working-directory: ${{ env.WORKING_DIR }} + + - name: Output Terraform Outputs + run: terraform output -json > terraform-outputs.json + working-directory: ${{ env.WORKING_DIR }} + + - name: Upload Terraform Outputs + uses: actions/upload-artifact@v4 + with: + name: terraform-outputs + path: ${{ env.WORKING_DIR }}/terraform-outputs.json + retention-days: 90 + + # Stage 5: Terraform Destroy (Manual/Authorized Only) + destroy: + name: Terraform Destroy + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'destroy' + environment: + name: production-destroy # Requires manual approval in repository settings + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: https://github.com/hashicorp/setup-terraform@v3 + with: + terraform_version: ${{ env.TF_VERSION }} + terraform_wrapper: false + + - name: Configure Terraform Credentials + run: | + # Same credentials configuration as previous stages + echo "Configure your provider credentials here" + + - name: Terraform Init + run: terraform init + working-directory: ${{ env.WORKING_DIR }} + + - name: Terraform Destroy + run: terraform destroy -auto-approve + working-directory: ${{ env.WORKING_DIR }} + + - name: Notify Destroy Completion + run: | + echo "🔥 Terraform infrastructure has been destroyed!" + echo "Destroyed by: ${{ github.actor }}" + echo "Timestamp: $(date -u)"