В шаблоне шага 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? Спасибо
@GalnaGreta, спасибо, что присоединились. Это строка, содержащая путь к файлу, разделенный пробелами. Поэтому я практически преобразовал что-то вроде: «C:\Project1\myfile.dll C:\Project1\myOtherFile.dll» => C:\Project1** C:\Project2**
@ user2896152 Я проверил образец YAML и описание. если вы используете команду регистрации для установки переменной, она будет содержать некоторые ограничения. Я добавил информацию в ответ. Чтобы полностью удовлетворить ваши требования, я предлагаю вам разделить конвейеры на два, чтобы значения переменных могли быть прочитаны шаблоном.
Спасибо, что присоединились к @KevinLu-MSFT. К сожалению, я не могу изменить существующую структуру конвейера. Я проверю, можно ли это сделать другим способом. Спасибо=)
@user2896152 user2896152 Если вам нужно сохранить текущую структуру конвейера (один конвейер), вам необходимо жестко запрограммировать многострочный путь в параметрах или переменных. Помимо этого, я боюсь, что нет других методов, которые могут удовлетворить ваши потребности.
В обновленном ответе я поделился примерами, связанными с жестким кодированием многострочного пути. Вы можете это проверить.
@KevinLu-MSFT, как вы думаете, это возможно, если, например, я передам встроенную строку в формате json, а затем попытаюсь десериализовать ее в задаче DownloadPipelineArtifact@2?
@user2896152 user2896152 Я понимаю твою идею. Но ответ НЕТ. Это пока невозможно. Задача Download Pipeline Artifact не поддерживает десериализацию файлов JSON. Он сохранит формат входного значения.
@KevinLu-MSFT Кроме того, передача одной строки и разделение строки непосредственно в задаче DownloadArtifact кажется невозможным. Я пытаюсь сделать что-то вроде этого: itemPattern: | ${{ replace(parameters.workingDirectoryTestPattern, " ", "\n ") }}
@ user2896152 Да. Это неосуществимо. Я пробовал это раньше, и это тоже не может сработать. На это есть две причины: (1) Когда мы используем |
для создания многострочной строки, он не поддерживает использование каких-либо выражений. (2) Только когда мы передаем \n
в Rest API для запуска конвейера, он будет распознан как символ разрыва строки. В других случаях он по-прежнему будет рассматриваться как однострочная строка в параметрах и переменной.
@KevinLu-MSFT большое спасибо за поддержку!
@ user2896152 Подводя итог: в настоящее время мы можем жестко закодировать только многострочные строки в одном конвейере YAML, за исключением разделения конвейера для передачи многострочных строк через Rest API. Для получения более подробной информации вы можете обратиться к ответу ниже. А пока большое спасибо за ваши мысли в комментариях.
Я проверил ваш образец 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}}
Не могли бы вы показать примеры данных, которые сейчас находятся в
$(fileCollection)
?