Skip to content

πŸš€ Deploying to release-2.3.1 #672

πŸš€ Deploying to release-2.3.1

πŸš€ Deploying to release-2.3.1 #672

Workflow file for this run

# Overview
# ********
# This workflow automates the deployment of web apps and Azure Functions to Azure upon successful completion of a QAT workflow.
# Key Stages:
#
# 1. Setup
# ********
# Sets environment variables for product, environment, and timezone.
# Outputs these variables for use in subsequent jobs.
#
# 2. SQL Migrations
# *****************
# Runs new SQL migrations on the environment SQL database
#
# 3. WebApp
# *********
# Runs sequentially for each web app defined in the matrix.webapp list.
# Sets the Dockerfile location based on the microservice (using the portal directory for portal-ui and the app's name for others).
# Builds and pushes Docker images using the root workspace as the context and the Dockerfile location specified for the microservice.
# Creates a temporary deployment slot using the FROM tag (latest by default).
# Swaps the slot to make the new image live.
# Cleans up the temporary slot.
#
# 4. Functions
# ************
# Runs sequentially for each function defined in the matrix.functions list.
# Builds and pushes Docker images for each function.
# Creates a temporary deployment slot using the FROM tag.
# Swaps the slot to make the new image live.
# Cleans up the temporary slot.
#
# Key Points
# **********
# Triggers on Completed QAT Workflow: The workflow only runs if the preceding QAT workflow completes successfully.
# Environment-Specific: Uses environment variables to tailor deployments for different environments (dev, feature, staging, prod).
# Matrix Strategies: Employs matrices to iterate through lists of web apps and functions for sequential deployment.
# Concurrency Control: Uses concurrency groups to prevent multiple deployments of the same web app or function from running concurrently.
# Fail-Fast Disabled: Allows all matrix jobs to complete even if some fail.
# Temporary Slots: Utilizes deployment slots to minimize downtime during deployments.
# Cleanup: Always removes temporary slots to maintain resource hygiene.
#
name: Deployment
run-name: πŸš€ Deploying to ${{ github.event.workflow_run.head_branch }}
on:
workflow_run:
workflows: ['QAT']
types:
- completed
branches:
- dev
- feature
- staging
- prod
- release-*
- '!release-please*'
env:
PRODUCT: dtfs
ENVIRONMENT: ${{ github.event.workflow_run.head_branch }}
TIMEZONE: ${{ vars.TIMEZONE }}
# Base artifact
FROM: latest
jobs:
setup:
name: Setup πŸ”§
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: [self-hosted, linux, deployment]
outputs:
product: ${{ env.PRODUCT }}
environment: ${{ steps.environment.outputs.environment }}
timezone: ${{ env.TIMEZONE }}
steps:
- name: Environment πŸ§ͺ
id: environment
run: |
if [[ "${{ env.ENVIRONMENT }}" == *release* ]]; then
echo "environment=staging" >> "$GITHUB_OUTPUT"
else
echo "environment=${{ github.event.workflow_run.head_branch }}" >> "$GITHUB_OUTPUT"
fi
- name: Timezone 🌐
run: echo "Timezone set to ${{ env.TIMEZONE }}"
database:
name: MSSQL πŸ—„οΈ
if: ${{ github.event.workflow_run.conclusion == 'success' }}
needs: [setup]
environment: ${{ needs.setup.outputs.environment }}
runs-on: [self-hosted, DTFS, deployment]
env:
ENVIRONMENT: ${{ needs.setup.outputs.environment }}
SQL_DB_HOST: ${{ secrets.SQL_DB_HOST }}
SQL_DB_PORT: ${{ secrets.SQL_DB_PORT }}
SQL_DB_USERNAME: ${{ secrets.SQL_DB_USERNAME }}
SQL_DB_PASSWORD: ${{ secrets.SQL_DB_PASSWORD }}
SQL_DB_NAME: ${{ secrets.SQL_DB_NAME }}
SQL_DB_LOGGING_ENABLED: ${{ vars.SQL_DB_LOGGING_ENABLED }}
steps:
- name: Repository
uses: actions/checkout@v4
- name: Node
uses: actions/setup-node@v4
with:
node-version: ${{ vars.NODE_VERSION }}
- name: Dependencies
working-directory: ./libs/common
run: npm ci
- name: Migrate
working-directory: ./libs/common
run: npm run db:migrate
webapp:
name: WebApp 🌐
if: ${{ github.event.workflow_run.conclusion == 'success' }}
needs: [setup]
environment: ${{ needs.setup.outputs.environment }}
runs-on: [self-hosted, DTFS, deployment]
env:
ENVIRONMENT: ${{ needs.setup.outputs.environment }}
strategy:
max-parallel: 1
# Do not cancel in-progress jobs upon failure
fail-fast: false
# Single dimension matrix
matrix:
webapp: ['portal-ui', 'gef-ui', 'trade-finance-manager-ui', 'portal-api', 'dtfs-central-api', 'external-api', 'trade-finance-manager-api']
concurrency:
group: deployment-webapp-${{ github.workflow }}-${{ github.workflow_ref }}-${{ matrix.webapp }}
cancel-in-progress: true
steps:
- name: Repository πŸ—ƒοΈ
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_branch }}
- name: Defaults ✨
uses: azure/cli@v2
with:
inlineScript: |
# Basic
az configure --defaults location=${{ vars.REGION }}
az configure --defaults group=${{ secrets.RESOURCE_GROUP }}
- name: Azure πŸ”
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: CLI πŸ“
run: |
echo ACR=$(az acr show -n $(az resource list --resource-type 'Microsoft.ContainerRegistry/registries' --query '[0].name' -o tsv) --query loginServer -o tsv) >> $GITHUB_ENV
echo ACR_USER=$(az acr show -n $(az resource list --resource-type 'Microsoft.ContainerRegistry/registries' --query '[0].name' -o tsv) --query name -o tsv) >> $GITHUB_ENV
echo WEBAPP=$(az resource list --resource-type 'Microsoft.Web/sites' --query '[?contains(name, `${{ matrix.webapp }}`)].name' -o tsv) >> $GITHUB_ENV
- name: ACR πŸ”
uses: azure/docker-login@v2
with:
login-server: ${{ env.ACR }}
username: ${{ env.ACR_USER }}
password: ${{ secrets.ACR_PASSWORD }}
- name: Dockerfile 🐳
if: ${{ 'portal-ui' == matrix.webapp }}
run: echo "DOCKERFILE=portal/Dockerfile" >> $GITHUB_ENV
- name: Dockerfile 🐳
if: ${{ 'portal-ui' != matrix.webapp }}
run: echo "DOCKERFILE=${{ matrix.webapp }}/Dockerfile" >> $GITHUB_ENV
- name: Artifacts πŸ—ƒοΈ
working-directory: .
run: |
# Build images
docker build -f ./${{ env.DOCKERFILE }} . \
-t ${{ env.ACR }}/${{ matrix.webapp }}:${{ github.sha }} \
-t ${{ env.ACR }}/${{ matrix.webapp }}:${{ env.FROM }} \
--build-arg GITHUB_SHA=${{ github.sha }}
# Push images
docker push ${{ env.ACR }}/${{ matrix.webapp }}:${{ github.sha }}
docker push ${{ env.ACR }}/${{ matrix.webapp }}:${{ env.FROM }}
- name: Slot πŸ”€
uses: azure/cli@v2
with:
inlineScript: |
# Create new temporary slot
az webapp deployment slot create \
--slot ${{ github.sha }} \
--name ${{ env.WEBAPP }} \
--configuration-source ${{ env.WEBAPP }} \
--deployment-container-image-name ${{ env.ACR }}/${{ matrix.webapp }}:${{ env.FROM }} \
--docker-registry-server-user ${{ env.ACR_USER }} \
--docker-registry-server-password ${{ secrets.ACR_PASSWORD }}
# Swap slot
az webapp deployment slot swap \
--slot ${{ github.sha }} \
--name ${{ env.WEBAPP }} \
--action swap
- name: Cleanup 🧹
if: always()
uses: azure/cli@v2
with:
inlineScript: |
# Delete temporary slot
az webapp deployment slot delete \
--slot ${{ github.sha }} \
--name ${{ env.WEBAPP }}
functions:
name: Functions ⚑
if: ${{ github.event.workflow_run.conclusion == 'success' }}
needs: [setup, webapp]
environment: ${{ needs.setup.outputs.environment }}
runs-on: [self-hosted, DTFS, deployment]
env:
ENVIRONMENT: ${{ needs.setup.outputs.environment }}
strategy:
max-parallel: 1
# Do not cancel in-progress jobs upon failure
fail-fast: false
# Single dimension matrix
matrix:
functions: ['acbs-function']
concurrency:
group: deployment-functions-${{ github.workflow }}-${{ github.workflow_ref }}-${{ matrix.functions }}
cancel-in-progress: true
steps:
- name: Repository πŸ—ƒοΈ
uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_branch }}
- name: Defaults ✨
uses: azure/cli@v2
with:
inlineScript: |
# Basic
az configure --defaults location=${{ vars.REGION }}
az configure --defaults group=${{ secrets.RESOURCE_GROUP }}
- name: Azure πŸ”
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Directory πŸ“
if: ${{ 'acbs-function' == matrix.functions }}
run: echo "NAME=acbs" >> $GITHUB_ENV
- name: CLI πŸ“
run: |
echo ACR=$(az acr show -n $(az resource list --resource-type 'Microsoft.ContainerRegistry/registries' --query '[0].name' -o tsv) --query loginServer -o tsv) >> $GITHUB_ENV
echo ACR_USER=$(az acr show -n $(az resource list --resource-type 'Microsoft.ContainerRegistry/registries' --query '[0].name' -o tsv) --query name -o tsv) >> $GITHUB_ENV
echo FUNCTION=$(az resource list --resource-type 'Microsoft.Web/sites' --query '[?contains(name, `${{ env.NAME }}`)].name' -o tsv) >> $GITHUB_ENV
- name: ACR πŸ”
uses: azure/docker-login@v2
with:
login-server: ${{ env.ACR }}
username: ${{ env.ACR_USER }}
password: ${{ secrets.ACR_PASSWORD }}
- name: Artifacts πŸ—ƒοΈ
working-directory: ./azure-functions/${{ matrix.functions }}
run: |
# Build images
docker build . \
-t ${{ env.ACR }}/${{ matrix.functions }}:${{ github.sha }} \
-t ${{ env.ACR }}/${{ matrix.functions }}:${{ env.FROM }}
# Push images
docker push ${{ env.ACR }}/${{ matrix.functions }}:${{ github.sha }}
docker push ${{ env.ACR }}/${{ matrix.functions }}:${{ env.FROM }}
- name: Slot πŸ”€
uses: azure/cli@v2
with:
inlineScript: |
# Create new temporary slot
az functionapp deployment slot create \
--slot ${{ github.sha }} \
--name ${{ env.FUNCTION }} \
--configuration-source ${{ env.FUNCTION }} \
--deployment-container-image-name ${{ env.ACR }}/${{ matrix.functions }}:${{ env.FROM }} \
--docker-registry-server-user ${{ env.ACR_USER }} \
--docker-registry-server-password ${{ secrets.ACR_PASSWORD }}
# Swap slot
az functionapp deployment slot swap \
--slot ${{ github.sha }} \
--name ${{ env.FUNCTION }} \
--action swap
- name: Cleanup 🧹
if: always()
uses: azure/cli@v2
with:
inlineScript: |
# Delete temporary slot
az functionapp deployment slot delete \
--slot ${{ github.sha }} \
--name ${{ env.FUNCTION }}