Параметр управления задачами - Пользовательское условие - запускать задачу при предыдущем сбое или истечении времени ожидания

Есть ли возможность установить настраиваемое условие, которое будет проверять, не удалось ли выполнить предыдущую задачу ИЛИ истекло ли время ожидания?

В настоящее время я использую Only when a previous task has failed, который работает, когда задача не выполняется. Если время выполнения задачи истекает, это не считается ошибкой и пропускается.

Тогда мне нужно специальное условие, что-то вроде or(failed(), timedout()). Является ли это возможным?

Контекст

У нас есть эта периодически возникающая проблема с npm install задачей, причину которой мы не можем найти, но она решается при следующем запуске задания, поэтому мы искали возможность повторной попытки. Частичным решением было продублировать npm install и использовать параметр управления, но он не работал во всех случаях «сбоя». Решение, предоставленное @Levi Lu-MSFT, похоже, работает для всех наших потребностей (оно повторяет попытку), но, к сожалению, оно не решает проблему, повторная задача 2-й строки также не выполняется.

Примеры ошибок:

20741 error   stack: 'Error: EPERM: operation not permitted, unlink \'C:\\agent2\\_work\\4\\s\\node_modules\\.staging\\typescript-4440ace9\\lib\\tsc.js\'',
20741 error   errno: -4048,
20741 error   code: 'EPERM',
20741 error   syscall: 'unlink',
20741 error   path: 'C:\\agent2\\_work\\4\\s\\node_modules\\.staging\\typescript-4440ace9\\lib\\tsc.js',
20741 error   parent: 's' }
20742 error The operation was rejected by your operating system.
20742 error It's possible that the file was already in use (by a text editor or antivirus),
20742 error or that you lack permissions to access it.

or

21518 verbose stack SyntaxError: Unexpected end of JSON input while parsing near '...ter/doc/TypeScript%20'
21518 verbose stack     at JSON.parse (<anonymous>)
21518 verbose stack     at parseJson (C:\agent2\_work\_tool\node\8.17.0\x64\node_modules\npm\node_modules\json-parse-better-errors\index.js:7:17)
21518 verbose stack     at consumeBody.call.then.buffer (C:\agent2\_work\_tool\node\8.17.0\x64\node_modules\npm\node_modules\node-fetch-npm\src\body.js:96:50)
21518 verbose stack     at <anonymous>
21518 verbose stack     at process._tickCallback (internal/process/next_tick.js:189:7)
21519 verbose cwd C:\agent2\_work\7\s
21520 verbose Windows_NT 10.0.14393
21521 verbose argv "C:\\agent2\\_work\\_tool\\node\\8.17.0\\x64\\node.exe" "C:\\agent2\\_work\\_tool\\node\\8.17.0\\x64\\node_modules\\npm\\bin\\npm-cli.js" "install"
21522 verbose node v8.17.0
21523 verbose npm  v6.13.4
21524 error Unexpected end of JSON input while parsing near '...ter/doc/TypeScript%20'
21525 verbose exit [ 1, true ]

Иногда тоже время вышло


person Lukasz 'Severiaan' Grela    schedule 23.03.2020    source источник


Ответы (2)


Можно добавить собственное условие. Если вы хотите, чтобы задача выполнялась, когда предыдущая задача не удалась или была пропущена, вы можете использовать настраиваемое условие not(succeeded())

введите здесь описание изображения

Однако существует проблема с указанным выше пользовательским условием, оно не работает в сценарии с несколькими задачами.

Например, есть три задачи A, B, C. Ожидаемое поведение - задача C выполняется только в случае сбоя задачи B. Но на самом деле задача C также будет выполняться при сбое задачи A, даже если задача B выполнена успешно. Посмотрите скриншот ниже.

введите здесь описание изображения

Обходной путь для вышеуказанной проблемы - добавить задачу сценария для вызова azure DevOps restful api, чтобы получить статус Задачи B и установить его в переменную, используя это выражение echo "##vso[task.setvariable variable=taskStatus]taskStatus".

В приведенном ниже примере добавьте задачу PowerShell (вам необходимо установить для этой задачи значение Even if a previous task has failed, even if the build was canceled, чтобы всегда запускать эту задачу PowerShell) перед задачей C для запуска следующих встроенных скриптов:

$url = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/timeline?api-version=5.1"

