November Happy Hour will be moved to Thursday December 5th.
AI OnAI Off
November Happy Hour will be moved to Thursday December 5th.
You're using the Deployment API correct? As there's a requirement now to do so for the new infrastructure. I should imagine it should just be the same process as before.
FYI there's extensions in Azure DevOps by EpiNova that can help make it easier https://www.epinova.se/en/folg-med/blog/2020/epinova-dxp-deployment-part-1-introduction/
Following on from what Scott added and with the help of Epinova, I put togeather the following for a CICD pipeline, utilises DirectDeploy to Integration and than slot swaps for pre-prod and prod
# Pipeline to deploy to Integration DXP environment using Azure App Service Deploy task
# -----------------------------
# Set the pipeline build number format
name: $(Build.DefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)
trigger:
branches:
include:
- master
paths:
include:
- src/Content
pool:
vmImage: 'windows-2019'
variables:
- name: buildConfiguration
value: 'Release'
- name: workingDirectory
value: '$(Build.SourcesDirectory)/src/Content'
- name: sourcePath
value: '$(Agent.TempDirectory)/SitePackageContent'
- name: artifact.Name
value: "Optimizely CMS DXP Package"
- name: archiveName
value: 'optimizely.cms.app.$(Build.BuildId).nupkg'
- group: Optimizely-common-vars
stages:
- stage: CI
jobs:
- job: CI
displayName: 'Build & package'
steps:
- script: dotnet restore ./ProjectName.sln
displayName: Restore
workingDirectory: $(workingDirectory)
- script: dotnet build ./ProjectName.sln --configuration $(buildConfiguration)
displayName: Build
workingDirectory: $(workingDirectory)
- script: dotnet publish ./ProjectName.Cms --configuration $(buildConfiguration) --output $(sourcePath)
displayName: Publish Optimizely CMS Artifact
workingDirectory: $(workingDirectory)
- task: ArchiveFiles@2
displayName: "Archive Files"
inputs:
rootFolderOrFile: '$(sourcePath)'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(archiveName)'
replaceExistingArchive: true
- publish: '$(Build.ArtifactStagingDirectory)/$(archiveName)'
artifact: $(artifact.Name)
- task: PowerShell@2
displayName: 'Upload package to DXP'
env:
# Map secret variable
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
$env:PSModulePath = "C:\Modules\azurerm_6.13.1;" + $env:PSModulePath
if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
Install-Module EpiCloud -Scope CurrentUser -Force
}
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
$packagePath = "$(Build.ArtifactStagingDirectory)/$(archiveName)"
$saslink = Get-EpiDeploymentPackageLocation
Add-EpiDeploymentPackage -SasUrl $saslink -Path $packagePath
- stage: Optimizely_CMS_Integration
jobs:
# Add a Deployment job.
# Artifacts are automatically downloaded in deployment jobs. To disable use -download: none
- deployment: DeployApp
displayName: 'Deploy to Integration'
variables:
# Explicitly set the EnvironmentName variable in multi-stage YAML to ensure environment config transform is applied automatically
Release.EnvironmentName: 'Optimizely_CMS_Integration'
# Creates an environment if it doesn't exist
environment: 'Optimizely_CMS_Integration'
strategy:
runOnce:
deploy:
steps:
- download: none
- task: PowerShell@2
displayName: 'Deploy to Integration'
env:
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
Install-Module EpiCloud -Scope CurrentUser -Force
}
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
$packageName = "$(archiveName)"
echo "Starting deployment using package $packageName"
$params = @{
DeploymentPackage = $packageName
TargetEnvironment = 'Integration'
UseMaintenancePage = $false
DirectDeploy = $true
Wait = $true
}
$deploy = Start-EpiDeployment @params
echo "DeploymentId - $($deploy.id)"
echo "##vso[task.setvariable variable=deploymentId;]$($deploy.id)"
- stage: Optimizely_CMS_PreProduction
jobs:
# Add a Deployment job.
# Artifacts are automatically downloaded in deployment jobs. To disable use -download: none
- deployment: DeployApp
displayName: 'Deploy to Preproduction'
# Creates an environment if it doesn’t exist
environment: 'Optimizely_CMS_PreProduction'
strategy:
runOnce:
deploy:
steps:
- download: none
- task: PowerShell@2
displayName: 'Deploy to slot'
env:
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
Install-Module EpiCloud -Scope CurrentUser -Force
}
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
$packageName = "$(archiveName)"
echo "Starting deployment using package $packageName"
$params = @{
DeploymentPackage = $packageName
TargetEnvironment = 'Preproduction'
UseMaintenancePage = $(UseMaintenancePage)
Wait = $true
}
$deploy = Start-EpiDeployment @params
echo "DeploymentId - $($deploy.id)"
echo "##vso[task.setvariable variable=deploymentId;]$($deploy.id)"
- task: PowerShell@2
displayName: 'Validate slot'
env:
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
$deploy = Get-EpiDeployment -Id $env:DeploymentId
if ($deploy.status -eq 'AwaitingVerification'){
$response = Invoke-WebRequest -Uri $deploy.validationLinks[0]
if ($response.StatusCode -ne 200){
echo "Smoke test of slot url failed"
exit 1
}
}
- task: PowerShell@2
displayName: 'Reset'
env:
API_SECRET: $(ApiSecret)
condition: failed()
inputs:
targetType: 'inline'
script: |
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
Reset-EpiDeployment -Id $env:DeploymentId -Wait
- task: PowerShell@2
displayName: 'Complete deployment'
env:
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
Complete-EpiDeployment -Id $env:DeploymentId -Wait
# Run performance tests
- stage: Optimizely_CMS_Production
jobs:
# Add a Deployment job.
# Artifacts are automatically downloaded in deployment jobs. To disable use -download: none
- deployment: DeployApp
displayName: 'Deploy to Production'
# Creates an environment if it doesn’t exist
environment: 'Optimizely_CMS_Production'
strategy:
runOnce:
deploy:
steps:
- download: none
- task: PowerShell@2
displayName: 'Deploy to slot'
env:
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
if (-not (Get-Module -Name EpiCloud -ListAvailable)) {
Install-Module EpiCloud -Scope CurrentUser -Force
}
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
$packageName = "$(archiveName)"
echo "Starting deployment using package $packageName"
$params = @{
DeploymentPackage = $packageName
TargetEnvironment = 'Production'
UseMaintenancePage = $(UseMaintenancePage)
Wait = $true
}
$deploy = Start-EpiDeployment @params
echo "DeploymentId - $($deploy.id)"
echo "##vso[task.setvariable variable=deploymentId;]$($deploy.id)"
- task: PowerShell@2
displayName: 'Validate slot'
env:
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
$deploy = Get-EpiDeployment -Id $env:DeploymentId
if ($deploy.status -eq 'AwaitingVerification'){
$response = Invoke-WebRequest -Uri $deploy.validationLinks[0]
if ($response.StatusCode -ne 200){
echo "Smoke test of slot url failed"
exit 1
}
}
- task: PowerShell@2
displayName: 'Reset'
env:
API_SECRET: $(ApiSecret)
condition: failed()
inputs:
targetType: 'inline'
script: |
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
Reset-EpiDeployment -Id $env:DeploymentId -Wait
- task: PowerShell@2
displayName: 'Complete deployment'
env:
API_SECRET: $(ApiSecret)
inputs:
targetType: 'inline'
script: |
Connect-EpiCloud -ClientKey $(ApiKey) -ClientSecret $env:API_SECRET -ProjectId $(ProjectId)
Complete-EpiDeployment -Id $env:DeploymentId -Wait
And the following variables
Project Structure
Epinova have an updated blog post for CMS 12.
https://www.epinova.no/folg-med/blogg/2021/epinova-dxp-deployment-extension-for-azure-devops--version-2/
I'm trying to set up a build pipeline (using yaml) for CMS 12 (.NET 5) in Azure DevOps and need some assistance. Does anyone have a working example or a guide for doing this? There are plenty of guides for older CMS versions (.NET Framework) but I'm not able to find any that covers the .NET 5 version.