Использование многострочной строки в качестве параметра в шаблоне задачи Azure DevOps

В шаблоне шага yml я использую DownloadPipelineArtifact@2 для загрузки определенного артефакта, созданного из моего конвейера сборки.

Поскольку артефакт довольно большой и, в зависимости от случая, мне не нужно все содержимое артефакта целиком, я предоставляю свойство itemPattern в качестве входного параметра в свой шаблон шага и передаю его в таком виде задаче DownloadPipelineArtifact@2, чтобы выполнить некоторые операции фильтрации и ускорить сборку.

Ниже представлена ​​упрощенная версия реализованного мной шаблона шага под названием filteredDownloadArtifact:

parameters:
artifactItemPattern: '**'

steps:
- task: DownloadPipelineArtifact@2
  displayName: 'Download artifact'
  inputs:
    buildType: 'current'
    artifactName: 'MyArtifact'
    itemPattern: |
       ${{ parameters.artifactItemPattern}}

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

Например, в другом шаблоне шага yml у меня есть задача pwsh, используемая для определения того, какие папки следует загрузить.

- powershell: |
     $itemPattern= (("$(fileCollection)" -split ' ') | ForEach-Object {
        $dllName = [System.IO.Path]::GetFileName($_)
        $_.replace($dllName, '**')
      })  -join "`r`n"
      
      Write-Host "##vso[task.setvariable variable=_itemPattern]$itemPattern"

а затем я использую filteredDownloadArtifact следующим образом:

- template: filteredDownloadArtifact.yml
  parameters:
    artifactItemPattern: |
      $(_itemPattern)

Но, похоже, это не работает. В моем шаблоне шагов предусмотрен только один шаблон элемента.

Итак, существует ли другой способ использования многострочных параметров при передаче в шаблон шага Azure DevOps? Спасибо

Не могли бы вы показать примеры данных, которые сейчас находятся в $(fileCollection)?

GalnaGreta 04.07.2024 09:43

@GalnaGreta, спасибо, что присоединились. Это строка, содержащая путь к файлу, разделенный пробелами. Поэтому я практически преобразовал что-то вроде: «C:\Project1\myfile.dll C:\Project1\myOtherFile.dll» => C:\Project1** C:\Project2**

user2896152 04.07.2024 09:46

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

Kevin Lu-MSFT 04.07.2024 09:49

Спасибо, что присоединились к @KevinLu-MSFT. К сожалению, я не могу изменить существующую структуру конвейера. Я проверю, можно ли это сделать другим способом. Спасибо=)

user2896152 04.07.2024 10:14

@user2896152 user2896152 Если вам нужно сохранить текущую структуру конвейера (один конвейер), вам необходимо жестко запрограммировать многострочный путь в параметрах или переменных. Помимо этого, я боюсь, что нет других методов, которые могут удовлетворить ваши потребности.

Kevin Lu-MSFT 04.07.2024 10:16

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

Kevin Lu-MSFT 04.07.2024 10:26

@KevinLu-MSFT, как вы думаете, это возможно, если, например, я передам встроенную строку в формате json, а затем попытаюсь десериализовать ее в задаче DownloadPipelineArtifact@2?

user2896152 04.07.2024 10:46

@user2896152 user2896152 Я понимаю твою идею. Но ответ НЕТ. Это пока невозможно. Задача Download Pipeline Artifact не поддерживает десериализацию файлов JSON. Он сохранит формат входного значения.

Kevin Lu-MSFT 04.07.2024 10:50

@KevinLu-MSFT Кроме того, передача одной строки и разделение строки непосредственно в задаче DownloadArtifact кажется невозможным. Я пытаюсь сделать что-то вроде этого: itemPattern: | ${{ replace(parameters.workingDirectoryTestPattern, " ", "\n ") }}

user2896152 04.07.2024 12:06

@ user2896152 Да. Это неосуществимо. Я пробовал это раньше, и это тоже не может сработать. На это есть две причины: (1) Когда мы используем | для создания многострочной строки, он не поддерживает использование каких-либо выражений. (2) Только когда мы передаем \n в Rest API для запуска конвейера, он будет распознан как символ разрыва строки. В других случаях он по-прежнему будет рассматриваться как однострочная строка в параметрах и переменной.

Kevin Lu-MSFT 04.07.2024 12:29

@KevinLu-MSFT большое спасибо за поддержку!

user2896152 04.07.2024 12:33