$result = Invoke-RestMethod -Uri $url -Headers @{authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"} -ContentType "application/json" -Method get

#Get the task B's task result  
$taskResult = $result.records | where {$_.name -eq "B"} | select result  

#set the Task B's taskResult to variable taskStatus
echo "##vso[task.setvariable variable=taskStatus]$($taskResult.result)" 

Чтобы указанные выше сценарии могли получить доступ к токену доступа, вам также необходимо щелкнуть задание агента и установить флажок Allow scripts to access the OAuth token. См. Снимок экрана ниже.

введите здесь описание изображения

Наконец, вы можете использовать настраиваемое условие and(not(canceled()), ne(variables.taskStatus, 'succeeded')) для задачи C. Задача C должна выполняться только в том случае, если задача B не выполнена.

введите здесь описание изображения

person Levi Lu-MSFT    schedule 24.03.2020
comment
Если задание будет отменено, будет ли оно выполнено или будет соблюдено это? Все, что мне нужно, это статус только на уровне задачи. - person Lukasz 'Severiaan' Grela; 24.03.2020
comment
Привет, @ Lukasz'Severiaan'Grela С указанным выше условием задача будет запущена, если задание будет отменено. легко пропустить выполнение задачи, если она отменена. нужно только добавить еще одно условие not(canceled()). Я обновил ответ выше. Пожалуйста, проверьте это - person Levi Lu-MSFT; 24.03.2020
comment
Azure PowerShell не работает с ##[error]Could not find the modules: 'Az.Accounts' with Version: '3.1.0'. If the module was recently installed, retry after restarting the Azure Pipelines task agent. - независимо от того, какую версию я установил ... С задачей PowerShell ничего не отображается на экране, а задача C выполняется, даже если задача B в порядке. - person Lukasz 'Severiaan' Grela; 24.03.2020
comment
Если модуль не найден, проверьте эту ветку. Не могли бы вы поделиться своими скриптами, которые вызывают rest api и устанавливают переменную taskStatus. Вышеупомянутые сценарии у меня работали. - person Levi Lu-MSFT; 24.03.2020
comment
echo "result: $($taskResult)" результаты result: @{result=succeeded} это правильно? как тогда этот скрипт (echo "##vso[task.setvariable variable=taskStatus]$($taskResult)") мог оценить до echo "##vso[task.setvariable variable=taskStatus]@{result=succeeded}"? - person Lukasz 'Severiaan' Grela; 24.03.2020
comment
Извините моя ошибка. Пожалуйста, попробуйте echo "##vso[task.setvariable variable=taskStatus]$($taskResult.result)" , чтобы получить результат. - person Levi Lu-MSFT; 24.03.2020

Хотя мне не удалось найти встроенную функцию для определения времени ожидания этапа сборки, вы можете попытаться эмулировать это с помощью переменных.

Рассмотрим следующий фрагмент объявления конвейера на языке YAML:

steps:
- script: |
    echo Hello from the first task!
    sleep 90
    echo "##vso[task.setvariable variable=timedOut]false"
  timeoutInMinutes: 1
  displayName: 'A'
  continueOnError: true

- script: echo Previous task has failed or timed out!
  displayName: 'B'
  condition: or(failed(), ne(variables.timedOut, 'false'))

Для первой задачи (A) установлено время ожидания через 1 минуту, но сценарий внутри эмулирует длительную задачу (sleep 90) в течение 1,5 минут. В результате время ожидания задачи истекает, и переменная timedOut НЕ установлена ​​на false. Следовательно, условие задачи B оценивается как true, и она выполняется. То же самое произойдет, если вы замените sleep 90 на exit 1, чтобы имитировать сбой задачи A.

С другой стороны, если задача A завершается успешно, ни одна из частей условия задачи B не оценивается как истинная, и вся задача B пропускается.

Это очень упрощенный пример, но он демонстрирует идею, которую вы можете настроить в дальнейшем, чтобы удовлетворить потребности вашего конвейера.

person Yan Sklyarenko    schedule 23.03.2020
comment
Не могли бы вы добавить раздел, объясняющий, как его использовать без YAML? Если можно конечно. Все, что я вижу для своей задачи, - это нажимать кнопку View YAML, но не редактировать. Я предполагаю, что or(failed(), ne(variables.timedOut, 'false')) переходит в поле Custom Condition, и у меня должна быть задача сценария, где я echo команда ##vso? - person Lukasz 'Severiaan' Grela; 24.03.2020
comment
Я бы посоветовал вам следовать подходу, описанному в ответе @Levi Lu-MSFT - он гораздо более подходит для вашей ситуации и более правильный в более широком сценарии. - person Yan Sklyarenko; 24.03.2020