Подтвердить что ты не робот

Трубопровод сборки 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.

Спасибо!!

4b9b3361

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

Ответ 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

Немного старая тема, но поскольку Дженкинс до сих пор (!) Не поддерживает это, я отправляю другое решение для реализации сценариев с использованием сценариев. Он основан на списке этапов строительства динамически при запуске конвейера.

  1. шаг - этапы определения 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()
    }
}
  1. метод создания списка последних шагов
  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
    }
  1. и вы можете использовать это так

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, который загружает все сценарии в правильном порядке и отдельные задания для разных шагов.

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

Встроенное решение будет намного лучше.