Вот что у меня работает. У меня есть конвейер, который развертывает шаблон из репо Azure Devops. Конвейер развертывает его в среде разработки, поэтому нарушение чего-либо еще не конец света. Вы также можете выполнить локальное тестирование, прежде чем нажимать на репо, если это вариант (это может быть очень трудно сделать в некоторых случаях, когда шаблон имеет много зависимостей от материала в «реальной» среде разработки, и тестирование его на других подписках невозможно из-за ссылок на существующие ресурсы \ хранилища ключей \ et c). Я использую следующий фрагмент в azure devops для запуска сценария powershell и последующего развертывания:
- task: AzurePowerShell@3
displayName: UpdatePrereq
inputs:
azureSubscription: ${{ parameters.azureSubscription }}
ScriptType: InlineScript
Inline: |
${{ format('. $(Build.Repository.LocalPath)\scripts\_helpers.ps1
Update-DeploymentPrereq -resourceGroup {1} -location {3}
Update-Prereq -pathSuffix {0} -pathBase $(Build.Repository.LocalPath) -resourceGroup {1} -buildId $(Build.BuildNumber) -paramFile {2}
Update-DeploymentConcurrency -resourceGroup {1} -buildId $(Build.BuildNumber)',
parameters.buildDir, parameters.resourceGroupName, parameters.paramFile, parameters.location ) }}
azurePowerShellVersion: LatestVersion
- task: AzureResourceGroupDeployment@2
displayName: DeploySolution
inputs:
azureSubscription: ${{ parameters.azureSubscription }}
resourceGroupName: ${{ parameters.resourceGroupName }}
location: ${{ parameters.location }}
templateLocation: 'URL of the file'
csmFileLink: "https://xxx.blob.core.windows.net/$(containerName)/azuredeploy.json"
csmParametersFileLink: ${{ format('https://xxx.blob.core.windows.net/$(containerName)/param.{0}.json', parameters.paramFile) }}
Позвольте мне немного объяснить, что здесь происходит:
- Update-DeploymentPrereq - используется для проверки, существует ли целевая группа ресурсов и установлены ли соответствующие теги. создает и помечает его, если его нет. теги:
Version
- означает последнюю успешно развернутую версию; FailedVersion
- это фактически означает, что последнее развертывание не выполнено, и содержит идентификатор сборки, который запустил развертывание (он будет удален после успешного развертывания); InProgress
- содержит идентификатор сборки, которая начала развертывание в группе ресурсов; это будет сброшено после завершения развертывания (независимо от того, провалилось оно или нет), поэтому оно имеет значение только во время сборки. - Update-Prereq - этот файл загружает все шаблоны \ артефакты в выделенное хранилище. account (подробнее об этом позже)
- Update-DeploymentConcurrency - проверяет, выполняется ли уже развертывание в этой группе ресурсов, путем проверки значения тега
InProgress
. Если значение соответствует not running
(или какой-либо другой строке, которую вы кодируете для проверки тега - it sets the
InProgress` с идентификатором сборки задания, в противном случае - завершает работу сценария с ненулевым кодом выхода, эффективно нарушая сборку (таким образом предотвращая столкновение). ). - Развертывание должно быть очевидным
Теперь давайте немного поговорим о Update-Prereq
, так как все это необходимо для работы. Он генерирует случайное имя контейнера для каждая сборка выполняется следующим образом:
Function Get-StringHash ([String]$String, $HashName = "MD5") {
$StringBuilder = New-Object System.Text.StringBuilder
[System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String))|
ForEach-Object { [Void]$StringBuilder.Append($_.ToString("x2"))
}
$StringBuilder.ToString().Substring(0, 24)
}
...
Function Update-Prereq {
...
$containerName = Get-StringHash ( $resourceGroup + $buildId )
New-AzureStorageContainer -Name $containerName -Context $storageContext -Permission Blob
Write-Host "##vso[task.setvariable variable=containerName]$containerName"
...
}
В результате получается строка длиной 24 символа, которая определяется c (она всегда будет одинаковой для тех же входных данных, которые предоставляются функции Get-StringHash
, это означает, что когда вы запускаете сборку из одного и того же коммита в одну и ту же группу ресурсов - она всегда загружается в один и тот же контейнер, но если вы запускаете ее для другого коммита или другой группы ресурсов - это генерирует новое имя контейнера), что позволяет избежать sh о котором вы говорите. Вышеупомянутые теги выделяют идентификатор сборки, который отображается на конкретный коммит с помощью GitVersion (s). o вы всегда можете выяснить, какая версия кода развернута или не удалось развернуть в определенной среде). И выводит сгенерированное имя контейнера, так что AzureResourceGroupDeployment@2
сможет выяснить его и использовать этот указанный c контейнер для поиска шаблона.
Существуют и другие этапы сборки, которые контролируют сбой \ Успешная пометка, очистка старых сборок \ старых контейнеров. Я, вероятно, могу превратить это в сообщение в блоге, если вам нужна моя конкретная c реализация
По сути все сводится к:
- предотвращению параллельного выполнения
- с отдельный набор шаблонов для каждой комбинации группы ресурсов / коммитов, поэтому они никогда не перекрывают
- , имея возможность определить, какая сборка развернута в среде
- и иметь возможность откатить ее до идентификатора фиксации без к большим неприятностям.
Возможно, это не самый оптимальный способ сделать это, но это лучшее, что я мог придумать, когда мне это нужно.
пс. для локального тестирования вы можете просто использовать функцию Update-Prereq
, так как вам не нужна вся проверка, просто уникальный URL для ваших шаблонов