Skip to content

Merge pull request #448 from cds-snc/fix/feedback-survey-links #84

Merge pull request #448 from cds-snc/fix/feedback-survey-links

Merge pull request #448 from cds-snc/fix/feedback-survey-links #84

name: Deploy to AWS App Runner
on:
workflow_dispatch:
push:
branches:
- main
permissions:
contents: read
id-token: write
jobs:
deploy:
runs-on: ubuntu-latest
env:
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_ASSUME_ROLE_ARN: ${{ secrets.AWS_ASSUME_ROLE_ARN }}
APP_RUNNER_SERVICE_ARN: ${{ secrets.APP_RUNNER_SERVICE_ARN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GOOGLE_SEARCH_ENGINE_ID: ${{ secrets.GOOGLE_SEARCH_ENGINE_ID }}
DOCDB_URI: ${{ secrets.DOCDB_URI }}
JWT_SECRET_KEY: ${{ secrets.JWT_SECRET_KEY }}
NODE_ENV: ${{ secrets.NODE_ENV }}
steps:
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ env.AWS_ASSUME_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Write update-input.json
run: |
cat > update-input.json <<-EOF
{
"ServiceArn": "${{ env.APP_RUNNER_SERVICE_ARN }}",
"SourceConfiguration": {
"CodeRepository": {
"RepositoryUrl": "https://github.com/${{ github.repository }}",
"SourceCodeVersion": {
"Type": "BRANCH",
"Value": "main"
},
"CodeConfiguration": {
"ConfigurationSource": "API",
"CodeConfigurationValues": {
"Runtime": "NODEJS_22",
"BuildCommand": "npm install && npm run build",
"StartCommand": "npm run start-server",
"RuntimeEnvironmentVariables": {
"DEPLOY_RUN_ID": "${{ github.run_id }}",
"ANTHROPIC_API_KEY": "${{ env.ANTHROPIC_API_KEY }}",
"OPENAI_API_KEY": "${{ env.OPENAI_API_KEY }}",
"GOOGLE_API_KEY": "${{ env.GOOGLE_API_KEY }}",
"GOOGLE_SEARCH_ENGINE_ID": "${{ env.GOOGLE_SEARCH_ENGINE_ID }}",
"DOCDB_URI": "${{ env.DOCDB_URI }}",
"JWT_SECRET_KEY": "${{ env.JWT_SECRET_KEY }}",
"NODE_ENV": "${{ env.NODE_ENV }}"
}
}
}
}
},
"InstanceConfiguration": { "Cpu": "512", "Memory": "1024" },
"HealthCheckConfiguration": {
"Protocol": "HTTP",
"Path": "/health",
"Interval": 20,
"Timeout": 15,
"HealthyThreshold": 1,
"UnhealthyThreshold": 10
}
}
EOF
- name: Wait up to 4h for idle
run: |
echo "Waiting for App Runner to be idle..."
for i in {1..240}; do
STATUS=$(aws apprunner describe-service \
--service-arn "${{ env.APP_RUNNER_SERVICE_ARN }}" \
--region ${{ env.AWS_REGION }} \
--query 'Service.OperationSummary.Status' --output text)
[[ "$STATUS" != "IN_PROGRESS" ]] && break
sleep 60
done
- name: Update service (retries)
run: |
set -e
for i in {1..10}; do
if aws apprunner update-service --cli-input-json file://update-input.json --region ${{ env.AWS_REGION }}; then
echo "✅ update-service succeeded"
break
else
echo "🔁 Retrying in 60s..."
sleep 60
fi
done
- name: Wait up to 4h for RUNNING (force if not deploying)
run: |
echo "Waiting for service RUNNING or IN_PROGRESS..."
for i in {1..240}; do
STATE=$(aws apprunner describe-service \
--service-arn "${{ env.APP_RUNNER_SERVICE_ARN }}" \
--region ${{ env.AWS_REGION }} \
--query 'Service.Status' --output text)
OP_STATUS=$(aws apprunner describe-service \
--service-arn "${{ env.APP_RUNNER_SERVICE_ARN }}" \
--region ${{ env.AWS_REGION }} \
--query 'Service.OperationSummary.Status' --output text)
if [[ "$STATE" == "RUNNING" ]]; then
if [[ "$OP_STATUS" != "IN_PROGRESS" ]]; then
echo "⚠️ No deployment in progress, forcing deployment..."
aws apprunner start-deployment \
--service-arn "${{ env.APP_RUNNER_SERVICE_ARN }}" \
--region ${{ env.AWS_REGION }}
sleep 10
else
echo "🟢 Service is RUNNING and deployment is in progress."
exit 0
fi
elif [[ "$STATE" == "FAILED" ]]; then
echo "❌ Deployment FAILED!"
exit 1
else
echo "⏳ Service state: $STATE, operation: $OP_STATUS. Waiting..."
fi
sleep 60
done
echo "❌ Timed out"; exit 1
- name: Output App Runner URL
run: |
URL=$(aws apprunner describe-service \
--service-arn "${{ env.APP_RUNNER_SERVICE_ARN }}" \
--region ${{ env.AWS_REGION }} \
--query 'Service.ServiceUrl' --output text)
echo "✅ App Runner URL: $URL"