Skip to content

Commit

Permalink
[#IPV-22] Enable deploy on multiple app services (#128)
Browse files Browse the repository at this point in the history
  • Loading branch information
Emanuele De Cupis authored Jun 7, 2021
1 parent 2995a4e commit b0a3b4f
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 70 deletions.
29 changes: 10 additions & 19 deletions .devops/code-review-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
# - DANGER_GITHUB_API_TOKEN
#

variables:
NODE_VERSION: '10.14.1'
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn

# Automatically triggered on PR
# https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#pr-trigger
trigger: none

# Execute agents (jobs) on latest Ubuntu version.
# To change OS for a specific, ovverride "pool" attribute inside the job definition
pool:
vmImage: 'ubuntu-latest'

resources:
repositories:
- repository: pagopaCommons
Expand All @@ -22,20 +23,10 @@ resources:
ref: refs/tags/v14
endpoint: 'io-azure-devops-github-ro'

# This pipeline has been implemented to be run on hosted agent pools based both
# on 'windows' and 'ubuntu' virtual machine images and using the scripts defined
# in the package.json file. Since we are deploying on Azure functions on Windows
# runtime, the pipeline is currently configured to use a Windows hosted image for
# the build and deploy.
pool:
vmImage: 'ubuntu-latest'

stages:
# A) Build and code validation
- stage: Build
dependsOn: []
jobs:
# A1) Checkout, install module and build code
- job: make_build
pool:
# As we deploy on Wondows machines, we use Windows to build
Expand All @@ -45,15 +36,13 @@ stages:
- script: |
yarn build
displayName: 'Build'
- stage: Static_analysis
dependsOn: []
jobs:

- job: lint
steps:
- template: templates/node-job-setup/template.yaml@pagopaCommons

- script: |
yarn lint
displayName: 'Lint'
Expand Down Expand Up @@ -91,16 +80,18 @@ stages:
DANGER_GITHUB_API_TOKEN: '$(DANGER_GITHUB_API_TOKEN)'
displayName: 'Danger CI'
# B) Run unit tests if there is a push or pull request on any branch.
- stage: Test
dependsOn: []
jobs:
- job: unit_tests
steps:
- template: templates/node-job-setup/template.yaml@pagopaCommons

- script: |
yarn generate
displayName: 'Generate defintions'
displayName: 'Generate definitions'
- script: |
yarn test:coverage
Expand Down
143 changes: 92 additions & 51 deletions .devops/deploy-pipelines.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Azure DevOps pipeline to release a new version and deploy to production.

variables:
NODE_VERSION: '10.14.1'
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
# Configuration to run the healthcheck container
HEALTHCHECK_CONTAINER_RG: 'io-p-rg-common'
HEALTHCHECK_CONTAINER_VNET: 'io-p-vnet-common'
HEALTHCHECK_CONTAINER_SUBNET: 'azure-devops'
HEALTHCHECK_PATH: 'api/v1/info'

parameters:
- name: 'RELEASE_SEMVER'
Expand All @@ -13,6 +16,20 @@ parameters:
- minor
- patch
default: minor
# Map of production apps to deploy to, in the form
# {logicName}:
# appname: {name of the resource}
# rg: {name of the resource group}
# Although it's a parameter, it's not intended to be edited at runtime.
# It's here because variables only handle scalar values
- name: 'PRODUCTION_APPS'
displayName: ''
type: object
default:
services:
appname: io-p-fn3-services
rg: io-p-rg-functions_services


# Only manual activations are intended
trigger: none
Expand Down Expand Up @@ -73,12 +90,13 @@ stages:
echo "We assume this reference to be a valid release: $(Build.SourceBranch). Therefore, there is no need to bundle a new release."
displayName: 'Skip release bundle'
# Prepare Artifact
- stage: Deploy_staging
- stage: Prepare_artifact
dependsOn:
- Release
jobs:
- job: 'prepare_artifact_and_deploy'
- job: 'prepare_artifact'
steps:
# Build application
- template: templates/node-job-setup/template.yaml@pagopaCommons
Expand All @@ -102,72 +120,95 @@ stages:
- task: CopyFiles@2
inputs:
SourceFolder: '$(System.DefaultWorkingDirectory)'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
TargetFolder: '$(System.DefaultWorkingDirectory)/bundle'
Contents: |
**/*
!.git/**/*
!**/*.js.map
!**/*.ts
!.vscode/**/*
!azure-templates/**/*
!azure-pipelines.yml
!.devops/**/*
!.prettierrc
!.gitignore
!README.md
!jest.config.js
!local.settings.json
!test
!tsconfig.json
!tslint.json
!yarn.lock
!Dangerfile.js
!CODEOWNERS
!__*/**/*
displayName: 'Copy deploy files'

- publish: $(System.DefaultWorkingDirectory)/bundle
artifact: Bundle

# Deploy on staging slot
- ${{ each app in parameters.PRODUCTION_APPS }}:
- stage: Deploy_${{ app.Key }}_to_staging
dependsOn:
- Prepare_artifact
jobs:
- job: 'do_deploy_${{ app.Key }}'
steps:
- checkout: none
- download: current
artifact: Bundle

- task: AzureFunctionApp@1
inputs:
azureSubscription: '$(PRODUCTION_AZURE_SUBSCRIPTION)'
resourceGroupName: '$(PRODUCTION_RESOURCE_GROUP_NAME)'
appType: 'functionApp'
appName: '$(PRODUCTION_APP_NAME)'
package: '$(Build.ArtifactStagingDirectory)/'
deploymentMethod: 'auto'
deployToSlotOrASE: true
slotName: 'staging'
displayName: Deploy to staging slot
- task: AzureFunctionApp@1
inputs:
azureSubscription: '$(PRODUCTION_AZURE_SUBSCRIPTION)'
resourceGroupName: '${{ app.Value.rg }}'
appType: 'functionApp'
appName: '${{ app.Value.appname }}'
package: '$(Pipeline.Workspace)/Bundle'
deploymentMethod: 'auto'
deployToSlotOrASE: true
slotName: 'staging'
displayName: Deploy to staging slot

# Check that the staging instance is healthy
- stage: Healthcheck
dependsOn:
- Deploy_staging
jobs:
- job: 'do_healthcheck'
steps:
- checkout: none
- template: templates/rest-healthcheck/template.yaml@pagopaCommons
parameters:
azureSubscription: '$(PRODUCTION_AZURE_SUBSCRIPTION)'
appName: '$(PRODUCTION_APP_NAME)'
endpoint: 'https://$(PRODUCTION_APP_NAME)-staging.azurewebsites.net/api/info'
endpointType: 'private'
containerInstanceResourceGroup: 'io-p-rg-common'
containerInstanceVNet: 'io-p-vnet-common'
containerInstanceSubnet: 'azure-devops'
- ${{ each app in parameters.PRODUCTION_APPS }}:
- stage: Healthcheck_${{ app.Key }}
dependsOn:
- Deploy_${{ app.Key }}_to_staging
jobs:
- job: 'do_healthcheck_${{ app.Key }}'
steps:
- checkout: none
- template: templates/rest-healthcheck/template.yaml@pagopaCommons
parameters:
azureSubscription: '$(PRODUCTION_AZURE_SUBSCRIPTION)'
appName: '${{ app.Value.appname }}'
endpoint: 'https://${{ app.Value.appname }}-staging.azurewebsites.net/$(HEALTHCHECK_PATH)'
endpointType: 'private'
containerInstanceResourceGroup: '$(HEALTHCHECK_CONTAINER_RG)'
containerInstanceVNet: '$(HEALTHCHECK_CONTAINER_VNET)'
containerInstanceSubnet: '$(HEALTHCHECK_CONTAINER_SUBNET)'

# Promote the staging instance to production
- stage: Deploy_production
dependsOn:
- Healthcheck
- Deploy_staging
jobs:
- job: 'do_deploy'
steps:
- checkout: none
- task: AzureAppServiceManage@0
inputs:
azureSubscription: '$(PRODUCTION_AZURE_SUBSCRIPTION)'
resourceGroupName: '$(PRODUCTION_RESOURCE_GROUP_NAME)'
webAppName: '$(PRODUCTION_APP_NAME)'
sourceSlot: staging
swapWithProduction: true
displayName: Swap with production slot

- ${{ each app in parameters.PRODUCTION_APPS }}:
- stage: Swap_${{ app.Key }}_to_production
dependsOn:
- Deploy_${{ app.Key }}_to_staging
# Wait for every healthcheck to succeed
# This implied that no app is swapped to prod if at least one healthcheck fails
- ${{ each appInner in parameters.PRODUCTION_APPS }}:
- Healthcheck_${{ appInner.Key }}
jobs:
- job: 'do_deploy_${{ app.Key }}'
steps:
- checkout: none
- task: AzureAppServiceManage@0
inputs:
azureSubscription: '$(PRODUCTION_AZURE_SUBSCRIPTION)'
resourceGroupName: '${{ app.Value.rg }}'
webAppName: '${{ app.Value.appname }}'
sourceSlot: staging
swapWithProduction: true
displayName: Swap with production slot

# Publish client SDK to NPM
- stage: PublishClientSDKtoNPM
Expand Down

0 comments on commit b0a3b4f

Please sign in to comment.