Skip to content

Deploy to Novu Cloud #38

Deploy to Novu Cloud

Deploy to Novu Cloud #38

Workflow file for this run

name: Deploy to Novu Cloud
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
type: choice
default: staging
options:
- staging
- production-us
- production-eu
- production-both
deploy_api:
description: 'Deploy API'
required: true
type: boolean
default: true
deploy_worker:
description: 'Deploy Worker'
required: true
type: boolean
default: false
deploy_ws:
description: 'Deploy WS'
required: true
type: boolean
default: false
deploy_webhook:
description: 'Deploy Webhook'
required: true
type: boolean
default: false
jobs:
prepare-matrix:
runs-on: ubuntu-latest
outputs:
env_matrix: ${{ steps.set-matrix.outputs.env_matrix }}
service_matrix: ${{ steps.set-matrix.outputs.service_matrix }}
deploy_matrix: ${{ steps.set-matrix.outputs.deploy_matrix }}
steps:
- name: Generate Environment, Service, and Deploy Matrices
id: set-matrix
env:
WORKER_SERVICE: ${{ secrets.WORKER_SERVICE }}
run: |
envs=()
services=()
deploy_matrix=()
# Collect selected environments
if [ "${{ github.event.inputs.environment }}" == "staging" ]; then
envs+=("\"staging-eu\"")
fi
if [ "${{ github.event.inputs.environment }}" == "production-us" ]; then
envs+=("\"prod\"")
fi
if [ "${{ github.event.inputs.environment }}" == "production-eu" ]; then
envs+=("\"prod-eu\"")
fi
if [ "${{ github.event.inputs.environment }}" == "production-both" ]; then
envs+=("\"prod\"")
envs+=("\"prod-eu\"")
fi
# Collect selected services
if [ "${{ github.event.inputs.deploy_api }}" == "true" ]; then
services+=("\"api\"")
fi
if [ "${{ github.event.inputs.deploy_worker }}" == "true" ]; then
services+=("\"worker\"")
fi
if [ "${{ github.event.inputs.deploy_ws }}" == "true" ]; then
services+=("\"ws\"")
fi
if [ "${{ github.event.inputs.deploy_webhook }}" == "true" ]; then
services+=("\"webhook\"")
fi
# Parse service secrets and generate deploy_matrix
for service in "${services[@]}"; do
if [ "$service" == "\"worker\"" ]; then
IFS=',' read -r -a worker_services <<< "$WORKER_SERVICE"
for worker_service in "${worker_services[@]}"; do
cluster_name=$(echo "$worker_service" | jq -r '.cluster_name')
container_name=$(echo "$worker_service" | jq -r '.container_name')
service_name=$(echo "$worker_service" | jq -r '.service')
task_name=$(echo "$worker_service" | jq -r '.task_name')
deploy_matrix+=("{\"cluster_name\": \"$cluster_name\", \"container_name\": \"$container_name\", \"service_name\": \"$service_name\", \"task_name\": \"$task_name\"}")
done
elif [ "$service" == "\"api\"" ]; then
cluster_name=api-cluster
container_name=api-container
service_name=api-service
task_name=api-task
deploy_matrix+=("{\"cluster_name\": \"$cluster_name\", \"container_name\": \"$container_name\", \"service_name\": \"$service_name\", \"task_name\": \"$task_name\"}")
elif [ "$service" == "\"ws\"" ]; then
cluster_name=ws-cluster
container_name=ws-container
service_name=ws-service
task_name=ws-task
deploy_matrix+=("{\"cluster_name\": \"$cluster_name\", \"container_name\": \"$container_name\", \"service_name\": \"$service_name\", \"task_name\": \"$task_name\"}")
elif [ "$service" == "\"webhook\"" ]; then
cluster_name=webhook-cluster
container_name=webhook-container
service_name=webhook-service
task_name=webhook-task
deploy_matrix+=("{\"cluster_name\": \"$cluster_name\", \"container_name\": \"$container_name\", \"service_name\": \"$service_name\", \"task_name\": \"$task_name\"}")
fi
done
env_matrix="{\"environment\": [$(
IFS=','; echo "${envs[*]}"
)]}"
service_matrix="{\"service\": [$(
IFS=','; echo "${services[*]}"
)]}"
deploy_matrix="[$(
IFS=','; echo "${deploy_matrix[*]}"
)]"
echo "env_matrix=$env_matrix" >> $GITHUB_OUTPUT
echo "service_matrix=$service_matrix" >> $GITHUB_OUTPUT
echo "deploy_matrix=$deploy_matrix" >> $GITHUB_OUTPUT
build:
needs: prepare-matrix
timeout-minutes: 60
runs-on: ubuntu-latest
environment: ${{ fromJson(needs.prepare-matrix.outputs.env_matrix).environment[0] }}
outputs:
registry: ${{ steps.build-image.outputs.registry }}
strategy:
matrix:
service: ${{ fromJson(needs.prepare-matrix.outputs.service_matrix).service }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
token: ${{ secrets.SUBMODULES_TOKEN }}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9.11.0
run_install: false
- name: Setup Node Version
uses: actions/setup-node@v4
with:
node-version: '20.8.1'
cache: 'pnpm'
- name: Install Dependencies
shell: bash
run: pnpm install --frozen-lockfile
- name: Set Up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: 'image=moby/buildkit:v0.13.1'
- name: Prepare Variables
run: echo "BULL_MQ_PRO_NPM_TOKEN=${{ secrets.BULL_MQ_PRO_NPM_TOKEN }}" >> $GITHUB_ENV
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID}}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: ${{ vars.ECR_REPO_PREFIX }}
SERVICE: ${{ matrix.service }}
IMAGE_TAG: ${{ github.sha }}
DOCKER_BUILD_ARGUMENTS: >
--platform=linux/amd64
--output=type=image,name=$REGISTRY/$REPOSITORY/$SERVICE,push-by-digest=true,name-canonical=true
run: |
cp scripts/dotenvcreate.mjs apps/$SERVICE/src/dotenvcreate.mjs
cd apps/$SERVICE && pnpm run docker:build
docker tag novu-$SERVICE $REGISTRY/$REPOSITORY/$SERVICE:latest
docker tag novu-$SERVICE $REGISTRY/$REPOSITORY/$SERVICE:$IMAGE_TAG
docker push $REGISTRY/$REPOSITORY/$SERVICE:latest
docker push $REGISTRY/$REPOSITORY/$SERVICE:$IMAGE_TAG
echo "registry=$REGISTRY/$REPOSITORY" >> $GITHUB_OUTPUT
deploy:
needs: [build, prepare-matrix]
runs-on: ubuntu-latest
strategy:
matrix:
env: ${{ fromJson(needs.prepare-matrix.outputs.env_matrix).environment }}
service: ${{ fromJson(needs.prepare-matrix.outputs.deploy_matrix) }}
steps:
- name: Print Important Info
env:
IMAGE_TAG: ${{ github.sha }}
REGISTRY: ${{ needs.build.outputs.registry }}
run: |
echo "Deploying to cluster: ${{matrix.env}}-${{ matrix.service.cluster_name }}"
echo "Deploying to service: ${{matrix.env}}-${{ matrix.service.service_name }}"
echo "Deploying to container: ${{ matrix.service.container_name }}"
echo "Deploying to task: ${{ matrix.service.task_name }}"
echo "Deploying to environment: ${{ matrix.env }}"
echo "Deploying to image: $REGISTRY/$IMAGE_TAG"