Как передать параметр шаблона сложного конвейера DevOps в скрипт - PullRequest
2 голосов
/ 29 января 2020

В шаблоне конвейера 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? Если да, то как ты этого добился?

Ответы [ 3 ]

2 голосов
/ 25 марта 2020

Я также сталкиваюсь с аналогичной проблемой, мой обходной путь состоит в том, чтобы сгладить массив в строку, используя разные разделители для разных измерений.

Например, я хочу сделать некоторые параметры обязательными и завершить сборку, если они параметры не передаются, вместо того, чтобы добавлять задачу для проверки каждого параметра, я хочу сделать это в одной задаче.

Для этого я сначала передаю в качестве параметра (в другой шаблон, называемый * 1005) * которые содержат задачу, ответственную за проверку параметров), массив, в котором каждый элемент является строкой типа 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) }}, это создает строку типа endpoint:value;archiveName:value и передает это в качестве переменной среды.

На этом этапе, используя несколько манипуляций со строками, в скрипте я могу разбить строку, используя th Точка с запятой в качестве разделителя, поэтому я получу массив строк типа 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

В этом примере сборка не удастся, потому что я не передаю параметр archiveName

Вы можете добавить некоторую гибкость, используя переменные также для определения разделителей вместо жесткого кодирования в сценариях и в выражениях

0 голосов
/ 03 февраля 2020

Поскольку @ Leo Liu MSFT упоминается в ответе , это действительно сейчас не поддерживается, но кто-то уже открыл проблему для этого улучшения .

Эта проблема также содержит хороший обходной путь для использования вместо этого переменных среды. Недостатком этого решения является то, что вам необходимо знать структуру данных, чтобы правильно отобразить ее.

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 }}
0 голосов
/ 30 января 2020

Как передать параметр шаблона сложного конвейера DevOps в скрипт

Боюсь, мы не смогли передать параметры шаблона сложного конвейера DevOps в скрипт PowerShell.

В настоящее время задача Azure devops поддерживает только передачу одномерных массивов. Он не может принимать и передавать двумерные массивы. Хотя мы можем определить параметры двумерного массива, но нам нужно расширить параметры из шаблона с помощью сценариев, таких как:

- ${{ 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.

Вы можете проверить документ Расширить шаблон для получения более подробной информации.

Надеюсь, это поможет.

...