Jenkinsfile学习经验分享

    Jenkinsfile是Jenkins2.x版本推出流水线pipeline之后的配置文件,可以将构建过程全部以代码的形式写在Jenkinsfile里面,Jenkinsfile随代码库一起进行维护。关于Jenkinsfile的更多信息请查看Jenkins官网。

流水线

    流水线是Jenkins2.x版本推出的新特性,按照其字面意思理解,将软件的生产过程与传统工艺的生产过程相比较,从原料(code)到完整的,可交付的产品,中间不需要人工进行干预。
    流水线支持两种语法, 声明式 (在流水线 2.5 引入)和脚本化流水线。 两种都支持构建持续交付流水线。两种都可以用来在 web UI 或 Jenkinsfile 中定义流水线, 不过通常认为创建一个 Jenkinsfile 并将其检入带源代码控制仓库是最佳实践。

建议着重理解下声明式和脚本化,在刚开始接触流水线时,通过Web UI上创建的,node开头的,为脚本化流水线。所有code都写在pipeline块里面的,为声明式流水线。

本文以声明式流水线为例

声明式流水线

声明式流水线所有有效的内容必须包含在一个pipeline块中

pipeline {
    /* insert Declarative Pipeline here */
}

Sections

agent

agent指定了整个流水线或特定的stage将会在Jenkins的哪个节点执行,这取决于 agent 区域的位置。agent必须在 pipeline 块的顶层被定义, 在 stage 级别的定义是可选的。
参数:

  • any:在任何可用的节点上执行流水线或stage部分。
pipeline {
   agent any
}
  • none:当agent在pipeline的顶层被设置为none时,那么在每个stage中都需要添加agent,并指定构建节点。
pipeline {
   agent none
   stages {
   stage('Example Build') {
     agent any
     steps {
       'do some thing'
      }
    }
  }   
}
  • label:选择特定标签的Jenkins节点作为构建环境。
pipeline {
   agent { label 'my-defined-label' }
}
  • node:node用法与label用法一样,但是node有额外的可选参数customWorkspace,可以指定工作空间。
pipeline {
  agent {
    node {
      label 'my-defined-label'
      customWorkspace '/some/other/path'
    }
  }
}
  • docker:使用指定的容器进行构建,该参数需要结合node或者label进行使用,以便指定在哪个节点上执行docker。该选项可以添加args参数,args参数将直接传递给docker run,alwaysPull 则强制docker执行pull,即使镜像名称已经存在。
pipeline {
  agent {
      docker {
          image 'maven:3-alpine'
          label 'my-defined-label'
          args  '-v /tmp:/tmp'
      }
  }
}
  • dockerfile:使用源代码库中已有的Dcoekrfile构建的容器来进行构建。要使用该选项, Jenkinsfile 必须从多个分支流水线中加载或者选择 "Pipeline from SCM."选项。
pipeline {
  agent {
    // Equivalent to "docker build -f Dockerfile.build --build-arg version=1.0.2 ./build/
    dockerfile {
        filename 'Dockerfile.build'
        dir 'build'
        label 'my-defined-label'
        additionalBuildArgs  '--build-arg version=1.0.2'
    }
  }
}

additionalBuildArgs参数将传递给docker build

post

post 部分定义一个或多个steps ,post里面的steps将根据流水线或阶段的返回结果来判断是否执行。
参数:

  • always:无论流水线或阶段的返回结果如何,都将执行该steps。
  • changed:只有当前流水线或阶段的完成状态与它之前的运行不同时,才执行该steps。
  • failure:只有当前流水线或阶段的返回值为非0时,才执行该steps。
  • success:只有当前流水线或阶段的返回值为0时,才执行该steps。
  • unstable:只有当前流水线或阶段的状态为"unstable",才允许在 post 部分运行该步骤, 通常由于测试失败,代码违规等造成。
  • aborted:只有当前流水线或阶段的状态为"aborted",才执行该steps,aborted通常为手动取消构建时的状态。
Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
    post { 
        always { 
            echo 'I will always say Hello again!'
        }
    }
}

post部分一般写在Jenkinsfile的最后。

stages

包含一个或多个 stage 指令。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages { 
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

steps

在一个stage中包含一个或多个 steps,steps中至少包含一个操作。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Example') {
            steps { 
                echo 'Hello World'
            }
        }
    }
}

Directives

environment

以键值对的方式添加环境变量,可以是添加全局环境变量,也可以是在某个stage中添加环境变量,stage中添加的环境变量只作用于当前stage。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    environment { 
        CC = 'clang'
    }
    stages {
        stage('Example') {
            environment { 
                AN_ACCESS_KEY = credentials('my-prefined-secret-text') 
            }
            steps {
                sh 'printenv'
            }
        }
    }
}

stage中的环境变量只适用于该stage阶段

options

