在Azure DevOps管道模板中,我将参数声明为数组/序列
parameters:
mySubscription: ''
myArray: []
steps:
- AzureCLI@2
inputs:
azureSubscription: ${{ parameters.mySubscription }}
scriptType: pscore
scriptPath: $(Build.SourcesDirectory)/script.ps1
arguments: '-MyYAMLArgument ${{ parameters.myArray }}'
然后将参数值从管道定义传递为
steps:
- template: myTemplate.yml
parameters:
mySubscription: 'azure-connection'
myArray:
- field1: 'a'
field2: 'b'
- field1: 'aa'
field2: 'bb'
我的问题是我无法按YAML语法(ToString()
类)原样传递该数组,以便能够在我的模板中使用PowerShell处理和处理该数组。尝试运行此管道时,出现以下错误:
/myTemplate.yml (Line: X, Col: X): Unable to convert from Array to String. Value: Array
。错误消息中引用的行/列对应于我模板中的arguments: '-MyYAMLArgument ${{ parameters.myArray }}'
。
我还尝试将参数映射为脚本的环境
- AzureCLI@2
inputs:
azureSubscription: ${{ parameters.mySubscription }}
scriptType: pscore
scriptPath: $(Build.SourcesDirectory)/script.ps1
arguments: '-MyYAMLArgument $Env:MY_ENV_VAR'
env:
MY_ENV_VAR: ${{ parameters.myArray }}
这也不起作用:
/myTemplate.yml (Line: X, Col: Y): A sequence was not expected
。该时间轴/列指向MY_ENV_VAR: ${{ parameters.myArray }}
。
是否有人面临过类似的要求,即将从管道定义中定义的复杂类型(此处为对象的数组/序列)传递给PowerShell脚本?如果是这样,您是如何实现的?
答案 0 :(得分:3)
我也面临类似的问题,我的解决方法是使用不同尺寸的分隔符将字符串中的数组弄平。
例如,我想使某些参数成为必需,并且如果未传递这些参数,则会使构建失败,而不是为每个参数添加任务以供检查,而是希望在单个任务中执行此操作。
为此,我首先将一个数组作为参数(传递给另一个名为check-required-params.yml
的模板,该模板负责负责检查参数的任务),其中每个元素都是类型为{{1}的字符串},它是name:value
和format
的必需参数(用冒号隔开)的串联(使用name
表达式:
value
然后在# templates/pipeline-template.yml
parameters:
- name: endpoint
type: string
default: ''
- name: rootDirectory
type: string
default: $(Pipeline.Workspace)
- name: remoteDirectory
type: string
default: '/'
- name: archiveName
type: string
default: ''
#other stuff
- template: check-required-params.yml
parameters:
requiredParams:
- ${{ format('endpoint:{0}', parameters.endpont) }}
- ${{ format('archiveName:{0}', parameters.archiveName) }}
中,使用表达式check-required-params.yml
连接用分号分隔元素的数组,这将创建类型为${{ join(';', parameters.requiredParams) }}
的字符串,并将其作为环境变量传递。 / p>
在这一点上,使用一些字符串操作,在脚本中,我可以使用分号作为分隔符来拆分字符串,这样我将得到一个字符串数组,例如endpoint:value;archiveName:value
,我可以进一步拆分,但是这次使用冒号作为分隔符。
我的name:value
如下:
check-required-params.yml
然后在我的# templates/check-required-params.yml
parameters:
- name: requiredParams
type: object
default: []
steps:
- task: PowerShell@2
inputs:
script: |
$params = $env:REQURED_PARAMS -split ";"
foreach($param in $params) {
if ([string]::IsNullOrEmpty($param.Split(":")[1])) {
Write-Host "##vso[task.logissue type=error;]Missing template parameter $($param.Split(":")[0])"
Write-Host "##vso[task.complete result=Failed;]"
}
}
targetType: inline
pwsh: true
env:
REQURED_PARAMS: ${{ join(';', parameters.requiredParams) }}
displayName: Check for required parameters
中可以做到:
azure-pipelines.yml
在此示例中,构建失败,因为我没有传递参数#other stuff
- template: templates/pipeline-template.yml
parameters:
endpoint: 'myEndpoint'
rootDirectory: $(Pipeline.Workspace)/mycode
您还可以通过使用变量来定义分隔符来增加灵活性,而不是在脚本和表达式中进行硬编码
答案 1 :(得分:3)
您现在可以在 ADO 管道中使用(未记录的)convertToJson
函数将这些类型的参数转换为字符串:
parameters:
- name: myParameter
type: object
default:
name1: value1
name2: value2
...
- task: Bash@3
inputs:
targetType: inline
script: |
echo "${{ convertToJson(parameters.myParameter) }}"
答案 2 :(得分:0)
如何将复杂的DevOps管道模板参数传递给脚本
恐怕我们无法将复杂的DevOps管道模板参数传递给PowerShell脚本。
当前,Azure开发人员的任务仅支持一维数组的传输。它不能接受和传送二维数组。尽管我们可以定义二维数组的参数,但是我们需要使用以下脚本从模板扩展参数:
- ${{ each field in parameters.myArray}}:
我们可以像这样使用它:
- ${{ each step in parameters.buildSteps }}:
#- ${{ each pair in step }}:
- task: PowerShell@2
inputs:
targetType : inline
script: |
Write-Host 'Hello World'
但是我们无法将二维数组直接传递给任务,例如:[field1: 'a', field2: 'b']
。这就是您收到错误Unable to convert from Array to String
的原因。
您可以查看文档Extend from a template了解更多详细信息。
希望这会有所帮助。
答案 3 :(得分:0)
与@Leo Liu MSFT mentioned in its answer一样,目前确实不支持此功能,但是已经有人opened an issue for this improvement 。
此问题现在还包含一个很好的解决方法,现在可以使用环境变量。该解决方案的缺点是您需要了解数据结构才能正确映射它。
parameters:
mylist:[]
#where mylist is a sequence of object matching the mapping:
#- name: 'the name 1'
# value: 'the value of 1'
# index: 0
#- name: 'the name 2'
# value: 'the value of 2'
# index: 1
env:
${{ each item in parameters.mylist }}:
${{ format('SCRIPT_PARAM_{0}_KEY', item.index) }}: ${{ item.name }}
${{ format('SCRIPT_PARAM_{0}_VAL', item.index) }}: ${{ item.value }}