2016-06-30 53 views
20

Ho la seguente costruire oleodotto impostato come un lavoro:Jenkins costruire Pipeline - Restart Alla fase

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) 

Sto cercando un modo per iniziare la pipeline generazione da un particolare fase in caso di un errore temporaneo . Ad esempio, diciamo che c'era un problema di rete quando l'utente ha fatto clic per distribuire in produzione. Non penso che abbia senso iniziare la pipeline dalla fase 1 ... vorrei provare di nuovo quel passo e continuare da lì nella pipeline. Non vedo alcuna funzionalità come questa nel plug-in Build Pipeline.

Grazie !!

+0

Correlati: http: // stackoverflow.it/questions/39905978/complex-and-long-single-job-jenkins-job-pipeline-builds-there-yet –

risposta

2

Puoi avvolgere il codice in un passaggio retry:

stage "Deployment" 
retry(3) { 
    sh "deploy.." 
} 

EDIT: Questo potrebbe aiutare nella versione gratuita di Jenkins. Utenti di CloudBees Enterprise, vedere la risposta @tarantoga.

+0

Non significa che Jenkins riproverà quel passaggio 3 volte automaticamente? – threejeez

+0

Vuoi dire che vuoi provare di nuovo manualmente? Quindi questo non funziona. Non sono a conoscenza di qualcosa di simile in combinazione con il plug-in Pipeline. – StephenKing

+0

Sì, manualmente. Diciamo, per esempio, che i test di integrazione falliscono perché uno dei test era sbagliato invece della logica dell'applicazione ... non è necessario ricostruire l'applicazione da zero ... vorresti semplicemente aggiornare il test di integrazione e riprendere il test gasdotto da quel punto. Ha senso? – threejeez

8

Penso che checkpoint sia quello che stai cercando. Sfortunatamente è disponibile solo nella suite CloudBees Jenkins Enterprise, non nella versione gratuita.

Speriamo che entri nella versione open-source in quanto sembra essere un caso d'uso molto comune.

0

Quello che potresti fare è inserire i singoli passaggi in script groovy. Quindi puoi creare un "runAll" -job che carica tutti gli script nell'ordine corretto e singoli lavori per i diversi passaggi.

Anche se questo è un modo che dovrebbe funzionare, non penso che questa sia la soluzione ideale, poiché significa che devi fare attenzione a come i diversi passaggi si scambiano le informazioni, in modo che i passaggi possano essere eseguiti indipendentemente.

Una soluzione integrata sarebbe molto meglio.

+0

Si rinunciare quindi a molti vantaggi del plug-in per la pipeline;) – StephenKing

+0

Sì e no. Vorrei rinunciare a parte della sua flessibilità, ma manterrei la possibilità di controllare la versione dei lavori. – olenz

+0

Nel mio caso, ho una pipeline di lavoro di 4 posti di lavoro in cui ogni lavoro richiede circa 4 ore per essere completato. In particolare durante lo sviluppo dei lavori, sarebbe molto utile se potessi riavviare una fase successiva. – olenz

5

Una soluzione migliore è una soluzione simile a quello che ho suggerito in this question:

scrivere uno script pipelining che ha ha "se" -guards intorno alle singole tappe, come questo:

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 
} 

Poi puoi creare un lavoro "principale" che utilizza questo script e che esegue tutte le fasi contemporaneamente impostando il parametro "theStage" su "s1". Questo lavoro raccoglierà le statistiche quando tutte le fasi vengono eseguite contemporaneamente e ti forniscono utili tempi di stima.

Inoltre, è possibile eseguire un lavoro di "esecuzione parziale" che utilizza questo script e che viene parametrizzato con lo stage da cui si desidera iniziare. La stima non sarà molto utile, però.

+0

Questo è essenzialmente ciò che ho fatto, anche se in qualche modo diverso. Ho creato i blocchi controllando per vedere se la versione jar fosse già stata creata, in tal caso vado alla fase di test di integrazione e controllo se è già passata per quella versione jar (creando touchfile nello spazio di lavoro). – threejeez

+0

Ho fatto anche questo: le mie fasi sono "Build", "Push to dev", "Push to QA" e "Release". Dato che ho messo l'output in fase di compilazione nella fase di creazione, ho memorizzato il numero di build in una variabile nella parte superiore del mio script, quindi gli stage 'push' possono ricostituire il nome del contenitore dal passo di generazione utilizzando un numero inserito manualmente durante la riproduzione il copione. In questo modo, sono in grado di ridistribuire poiché non riesco a pensare a una buona ragione per non ricostruire/ripetere il test dopo aver corretto una build (o test) non funzionante. È disordinato, ma funziona. È così deludente che i ragazzi Jenkins non realizzeranno una versione OSS di "Checkpoint" – Jay

1

Ecco un altro schizzo per eseguire le fasi in modo condizionale senza interrompere la cronologia plug-in Stage View.

Come they say:

fasi dinamiche: in generale, se si desidera visualizzare in modo dinamico cambiando fasi, subordinarla ad eseguire il contenuto dello stage, non condizionali per includere la fase

Ecco quello che ho inventato finora. Sembra funzionare principalmente: (Basta ignorare gli altri passaggi fittizi)

Definiamo una piccola funzione di supporto conditionalStage che avvolge ordinatamente il controllo del nome stage dal parametro JP_STAGE Jenkins Job.

Notate come conditionalStageprima apre la stage e poi controlla stageIsActive all'interno dello stadio, basta saltare tutti i passaggi. In questo modo, il Plugin di Stage View vede tutte le fasi e non si rovina, ma i passaggi degli stadi sono ancora saltati.

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 
0

Un po 'vecchio argomento, ma dal momento che Jenkins ancora (!) Non supporta questo sto inviando un'altra soluzione per le implementazioni di pipeline script. Si basa sull'elenco di fasi di costruzione in modo dinamico quando si esegue la pipeline.

  1. step - fasi definizione 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. metodo di creazione della lista fasi finali
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. e la u può usare in questo modo

fasi def = 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' } 
       //..... 
      } 
     } //... 

la "startStage" è un parametro di build definito come segue

parametri { choiceParam ('startStage', [ 'preparare', 'costruire', 'analizzare' , 'checkQG', 'disposizione', 'distribuire', 'attiva', 'verificare', 'pulizia' ], 'Sollevare il palco si desidera iniziare da') }

Questo mi consente di riprendere il palco dal quale voglio iniziare la pipeline (la fase di preparazione è impostata di default)