Jenkins – Convert Script to Declarative Pipeline

Jenkins

I have a scripted pipeline which I need to checkout from a repo rather than have locally. However, when I add it to git the job fails instantly. Here is the working script;

node {
    INSTANCE_ID = ""

    stage('Get Instance Id') {
        INSTANCE_ID = sh (
            script: 'aws ec2 describe-instances --region=$awsRegion --filters Name=tag:Name,Values=\"$instanceName\" --query \'Reservations[0].Instances[0].InstanceId\'',
            returnStdout: true
        ).trim()

        if (INSTANCE_ID == "") {
            error 'No instance with the name ' + $instanceName + ' was found in the ' + $awsRegion + ' region.'
        }
    }

    stage('Start EC2 Instance') {
        sh ('aws ec2 start-instances --region=$awsRegion --instance-ids ' + INSTANCE_ID)
    }

    stage('Wait for instance to be running') {
        INSTANCE_STATE = sh (
            script: 'aws ec2 describe-instances --region=$awsRegion --instance-id ' + INSTANCE_ID + ' --query \'Reservations[0].Instances[0].State.Name\'',
            returnStdout: true
        ).trim()

        numberOfStatusChecksPerformed = 0
        while (INSTANCE_STATE != '"running"') {
            echo INSTANCE_STATE
            sleep 20
            numberOfStatusChecksPerformed = numberOfStatusChecksPerformed + 1

            // Wait 5 minutes
            if (numberOfStatusChecksPerformed > 15) {
                error 'Instance state was not running, it status is: ' + INSTANCE_STATE
            }

            INSTANCE_STATE = sh (
                script: 'aws ec2 describe-instances --region=$awsRegion --instance-id ' + INSTANCE_ID + ' --query \'Reservations[0].Instances[0].State.Name\'',
                returnStdout: true
            ).trim()
        }
    }
}

I try to convert it by changing; node { to;

#!/usr/bin/env groovy

def INSTANCE_ID = ""

pipeline {
    agent any
    stages {

The rest stays the same. I get the following error;

java.io.FileNotFoundException
    at jenkins.plugins.git.GitSCMFile$3.invoke(GitSCMFile.java:167)
    at jenkins.plugins.git.GitSCMFile$3.invoke(GitSCMFile.java:159)
    at jenkins.plugins.git.GitSCMFileSystem$3.invoke(GitSCMFileSystem.java:193)
    at org.jenkinsci.plugins.gitclient.AbstractGitAPIImpl.withRepository(AbstractGitAPIImpl.java:29)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.withRepository(CliGitAPIImpl.java:72)
    at jenkins.plugins.git.GitSCMFileSystem.invoke(GitSCMFileSystem.java:189)
    at jenkins.plugins.git.GitSCMFile.content(GitSCMFile.java:159)
    at jenkins.scm.api.SCMFile.contentAsString(SCMFile.java:338)
    at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:110)
    at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:67)
    at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:303)
    at hudson.model.ResourceController.execute(ResourceController.java:97)
    at hudson.model.Executor.run(Executor.java:429)
Finished: FAILURE

Best Answer

Did you ever get this working? It's hard to tell without seeing the rest of the Jenkinsfile after you attempted to convert it. But the error output you pasted seems like something else is going on other than just declarative syntax issues. A simplified version I can offer based off the scripted one might look something like this:

#!/usr/bin/env groovy

def INSTANCE_ID = ""

pipeline {
  agent any
  options {
    // your options here
  }
  parameters {
    // your parameters here
  }
  environment {
    // KEY = "Value"
  }
  stages {
    stage('Get Instance Id') {
      steps {
        script {
          sh "./some_command.sh"
          INSTANCE_ID = sh(returnStdout: true, script: 'aws ec2 describe-instances ... ').trim()
        }
      }
    }
  }
}

Hopefully that helps.

It could have been the script {} wrapper for the sh(returnStdout: true, script: ... part. I think that might matter.