feat: Terraform CI via Forgejo Actions + MinIO S3 state backend
- ArgoCD manages MinIO (phase 0), Terraform manages infrastructure - Runner workflow: pulls state from S3, validates, plans, applies - 34 resources imported to state, S3 backend operational - Fixed AppProject repos, S3 endpoint deprecation, runner package manager
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
name: Terraform Apply CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'terraform/**'
|
||||
- '.forgejo/workflows/terraform-apply.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
terraform:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
# Install tools: wget (download terraform), unzip (extract), curl (optional)
|
||||
# Runner uses node:22-bookworm (Debian), not Alpine, so use apt-get
|
||||
apt-get update && apt-get install -y wget unzip curl
|
||||
|
||||
- name: Setup Terraform
|
||||
run: |
|
||||
TF_VERSION=1.8.4
|
||||
TF_URL="https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip"
|
||||
mkdir -p /tmp/tf-bin
|
||||
cd /tmp/tf-bin
|
||||
wget -q "$TF_URL" || { echo "Failed to download terraform"; exit 1; }
|
||||
unzip -q "terraform_${TF_VERSION}_linux_amd64.zip"
|
||||
chmod +x terraform
|
||||
./terraform version
|
||||
echo "/tmp/tf-bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Terraform Format Check
|
||||
run: terraform fmt -check -recursive terraform/
|
||||
continue-on-error: true
|
||||
|
||||
- name: Generate In-Cluster Kubeconfig
|
||||
run: |
|
||||
mkdir -p /tmp
|
||||
cat > /tmp/kubeconfig << 'EOF'
|
||||
apiVersion: v1
|
||||
kind: Config
|
||||
clusters:
|
||||
- cluster:
|
||||
certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
server: https://kubernetes.default:443
|
||||
name: in-cluster
|
||||
contexts:
|
||||
- context:
|
||||
cluster: in-cluster
|
||||
user: terraform
|
||||
name: in-cluster
|
||||
current-context: in-cluster
|
||||
users:
|
||||
- name: terraform
|
||||
user:
|
||||
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
|
||||
EOF
|
||||
chmod 600 /tmp/kubeconfig
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
run: |
|
||||
mkdir -p ~/.aws
|
||||
cat > ~/.aws/credentials << EOF
|
||||
[minio]
|
||||
aws_access_key_id = $AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key = $AWS_SECRET_ACCESS_KEY
|
||||
EOF
|
||||
chmod 600 ~/.aws/credentials
|
||||
|
||||
- name: Terraform Init
|
||||
working-directory: terraform
|
||||
env:
|
||||
# MinIO S3 backend — use internal DNS (storage ns) instead of external hostname
|
||||
# Runner pod blocked from external DNS; internal DNS is routable
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
TF_VAR_kubeconfig_path: /tmp/kubeconfig
|
||||
TF_SKIP_CREDENTIALS_VALIDATION: "true"
|
||||
TF_SKIP_REGION_VALIDATION: "true"
|
||||
TF_SKIP_REQUESTING_ACCOUNT_ID: "true"
|
||||
run: |
|
||||
# Override S3 endpoint to use internal cluster DNS
|
||||
export TF_CLI_ARGS_init="-backend-config=endpoints.s3=http://minio.storage.svc.cluster.local:9000"
|
||||
terraform init
|
||||
|
||||
- name: Pull Terraform State
|
||||
working-directory: terraform
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
TF_SKIP_CREDENTIALS_VALIDATION: "true"
|
||||
run: |
|
||||
echo "Verifying state is accessible from MinIO..."
|
||||
terraform state pull > /tmp/tfstate-verify.json
|
||||
STATE_SIZE=$(wc -c < /tmp/tfstate-verify.json)
|
||||
RESOURCE_COUNT=$(terraform state list | wc -l)
|
||||
echo "State size: $STATE_SIZE bytes"
|
||||
echo "Resources in state: $RESOURCE_COUNT"
|
||||
|
||||
- name: Terraform Validate
|
||||
working-directory: terraform
|
||||
run: terraform validate
|
||||
|
||||
- name: Terraform Plan
|
||||
working-directory: terraform
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
TF_VAR_kubeconfig_path: /tmp/kubeconfig
|
||||
TF_SKIP_CREDENTIALS_VALIDATION: "true"
|
||||
run: |
|
||||
terraform plan -out=tfplan
|
||||
|
||||
- name: Terraform Apply
|
||||
working-directory: terraform
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
TF_VAR_kubeconfig_path: /tmp/kubeconfig
|
||||
TF_SKIP_CREDENTIALS_VALIDATION: "true"
|
||||
run: |
|
||||
terraform apply -auto-approve tfplan
|
||||
Reference in New Issue
Block a user