Jenkins Pipeline共享库Shared Libraries

一、简介

随着Job的增多和pipeline的功能越来越复杂,Pipeline代码冗余度高。所以可以将一些公共的pipeline抽象做成模块代码,在各种项目pipeline之间共享核心实现,同时可以放到SVM中进行版本控制。以减少冗余并保证所有job在构建的时候会调用最新的共享库代码。这时就可以用到pipline的共享库Shared Libraries功能。

  • 模块化
  • 可重用性

二、共享库的目录结构

共享库根目录
|-- vars
    |-- test1.groovy
|-- src
    |-- test2.groovy
|-- resources
  • vars: 依赖于Jenkins运行环境的Groovy脚本。其中的Groovy脚本被称之为全局变量

  • src: 标准的Java源码目录结构,其中的Groovy脚本被称为类库(Library class)。该目录所有下的所有类都一次性静态被添加到类路径classpath下

  • resources: 目录允许从外部库中使用 libraryResource 步骤来加载有关的非 Groovy 文件。 目前,内部库不支持该特性

三、配置全局共享库

可在Jenkins中的Manage Jenkins –> Configure System –> Global Pipeline Libraries 添加一个或多个全局的共享库,同时也可以在构建过程中的任何位置使用library step动作动态地配置引用共享库,详见动态引用共享库

1571906388403

四、引用共享库

1. 引用全局共享库

格式:@Library('my-shared-library-1@$Branch/Tag','my-shared-library-1@$Branch/Tag') _

#!groovy
// 引用默认配置的共享库
@Library('demo-shared-library') _

// 引用指定分支、tag的共享库代码
@Library('demo-shared-library@1.0') _

// 引用多个指定分支tag的共享库
@Library('demo-shared-library@$Branch/Tag','demo-shared-library-test@$Branch/Tag') _

@Library('utils') import org.foo.Utilities

@Library('utils') import static org.foo.Utilities.*

2. 动态引用共享库

2.7版本后的Shared Groovy Libraries插件,增加了一个librarysetp,可以随时在构建过程中引用共享库

#!groovy

library 'demo-shared-library@$BRANCH_NAME'

library "demo-shared-library@${params.LIB_VERSION}"

library('demo-shared-library').com.mycorp.pipeline.Utils.someStaticMethod()

// 此时共享库的版本必须指定
library identifier: 'custom-lib@master', retriever: modernSCM(
  [$class: 'GitSCMSource',
   remote: 'git@git.mycorp.com:my-jenkins-utils.git',
   credentialsId: 'my-private-key'])

3. 调用第三方Java库

@Grab('org.apache.commons:commons-math3:3.4.1')
import org.apache.commons.math3.primes.Primes

引用完的第三方Java库后会缓存在Jenkins Master节点的~/.groovy/grapes/ 目录下

五、全局变量和类库的编写规则和调用方法

1. /var下定义的全局变量

  • 全局变量必须以全小写或驼峰(camelCased)命名以便于能够在流水线中正确的加载
  • /vars目录中的脚本根据需求以单例的方式实例化,这允许在单个.groovy` 文件中定义多个方法

  • /vars/*.groovy若实现call()方法,直接引用时默认执行其中的方法,该方法可以让全局变量以一种以类似于step的方式被调用

    /vars/log.groovy

    #!groovy
    def call(String name = 'human') {
        echo "Hello, ${name}."
    }
    def info(message) {
        echo "INFO: ${message}"
    }
    def warning(message) {
        echo "WARNING: ${message}"
    }
    

    Jenkinsfile

    #!groovy
    @Library('demo-shared-library@1.0') _
    
    log()                            // 输出"Hello, human."
    log.info 'Starting'                // 输出"INFO: Starting"
    log.warning 'Nothing to do!'    // 输出"WARNING: Nothing to do!"
    
  • 从2017年9月下旬发布的声明式 1.2开始,可以在全局变量中直接定义声明式流水线

    /vars/evenOrOdd.groovy

    #!groovy
    def call(int buildNumber) {
      if (buildNumber % 2 == 0) {
        pipeline {
          agent any
          stages {
            stage('Even Stage') {
              steps {
                echo "The build number is even"
              }
            }
          }
        }
      } else {
        pipeline {
          agent any
          stages {
            stage('Odd Stage') {
              steps {
                echo "The build number is odd"
              }
            }
          }
        }
      }
    }
    

    Jenkinsfile

    #!groovy
    @Library('demo-shared-library@1.0') _
    
    evenOrOdd(currentBuild.getNumber())
    
  • 全局变量的传参

    /vars/buildPlugin.groovy

    #!groovy
    def call(Map config) {
        node {
            git url: "https://github.com/jenkinsci/${config.name}-plugin.git"
            sh 'mvn install'
            mail to: '...', subject: "${config.name} plugin build", body: '...'
        }
    }
    

    Jenkinsfile

    #!groovy
    @Library('demo-shared-library@1.0') _
    
    buildPlugin name: 'git'
    
  • 声明式流水线不允许在script指令之外使用全局变量

    Jenkinsfile

    #!groovy
    @Library('demo-shared-library@1.0') _
    
    pipeline {
        agent none
        stage ('Example') {
            steps {
                 script { 
                     log.info 'Starting'
                     log.warning 'Nothing to do!'
                 }
            }
        }
    }
    

2. /src下定义的类库

  • 类库不能直接调用 shgit这样的步骤。 但是他们可以在封闭的类的范围之外实现方法,从而调用流水线步骤

    /src/org/foo/Zot.groovy

    #!groovy
    package org.foo;
    
    def checkOutFrom(repo) {
      git url: "git@github.com:jenkinsci/${repo}"
    }
    
    return this
    

    Jenkinsfile

    #!groovy
    @Library('demo-shared-library@1.0') _
    
    def z = new org.foo.Zot()
    z.checkOutFrom(repo)
    
  • 类库中使用”class“声明父类

    /src/org/foo/Utilities.groovy

    package org.foo
    class Utilities implements Serializable {
      def steps
      Utilities(steps) {this.steps = steps}
    
      def mvn(args) {
        steps.sh "${steps.tool 'Maven'}/bin/mvn -o ${args}"
      }
    }
    

    Jenkinsfile

    @Library('utils') import org.foo.Utilities
    def utils = new Utilities(this)
    node {
      utils.mvn 'clean package'
    }
    
  • 类库中的方法访问流水线中的变量

    /src/org/foo/Utilities.groovy

    package org.foo
    class Utilities {
      static def mvn(script, args) {
        script.sh "${script.tool 'Maven'}/bin/mvn -s ${script.env.HOME}/jenkins.xml -o ${args}"
      }
    }
    

    Jenkinsfile

    @Library('utils') import static org.foo.Utilities.*
    
    node {
      mvn this, 'clean package'
    }
    

六、Jenkins Pipeline生成器生成动态引用共享库的代码

1571909795787

Copyright Curiouser all right reserved,powered by Gitbook该文件最后修改时间: 2020-06-16 21:35:29

results matching ""

    No results matching ""