options配置流水线的构建配置,类似于自由构建的丢弃旧的构建,是否允许并行构建等等。也可以由插件提供参数,比如timestamps(在控制台输出时间)

  • buildDiscarder:保留最近的构建次数。
    options { buildDiscarder(logRotator(numToKeepStr: '1')) }
  • disableConcurrentBuilds:不允许同时执行流水线,可被用来防止同时访问共享资源等.
    options { disableConcurrentBuilds() }
  • skipDefaultCheckout:跳过在版本控制器中检出代码。
    options { skipDefaultCheckout() }
  • skipStagesAfterUnstable:当构建状态为UNSTABLE时,跳过该阶段。
    options { skipStagesAfterUnstable() }
  • checkoutToSubdirectory:在工作空间的子目录中自动执行源代码控制检出。
    options { checkoutToSubdirectory('foo') }
  • timeout:设置流水线运行的超时时间, 若在此时间内任务未执行完,则自行停止构建。
    options { timeout(time: 1, unit: 'HOURS') }
  • retry:在失败时, 重新尝试整个流水线的指定次数。
    options { retry(3) }
  • timestamps:在控制台输出时间戳。
    options { timestamps() }
Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    options {
        timeout(time: 1, unit: 'HOURS') 
        buildDiscarder(logRotator(numToKeepStr: '1'))
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

在stage块中,只能使用部分options选项,skipDefaultCheckouttimeoutretrytimestamps

参数

parameters 指令提供了一个用户在触发流水线时应该提供的参数列表。这些用户指定参数的值可通过 params 对象提供给流水线步骤。

  • string:字符串类型的参数。
    parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }
  • booleanParam:布尔参数
    parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') }
Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    parameters {
        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
    }
    stages {
        stage('Example') {
            steps {
                echo "Hello ${params.PERSON}"
            }
        }
    }
}

触发器

triggers 指令定义了流水线被重新触发的自动化方法。对于集成了源( 比如 GitHub 或 BitBucket)的流水线, 可能不需要 triggers ,因为基于 web 的集成很肯能已经存在。 当前可用的触发器是 cron, pollSCM 和 upstream。

  • cron:接收 cron 样式的字符串来定义要重新触发流水线的常规间隔。
    triggers { cron('H */4 * * 1-5') }
  • pollSCM:接收 cron 样式的字符串来定义一个固定的间隔,在这个间隔中,Jenkins 会检查新的源代码更新。如果存在更改, 流水线就会被重新触发。
    triggers { pollSCM('H */4 * * 1-5') }
  • upstream:接受逗号分隔的工作字符串和阈值。 当字符串中的任何作业以最小阈值结束时,流水线被重新触发。
    triggers { upstream(upstreamProjects: 'job1,job2', threshold: hudson.model.Result.SUCCESS) }

pollSCM只在Jenkins 2.22 及以上版本中可用。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    triggers {
        cron('H */4 * * 1-5')
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

stage

stage 指令在 stages 部分进行,至少有一个stage块, 流水线所有的任务都将封装进一个或多个 stage 指令中。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

工具

定义使用工具的名称,该工具需在系统设置中进行设置。当前支持maven、jdk、gradle

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    tools {
        maven 'apache-maven-3.0.1' 
    }
    stages {
        stage('Example') {
            steps {
                sh 'mvn --version'
            }
        }
    }
}

这里使用到的工具必须在Jenkins的系统管理→全局工具配置中进行设置。

when

when 指令允许流水线根据给定的条件决定是否应该执行阶段。 when 指令必须包含至少一个条件。 如果 when 指令包含多个条件, 所有的子条件必须返回True,阶段才能执行。

  • branch:当正在构建的分支与给定的分支匹配时,执行该阶段。
    when { branch 'master' }

注意,这只适用于多分支流水线。

  • environment:当指定的环境变量是给定的值时,执行该阶段。
    when { environment name: 'DEPLOY_TO', value: 'production' }
  • expression:当指定的Groovy表达式评估为true时,执行这个阶段。
    when { expression { return params.DEBUG_BUILD } }
  • not:取反,与其它语言的not类似。
    when { not { branch 'master' } }
  • allOf:当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件.
    when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }
  • anyOf:当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件。
    when { anyOf { branch 'master'; branch 'staging' } }

默认情况下, 如果定义了某个阶段的agent,在进入该stage 的 agent 后才会执行when 条件判断。想要在agent前执行when的条件判断,可以通过在 when 块中指定 beforeAgent 选项来更改此选项。 如果 beforeAgent 被设置为 true, 那么就会首先对 when 条件进行评估 , 并且只有在 when 条件验证为真时才会进入 agent 。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

Parallel

并行任务,Parallel指令可以编排两个或多个并行任务。

failFast true:当某个任务失败时,终止Parallel阶段的其它任务。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Non-Parallel Stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        }
        stage('Parallel Stage') {
            when {
                branch 'master'
            }
            failFast true
            parallel {
                stage('Branch A') {
                    agent {
                        label "for-branch-a"
                    }
                    steps {
                        echo "On Branch A"
                    }
                }
                stage('Branch B') {
                    agent {
                        label "for-branch-b"
                    }
                    steps {
                        echo "On Branch B"
                    }
                }
            }
        }
    }
}

script

script块,script块使用groovy语法,提供更加了灵活的用法。

Jenkinsfile (Declarative Pipeline)
pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
                script {
                    def browsers = ['chrome', 'firefox']
                    for (int i = 0; i < browsers.size(); ++i) {
                        echo "Testing the ${browsers[i]} browser"
                    }
                }
            }
        }
    }
}

参考文献

1、Jenkins官网

你可能感兴趣的:(持续集成)