Skip to content

Deploy Kainoscore to Prod #9

Deploy Kainoscore to Prod

Deploy Kainoscore to Prod #9

name: Deploy Kainoscore to Prod
on:
workflow_dispatch:
inputs:
version:
description: 'Version to deploy to prod (e.g. 1.10.1)'
required: true
env:
AWS_REGION: eu-west-2
NON_PROD_DEPLOYMENT_ROLE: arn:aws:iam::975050265283:role/GHA-CodeBuild-Service-Role
PROD_DEPLOYMENT_ROLE: arn:aws:iam::696793786584:role/GHA-CodeBuild-Service-Role
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ENVIRONMENT: prod
permissions:
id-token: write
contents: write
jobs:
deploy:
name: Deploy to Prod
runs-on: ubuntu-latest
environment: Prod
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Required Tools
run: |
npm install -g typescript
echo "NODE.JS version: $(node -v)"
echo "NPM version: $(npm -v)"
echo "AWS CLI version: $(aws --version)"
# First, authenticate to non-prod to access staging artifacts
- name: Configure AWS credentials for Non-Prod (Staging)
uses: aws-actions/[email protected]
with:
role-to-assume: ${{ env.NON_PROD_DEPLOYMENT_ROLE }}
aws-region: ${{ env.AWS_REGION }}
role-session-name: staging-access
- name: Setup Non-Prod AWS Profile
run: |
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile nonprod
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile nonprod
aws configure set aws_session_token $AWS_SESSION_TOKEN --profile nonprod
aws configure set region ${{ env.AWS_REGION }} --profile nonprod
echo "Non-Prod profile configured"
# Then, authenticate to prod for deployment
- name: Configure AWS credentials for Prod
uses: aws-actions/[email protected]
with:
role-to-assume: ${{ env.PROD_DEPLOYMENT_ROLE }}
aws-region: ${{ env.AWS_REGION }}
- name: Setup Prod AWS Profile
run: |
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile prod
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile prod
aws configure set aws_session_token $AWS_SESSION_TOKEN --profile prod
aws configure set region ${{ env.AWS_REGION }} --profile prod
echo "Prod profile configured"
- name: Prepare Scripts
run: |
# Make sure the script file exists before making it executable
if [ ! -f "./pipeline_scripts/deploy-to-prod.sh" ]; then
echo "ERROR: deploy-to-prod.sh not found in pipeline_scripts directory"
ls -la ./pipeline_scripts/
exit 1
fi
chmod +x ./pipeline_scripts/deploy-to-prod.sh
chmod +x ./pipeline_scripts/update-lambda-functions.sh
chmod +x ./pipeline_scripts/functions.sh
ls -la ./pipeline_scripts/
- name: Verify AWS Profiles
run: |
echo "Available AWS profiles:"
aws configure list-profiles
echo "Testing nonprod profile access:"
aws sts get-caller-identity --profile nonprod
echo "Testing prod profile access:"
aws sts get-caller-identity --profile prod
- name: Copy Artifacts and Deploy to Prod
run: |
echo "Starting prod deployment for version ${{ github.event.inputs.version }}"
./pipeline_scripts/deploy-to-prod.sh "${{ github.event.inputs.version }}"
deploy-static-files:
name: Deploy Static Files to Prod
runs-on: ubuntu-latest
needs: deploy
environment: Prod
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials for Non-Prod (Staging)
uses: aws-actions/[email protected]
with:
role-to-assume: ${{ env.NON_PROD_DEPLOYMENT_ROLE }}
aws-region: ${{ env.AWS_REGION }}
role-session-name: staging-access
- name: Download staging files
run: |
mkdir -p temp-static-files
chmod +x ./pipeline_scripts/functions.sh
cd ./pipeline_scripts
source ./functions.sh
s3_bucket_static_files
STAGING_BUCKET="$S3-staging"
echo "Downloading from staging bucket: $STAGING_BUCKET"
aws s3 sync s3://$STAGING_BUCKET/ ../temp-static-files/
- name: Configure AWS credentials for Prod
uses: aws-actions/[email protected]
with:
role-to-assume: ${{ env.PROD_DEPLOYMENT_ROLE }}
aws-region: ${{ env.AWS_REGION }}
- name: Deploy static files to prod
run: |
chmod +x ./pipeline_scripts/functions.sh
cd ./pipeline_scripts
source ./functions.sh
s3_bucket_static_files
PROD_BUCKET="$S3-prod"
echo "Uploading to prod bucket: $PROD_BUCKET"
# Count files
file_count=$(find ../temp-static-files -type f | wc -l)
echo "Found $file_count files to upload"
# Upload files
aws s3 sync ../temp-static-files/ s3://$PROD_BUCKET/ --delete
# Verify
prod_count=$(aws s3 ls s3://$PROD_BUCKET/ --recursive | wc -l)
echo "Files in prod bucket: $prod_count"
# Tag bucket
aws s3api put-bucket-tagging --bucket $PROD_BUCKET --tagging "TagSet=[{Key=DeployedVersion,Value=v${{ github.event.inputs.version }}},{Key=DeployedDate,Value=$(date +"%Y-%m-%d")}]"
echo "✅ Successfully deployed static files to prod"
finalize-deployment:
name: Finalize Deployment
runs-on: ubuntu-latest
needs: [deploy, deploy-static-files]
steps:
- name: Deployment Summary
run: |
echo "✅ Successfully deployed version v${{ github.event.inputs.version }} to prod"
echo " • Lambda Functions: ✅ Deployed"
echo " • Static Files: ✅ Deployed"
echo " • Deployment Time: $(date -u +"%Y-%m-%d %H:%M:%S UTC")"
echo " • Deployed by: ${{ github.actor }}"
# Create an artifact with deployment details for tracking
mkdir -p deployment-info
cat > deployment-info/prod-deployment.txt << EOF
Version: v${{ github.event.inputs.version }}
Lambda Functions: Deployed
Static Files: Deployed
Time: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
Actor: ${{ github.actor }}
Workflow Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
EOF
- name: Upload Deployment Info
uses: actions/[email protected]
with:
name: prod-deployment-v${{ github.event.inputs.version }}-${{ github.run_id }}
path: deployment-info
retention-days: 90
create-release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: [deploy, deploy-static-files, finalize-deployment]
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate release notes
id: release-notes
run: |
echo "Generating release notes for v${{ github.event.inputs.version }}"
# Extract commits since last production release (not pre-release)
git fetch --tags
# Get the last production release tag (excluding pre-releases)
PREV_TAG=$(git tag -l "v*" --sort=-version:refname | grep -v "staging\|alpha\|beta\|rc" | head -2 | tail -1 2>/dev/null || echo "none")
echo "Previous production tag: $PREV_TAG"
if [ "$PREV_TAG" == "none" ] || [ -z "$PREV_TAG" ]; then
echo "No previous production release found, getting last 20 commits"
COMMITS=$(git log --pretty=format:"- **%s** (%h) by %an" -20)
else
echo "Getting commits since $PREV_TAG"
COMMITS=$(git log --pretty=format:"- **%s** (%h) by %an" ${PREV_TAG}..HEAD)
fi
# Count commits
COMMIT_COUNT=$(echo "$COMMITS" | wc -l)
# Create release notes file
cat > release-notes.md << EOF
# 🚀 Production Release v${{ github.event.inputs.version }}
## 📋 What's Changed
${COMMITS}
**Total commits in this release:** $COMMIT_COUNT
## 🚀 Deployment Information
- **Environment:** Production
- **Deployment time:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")
- **Deployed by:** ${{ github.actor }}
- **Workflow run:** [${{ github.run_id }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
## 🔗 Links
- [Compare changes](https://github.com/${{ github.repository }}/compare/${PREV_TAG}...v${{ github.event.inputs.version }})
- [Full changelog](https://github.com/${{ github.repository }}/commits/v${{ github.event.inputs.version }})
EOF
echo "Generated release notes:"
cat release-notes.md
- name: Create GitHub Release
uses: softprops/[email protected]
with:
name: "🚀 v${{ github.event.inputs.version }} (Production)"
tag_name: "v${{ github.event.inputs.version }}"
body_path: release-notes.md
draft: false
prerelease: false
make_latest: true
token: ${{ secrets.GITHUB_TOKEN }}