diff --git a/.github/workflows/terraform.yaml b/.github/workflows/terraform.yaml
new file mode 100644
index 0000000..f686aac
--- /dev/null
+++ b/.github/workflows/terraform.yaml
@@ -0,0 +1,196 @@
+name: "Terraform CICD - AWS ECS Instance"
+
+on:
+ pull_request:
+ branches:
+ - main
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: read
+ issues: write
+ pull-requests: write
+
+env:
+ # Verbosity setting for Terraform logs
+ TF_LOG: ERROR
+ # Credentials for deployment to AWS
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ # S3 bucket for the Terraform state
+ BUCKET_TF_STATE: ${{ secrets.BUCKET_TF_STATE}}
+
+jobs:
+# Terraform Dev CICD
+ terraform-dev:
+ name: "Terraform Infra CICD Dev"
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ shell: bash
+ working-directory: infra
+ environment: dev
+
+ steps:
+ - name: Checkout the repository to the runner
+ uses: actions/checkout@v4
+
+ - name: Setup Terraform with specified version on the runner
+ uses: hashicorp/setup-terraform@v3
+ with:
+ terraform_version: 1.11.3
+
+ - name: Terraform init dev
+ id: init-dev
+ run: terraform init -reconfigure -backend-config=bucket=$BUCKET_TF_STATE
+
+ # Quality checks DEV
+ - name: Terraform format
+ id: fmt-dev
+ if: github.event_name == 'pull_request'
+ run: terraform fmt -check
+
+ - name: Terraform validate
+ id: validate-dev
+ if: github.event_name == 'pull_request'
+ run: terraform validate
+
+ - name: Terraform plan - dev
+ id: plan-dev
+ if: github.event_name == 'pull_request'
+ run: terraform plan -var-file=envs/dev.tfvars -no-color -input=false
+ continue-on-error: true
+
+ - uses: actions/github-script@v7
+ if: github.event_name == 'pull_request'
+ env:
+ PLAN: "terraform\n${{ steps.plan-dev.outputs.stdout }}"
+ with:
+ script: |
+ const output = `#### Terraform Format and Style - DEV π\`${{ steps.fmt-dev.outcome }}\`
+ #### Terraform Initialization - DEV βοΈ\`${{ steps.init-dev.outcome }}\`
+ #### Terraform Validation - DEV π€\`${{ steps.validate-dev.outcome }}\`
+ #### Terraform Plan - DEV π\`${{ steps.plan-dev.outcome }}\`
+
+ Show Plan
+
+ \`\`\`\n
+ ${process.env.PLAN}
+ \`\`\`
+
+
+ *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
+
+ github.rest.issues.createComment({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: output
+ })
+
+ - name: Terraform Plan Status
+ if: steps.plan-dev.outcome == 'failure'
+ run: exit 1
+
+ - name: Terraform Apply
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
+ run: terraform apply -auto-approve -input=false
+
+# # Terraform Prod CI
+# terraform-prod-ci:
+# name: "Terraform Infra CI Prod"
+# runs-on: ubuntu-latest
+# defaults:
+# run:
+# shell: bash
+# environment: prod
+
+# steps:
+# - name: Checkout the repository to the runner
+# uses: actions/checkout@v4
+
+# - name: Setup Terraform with specified version on the runner
+# uses: hashicorp/setup-terraform@v3
+# with:
+# terraform_version: 1.11.3
+
+# - name: Terraform init prod
+# id: init-prod
+# run: terraform init -reconfigure -backend-config=bucket=$BUCKET_TF_STATE #Create new bucket for prod
+
+# # Quality checks PROD
+# - name: Terraform format
+# id: fmt-prod
+# if: github.event_name == 'pull_request'
+# run: terraform fmt -check
+
+# - name: Terraform validate
+# id: validate-prod
+# if: github.event_name == 'pull_request'
+# run: terraform validate
+
+# - name: Terraform plan - prod
+# id: plan-prod
+# if: github.event_name == 'pull_request'
+# run: terraform plan -var-file=envs/prod.tfvars -no-color -input=false
+# continue-on-error: true
+
+# - uses: actions/github-script@v6
+# if: github.event_name == 'pull_request'
+# env:
+# PLAN: "terraform\n${{ steps.plan-prod.outputs.stdout }}"
+# with:
+# script: |
+# const output = `#### Terraform Format and Style - PROD π\`${{ steps.fmt-prod.outcome }}\`
+# #### Terraform Initialization - PROD βοΈ\`${{ steps.init-prod.outcome }}\`
+# #### Terraform Validation - PROD π€\`${{ steps.validate-prod.outcome }}\`
+# #### Terraform Plan - PROD π\`${{ steps.plan-prod.outcome }}\`
+
+# Show Plan
+
+# \`\`\`\n
+# ${process.env.PLAN}
+# \`\`\`
+
+#
+# *Pushed by: @${{ github.actor }}, Action: \`${{ github.event_name }}\`*`;
+
+# github.rest.issues.createComment({
+# issue_number: context.issue.number,
+# owner: context.repo.owner,
+# repo: context.repo.repo,
+# body: output
+# })
+
+# - name: Terraform Plan Status
+# if: steps.plan-prod.outcome == 'failure'
+# run: exit 1
+
+# # Terraform PROD CD
+# terraform-prod-cd:
+# name: "Terraform Infra CD Prod"
+# needs: [terraform-dev, terraform-prod-ci]
+# runs-on: ubuntu-latest
+# defaults:
+# run:
+# shell: bash
+# environment: prod
+
+# steps:
+# - name: Checkout the repository to the runner
+# uses: actions/checkout@v3
+
+# - name: Setup Terraform with specified version on the runner
+# uses: hashicorp/setup-terraform@v2
+# with:
+# terraform_version: 1.3.9
+
+# - name: Terraform init prod
+# id: init-prod
+# run: terraform init -reconfigure -backend-config=bucket=$BUCKET_TF_STATE
+
+# - name: Terraform Apply
+# if: github.ref == 'refs/heads/main' && github.event_name == 'push' # only on push/merge to main
+# run: terraform apply -auto-approve -input=false
\ No newline at end of file
diff --git a/README.md b/README.md
index ac1d408..81618a7 100644
--- a/README.md
+++ b/README.md
@@ -17,45 +17,25 @@ The VPC, public subnets, Internet Gateway, and Terraform remote-state bucket (S3
---
-## Repo structure
-
-```
-infra/
-ββ _backend.tf # remote state (S3 + DynamoDB)
-ββ _providers.tf # AWS provider / default tags
-ββ _variables.tf # all inputs
-ββ cluster.tf # ECS cluster (awsvpc)
-ββ asg_capacity.tf # ASG + capacity provider
-ββ task_definition.tf # image, ports, health check, logs
-ββ ecs_service.tf # service + load balancer attachment
-ββ cloudwatch_logs.tf
-ββ envs/
- ββ dev.tfvars
- ββ prod.tfvars
-```
-
----
-
## 1Β Β· Initialise Terraform (oneβtime per env)
```bash
cd infra
-terraform init -backend-config="bucket=node-app-infra-tfstate-dev" -backend-config="profile=node-app-terraform-dev"
+terraform init -reconfigure -backend-config=bucket=node-app-infra-tfstate-dev -backend-config=profile=node-app-terraform-dev
```
---
-## 2Β Β· Build & push the container image
+## 2Β Β· Build & push the container image (Apply new version tag where appropriate)
```bash
-docker buildx create --name multi --use 2>/dev/null || true
-docker buildx build --platform linux/amd64 -t nrampling/demo-node-app:1.0.0 --push .
+docker buildx build --platform linux/amd64 -t nrampling/demo-node-app:1.0.2 --push .
```
Update the image tag in `infra/envs/dev.tfvars`:
```hcl
-docker_image = "nrampling/demo-node-app:1.0.0"
+node_app_image = "nrampling/demo-node-app:1.0.2"
```
---
@@ -63,12 +43,12 @@ docker_image = "nrampling/demo-node-app:1.0.0"
## 3Β Β· Deploy with Terraform
```bash
-AWS_PROFILE=node-app-terraform-dev terraform plan -var-file=envs/dev.tfvars
+AWS_PROFILE=node-app-terraform-dev terraform plan -var-file=envs/dev.tfvars
AWS_PROFILE=node-app-terraform-dev terraform apply -var-file=envs/dev.tfvars
```
-### Outputs (example)
+### Outputs (example only - plug in aws account)
```text
alb_dns_name = dev-app-alb-123456.ap-southeast-2.elb.amazonaws.com
diff --git a/infra/envs/dev.tfvars b/infra/envs/dev.tfvars
index e4e19ab..84cd5d3 100644
--- a/infra/envs/dev.tfvars
+++ b/infra/envs/dev.tfvars
@@ -6,4 +6,4 @@ alb_public_subnet_ids = ["subnet-055583b9b74d44b56", "subnet-0e9b56625d00f6c88",
vpc_id = "vpc-0fabd74c01d8c9d4a"
-node_app_image = "nrampling/demo-node-app:1.0.2"
+node_app_image = "nrampling/demo-node-app:1.0.3"
diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml
index 62be5b7..a6ea2a0 100644
--- a/k8s/deployment.yaml
+++ b/k8s/deployment.yaml
@@ -14,7 +14,7 @@ spec:
spec:
containers:
- name: demo-node-app
- image: nrampling/demo-node-app:1.0.0
+ image: nrampling/demo-node-app:1.0.3
ports:
- containerPort: 3000
---