Трубопровод сборки Jenkins - перезагрузка на стадии
У меня есть следующий конвейер сборки, настроенный как задание:
Stage 1 - verify all dependencies exist
Stage 2 - build the new jar
Stage 3 - Run integration tests
Stage 4 - Deploy to staging environment (manual step)
Stage 5 - Deploy to production environment (manual step)
Я ищу способ начать конвейер сборки с определенного этапа в случае переходного отказа. Например, допустим, что возникла проблема с сетью, когда пользователь нажал кнопку для развертывания на производство. Я не думаю, что имеет смысл начать конвейер со стадии 1... Я хотел бы снова попробовать этот шаг и продолжить дальше оттуда. Я не вижу таких функциональных возможностей в плагине Build Pipeline.
Спасибо!!
Ответы
Ответ 1
Я думаю, что checkpoint
- это то, что вы ищете. К сожалению, он доступен только в пакете CloudBees Jenkins Enterprise, а не в бесплатной версии.
Пусть надеется, что это превратит его в версию с открытым исходным кодом, поскольку это кажется очень распространенным вариантом использования.
Ответ 2
Лучшее решение - это решение, аналогичное тому, что я предложил в этом вопросе:
Напишите конвейерную обработку script, которая имеет "if" -guards вокруг отдельных этапов, например:
stage "s1"
if (theStage in ["s1"]) {
sleep 2
}
stage "s2"
if (theStage in ["s1", "s2"]) {
sleep 2
}
stage "s3"
if (theStage in ["s1", "s2", "s3"]) {
sleep 2
}
Затем вы можете сделать "основное" задание, которое использует этот script, и запускает все этапы сразу, установив параметр "theStage" в "s1". Эта работа будет собирать статистику, когда все этапы запускаются сразу и дают вам полезное время оценки.
Кроме того, вы можете выполнить задание "частичного запуска", которое использует этот script, и которое параметризуется на этапе, с которого вы хотите начать. Однако оценка будет не очень полезной.
Ответ 3
Между тем, многие другие ответы устарели, поскольку Jenkins предоставляет встроенное решение, позволяющее перезапустить задание с любого этапа: https://jenkins.io/doc/book/pipeline/running-pipelines/. Это применимо к декларативному трубопровод только через.
Ответ 4
Вы можете обернуть свой код в retry
:
stage "Deployment"
retry(3) {
sh "deploy.."
}
EDIT: Это может помочь в бесплатной версии Дженкинса. Пользователи CloudBees Enterprise, см. Ответ @tarantoga.
Ответ 5
Здесь еще один эскиз, чтобы выполнить стадии условно, не нарушая историю плагина Stage View.
Как говорят:
Динамические этапы: в общем, если вы хотите визуализировать динамически изменяя этапы, делают его условным для выполнения содержания сцены, не условно включать стадию
Вот что я придумал до сих пор. Кажется, работает в основном: (просто игнорируйте другие фиктивные шаги)
Определим небольшую вспомогательную функцию conditionalStage
, которая аккуратно завершает проверку имени сцены из параметра JP_STAGE
Jenkins Job.
Обратите внимание, что conditionalStage
сначала открывает stage
, а затем проверяет stageIsActive
на этапе, просто пропустив все шаги. Таким образом, плагин Stage View видит все этапы и не бесполезен, но шаги этапов все еще пропущены.
def stageSelect = JP_STAGE.toLowerCase()
// test if stage or any of sub-stages is active
def stageIsActive(theStage, theStages) {
// echo "pass: $theStages"
// ARGL: https://issues.jenkins-ci.org/browse/JENKINS-26481
// def lcStages = theStages.collect {it.toLowerCase()}
def lcStages = []
for (def s : theStages) { lcStages += s.toLowerCase() }
def lcAllStages = lcStages + ['all']
// echo "check: $lcAllStages"
// echo JP_STAGE.toLowerCase()
if (JP_STAGE.toLowerCase() in lcAllStages) {
echo "Run: Stage '$theStage' is active through '$JP_STAGE'."
return true
} else {
echo "Skip: Stage '$theStage' is NOT active through '$JP_STAGE'."
return false
}
}
// 1st element should be the stage, optionally followed by all sub-stages
def conditionalStage(names, stageBody) {
stage(names[0]) { if (stageIsActive(names[0], names)) {
stageBody()
}}
}
timestamps {
// --S--
conditionalStage(['Intro']) {
echo 'Outside Node'
build job: 'FreeX', wait: true
sleep 3
}
// --S--
conditionalStage(['AtNode', 'Hello', 'Done']) {
node {
// Cloudbees Enterprise Only: checkpoint 'Now'
conditionalStage(['Hello']) {
echo 'Hello World @ Node'
sleep 4
}
conditionalStage(['Done']) {
dir('C:/local') {
echo pwd()
}
}
}
}
}//timestamps
Ответ 6
Немного старая тема, но поскольку Дженкинс до сих пор (!) Не поддерживает это, я отправляю другое решение для реализации сценариев с использованием сценариев. Он основан на списке этапов строительства динамически при запуске конвейера.
- шаг - этапы определения enum
enum Steps {
PREPARE(0, "prepare"),
BUILD(1, "build"),
ANALYSE(2, "analyse"),
CHECKQG(3, "checkQG"),
PROVISION(4, "provision"),
DEPLOY(5, "deploy"),
ACTIVATE(6, "activate"),
VERIFY(7, "verify"),
CLEANUP(8, "cleanup")
Steps(int id, String name) {
this.id = id
this.name = name
}
private final int id
private final String name
int getId() {
id
}
String getName() {
name
}
public static Steps getByName(String name) {
println "getting by name " + name
for(Steps step : Steps.values()) {
if(step.name.equalsIgnoreCase(name)) {
return step
}
}
throw new IllegalArgumentException()
}
}
- метод создания списка последних шагов
def prepareStages(def startPoint){
println "preparing build steps starting from " + startPoint
Set steps = new LinkedHashSet()
steps.add(Steps.PREPARE)
steps.add(Steps.BUILD)
steps.add(Steps.ANALYSE)
steps.add(Steps.CHECKQG)
steps.add(Steps.PROVISION)
steps.add(Steps.DEPLOY)
steps.add(Steps.ACTIVATE)
steps.add(Steps.VERIFY)
steps.add(Steps.CLEANUP)
List finalSteps = new ArrayList()
steps.each{
step ->
if (step.id >= startPoint.id) {
finalSteps.add(step)
}
}
return finalSteps
}
- и вы можете использовать это так
def stage = prepareStages (Steps.getByName("$ {startStage}"))
node {
try {
//pipelineTriggers([pollSCM('${settings.scmPoolInterval}')]) //this can be used in future to get rid build hooks
sh "echo building " + buildVersionNumber(${settings.isTagDriven})
tool name: 'mvn_339_jenkins', type: 'maven'
script {
println "running: " + stages
}
stage('Prepare') {
if (stages.contains(Steps.PREPARE)) {
script { currentStage = 'Prepare' }
//.....
}
} //...
"startStage" - это параметр сборки, определенный следующим образом
параметры {choiceParam ('startStage', ['подготовить', 'построить', 'проанализировать', 'checkQG', 'предоставление', 'развертывать', 'активировать', 'проверить', 'очистить'], 'забрать этап, с которого вы хотите начать ')}
Это позволяет мне выбрать этап, с которого я хочу запустить конвейер (этап подготовки установлен по умолчанию)
Ответ 7
Что вы можете сделать, это поместить отдельные шаги в скрипты groovy. Затем вы можете создать "runAll" -job, который загружает все сценарии в правильном порядке и отдельные задания для разных шагов.
Хотя это способ, который должен работать, я не думаю, что это идеальное решение, так как это означает, что вам нужно позаботиться о том, как различные этапы обмениваются информацией, так что этапы могут выполняться независимо.
Встроенное решение будет намного лучше.