Skip to content

ci: update deployment summary job exec condition #81

ci: update deployment summary job exec condition

ci: update deployment summary job exec condition #81

name: Deploy EKS Infrastructure
on:
push:
branches:
- main
env:
AWS_REGION: eu-west-1
TERRAFORM_VERSION: 1.10.3
KUBECTL_VERSION: 1.28.0
HELM_VERSION: 3.13.0
jobs:
test-eks-terraform-modules:
name: Test EKS Terraform Modules
runs-on: ubuntu-latest
# Skip this job if the commit message starts with 'ci:' or 'docs:'
if: |
github.event_name == 'push' &&
!startsWith(github.event.head_commit.message, 'ci:') &&
!startsWith(github.event.head_commit.message, 'docs:')
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Run Terraform module tests for EKS
run: |
if [ -f "run-tests.sh" ]; then
chmod +x run-tests.sh
./run-tests.sh
else
echo "No tests found for EKS modules (tests are optional)"
fi
working-directory: infra-eks
env:
AWS_ACCESS_KEY_ID: "mock-access-key"
AWS_SECRET_ACCESS_KEY: "mock-secret-key" # pragma: allowlist secret
AWS_DEFAULT_REGION: "eu-west-1"
deploy-terraform-state-bucket:
name: Deploy Terraform State Bucket
needs: test-eks-terraform-modules
uses: ./.github/workflows/eks_deploy_terraform_state_bucket.yaml # reusable workflow
with:
github_head_commit_message: ${{ github.event.head_commit.message }}
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
deploy-ecr:
name: Deploy ECR on AWS
needs: [test-eks-terraform-modules, deploy-terraform-state-bucket]
runs-on: ubuntu-latest
env: # required by some steps
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
ECR_REPO_URL: ecr_repository_url # Must match that of the output variable at ECR module
outputs:
ecr_repository_name: ${{ steps.get-ecr-output.outputs.ecr_repository_name }}
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{env.TERRAFORM_VERSION}}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Initialise Terraform on ECR directory
run: terraform init -backend-config="../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/ecr
- name: Validate IaC changes on ECR directory
run: terraform plan -var-file="../common.tfvars"
working-directory: infra-eks/deployment/ecr
- name: Create ECR repository if it does not yet exist
run: terraform apply -var-file="../common.tfvars" -auto-approve
working-directory: infra-eks/deployment/ecr
- name: Fetch ECR repository name from Terraform output
id: get-ecr-output # make the output available to other jobs
run: |
ecr_repo_url=$(terraform output -raw ${{ env.ECR_REPO_URL }})
echo "ecr_repository_name=$ecr_repo_url" >> $GITHUB_OUTPUT
working-directory: infra-eks/deployment/ecr
env:
TF_IN_AUTOMATION: true # suppresses prompts
retrieve-ssl:
name: Retrieve SSL certificate
needs: [test-eks-terraform-modules, deploy-terraform-state-bucket]
runs-on: ubuntu-latest
env: # required by some steps
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{env.TERRAFORM_VERSION}}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Initialise Terraform on SSL directory
run: terraform init -backend-config="../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/ssl
- name: Validate IaC changes on SSL directory
run: terraform plan -var-file="../common.tfvars" -var-file="../domain.tfvars" -var-file="../backend.tfvars"
working-directory: infra-eks/deployment/ssl
- name: Retrieve SSL certificate
run: terraform apply -var-file="../common.tfvars" -var-file="../domain.tfvars" -var-file="../backend.tfvars" -auto-approve
working-directory: infra-eks/deployment/ssl
build-and-push-app-docker-image-to-ecr:
name: Build and Push App Docker Image to ECR
needs: deploy-ecr
runs-on: ubuntu-latest
outputs:
image_tag: ${{ steps.set-tag.outputs.image_tag }}
env:
ECR_APP_IMAGE: ''
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Set Full ECR Image Tag
id: set-tag
run: |
# Extract environment from common.tfvars and construct ECR image tag
REPO_URL="${{ needs.deploy-ecr.outputs.ecr_repository_name }}"
ENVIRONMENT=$(grep "^environment" infra-eks/deployment/common.tfvars | cut -d'"' -f2)
IMAGE_TAG="${ENVIRONMENT}-${{ github.sha }}"
FULL_IMAGE="${REPO_URL}:${IMAGE_TAG}"
echo "ECR_APP_IMAGE=$FULL_IMAGE" >> $GITHUB_ENV
echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
echo "Image tag: $IMAGE_TAG"
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to AWS ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build the NestJS app
run: |
corepack enable
corepack prepare pnpm@latest --activate
pnpm install
pnpm build
- name: Build the Docker image
run: |
docker build -t ${{ env.ECR_APP_IMAGE }} -f Dockerfile .
- name: Push the Docker image to ECR
run: |
docker push ${{ env.ECR_APP_IMAGE }}
deploy-vpc:
name: Deploy the VPC on AWS
needs: deploy-ecr
runs-on: ubuntu-latest
env: # required by some steps
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{env.TERRAFORM_VERSION}}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Initialise Terraform on the VPC directory
run: terraform init -backend-config="../../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/app/vpc
- name: Validate IaC changes on the VPC directory
run: terraform plan -var-file="../../common.tfvars"
working-directory: infra-eks/deployment/app/vpc
- name: Deploy the VPC
run: terraform apply -var-file="../../common.tfvars" -auto-approve
working-directory: infra-eks/deployment/app/vpc
deploy-eks-cluster:
name: Deploy EKS Cluster
needs: deploy-vpc
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
outputs:
cluster_id: ${{ steps.get-cluster-output.outputs.cluster_id }}
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Initialize Terraform on EKS cluster directory
run: terraform init -backend-config="../../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/app/eks_cluster
- name: Validate IaC changes on EKS cluster directory
run: terraform plan -var-file="../../common.tfvars" -var-file="../../backend.tfvars"
working-directory: infra-eks/deployment/app/eks_cluster
- name: Deploy EKS cluster
run: terraform apply -var-file="../../common.tfvars" -var-file="../../backend.tfvars" -auto-approve
working-directory: infra-eks/deployment/app/eks_cluster
# Export job outputs for downstream job consumption
- name: Fetch EKS cluster outputs
id: get-cluster-output
run: |
cluster_id=$(terraform output -raw cluster_id)
echo "cluster_id=$cluster_id" >> $GITHUB_OUTPUT
echo "EKS Cluster ID: $cluster_id"
working-directory: infra-eks/deployment/app/eks_cluster
env:
TF_IN_AUTOMATION: true
deploy-eks-node-group:
name: Deploy EKS Node Group
needs: deploy-eks-cluster
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
outputs:
node_group_id: ${{ steps.get-node-group-output.outputs.node_group_id }}
node_group_name: ${{ steps.get-node-group-output.outputs.node_group_name }}
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Initialize Terraform on EKS node group directory
run: terraform init -backend-config="../../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/app/eks_node_group
- name: Validate IaC changes on EKS node group directory
run: terraform plan -var-file="../../common.tfvars" -var-file="../../backend.tfvars"
working-directory: infra-eks/deployment/app/eks_node_group
- name: Deploy EKS node group
run: terraform apply -var-file="../../common.tfvars" -var-file="../../backend.tfvars" -auto-approve
working-directory: infra-eks/deployment/app/eks_node_group
- name: Fetch EKS node group outputs
id: get-node-group-output
run: |
node_group_id=$(terraform output -raw node_group_id)
node_group_name=$(terraform output -raw node_group_name)
echo "node_group_id=$node_group_id" >> $GITHUB_OUTPUT
echo "node_group_name=$node_group_name" >> $GITHUB_OUTPUT
echo "EKS Node Group ID: $node_group_id"
echo "EKS Node Group Name: $node_group_name"
working-directory: infra-eks/deployment/app/eks_node_group
env:
TF_IN_AUTOMATION: true
- name: Wait for node group to be active
run: |
echo "Waiting for node group to be active..."
aws eks wait nodegroup-active \
--cluster-name ${{ needs.deploy-eks-cluster.outputs.cluster_id }} \
--nodegroup-name ${{ steps.get-node-group-output.outputs.node_group_name }} \
--region ${{ env.AWS_REGION }}
echo "Node group is now active!"
install-aws-load-balancer-controller:
name: Install AWS Load Balancer Controller
needs: [deploy-eks-cluster, deploy-eks-node-group]
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Initialize Terraform on AWS LB Controller directory
run: terraform init -backend-config="../../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/app/aws_lb_controller
- name: Validate IaC changes on AWS LB Controller directory
run: terraform plan -var-file="../../common.tfvars" -var-file="../../backend.tfvars"
working-directory: infra-eks/deployment/app/aws_lb_controller
- name: Deploy AWS Load Balancer Controller
run: terraform apply -var-file="../../common.tfvars" -var-file="../../backend.tfvars" -auto-approve
working-directory: infra-eks/deployment/app/aws_lb_controller
deploy-k8s-application:
name: Deploy Kubernetes Application
needs: [deploy-ecr, retrieve-ssl, build-and-push-app-docker-image-to-ecr, deploy-eks-cluster, deploy-eks-node-group, install-aws-load-balancer-controller]
runs-on: ubuntu-latest
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
outputs:
application_url: ${{ steps.get-app-url.outputs.application_url }}
steps:
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ env.TERRAFORM_VERSION }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Install kubectl
run: |
curl -LO "https://dl.k8s.io/release/v${{ env.KUBECTL_VERSION }}/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
kubectl version --client
- name: Configure kubectl for EKS
run: |
aws eks update-kubeconfig \
--name ${{ needs.deploy-eks-cluster.outputs.cluster_id }} \
--region ${{ env.AWS_REGION }}
echo "KUBECONFIG=$HOME/.kube/config" >> $GITHUB_ENV
- name: Verify kubectl access
run: |
kubectl config current-context
kubectl get nodes
- name: Initialize Terraform on K8s app directory
run: terraform init -backend-config="../../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/app/k8s_app
- name: Create runtime tfvars with image tag
run: |
cat > runtime.auto.tfvars <<EOF
# Auto-generated runtime configuration
image_tag = "${{ needs.build-and-push-app-docker-image-to-ecr.outputs.image_tag }}"
EOF
echo "Created runtime.auto.tfvars with image_tag:"
cat runtime.auto.tfvars
working-directory: infra-eks/deployment/app/k8s_app
- name: Validate IaC changes on K8s app directory
run: terraform plan -var-file="../../common.tfvars" -var-file="../../domain.tfvars" -var-file="../../backend.tfvars"
working-directory: infra-eks/deployment/app/k8s_app
- name: Deploy Kubernetes application
run: terraform apply -var-file="../../common.tfvars" -var-file="../../domain.tfvars" -var-file="../../backend.tfvars" -auto-approve
working-directory: infra-eks/deployment/app/k8s_app
- name: Debug pods on failure
if: failure()
continue-on-error: true
run: |
echo "=== Pods ==="
kubectl get pods -n default || true
echo ""
echo "=== Pod Descriptions ==="
kubectl describe pods -n default || true
echo ""
echo "=== Pod Logs ==="
kubectl logs -n default --all-containers --tail=200 || true
echo ""
echo "=== Deployment Description ==="
kubectl describe deployment nestjs-app-deployment -n default || true
- name: Fetch application URL
id: get-app-url
run: |
application_url=$(terraform output -raw application_url || echo "Not available yet")
echo "application_url=$application_url" >> $GITHUB_OUTPUT
echo "Application URL: $application_url"
working-directory: infra-eks/deployment/app/k8s_app
env:
TF_IN_AUTOMATION: true
- name: Wait for Ingress to be ready
run: |
echo "Waiting for Ingress to provision ALB..."
kubectl wait --for=jsonpath='{.status.loadBalancer.ingress}' \
--timeout=600s ingress/nestjs-app-ingress || echo "Timeout waiting for Ingress"
continue-on-error: true
- name: Display deployment status
run: |
echo "=== Deployments ==="
kubectl get deployments
echo ""
echo "=== Services ==="
kubectl get services
echo ""
echo "=== Ingress ==="
kubectl get ingress
echo ""
echo "=== HPA ==="
kubectl get hpa
echo ""
echo "=== Pods ==="
kubectl get pods
deploy-routing:
name: Route to app via custom domain
needs: [deploy-eks-cluster, install-aws-load-balancer-controller, deploy-k8s-application]
runs-on: ubuntu-latest
env: # required by some steps
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
steps:
# Checkout the repository to enable the runner clone the project repo into its filesystem from the last repo
# commit, and make the files available to other steps of the workflow
- name: Checkout code from the repository
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{env.TERRAFORM_VERSION}}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Install kubectl
run: |
curl -LO "https://dl.k8s.io/release/v${{ env.KUBECTL_VERSION }}/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
kubectl version --client
- name: Configure kubectl for EKS
run: |
aws eks update-kubeconfig \
--name ${{ needs.deploy-eks-cluster.outputs.cluster_id }} \
--region ${{ env.AWS_REGION }}
echo "KUBECONFIG=$HOME/.kube/config" >> $GITHUB_ENV
- name: Verify load balancer controller ingress config
run: |
kubectl get ingress -A
- name: Wait for ALB to be ready
run: |
kubectl wait \
--for=jsonpath='{.status.loadBalancer.ingress[0].hostname}' \
ingress/nestjs-app-ingress \
-n default \
--timeout=10m
- name: Initialise Terraform on the routing directory
run: terraform init -backend-config="../../backend-config.hcl" -backend-config="region=${{ env.AWS_REGION }}"
working-directory: infra-eks/deployment/app/routing
- name: Validate IaC changes on the routing directory
run: terraform plan -var-file="../../common.tfvars" -var-file="../../domain.tfvars" -var-file="../../backend.tfvars"
working-directory: infra-eks/deployment/app/routing
- name: Deploy the Route53 DNS record
run: terraform apply -var-file="../../common.tfvars" -var-file="../../domain.tfvars" -var-file="../../backend.tfvars" -auto-approve
working-directory: infra-eks/deployment/app/routing
deployment-summary:
name: Deployment Summary
needs: [deploy-ecr, retrieve-ssl, build-and-push-app-docker-image-to-ecr, deploy-vpc, deploy-eks-cluster, deploy-eks-node-group, install-aws-load-balancer-controller, deploy-k8s-application, deploy-routing]
runs-on: ubuntu-latest
steps:
- name: Display deployment summary
run: |
cat << 'EOF'
╔════════════════════════════════════════════════════════════════╗
║ EKS Infrastructure Deployment Complete ║
╚════════════════════════════════════════════════════════════════╝
✓ Terraform State Bucket: Created
✓ ECR Repository: ${{ needs.deploy-ecr.outputs.ecr_repository_name }}
✓ SSL Certificate: Retrieved/Created
✓ VPC: Deployed with EKS-specific subnet tags
✓ Docker Image: Built and pushed to ECR
✓ EKS Cluster: ${{ needs.deploy-eks-cluster.outputs.cluster_id }}
✓ Node Group: ${{ needs.deploy-eks-node-group.outputs.node_group_name }}
✓ AWS Load Balancer Controller: Installed
✓ Application: Deployed
Application URL: ${{ needs.deploy-k8s-application.outputs.application_url }}
Next Steps:
1. Verify the application is accessible via the URL above
2. Check the ALB in AWS Console
3. Monitor pods: kubectl get pods -w
4. View logs: kubectl logs -f deployment/nestjs-app-deployment
╚════════════════════════════════════════════════════════════════╝
EOF