Skip to content

Commit

Permalink
feat: add new rainbow deployment github action script
Browse files Browse the repository at this point in the history
  • Loading branch information
craigzour committed Mar 4, 2025
1 parent 809c1c4 commit 33630bb
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 0 deletions.
114 changes: 114 additions & 0 deletions .github/workflows/rainbow-deployment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Rainbow deployment (WIP)

on:
pull_request:
branches:
- main
- feature/*
types:
- labeled
- opened
- reopened
- synchronize

env:
AWS_ACCOUNT_ID: ${{ vars.STAGING_AWS_ACCOUNT_ID }}
AWS_REGION: ca-central-1
GITHUB_SHA: ${{ github.sha }}
REGISTRY: ${{ vars.STAGING_AWS_ACCOUNT_ID }}.dkr.ecr.ca-central-1.amazonaws.com
COGNITO_APP_CLIENT_ID: ${{secrets.STAGING_COGNITO_APP_CLIENT_ID}}
COGNITO_USER_POOL_ID: ${{ secrets.STAGING_COGNITO_USER_POOL_ID}}
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY: ${{ secrets.STAGING_NEXT_SERVER_ACTIONS_ENCRYPTION_KEY }}
ROLE_ARN: arn:aws:iam::${{ vars.STAGING_AWS_ACCOUNT_ID }}:role/forms-lambda-client
LISTENER_ARN: arn:aws:elasticloadbalancing:ca-central-1:${{ vars.STAGING_AWS_ACCOUNT_ID }}:listener/app/form-viewer/5e6bc2d9ab810b68/028e8eeeed9c3a34

permissions:
id-token: write
contents: write
pull-requests: write

jobs:
rainbow-deployment:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0

# - name: Get second to last release commit identifier
# id: get-second-to-last-release
# shell: bash
# run: echo "commit-id=$(git rev-parse @~)" >> $GITHUB_OUTPUT

# - name: Checkout
# uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# with:
# ref: ${{ steps.get-second-to-last-release.outputs.commit-id }}

- name: Configure AWS credentials using OIDC
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
with:
role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/platform-forms-client-pr-review-env
role-session-name: RainbowDeployment
aws-region: ${{ env.AWS_REGION }}

- name: Login to Staging Amazon ECR
id: login-ecr-staging
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1

# BASE_IMAGE should use the ECS image built for the previous release
# NEXT_DEPLOYMENT_ID should use right deployment identifier based on whether we are in Staging (git sha) or Production (git tag)
- name: Build Rainbow Lambda image
run: |
docker build -t rainbow \
-f Dockerfile.rainbow \
--build-arg BASE_IMAGE=$REGISTRY/forms_app_legacy:ecs \
--build-arg COGNITO_APP_CLIENT_ID=$COGNITO_APP_CLIENT_ID \
--build-arg COGNITO_USER_POOL_ID=$COGNITO_USER_POOL_ID \
--build-arg NEXT_DEPLOYMENT_ID=$GITHUB_SHA .
- name: Tag and Push Rainbow Lambda image
run: |
docker tag rainbow $REGISTRY/forms_app_legacy:$GITHUB_SHA
docker push $REGISTRY/forms_app_legacy:$GITHUB_SHA
# Could be divided in multiple steps
# For "aws elbv2 create-target-group" there is a limitation name size (32 characters max)
# For "aws elbv2 create-rule" we need to find a solution to deal with priority since rules can't have the same one
# For "aws elbv2 create-rule", if possible, we need to find a way to dynamically pass the right host header value
- name: Rainbow magic
run: |
lambdaArn=$(aws lambda create-function \
--function-name rainbow-$GITHUB_SHA \
--package-type Image \
--role $ROLE_ARN \
--timeout 15 \
--memory-size 2048 \
--code ImageUri=$REGISTRY/forms_app_legacy:$GITHUB_SHA \
--vpc-config SubnetIds=${{ secrets.PR_REVIEW_ENV_SUBNET_IDS }},SecurityGroupIds=${{ secrets.PR_REVIEW_ENV_SECURITY_GROUP_IDS }} | jq -r ".FunctionArn")
aws lambda wait function-active --function-name rainbow-$GITHUB_SHA
./bin/set-rainbow-lambda-env-vars.sh rainbow-$GITHUB_SHA > /dev/null 2>&1
aws lambda add-permission \
--function-name rainbow-$GITHUB_SHA \
--statement-id rainbow-elb-invoke-permission \
--principal elasticloadbalancing.amazonaws.com \
--action lambda:InvokeFunction > /dev/null 2>&1
targetGroupArn=$(aws elbv2 create-target-group \
--name rainbow-${GITHUB_SHA:0:24} \
--target-type lambda | jq -r ".TargetGroups[0].TargetGroupArn")
aws elbv2 register-targets \
--target-group-arn $targetGroupArn \
--targets Id=$lambdaArn
aws elbv2 create-rule \
--listener-arn $LISTENER_ARN \
--conditions "[{\"Field\":\"host-header\",\"Values\":[\"forms-staging.cdssandbox.xyz\"]},{\"Field\":\"http-header\",\"HttpHeaderConfig\":{\"HttpHeaderName\":\"x-deployment-id\",\"Values\":[\"$GITHUB_SHA\"]}}]" \
--priority 1 \
--actions Type=forward,TargetGroupArn=$targetGroupArn \
--tags Key=Name,Value=rainbow-$GITHUB_SHA > /dev/null 2>&1
41 changes: 41 additions & 0 deletions Dockerfile.rainbow
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
ARG BASE_IMAGE
FROM $BASE_IMAGE as base

FROM node:22-alpine as final
LABEL maintainer="-"

ARG COGNITO_APP_CLIENT_ID
ENV COGNITO_APP_CLIENT_ID=$COGNITO_APP_CLIENT_ID

ARG COGNITO_USER_POOL_ID
ENV COGNITO_USER_POOL_ID=$COGNITO_USER_POOL_ID

ARG INDEX_SITE="false"
ENV INDEX_SITE=$INDEX_SITE

ARG NEXT_DEPLOYMENT_ID
ENV NEXT_DEPLOYMENT_ID=$NEXT_DEPLOYMENT_ID

ENV AWS_LWA_ENABLE_COMPRESSION=true
ENV HOSTNAME=localhost
ENV PORT=3000

# Use the LAMBDA_ENV environment variable to determine if the app is running in a Lambda environment
# Enables memory caching for the prerendering of pages
ENV LAMBDA_ENV=1

WORKDIR /src

COPY --from=base /src/.next/standalone ./
COPY --from=base /src/.next/static ./.next/static

# Lambda web adapter: https://github.com/awslabs/aws-lambda-web-adapter
# The public.ecr.aws/awsguru/aws-lambda-adapter:0.7.0 image reference in the docs has
# been pushed to the public CDS ECR to avoid rate limiting when pulling the image.
COPY --from=public.ecr.aws/cds-snc/aws-lambda-adapter:0.7.0@sha256:00b1441858fb3f4ce3d67882ef6153bacf8ff4bb8bf271750c133667202926af /lambda-adapter /opt/extensions/lambda-adapter

RUN ln -s /tmp ./.next/cache

EXPOSE 3000

ENTRYPOINT [ "node", "server.js"]
25 changes: 25 additions & 0 deletions bin/set-rainbow-lambda-env-vars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

set -euo pipefail

LAMBDA_FUNCTION_NAME=$1

TASK_ARN="$(aws ecs list-tasks --cluster Forms --service-name form-viewer --output text --query 'taskArns[0]')"
TASK_DEF_ARN="$(aws ecs describe-tasks --cluster Forms --task "$TASK_ARN" --output text --query 'tasks[0].taskDefinitionArn')"
TASK_DEF="$(aws ecs describe-task-definition --task-definition "$TASK_DEF_ARN")"

# Get environment variables from current task definition
ENV_VARS=$(echo "$TASK_DEF" | jq -r '.taskDefinition.containerDefinitions[0].environment | map("\(.name)=\(.value)") | join(",")')

# Get secrets from current task definition
SECRET_VARS="$(echo "$TASK_DEF" | jq -r '.taskDefinition.containerDefinitions[0].secrets | flatten[] | [.name,.valueFrom] | join("=")')"
while IFS= read -r SECRET; do
SECRET_NAME="${SECRET%%=*}"
SECRET_ARN="${SECRET#*=}"
SECRET_VALUE="$(aws secretsmanager get-secret-value --secret-id "$SECRET_ARN" --query 'SecretString' --output text)"
ENV_VARS="$ENV_VARS"$','"$SECRET_NAME=$SECRET_VALUE"
done <<< "$SECRET_VARS"

# Set Lambda environment variables
LAMBDA_ENV_VARS="$(echo "$ENV_VARS" | sort | sed -e "s/{/'{/" -e "s/}/}'/")"
aws lambda update-function-configuration --function-name $LAMBDA_FUNCTION_NAME --environment "Variables={$LAMBDA_ENV_VARS}" > /dev/null 2>&1

0 comments on commit 33630bb

Please sign in to comment.