Skip to content

Merge branch 'main' of github.com:Terre8055/sus-db #10

Merge branch 'main' of github.com:Terre8055/sus-db

Merge branch 'main' of github.com:Terre8055/sus-db #10

Workflow file for this run

name: Deploy SUSDB CI/CD
on:
push:
branches: [ main ]
workflow_dispatch:
inputs:
version_increment:
description: 'Version increment type (major, minor, or patch)'
required: true
default: 'patch'
permissions:
contents: write
packages: write
env:
SECRETS_NAME: susdb
ECR_REPO: susdb
ECR_REGISTRY: 590183661216.dkr.ecr.eu-west-1.amazonaws.com
PROJECT_ID: susdb
S3_BUCKET: susdb
jobs:
build-push-and-tag:
runs-on: ubuntu-latest
outputs:
new_version: ${{ steps.versioning.outputs.new_version }}
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0
- 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: Generate Version
id: versioning
run: |
latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "Latest tag: $latest_tag"
# Remove 'v' prefix if present
latest_version=${latest_tag#v}
# Split the version into an array
IFS='.' read -ra VERSION_PARTS <<< "$latest_version"
MAJOR=${VERSION_PARTS[0]}
MINOR=${VERSION_PARTS[1]}
PATCH=${VERSION_PARTS[2]}
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
case "${{ github.event.inputs.version_increment }}" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
esac
else
# Auto-increment patch version for push events
PATCH=$((PATCH + 1))
fi
new_version="v$MAJOR.$MINOR.$PATCH"
echo "New version: $new_version"
echo "::set-output name=new_version::$new_version"
- name: Retrieve secrets from AWS Secrets Manager
run: |
echo "Retrieving secrets from AWS Secrets Manager..."
SECRETS=$(aws secretsmanager get-secret-value --secret-id ${{ env.SECRETS_NAME }} --query SecretString --output text)
echo "$SECRETS" | jq -r 'to_entries | map("\(.key)=\(.value)") | .[]' > .env
- name: Temporarily Store .env in s3 config store
run: |
echo "Upload env variables to s3..."
aws s3 cp .env s3://${{ env.S3_BUCKET }}
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
- name: Cache Docker layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.ref }}
restore-keys: |
${{ runner.os }}-buildx-${{ github.ref }}
${{ runner.os }}-buildx
- name: Build and push image to ECR
id: build-image
uses: docker/build-push-action@v6
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ env.ECR_REPO }}
IMAGE_TAG: ${{ steps.versioning.outputs.new_version }}
with:
context: .
push: true
builder: ${{ steps.buildx.outputs.name }}
tags: |
${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:latest
cache-from: type=gha,src=/tmp/.buildx-cache
cache-to: type=gha,dest=/tmp/.buildx-cache-new,mode=max
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
if [ -d /tmp/.buildx-cache-new ]; then
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
else
echo "No new cache to move."
fi
shell: /usr/bin/bash -e {0}
- name: Clean up
if: always()
run: rm -f .env
deploy_to_managed_instances:
runs-on: ubuntu-latest
needs:
- build-push-and-tag
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: Retrieve Managed Instances by Tags
id: get_instances
run: |
# Fetch instance IDs with specific tags, e.g., Environment=prod
instance_ids=$(aws ec2 describe-instances \
--filters "Name=tag:Project,Values=SUS" "Name=instance-state-name,Values=running" \
--query "Reservations[].Instances[].InstanceId" \
--output text)
# Check if any instances were found
if [ -z "$instance_ids" ]; then
echo "No instances found with the specified tags."
exit 1
fi
echo "Instance IDs: $instance_ids"
echo "::set-output name=instance_ids::$instance_ids"
echo "::set-output name=instance_ids::$instance_ids"
- name: Executing Docker Commands on Instances using SSM
uses: peterkimzz/aws-ssm-send-command@master
id: ssm
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
instance-ids: ${{ steps.get_instances.outputs.instance_ids }}
working-directory: /home/ec2-user
comment: "Running docker commands"
command: |
sudo sh -c "set -e && \
export PATH=\$PATH:/usr/local/bin && \
cd /home/ec2-user && \
rm -rf .env.llm && \
echo 'Downloading docker-compose.yml from S3...' && \
aws s3 cp s3://${{ env.S3_BUCKET }}/docker-compose.yml . && \
echo 'Downloading .env from S3...' && \
aws s3 cp s3://${{ env.S3_BUCKET }}/.env . && \
echo 'Stopping existing Docker containers...' && \
/usr/local/bin/docker-compose -f /home/ec2-user/docker-compose.yml down && \
echo 'Logging in to Amazon ECR...' && \
aws ecr get-login-password --region ${{ secrets.AWS_REGION }} | docker login --username AWS --password-stdin ${{ env.ECR_REGISTRY }} && \
echo 'Pulling latest Docker images...' && \
/usr/local/bin/docker-compose -f /home/ec2-user/docker-compose.yml pull && \
echo 'Starting Docker services with Docker Compose...' && \
/usr/local/bin/docker-compose -f /home/ec2-user/docker-compose.yml up -d"
- name: Get the outputs
run: echo "The Command ID is ${{ steps.ssm.outputs.command-id }}"
- name: Check AWS SSM Command Status
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
run: |
command_id=${{ steps.ssm.outputs.command-id }}
instance_ids=${{ steps.get_instances.outputs.instance_ids }}
# Initial delay to ensure the command has time to start
sleep 10
for instance_id in $instance_ids; do
while true; do
# Fetch the command invocation details
output=$(aws ssm get-command-invocation \
--command-id $command_id \
--instance-id $instance_id \
--output json)
echo "Output: $output"
# Extract the status from the output
status=$(echo $output | jq -r '.Status')
echo "Current status for instance $instance_id: $status"
# Check if the status is Success or Failed
if [[ "$status" == "Success" ]]; then
echo "Final status for instance $instance_id: $status"
break
elif [[ "$status" == "Failed" ]]; then
echo "Commands failed on instance $instance_id. Ending the pipeline."
exit 1
fi
# Delay before the next status check
sleep 60
done
done
- name: Remove env file from s3
if: always()
run: aws s3 rm s3://${{ env.S3_BUCKET }}/.env
create-release:
needs:
- build-push-and-tag
- deploy_to_managed_instances
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Generate Release Notes
id: generate_release_notes
run: |
# Get the latest tag
latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
# Get the new version tag from the previous job
new_version="${{ needs.build-push-and-tag.outputs.new_version }}"
# If there's no previous tag, use the initial commit
if [ -z "$latest_tag" ]; then
latest_tag=$(git rev-list --max-parents=0 HEAD)
fi
# Fetch the commit messages between the latest tag and HEAD
release_notes=$(git log ${latest_tag}..HEAD --pretty=format:"- %s (%h)")
# If there are no commit messages, provide a default message
if [ -z "$release_notes" ]; then
release_notes="- Initial release"
fi
echo "Generated release notes:"
echo "$release_notes"
# Escape newlines and quote special characters for GitHub Actions
release_notes="${release_notes//'%'/'%25'}"
release_notes="${release_notes//$'\n'/'%0A'}"
release_notes="${release_notes//$'\r'/'%0D'}"
# Save the release notes as output
echo "::set-output name=release_notes::$release_notes"
- name: Check for existing release
id: check_release
run: |
release_id=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ needs.build-push-and-tag.outputs.new_version }}" \
| jq -r '.id')
if [ "$release_id" != "null" ]; then
echo "::set-output name=release_exists::true"
echo "::set-output name=release_id::$release_id"
else
echo "::set-output name=release_exists::false"
fi
- name: Update existing release
if: steps.check_release.outputs.release_exists == 'true'
run: |
curl -X PATCH \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/releases/${{ steps.check_release.outputs.release_id }}" \
-d '{
"tag_name": "${{ needs.build-push-and-tag.outputs.new_version }}",
"name": "Release ${{ needs.build-push-and-tag.outputs.new_version }}",
"body": "${{ steps.generate_release_notes.outputs.release_notes }}"
}'
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ needs.build-push-and-tag.outputs.new_version }}
release_name: Release ${{ needs.build-push-and-tag.outputs.new_version }}
body: ${{ steps.generate_release_notes.outputs.release_notes }}
draft: false
prerelease: false
- name: Update version file
run: |
echo "${{ needs.build-push-and-tag.outputs.new_version }}" > VERSION
git config user.name Terre8055
git config user.email michaelappiah2018@icloud.com
git add VERSION
git commit -m "Bump version to ${{ needs.build-push-and-tag.outputs.new_version }}"
git pull --no-edit origin main
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}