Skip to content

Deploy Serverless Financial Transactions Processing App #126

Deploy Serverless Financial Transactions Processing App

Deploy Serverless Financial Transactions Processing App #126

Workflow file for this run

name: Deploy Serverless Financial Transactions Processing App
on:
workflow_dispatch:
inputs:
deploy_infrastructure:
description: "Deploy infrastructure (y/n) ?"
required: true
type: choice
options:
- "yes"
- "no"
default: "yes"
db_migration:
description: "Perform database migration (y/n) ?"
required: true
type: choice
options:
- "no"
- "yes"
default: "no"
permissions:
contents: read
id-token: write
pull-requests: write
env:
ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
ARM_USE_OIDC: true
TERRAFORM_WORKING_DIR: ./iac
BACKEND_RESOURCE_GROUP: rg-sp-txn-tf-backend
BACKEND_STORAGE_ACCOUNT: ${{ secrets.STORAGE_ACCOUNT_NAME }}
BACKEND_CONTAINER: tfstate
PYTHON_VERSION: "3.12"
ENVIRONMENT: dev
AZURE_FUNCTIONAPP_PACKAGE_PATH: "./function_apps/ingest_sharepoint_files"
jobs:
infrastructure:
name: Deploy Infrastructure
runs-on: ubuntu-latest
if: github.event.inputs.deploy_infrastructure == 'yes'
env:
TF_VAR_kv_name_base: ${{ secrets.KV_NAME }}
TF_VAR_alert_config: ${{ secrets.ALERT_CONFIG }}
TF_VAR_psql_admin_sg_object_id: ${{ secrets.POSTGRESQL_ADMINS_OBJECT_ID }}
TF_VAR_ip_address: ${{ secrets.IP_ADDRESS }}
TF_VAR_psql_server_name: ${{ secrets.PSQL_SERVER_NAME }}
TF_VAR_vault_url_dev: ${{ secrets.VAULT_URL_DEV }}
TF_VAR_db_host: ${{ secrets.DB_HOST }}
TF_VAR_tenant_id: ${{ secrets.AZURE_TENANT_ID }}
TF_VAR_kv_name: ${{ secrets.KV_NAME }}
steps:
- uses: actions/checkout@v5
- name: Azure Login (OIDC)
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: latest
- name: Terraform Init
run: terraform init
working-directory: ${{ env.TERRAFORM_WORKING_DIR }}
- name: Terraform Plan
run: |
terraform plan \
-var="environment=${{ env.ENVIRONMENT }}" \
-var-file="terraform.tfvars" \
-input=false
working-directory: ${{ env.TERRAFORM_WORKING_DIR }}
- name: Terraform Apply
run: |
echo "::add-mask::$ARM_SUBSCRIPTION_ID"
terraform apply \
-var="environment=${{ env.ENVIRONMENT }}" \
-var-file="terraform.tfvars" \
-auto-approve \
-input=false
working-directory: ${{ env.TERRAFORM_WORKING_DIR }}
build:
name: Build Function
runs-on: ubuntu-latest
needs: infrastructure
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Setup Python version
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: "pip"
- name: Create and start virtual environment
run: python -m venv venv
working-directory: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
- name: Install dependencies
run: |
source venv/bin/activate
pip install --target="./.python_packages/lib/site-packages" -r requirements.txt
working-directory: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
- name: Zip artifact for deployment
run: |
zip -r release.zip . -x "*.git*" -x "*venv*" -x "*__pycache__*" -x "*.pyc"
working-directory: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}
- name: Upload artifact for deployment job
uses: actions/upload-artifact@v4
with:
name: python-app
path: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}/release.zip
deploy:
name: Deploy Function
runs-on: ubuntu-latest
needs: build
steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: python-app
- name: Unzip artifact for deployment
run: unzip release.zip
- name: Login to Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Deploy to Azure Functions
uses: Azure/functions-action@v1
id: deploy-to-function
with:
app-name: sptxn-fn-app-${{ env.ENVIRONMENT }}
slot-name: "Production"
sku: "flexconsumption"
remote-build: false
package: "."
db_migration:
name: Database Migration
runs-on: ubuntu-latest
if: github.event.inputs.db_migration == 'yes'
steps:
- uses: actions/checkout@v5
- name: Azure login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: "pip"
- name: Install Python dependencies
working-directory: ./database
run: |
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
- name: Create GitHub Runner FW rule
env:
DB_NAME: ${{ secrets.PSQL_SERVER_NAME }}
run: |
echo "::add-mask::$DB_NAME"
RUNNER_IP=$(curl -s https://api.ipify.org?format=json | jq -r '.ip')
echo "Runner IP: $RUNNER_IP"
az postgres flexible-server firewall-rule create \
--resource-group rg-sp-txn-dev \
--name $DB_NAME \
--rule-name github-runner-ip \
--start-ip-address $RUNNER_IP
- name: Database migration
working-directory: ./database
env:
DB_HOST: ${{ secrets.DB_HOST }}
environment: "azure-dev"
run: |
echo "::add-mask::$DB_HOST"
source venv/bin/activate
export environment=${{ env.environment }}
export DB_PASSWORD=$(az account get-access-token --resource-type oss-rdbms --query accessToken --output tsv)
alembic upgrade head
- name: Delete GitHub Runner FW rule
env:
DB_NAME: ${{ secrets.PSQL_SERVER_NAME }}
run: |
echo "::add-mask::$DB_NAME"
RUNNER_IP=$(curl -s https://api.ipify.org?format=json | jq -r '.ip')
echo "Runner IP: $RUNNER_IP"
az postgres flexible-server firewall-rule delete \
--rule-name github-runner-ip \
--resource-group rg-sp-txn-dev \
--name $DB_NAME \
--yes