Skip to content

Publish Docker image and deploy on App Service #10

Publish Docker image and deploy on App Service

Publish Docker image and deploy on App Service #10

name: Publish Docker image and deploy on App Service
on:
workflow_dispatch:
inputs:
deploy:
type: boolean
description: Whether to deploy
use-staging-slot:
type: boolean
description: Whether to perform a blue-green deployment using a staging slot
# TODO: (keep disabled for the moment)
# on:
# push:
# tags:
# - '*'
env:
# use github packages as container registry
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push-image:
name: Build and push image
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
attestations: write
id-token: write
outputs:
image-tags: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Log in to the Container Registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 # v3.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# for TAG github event, it generates two image tags: the git tag itself and 'latest'
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 # v5.5.1
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: push
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 # v6.5.0
with:
context: .
# TODO put in standard {{context}}/Dockerfile ?
file: src/Presentation/PortaleFatture.BE.Api/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Generate artifact attestation
uses: actions/attest-build-provenance@5e9cb68e95676991667494a6a4e59b8a2f13e1d0 # v1.3.3
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
deploy:
name: Deploy
if: ${{ github.event.inputs.deploy == 'true' }}
needs: [build-and-push-image]
# self-hosted is needed to ping the health endpoint in subnet
# TODO temporary disabled
# runs-on: self-hosted
runs-on: ubuntu-22.04
environment: prod
permissions:
id-token: write
contents: read
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
ARM_USE_OIDC: true
RESOURCE_GROUP_NAME: fat-p-app-rg
APP_NAME: fat-p-app-api-container
HEALTH_CHECK_PATH: /health
steps:
- name: Azure Login
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
with:
client-id: ${{ env.ARM_CLIENT_ID }}
tenant-id: ${{ env.ARM_TENANT_ID }}
subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }}
- name: Deploy
uses: azure/webapps-deploy@de617f46172a906d0617bb0e50d81e9e3aec24c8 # v3.0.1
if: ${{ github.event.inputs.use-staging-slot == 'false' }}
with:
resource-group-name: ${{ env.RESOURCE_GROUP_NAME }}
app-name: ${{ env.APP_NAME }}
images: ${{ needs.build-and-push-image.outputs.image-tags }}
- name: Deploy to Staging Slot
uses: azure/webapps-deploy@de617f46172a906d0617bb0e50d81e9e3aec24c8 # v3.0.1
if: ${{ github.event.inputs.use-staging-slot == 'true' }}
with:
resource-group-name: ${{ env.RESOURCE_GROUP_NAME }}
app-name: ${{ env.APP_NAME }}
images: ${{ needs.build-and-push-image.outputs.image-tags }}
slot-name: staging
- name: Ping Staging Health
if: ${{ github.event.inputs.use-staging-slot == 'true' }}
run: |
curl \
--retry 5 \
--retry-max-time 120 \
--retry-all-errors \
-f 'https://${{ env.APP_NAME }}-staging.azurewebsites.net${{ env.HEALTH_CHECK_PATH }}'
- name: Swap Staging and Production Slots
if: ${{ github.event.inputs.use-staging-slot == 'true' }}
run: |
az webapp deployment slot swap \
-g ${{ env.RESOURCE_GROUP_NAME }} \
-n ${{ env.APP_NAME }} \
--slot staging \
--target-slot production