@ user2896152 Подводя итог: в настоящее время мы можем жестко закодировать только многострочные строки в одном конвейере YAML, за исключением разделения конвейера для передачи многострочных строк через Rest API. Для получения более подробной информации вы можете обратиться к ответу ниже. А пока большое спасибо за ваши мысли в комментариях.

Kevin Lu-MSFT 04.07.2024 12:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
12
99
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я проверил ваш образец YAML. Вот два ограничения:

1. Когда вы используете команду setvariable logging для создания переменной, она поддерживает только одну строку. Если вам нужно использовать строку из нескольких строк, вам необходимо жестко запрограммировать переменную в следующем формате:

variables:
- name: files
  value: |
    file1
    file2

2. Команда setvariable logging установит переменную во время выполнения, но параметр: artifactItemPattern в шаблоне будет считывать значение во время компиляции. В этом случае значение переменной не может быть успешно передано в шаблон.

Чтобы использовать параметры для передачи многострочной строки, вы можете использовать следующий формат:

parameters:
- name: artifactItemPattern
  type: object
  default: |
     file1
     file2



steps:
....

- task: DownloadPipelineArtifact@2
  displayName: 'Download artifact'
  inputs:
    buildType: 'current'
    artifactName: 'MyArtifact'
    itemPattern: ${{ parameters.artifactItemPattern}}

Судя по вашему описанию, вам необходимо использовать PowerShell для установки переменной и загрузки файлов на основе значения переменной.

Чтобы удовлетворить этому требованию, я предлагаю разделить конвейеры на два. Один используется для установки значения файлов и использования Rest API для запуска второго конвейера. Второй конвейер используется для сбора входного значения и загрузки артефактов.

Вот пример:

Трубопровод первый:

variables:
- name: fileCollection
  value: value1 value2

steps:


- powershell: |
     $itemPattern= (("$(fileCollection)" -split ' ') | ForEach-Object {
        $dllName = [System.IO.Path]::GetFileName($_)
        $_.replace($dllName, '**')
      })  -join "\n  "
     echo $itemPattern
      $token = "$(pat)"      
      $url = "https://dev.azure.com/{organizationname}/{ProjectName}/_apis/pipelines/{PipelineID}/runs?api-version=5.1-preview"
      
      $token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
      
      $JSON = "
      {
        
      
      
        `"resources`": {
          `"repositories`": {
            `"self`": {
              `"ref`": `"refs/heads/main`"
            }
          }
        },
        `"templateParameters`": {
          `"InputartifactItemPattern`":`"|\n  $itemPattern`"
        },
      
      
      
      }"
      
      
      $response = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Basic $token"} -Method Post -Body $JSON -ContentType application/json

Трубопровод второй

Шаблон второго конвейера:

parameters:
- name: artifactItemPattern
  type: object



steps:
....


- task: DownloadPipelineArtifact@2
  displayName: 'Download artifact'
  inputs:
    buildType: 'current'
    artifactName: 'MyArtifact'
    itemPattern: ${{ parameters.artifactItemPattern}}

- script: |
     cd $(pipeline.workspace)
     ls

Второй основной Yaml конвейера:

parameters:
  - name: InputartifactItemPattern
    type: object

  
jobs:
- template: filteredDownloadArtifact.yml
  parameters:
    artifactItemPattern: ${{parameters.InputartifactItemPattern}}

Обновлять:

Чтобы жестко запрограммировать переменные или параметры для передачи многострочной строки, мы можем использовать следующий формат:

Параметры:

parameters:
- name: InputartifactItemPattern
  type: object
  default: |
     file1
     file2

jobs:
- template: filteredDownloadArtifact.yml
  parameters:
    artifactItemPattern: ${{parameters.InputartifactItemPattern}}

Шаблон YAML:

parameters:
- name: artifactItemPattern
  type: object



steps:
....

- task: DownloadPipelineArtifact@2
  displayName: 'Download artifact'
  inputs:
    buildType: 'current'
    artifactName: 'MyArtifact'
    itemPattern: ${{ parameters.artifactItemPattern}}

Переменные:

variables:
- name: _itemPattern
  value: |
    file1
    file2

- template: filteredDownloadArtifact.yml
  parameters:
    artifactItemPattern: $(_itemPattern)

Шаблон YAML:

parameters:
artifactItemPattern: '**'

steps:
- task: DownloadPipelineArtifact@2
  displayName: 'Download artifact'
  inputs:
    buildType: 'current'
    artifactName: 'MyArtifact'
    itemPattern: |
       ${{ parameters.artifactItemPattern}}

Другие вопросы по теме