In this section, we provide a template for running CI/CD with GitHub Actions. You can reference and clone it to streamline setup and usage, making CI/CD deployment faster and more efficient. Additionally, you can configure your own CI/CD setup to better manage your code.
git clone https://github.com/AWS-First-Cloud-Journey/aws-fcj-container-app.git
You can edit elsewhere; this is just an example.
vi .github/workflows/main.yml
name: CI/CD Pipeline
on:
push:
tags:
- '*'
jobs:
frontend:
uses: ./.github/workflows/frontend.yml
secrets: inherit
backend:
uses: ./.github/workflows/backend.yml
secrets: inherit
vi .github/workflows/backend.yml
name: Backend CI/CD
on:
workflow_call:
env:
IMAGE_NAME_BE: ${{ secrets.AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com/${{ secrets.CI_PROJECT_BE_NAME }}:${{ github.ref_name }}
jobs:
# check_changes_backend:
# runs-on: ubuntu-latest
# outputs:
# backend: ${{ steps.filter.outputs.backend }}
# steps:
# - uses: actions/checkout@v2
# - uses: dorny/paths-filter@v2
# id: filter
# with:
# filters: |
# backend:
# - 'backend/**'
build-and-push:
# needs: check_changes_backend
runs-on: ubuntu-latest
# if: ${{ needs.check_changes_backend.outputs.backend == 'true' }}
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
working-directory: ./backend
run: |
docker build -f Dockerfile -t ${{ env.IMAGE_NAME_BE }} .
docker push ${{ env.IMAGE_NAME_BE }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Deploy Backend
env:
TASK_NAME_BE: ${{ secrets.TASK_NAME_BE }}
IMAGE_NAME_BE: ${{ env.IMAGE_NAME_BE }}
AWS_APPLICATION_NAME: ${{ secrets.AWS_APPLICATION_NAME }}
AWS_DEPLOYMENT_GROUP_NAME: ${{ secrets.AWS_DEPLOYMENT_GROUP_NAME }}
REGION: ${{ secrets.AWS_REGION }}
run: bash backend/deploy-backend.sh
vi backend/deploy-backend.sh
#!/bin/bash
# Retrieve the task definition from ECS
TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition "$TASK_NAME_BE" --region "$REGION")
# Register a new task definition with an updated image
NEW_TASK_DEFINITION=$(echo $TASK_DEFINITION | jq --arg IMAGE "$IMAGE_NAME_BE" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities) | del(.registeredAt) | del(.registeredBy)')
NEW_REVISION=$(aws ecs register-task-definition --region "$REGION" --cli-input-json "$NEW_TASK_DEFINITION")
echo $NEW_REVISION | jq '.taskDefinition.revision'
# Extract the task definition ARN, container name, and container port using jq
AWS_TASK_DEFINITION_ARN=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.taskDefinitionArn')
CONTAINER_NAME=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.containerDefinitions[0].name')
CONTAINER_PORT=$(echo $TASK_DEFINITION | jq -r '.taskDefinition.containerDefinitions[0].portMappings[0].containerPort')
# Create the application specification (AppSpec) in JSON format
APP_SPEC=$(jq -n --arg taskDef "$AWS_TASK_DEFINITION_ARN" --arg containerName "$CONTAINER_NAME" --argjson containerPort "$CONTAINER_PORT" '{
version: "0.0",
Resources: [
{
TargetService: {
Type: "AWS::ECS::Service",
Properties: {
TaskDefinition: $taskDef,
LoadBalancerInfo: {
ContainerName: $containerName,
ContainerPort: $containerPort
}
}
}
}
]
}')
# Create the revision configuration for the deployment
REVISION=$(jq -n --arg appSpec "$APP_SPEC" '{
revisionType: "AppSpecContent",
appSpecContent: {
content: $appSpec
}
}')
# Trigger the deployment using the specified application name, deployment group, and revision
aws deploy create-deployment --region "$REGION" \
--application-name "$AWS_APPLICATION_NAME" \
--deployment-group-name "$AWS_DEPLOYMENT_GROUP_NAME" \
--revision "$REVISION"