Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ name: "Terraform CICD - AWS ECS Instance"

on:
pull_request:
branches:
- main
branches: [main]
paths:
- 'infra/ecs/**'
- 'infra/envs/**'
- '.github/workflows/ecs_terraform.yaml'
push:
branches:
- main
branches: [main]
paths:
- 'infra/ecs/**'
- 'infra/envs/**'
- '.github/workflows/ecs_terraform.yaml'

permissions:
contents: read
Expand All @@ -30,7 +36,7 @@ jobs:
defaults:
run:
shell: bash
working-directory: infra
working-directory: infra/ecs
environment: dev

steps:
Expand Down Expand Up @@ -60,7 +66,7 @@ jobs:
- 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
run: terraform plan -var-file=../envs/dev.tfvars -no-color -input=false
continue-on-error: true

- uses: actions/github-script@v7
Expand Down Expand Up @@ -96,7 +102,7 @@ jobs:

- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -var-file=envs/dev.tfvars -no-color -auto-approve -input=false # TODO: use tf plan file
run: terraform apply -var-file=../envs/dev.tfvars -no-color -auto-approve -input=false # TODO: use tf plan file

# # Terraform Prod CI
# terraform-prod-ci:
Expand Down Expand Up @@ -134,7 +140,7 @@ jobs:
# - 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
# run: terraform plan -var-file=../envs/prod.tfvars -no-color -input=false
# continue-on-error: true

# - uses: actions/github-script@v6
Expand Down
202 changes: 202 additions & 0 deletions .github/workflows/eks_terraform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
name: "Terraform CICD - AWS EKS Cluster"

on:
pull_request:
branches: [main]
paths:
- 'infra/eks/**'
- 'infra/envs/**'
- '.github/workflows/eks_terraform.yaml'
push:
branches: [main]
paths:
- 'infra/eks/**'
- 'infra/envs/**'
- '.github/workflows/eks_terraform.yaml'

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.EKS_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/ecs
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 }}\`

<details><summary>Show Plan</summary>

\`\`\`\n
${process.env.PLAN}
\`\`\`

</details>
*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 -var-file=../envs/dev.tfvars -no-color -auto-approve -input=false # TODO: use tf plan file

# # 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 }}\`

# <details><summary>Show Plan</summary>

# \`\`\`\n
# ${process.env.PLAN}
# \`\`\`

# </details>
# *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
43 changes: 35 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
# TypeScript Node.js API → Docker → Amazon ECS
*(local build & Terraform deploy – GitHub Actions pipeline coming soon)*
*(local build & Terraform deploy – GitHub Actions EKS Infra CICD pipeline)*

This repo walks you through containerising a simple Node.js API, pushing the image to Docker Hub, and provisioning the infrastructure on **Amazon EKS (EC2 capacity)** with **Terraform**.
The VPC, Public Subnets, Internet Gateway, Route Table and Terraform remote-state bucket (S3 + DynamoDB) are assumed to exist already.

Remote backend: S3 bucket `node-app-eks-tfstate-<env>`

## 1 · Initialise Terraform (one‑time per env)

```bash
cd infra/eks
terraform init -reconfigure -backend-config=bucket=node-app-eks-tfstate-dev -backend-config=profile=node-app-terraform-dev
```

## 3 · Deploy with Terraform from directory infra/eks/

```bash
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
```



# TypeScript Node.js API → Docker → Amazon ECS
*(local build & Terraform deploy – GitHub Actions ECS Infra CICD pipeline)*

This repo walks you through containerising a simple Node.js API, pushing the image to Docker Hub, and provisioning the infrastructure on **Amazon ECS (EC2 capacity)** with **Terraform**.
The VPC, Public Subnets, Internet Gateway, Route Table and Terraform remote-state bucket (S3 + DynamoDB) are assumed to exist already.
Expand All @@ -20,32 +45,34 @@ The VPC, Public Subnets, Internet Gateway, Route Table and Terraform remote-stat
## 1 · Initialise Terraform (one‑time per env)

```bash
cd infra
cd infra/ecs
terraform init -reconfigure -backend-config=bucket=node-app-infra-tfstate-dev -backend-config=profile=node-app-terraform-dev
```

---

## 2 · Build & push the container image (Apply new version tag where appropriate)
## 2 · Local Build & push the container image (Apply new version tag)

```bash
docker buildx build --platform linux/amd64,linux/arm64 -t nrampling/demo-node-app:1.0.2 --push .
```

Update the image tag in `infra/envs/dev.tfvars`:
For ECS workload
Update the image tag in `infra/ecs/envs/dev.tfvars`:
For EKS workload
Update the image tag in `infra/eks/envs/dev.tfvars`:

```hcl
node_app_image = "nrampling/demo-node-app:1.0.2"
```

---

## 3 · Deploy with Terraform
## 3 · Deploy with Terraform from directory infra/ecs/

```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
AWS_PROFILE=node-app-terraform-dev terraform apply -var-file=../envs/dev.tfvars
```

### Outputs (example only - plug in aws account)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading