动机
减少对Azure DevOps任务的维护,该任务调用具有很多参数(“很多”可能是5)的Powershell脚本。
该想法基于Azure DevOps生成环境变量以反映生成变量这一事实。因此,我设计了以下方案:
MyBuild.
前缀所有非秘密Azure DevOps变量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 的逻辑打包到模块函数中时,该方法不起作用。这是因为模块作用域隔离-我只是不能修改调用者脚本的参数。
还有可能吗?是否可以更优雅地实现我的目标?记住,我想减少与在Azure DevOps中维护任务命令行相关的成本。
现在我倾向于退回到这个计划:
$xyz = $(Resolve-ParameterValue 'xyz' x y z ...)
Resolve-ParameterValue
首先要检查$env:MyBuild_xyz
的位置,如果找不到,请从x,y,z,...中选择第一个非空值。
但是,如果Resolve-ParameterValue
方法来自某个模块,则该脚本必须假定该模块已经安装,因为在评估参数之前无法安装该模块。还是有?
编辑1
请注意,用于调用 DefaultParameterValueBinding.ps1 脚本的命令行不包含调用方脚本参数!它确实包含$PSCommandPath
,用于获取PSBoundParameters
集合。
答案 0 :(得分:1)
是的,但是需要对调用脚本和函数进行修改。通过引用传递参数。亚当·B(Adam B.)在以下内容中很好地介绍了如何通过引用传递参数:
https://mcpmag.com/articles/2015/06/04/reference-variables-in-powershell.aspx
网络,下面是一个示例:
$age = 12;
function birthday {
param([ref]$age)
$age.value += 1
}
birthday -age ([ref]$age)
Write-Output $age
我已经12岁了,我将其作为参数传递给函数。该函数将$ age的值增加1。您可以对模块中的函数执行相同的操作。你让我流连忘返。