Мотивация
Уменьшите объем обслуживания задачи DevOps Azure, которая вызывает скрипт Powershell с большим количеством параметров («много» может быть 5).
Идея основана на том факте, что AzOv DevOps генерирует переменные среды для отражения переменных сборки.Итак, я разработал следующую схему:
- Префикс всех несекретных переменных DevOps Azure с
MyBuild.
- Сценарий PowerShell для задачи вызовет функцию для проверки параметров сценария на соответствие
MyBuild_
переменных среды и автоматически назначит значение переменной среды MyBuild_xyz
параметру сценария xyz
, если последний не имеет значения.
Таким образом, командная строка задачи будет содержать только секретпараметры (которые не отражаются в окружающей среде).Зачастую секретных параметров нет, поэтому командная строка остается пустой.Мы находим эту схему, чтобы уменьшить обслуживание задач, управляемых сценарием powershell.
Пример
param(
$DBUser,
[ValidateNotNullOrEmpty()]$DBPassword,
$DBServer,
$Configuration,
$Solutions,
$ClientDB = $env:Build_DefinitionName,
$RawBuildVersion = $env:Build_BuildNumber,
$BuildDefinition = $env:Build_DefinitionName,
$Changeset = $env:Build_SourceVersion,
$OutDir = $env:Build_BinariesDirectory,
$TempDir,
[Switch]$EnforceNoMetadataStoreChanges
)
$ErrorActionPreference = "Stop"
. $PSScriptRoot\AutomationBootstrap.ps1
$AutomationScripts = GetToolPackage DevOpsAutomation
. "$AutomationScripts\vNext\DefaultParameterValueBinding.ps1" $PSCommandPath -Required 'ClientDB' -Props @{
OutDir = @{ DefaultValue = [io.path]::GetFullPath("$PSScriptRoot\..\..\bin") }
TempDir = @{ DefaultValue = 'D:\_gctemp' }
DBUser = @{ DefaultValue = 'SomeUser' }
}
Описанная логика привязки параметров реализована в сценарии DefaultParameterValueBinding.ps1 , которая публикуется в пакете NuGet.Код устанавливает пакет и, таким образом, получает доступ к сценарию.
В приведенном выше примере некоторые параметры по умолчанию предопределены переменными Azure Devops, такими как $RawBuildVersion = $env:Build_BuildNumber
.Некоторые остаются неинициализированными, например $DBServer
, что означает, что по умолчанию будет $env:MyBuild_DBServer
.
. Мы можем обойтись без специальной функции для связывания, но тогда автор сценария должен будет написать что-то вродеэто:
$DBServer = $env:MyBuild_DBServer,
$Configuration = $env:MyBuild_Configuration,
$Solutions = $env:MyBuild_Solutions,
Я хотел избежать этого из-за возможности случайного несоответствия имени.
Проблема
Подход делаетне работает, когда я упаковываю логику DefaultParameterValueBinding.ps1 в функцию модуля.Это связано с изоляцией области видимости модуля - я просто не могу изменить параметры скрипта вызывающего абонента.
Возможно ли это сделать?Можно ли достичь своей цели более элегантным способом?Помните, я хочу сократить расходы, связанные с обслуживанием командной строки задачи в DevOps Azure.
Сейчас я склонен вернуться к этой схеме:
$xyz = $(Resolve-ParameterValue 'xyz' x y z ...)
Где Resolve-ParameterValue
сначала проверит $env:MyBuild_xyz
и, если не найден, выберет первое ненулевое значение из x, y, z, ...
Но если метод Resolve-ParameterValue
поступает из модуля, сценарий должен предположить, что модуль уже установлен, поскольку он не может установить его до того, как параметрыоценены.Или он есть?
EDIT 1
Обратите внимание на командную строку, используемую для вызова сценария DefaultParameterValueBinding.ps1 , который не содержит параметров сценария вызывающей программы!Он включает $PSCommandPath
, который используется для получения коллекции PSBoundParameters
.