开始使用 Jenkins

本导读将向您介绍使用 Jenkins、Jenkins 的主要特性和 Jenkins Pipeline 的基本知识。 本导读使用“独立”的 Jenkins 发行版,它可以在您自己本地的机器上运行。

准备工作

第一次使用 Jenkins,您需要:

  • 机器要求:

    • 256 MB 内存,建议大于 512 MB

    • 10 GB 的硬盘空间(用于 Jenkins 和 Docker 镜像)

  • 需要安装以下软件:

    • Java 8 ( JRE 或者 JDK 都可以)

    • Docker (导航到网站顶部的Get Docker链接以访问适合您平台的Docker下载)

下载并运行 Jenkins

  1. 下载 Jenkins.

  2. 打开终端进入到下载目录.

  3. 运行命令 java -jar jenkins.war --httpPort=8080.

  4. 打开浏览器进入链接 http://localhost:8080.

  5. 按照说明完成安装.

安装完成后,您可以开始使用 Jenkins!

 

创建您的第一个Pipeline

Table of Contents

什么是 Jenkins Pipeline?

Jenkins Pipeline(或简称为 "Pipeline")是一套插件,将持续交付的实现和实施集成到 Jenkins 中。

持续交付 Pipeline 自动化的表达了这样一种流程:将基于版本控制管理的软件持续的交付到您的用户和消费者手中。

Jenkins Pipeline 提供了一套可扩展的工具,用于将“简单到复杂”的交付流程实现为“持续交付即代码”。Jenkins Pipeline 的定义通常被写入到一个文本文件(称为 Jenkinsfile )中,该文件可以被放入项目的源代码控制库中。 [1]]

Pipeline 和 Jenkinsfile 的更多相关信息,请参考用户手册中的相关链接 Pipeline使用 Jenkinsfile

快速开始使用 Pipeline:

  1. 以下示例 复制到您的仓库中并命名为 Jenkinsfile

  2. 单击Jenkins中的 New Item 菜单 Classic UI left column

  3. 为您的新工程起一个名字 (例如 My Pipeline) ,选择 Multibranch Pipeline

  4. 单击 Add Source 按钮,选择您想要使用的仓库类型并填写详细信息.

  5. 单击 Save 按钮,观察您的第一个Pipeline运行!

您可能需要修改 Jenkinsfile 以便应用在您自己的项目中。尝试修改 sh 命令,使其与您本地运行的命令相同。

在配置好 Pipeline 之后,Jenkins 会自动检测您仓库中创建的任何新的分支或合并请求, 并开始为它们运行 Pipelines。

继续学习 "执行多个步骤"

快速开始示例

下面是一个简单的 Pipeline 各种语言的复制和粘贴示例。

Java

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent { docker 'maven:3.3.3' }
   stages {
       stage('build') {
           steps {
               sh 'mvn --version'
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)

Node.js / JavaScript

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent { docker 'node:6.3' }
   stages {
       stage('build') {
           steps {
               sh 'npm --version'
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)

Ruby

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent { docker 'ruby' }
   stages {
       stage('build') {
           steps {
               sh 'ruby --version'
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)

Python

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent { docker 'python:3.5.1' }
   stages {
       stage('build') {
           steps {
               sh 'python --version'
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)

PHP

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent { docker 'php' }
   stages {
       stage('build') {
           steps {
               sh 'php --version'
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)


继续学习“运行多重步骤 steps”


反馈修改意见?


1. https://en.wikipedia.org/wiki/Source_control_management[Source Control Management

执行多个步骤(step)

Table of Contents

Pipelines 由多个步骤(step)组成,允许你构建、测试和部署应用。 Jenkins Pipeline 允许您使用一种简单的方式组合多个步骤, 以帮助您实现多种类型的自动化构建过程。

可以把“步骤(step)”看作一个执行单一动作的单一的命令。 当一个步骤运行成功时继续运行下一个步骤。 当任何一个步骤执行失败时,Pipeline 的执行结果也为失败。

当所有的步骤都执行完成并且为成功时,Pipeline 的执行结果为成功。

Linux、BSD 和 Mac OS

在 Linux、BSD 和 Mac OS(类 Unix ) 系统中的 shell 命令, 对应于 Pipeline 中的一个 sh 步骤(step)。

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent any
   stages {
       stage('Build') {
           steps {
               sh 'echo "Hello World"'
               sh '''
                   echo "Multiline shell steps works too"
                   ls -lah
               '''
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)

Windows

基于 Windows 的系统使用 bat 步骤表示执行批处理命令。

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent any
   stages {
       stage('Build') {
           steps {
               bat 'set'
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)

超时、重试和更多

Jenkins Pipeline 提供了很多的步骤(step),这些步骤可以相互组合嵌套,方便地解决像重复执行步骤直到成功(重试)和如果一个步骤执行花费的时间太长则退出(超时)等问题。

Jenkinsfile (Declarative Pipeline)

pipeline {
   agent any
   stages {
       stage('Deploy') {
           steps {
               retry(3) {
                   sh './flakey-deploy.sh'
              }

               timeout(time: 3, unit: 'MINUTES') {
                   sh './health-check.sh'
              }
          }
      }
  }
}

Toggle Scripted Pipeline (Advanced)

“Deploy”阶段(stage)重复执行 flakey-deploy.sh 脚本3次,然后等待 health-check.sh 脚本最长执行3分钟。 如果 health-check.sh 脚本在 3 分钟内没有完成,Pipeline 将会标记在“Deploy”阶段失败。

内嵌类型的步骤,例如 timeoutretry 可以包含其他的步骤,包括 timeoutretry

我们也可以组合这些步骤。例如,如果我们想要重试部署任务 5 次,但是总共花费的时间不能超过 3 分钟。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                timeout(time: 3, unit: 'MINUTES') {
                    retry(5) {
                        sh './flakey-deploy.sh'
                    }
                }
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

完成时动作

当 Pipeline 运行完成时,你可能需要做一些清理工作或者基于 Pipeline 的运行结果执行不同的操作, 这些操作可以放在 post 部分。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh 'echo "Fail!"; exit 1'
            }
        }
    }
    post {
        always {
            echo 'This will always run'
        }
        success {
            echo 'This will run only if successful'
        }
        failure {
            echo 'This will run only if failed'
        }
        unstable {
            echo 'This will run only if the run was marked as unstable'
        }
        changed {
            echo 'This will run only if the state of the Pipeline has changed'
            echo 'For example, if the Pipeline was previously failing but is now successful'
        }
    }
}

Toggle Scripted Pipeline (Advanced)


完成定义多个步骤(step)的基本学习之后,我们 继续学习“定义执行环境”

定义执行环境

上一小节 您可能已经注意到每个示例中的 agent 指令。 agent 指令告诉Jenkins在哪里以及如何执行Pipeline或者Pipeline子集。 正如您所预料的,所有的Pipeline都需要 agent 指令。

在执行引擎中,agent 指令会引起以下操作的执行:

  • 所有在块block中的步骤steps会被Jenkins保存在一个执行队列中。 一旦一个执行器 executor 是可以利用的,这些步骤将会开始执行。

  • 一个工作空间 workspace 将会被分配, 工作空间中会包含来自远程仓库的文件和一些用于Pipeline的工作文件

在Pipeline中可以使用这几种 定义代理的方式 在本导读中,我们仅使用Docker容器的代理方式。

在Pipeline中可以很容易的运行 Docker 镜像和容器。 Pipeline可以定义命令或者应用运行需要的环境和工具, 不需要在执行代理中手动去配置各种各样的系统工具和依赖。 这种方式可以让你使用 Docker容器工具包 中的任何工具。

agent 指令更多选项和相关信息,可以查看 语法参考

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent {
        docker { image 'node:7-alpine' }
    }
    stages {
        stage('Test') {
            steps {
                sh 'node --version'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

当执行Pipeline时,Jenkins将会自动运行指定的容器,并执行Pipeline中已经定义好的步骤steps:

[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] sh
[guided-tour] Running shell script
+ node --version
v7.4.0
[Pipeline] }
[Pipeline] // stage
[Pipeline] }

在Pipeline中,混合和搭配不同的容器或者其他代理可以获得更大的灵活性。 更多配置选项和信息,可以参考 继续“使用环境变量”

使用环境变量

Table of Contents

环境变量可以像下面的示例设置为全局的,也可以是阶段(stage)级别的。 如你所想,阶段(stage)级别的环境变量只能在定义变量的阶段(stage)使用。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any

    environment {
        DISABLE_AUTH = 'true'
        DB_ENGINE    = 'sqlite'
    }

    stages {
        stage('Build') {
            steps {
                sh 'printenv'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

这种在 Jenkinsfile 中定义环境变量的方法对于指令性的脚本定义非常有用方便, 比如 Makefile 文件,可以在 Pipeline 中配置构建或者测试的环境,然后在 Jenkins 中运行。

环境变量的另一个常见用途是设置或者覆盖构建或测试脚本中的凭证。 因为把凭证信息直接写入 Jenkinsfile 很显然是一个坏主意, Jenkins Pipeline 允许用户快速安全地访问在 Jenkinsfile 中预定义的凭证信息,并且无需知道它们的值。

环境变量中的凭证信息

更多信息参考 用户手册 中的 凭证信息处理

继续学习“记录测试和构建结果”

 

记录测试和构建结果

虽然测试是良好的持续交付过程中的关键部分,但大多数人并不希望筛选数千行控制台输出来查找有关失败测试的信息。 为了简化操作,只要您的测试运行时可以输出测试结果文件,Jenkins 就可以记录和汇总这些测试结果。 Jenkins 通常与 junit 步骤捆绑在一起,但如果您的测试运行结果无法输出 JUnit 样式的 XML 报告, 那么还有其他插件可以处理任何广泛使用的测试报告格式。

为了收集我们的测试结果,我们将使用 post 部分。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh './gradlew check'
            }
        }
    }
    post {
        always {
            junit 'build/reports/**/*.xml'
        }
    }
}

Toggle Scripted Pipeline (Advanced)

这将会获得测试结果,Jenkins 会持续跟踪并计算测试的趋势和结果。 如果存在失败的测试用例,Pipeline 会被标记为 “UNSTABLE”,在网页上用黄色表示, 这不同于使用红色表示的 “FAILED” 失败状态。

当出现测试失败时,通常可以从 Jenkins 中获取构建结果报告进行本地分析和测试。 Jenkins 内置支持存储构建结果报告,在 Pipeline 执行期间生成记录文件。

通过 archiveArtifacts 步骤和文件匹配表达式可以很容易的完成构建结果记录和存储, 如下例所示:

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh './gradlew build'
            }
        }
        stage('Test') {
            steps {
                sh './gradlew check'
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: 'build/libs/**/*.jar', fingerprint: true
            junit 'build/reports/**/*.xml'
        }
    }
}

Toggle Scripted Pipeline (Advanced)

如果在 archiveArtifacts 步骤中指定了多个参数, 那么每个参数的名称必须在步骤代码中明确指定, 即文件的路径、文件名和 fingerprint 三个参数。 如果您只需指定文件的路径和文件名, 那么你可以省略参数名称 artifacts ,例如: archiveArtifacts 'build/libs/**/*.jar'

在 Jenkins 中记录测试和构建结果非常有助于向团队成员快速提供相关信息。 在下一节,我们将会展示如何通知团队成员在我们的 Pipeline 中所发生的事情。

继续学习“清理和通知”

 

清理和通知

因为 post 部分保证在 Pipeline 结束的时候运行, 所以我们可以添加通知或者其他的步骤去完成清理、通知或者其他的 Pipeline 结束任务。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('No-op') {
            steps {
                sh 'ls'
            }
        }
    }
    post {
        always {
            echo 'One way or another, I have finished'
            deleteDir() /* clean up our workspace */
        }
        success {
            echo 'I succeeeded!'
        }
        unstable {
            echo 'I am unstable :/'
        }
        failure {
            echo 'I failed :('
        }
        changed {
            echo 'Things were different before...'
        }
    }
}

Toggle Scripted Pipeline (Advanced)

有很多方法可以发送通知, 下面是一些示例展示了如何通过电子邮件、Hipchat room 或者 Slack channel 发送 Pipeline 的相关信息。

电子邮件

post {
    failure {
        mail to: 'team@example.com',
             subject: "Failed Pipeline: ${currentBuild.fullDisplayName}",
             body: "Something is wrong with ${env.BUILD_URL}"
    }
}

Hipchat

post {
    failure {
        hipchatSend message: "Attention @here ${env.JOB_NAME} #${env.BUILD_NUMBER} has failed.",
                    color: 'RED'
    }
}

Slack

post {
    success {
        slackSend channel: '#ops-room',
                  color: 'good',
                  message: "The pipeline ${currentBuild.fullDisplayName} completed successfully."
    }
}

当 Pipeline 失败、不稳定甚至是成功时,团队都会收到通知, 现在我们可以继续完成我们的持续交付 Pipeline 激动人心的部分:部署!

继续“部署”

部署

Table of Contents

大多数最基本的持续交付 Pipeline 至少会有三个阶段:构建、测试和部署,这些阶段被定义在 Jenkinsfile 中。 这一小节我们将主要关注部署阶段,但应该指出稳定的构建和测试阶段是任何部署活动的重要前提。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building'
            }
        }
        stage('Test') {
            steps {
                echo 'Testing'
            }
        }
        stage('Deploy') {
            steps {
                echo 'Deploying'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

阶段即为部署环境

一个常见的模式是扩展阶段的数量以获取额外的部署环境信息, 如 “staging” 或者 “production”,如下例所示。

stage('Deploy - Staging') {
    steps {
        sh './deploy staging'
        sh './run-smoke-tests'
    }
}
stage('Deploy - Production') {
    steps {
        sh './deploy production'
    }
}

在这个示例中,我们假定 ./run-smoke-tests 脚本所运行的冒烟测试足以保证或者验证可以发布到生产环境。 这种可以自动部署代码一直到生产环境的 Pipeline 可以认为是“持续部署”的一种实现。 虽然这是一个伟大的想法,但是有很多理由表明“持续部署”不是一种很好的实践, 即便如此,这种方式仍然可以享有“持续交付”带来的好处。 [1] Jenkins Pipeline可以很容易支持两者。

人工确认

通常在阶段之间,特别是不同环境阶段之间,您可能需要人工确认是否可以继续运行。 例如,判断应用程序是否在一个足够好的状态可以进入到生产环境阶段。 这可以使用 input 步骤完成。 在下面的例子中,“Sanity check” 阶段会等待人工确认,并且在没有人工确认的情况下不会继续执行。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        /* "Build" and "Test" stages omitted */

        stage('Deploy - Staging') {
            steps {
                sh './deploy staging'
                sh './run-smoke-tests'
            }
        }

        stage('Sanity check') {
            steps {
                input "Does the staging environment look ok?"
            }
        }

        stage('Deploy - Production') {
            steps {
                sh './deploy production'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

结论

本导读向您介绍了 Jenkins 和 Jenkins Pipeline 的基本使用。 由于 Jenkins 是非常容易扩展的,它可以被修改和配置去处理任何类型的自动化。 关于 Jenkins 可以做什么的更多相关信息,可以参考 用户手册, Jenkins 最新事件、教程和更新可以访问 Jenkins 博客


反馈修改意见?


1. en.wikipedia.org/wiki/Continuous_delivery

改善此页 | 网页记录

img

本网站的内容基于 Creative Commons Attribution-ShareAlike 4.0 License 许可.

资源
解决方案

教程概览

Jenkins 用户文档的这一部分包含一系列的入门教程帮你使用 Jenkins 以自动化的方式开始构建你的应用程序。

如果你是一个想要提高对持续集成(CI) / 持续交付 (CD) 概念的理解的开发者, 或者你已经对这些概念很熟悉 但不知道如何使用Jenkins去实现, 那就从这些教程开始学习吧。

入门教程

本教程展示如何使用 Jenkins 涉及到基于特定的技术栈的CI/CD 概念的基础。

选择与你的技术栈有关或你最熟悉的一个教程:

本教程展示 如何使用 Jenkins 的关键特性 (比如 Blue Ocean) 帮助实现 CI/CD 进程来构建你的应用:

高级教程

该教程展示 Jenkins 更高级的特性和如何管理你的更复杂更灵活的流水线项目。

  • 构建多分支流水线项目

    使用Maven构建Java应用程序

    Table of Contents

    本教程将向你展示如何使用Jenkins编排并构建一个使用Maven管理的简单Java应用程序。

    如果你是使用Maven的Java开发人员,并且对CI/CD概念不熟悉,或者你可能熟悉这些概念,但不知道如何使用Jenkins实现构建应用程序,那么本教程适合你。

    你将在Github示例仓库中获取一个输出"Hello world!"字符串的简单Java应用,该应用还包含若干单元测试,用于检查main方法。 测试结果保存在JUnit XML报告中。

    耗时: 假如你的机器符合配置要求,完成本教程需要20-40分钟。准确的耗时取决于你机器的性能, 以及你是否完成过在Docker中运行Jenkins教程,请参考另一个教程.

    你可以在任何时候停止本教程,并从你离开的地方继续。

    若你已经完成了另一个教程,可以跳过配置要求在Docker中运行Jenkins章节, 继续阅读fork示例仓库(确保你本地安装了Git)。 如果你需要重启Jenkins,请参考停止和重启Jenkins.

    配置要求

    对于本教程,您将需要:

    • 安装有macOS,Linux或Windows操作系统的机器,并拥有以下配置:

      • 最小256MB内存, 推荐512MB以上。

      • 10GB硬盘空间, 用于安装Jenkins,您的Docker镜像和容器。

    • 安装有以下软件:

      • Docker - 在安装Jenkins页面的安装Docker章节阅读更多信息。 注意: 如果您使用Linux,本教程假定您没有以root用户的身份运行Docker命令,而是使用单个用户帐户访问本教程中使用的其他工具。

      • GitGitHub Desktop.

    在 Docker中运行Jenkins

    在本教程中, 将Jenkins作为 Docker 容器并从 jenkinsci/blueocean Docker 镜像中运行。

    要在 Docker中运行Jenkins, 请遵循下面的macOS 和 LinuxWindows相关文档说明进行操作。 .

    你可以在 DockerInstalling Jenkins 页面的 Downloading and running Jenkins in Docker部分阅读更多有关Docker容器和镜像概念的信息。

    在 macOS 和 Linux 系统上

    1. 打开终端窗口

    2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

      docker run \
        --rm \
        -u root \
        -p 8080:8080 \
        -v jenkins-data:/var/jenkins_home \ 
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v "$HOME":/home \ 
        jenkinsci/blueocean
      
       将容器中的 /var/jenkins_home 目录映射到 Docker volume ,并将其命名为 jenkins-data。如果该卷不存在, 那么 docker run 命令会自动为你创建卷。
        将主机上的$HOME 目录 (即你的本地)映射到 (通常是 /Users/ 目录) 到容器的 /home 目录。

      Note: 如果复制或粘贴上面的命令片段不起作用, 尝试复制和粘贴这个没有注释的版本:

      docker run \
        --rm \
        -u root \
        -p 8080:8080 \
        -v jenkins-data:/var/jenkins_home \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v "$HOME":/home \
        jenkinsci/blueocean
      
    3. 继续 安装向导

    在 Windows 系统

    1. 打开命令提示窗口。

    2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

      docker run ^
        --rm ^
        -u root ^
        -p 8080:8080 ^
        -v jenkins-data:/var/jenkins_home ^
        -v /var/run/docker.sock:/var/run/docker.sock ^
        -v "%HOMEPATH%":/home ^
        jenkinsci/blueocean
      

      对这些选项的解释, 请参考上面的 macOS 和 Linux 说明。

    3. 继续安装向导

    访问 Jenkins/Blue Ocean Docker 容器

    如果你有一些使用 Docker 的经验,希望或需要使用 docker exec 命令通过一个终端/命令提示符来访问 Jenkins/Blue Ocean Docker 容器, 你可以添加如 --name jenkins-tutorials 选项(与上面的 docker run ), 这将会给Jenkins/Blue Ocean Docker容器一个名字 "jenkins-tutorials"。

    这意味着你可以通过 docker exec 命令访问Jenkins/Blue Ocean 容器(通过一个单独的终端 /命令提示窗口) ,例如:

    docker exec -it jenkins-tutorials bash
    

    安装向导

    在你访问 Jenkins之前, 你需要执行一些快速的 "一次性" 步骤。

    解锁 Jenkins

    当你第一次访问一个新的 Jenkins 实例时, 要求你使用自动生成的密码对其进行解锁。

    1. 当在终端/命令提示窗口出现两组星号时, 浏览 http://localhost:8080 并等待 Unlock Jenkins 页面出现。

      Unlock Jenkins page

    2. 再次从终端/命令提示窗口, 复制自动生成的字母数字密码(在两组星号之间)。 Copying initial admin password

    3. Unlock Jenkins 页面, 粘贴该密码到 Administrator password 字段并点击 Continue

    使用插件自定义 Jenkins

    解锁 Jenkins后, Customize Jenkins 页面出现。

    在该页面,点击 Install suggested plugins

    安装向导显示了正在配置的Jenkins的进程,以及建议安装的插件。这个过程肯需要几分钟。

    创建第一个管理员用户

    最后, Jenkins 要求创建你的第一个管理员用户。

    1. Create First Admin User 页面出现, 在相应的字段中指定你的详细消息并点击 Save and Finish

    2. Jenkins is ready 页面出现, 点击 Start using Jenkins Notes:

      • 该页面可能表明 Jenkins is almost ready! 如果相反, 点击 Restart.

      • 如果该页面在一分钟后没有自动刷新, 使用你的web浏览器手动刷新。

    3. 如果需要,登录 Jenkins , 你就可以开始使用 Jenkins了!

    停止和重启 Jenkins

    在本教程的其余部分, 你可以通过在终端/命令提示窗口输入 Ctrl-C停止 Jenkins/Blue Ocean Docker 容器,你可以从中运行<>的 docker run ... 命令。

    要重启Jenkins/Blue Ocean Docker 容器:

    1. 在上面的 macOS,LinuxWindows上运行相同的 docker run ... 命令 。 Note: 如果有更新的话,该进程会更新 jenkinsci/blueocean Docker 镜像。

    2. 浏览http://localhost:8080

    3. 等待直到登录页面出现并登陆。

    Fork 和 clone GitHub示例仓库

    通过将应用程序源代码所在的示例仓库fork到你自己的Github账号中, 并clone到本地,你就可以获取一个"Hello world!"简单Java应用程序。

    1. 请确保你登陆了你的GitHub账户。如果你还没有Github账户,你可以在 GitHub网站 免费注册一个账户。

    2. 将示例仓库 simple-java-maven-app fork到你的账户的Github仓库中。在此过程中,如果你需要帮助,请参考 Fork A Repo 文档。

    3. 将你的GitHub账户中的 simple-java-maven-app 仓库clone到你的本地机器。 根据你的情况完成以下步骤之一(其中 `` 是你的操作系统用户账户名称):

      • 如果你的机器安装了Github Desktop:

        1. 在GitHub网站上,点击绿色的 Clone or download 按钮,再点击 Open in Desktop.

        2. 在Github桌面版中,在点击 Clone a Repository 对话框上的 Clone 按钮之前,确保 Local Path 的配置为:

          • macOS 系统配置为 /Users//Documents/GitHub/simple-java-maven-app

          • Linux 系统配置为 /home//GitHub/simple-java-maven-app

          • Windows 系统配置为 C:\Users\\Documents\GitHub\simple-java-maven-app

      • 其他情况:

        1. 打开一个终端/命令提示符,并且 cd 进入正确的目录路径:

          • macOS 系统路径为 /Users//Documents/GitHub/

          • Linux 系统路径为 /home//GitHub/

          • Windows 系统路径为 C:\Users\\Documents\GitHub\ (推荐使用Git bash命令行,而不是通常的Microsoft命令提示符)

        2. 运行以下命令完成仓库的clone: git clone https://github.com/YOUR-GITHUB-ACCOUNT-NAME/simple-java-maven-app 其中 YOUR-GITHUB-ACCOUNT-NAME 是你的Github账户的名称。

    在Jenkins中创建你的流水线项目

    1. 回到Jenkins,如果有必要的话重新登录,点击 Welcome to Jenkins! 下方的 create new jobs 注意: 如果你无法看见以上内容,点击左上方的 New Item

    2. Enter an item name 域中,为新的流水线项目指定名称(例如 simple-java-maven-app)。

    3. 向下滚动并单击 Pipeline,然后单击页面末尾的 OK

    4. 可选 ) 在下一页中,在 Description 字段中填写流水线的简要描述 (例如 一个演示如何使用Jenkins构建Maven管理的简单Java应用程序的入门级流水线。

    5. 点击页面顶部的 Pipeline 选项卡,向下滚动到 Pipeline 部分。

    6. Definition 域中,选择 Pipeline script from SCM 选项。此选项指示Jenkins从源代码管理(SCM)仓库获取你的流水线, 这里的仓库就是你clone到本地的Git仓库。

    7. SCM 域中,选择 Git

    8. Repository URL 域中,填写你本地仓库的 目录路径, 这是从你主机上的用户账户home目录映射到Jenkins容器的 /home 目录:

      • MacOS系统 - /home/Documents/GitHub/simple-java-maven-app

      • Linux系统 - /home/GitHub/simple-java-maven-app

      • Windows系统 - /home/Documents/GitHub/simple-java-maven-app

    9. 点击 Save 保存你的流水线项目。你现在可以开始创建你的 Jenkinsfile,这些文件会被添加到你的本地仓库。

    将你的初始流水线创建为Jenkinsfile

    现在你已准备好创建你的流水线,它将使用Jenkins中的Maven自动构建你的Java应用程序。 你的流水线将被创建为 Jenkinsfile,它将被提交到你本地的Git仓库(simple-java-maven-app)。

    这是 "Pipeline-as-Code" 的基础,它将持续交付流水线作为应用程序的一部分,与其他代码一样进行版本控制和审查。 阅读更多关于 流水线 的信息,以及用户手册中的 使用Jenkinsfile 章节。

    首先,创建一个初始流水线来下载Maven Docker镜像,并将其作为Docker容器运行(这将构建你的简单Java应用)。 同时添加一个“构建”阶段到流水线中,用于协调整个过程。

    1. 使用你最称手的文本编辑器或者IDE,在你本地的 simple-java-maven-app Git仓库的根目录创建并保存一个名为 Jenkinsfile 的文本文件。

    2. 复制以下声明式流水线代码并粘贴到 Jenkinsfile 文件中:

      pipeline {
          agent {
              docker {
                  image 'maven:3-alpine' 
                  args '-v /root/.m2:/root/.m2' 
              }
          }
          stages {
              stage('Build') { 
                  steps {
                      sh 'mvn -B -DskipTests clean package' 
                  }
              }
          }
      }
      
       这里的 image 参数(参考 agent 章节的 docker 参数) 是用来下载 maven:3-apline Docker镜像 (如果你的机器还没下载过它)并将该镜像作为单独的容器运行。这意味着:你将在Docker中本地运行相互独立的Jenkins和Maven容器。Maven容器成为了Jenkins用来运行你的流水线项目的 agent。 这个容器寿命很短——它的寿命只是你的流水线的执行时间。
        这里的 args 参数在暂时部署的Maven Docker容器的 /root/.m2 (即Maven仓库)目录 和Docker主机文件系统的对应目录之间创建了一个相互映射。这背后的实现细节超出了本教程的范围,在此不做解释。 但是,这样做的主要原因是,在Maven容器的生命周期结束后,构建Java应用程序所需的工件 (Maven在流水线执行时进行下载)能够保留在Maven存储库中。这避免了在后续的流水线执行过程中, Maven反复下载相同的工件。请注意,不同于你为 jenkins-data 创建的Docker数据卷,Docker主机的文件系统在每次重启Docker时都会被清除。 这意味着每次Docker重新启动时,都会丢失下载的Maven仓库工件。
        定义了一个名为 Buildstage,之后会出现在Jenkins UI上。
        这里的 sh step(参考 steps 章节)运行Maven命令干净地构建你的Java应用(不运行任何tests)。
    3. 保存对 Jenkinsfile 的修改并且将其提交到你本地的 simple-java-maven-app Git仓库。例如,在 simple-java-maven-app 目录下,运行以下命令: git add . 继续运行 git commit -m "Add initial Jenkinsfile"

    4. 再次回到Jenkins,如果有必要的话重新登录,点击左侧的 Open Blue Ocean 进入Jenkins的Blue Ocean界面。

    5. This job has not been run 消息框中,点击 Run,然后快速点击右下角出现的 OPEN 链接, 观察Jenkins运行你的流水线项目。如果你不能点击 OPEN 链接,点击Blue Ocean主界面的一行来使用这一特性。 注意: 你可能需要几分钟时间等待第一次运行完成。在clone了你的本地 simple-java-maven-app Git仓库后, Jenkins接下来做了以下动作:

      1. 将项目排入队列等待在agent上运行。

      2. 下载Maven Docker镜像,并且将其运行在Docker中的一个容器中。

        Downloading Maven Docker image

      3. 在Maven容器中运行 Build 阶段 (Jenkinsfile 中所定义的)。在这期间,Maven会下载构建你的Java应用所需的工件, 这些工件最终会被保存在Jenkins的本地Maven仓库中(Docker的主机文件系统)。

        Downloading Maven artifacts

      若Jenkins成功构建了你的Java应用,Blue Ocean界面会变为绿色。

      Initial Pipeline runs successfully

    6. 点击右上方的 X 回到Blue Ocean主界面。

      Main Blue Ocean interface

    为你的流水线增加test阶段

    1. 回到你的文本编辑器/IDE,打开你的 Jenkinsfile

    2. 复制以下声明式流水线代码,并粘贴到 JenkinsfileBuild 阶段的下方:

              stage('Test') {
                  steps {
                      sh 'mvn test'
                  }
                  post {
                      always {
                          junit 'target/surefire-reports/*.xml'
                      }
                  }
              }
      

      最终的代码为:

      pipeline {
          agent {
              docker {
                  image 'maven:3-alpine'
                  args '-v /root/.m2:/root/.m2'
              }
          }
          stages {
              stage('Build') {
                  steps {
                      sh 'mvn -B -DskipTests clean package'
                  }
              }
              stage('Test') { 
                  steps {
                      sh 'mvn test' 
                  }
                  post {
                      always {
                          junit 'target/surefire-reports/*.xml' 
                      }
                  }
              }
          }
      }
      
       定义了一个名为 Teststage,之后会出现在Jenkins UI上。
        这里的 sh step (参考 steps 章节)执行Maven命令来运行你的Java应用的单元测试。 这个命令还生成一个JUnit XML报告,保存在 target/surefire-reports 目录 (位于Jenkins容器中的 /var/jenkins_home/workspace/simple-java-maven-app 目录)。
        这里的 junit step (由 JUnit Plugin 提供)用于归档JUnit XML报告(由上面的 mvn test 命令生成) 并通过Jenkins接口公开结果。在Blue Ocean中,可以在流水线运行的 Tests 页面获取结果。 post 章节的 always 条件包含了这个 junit step, 保证了这个step 总是Test 阶段 结束后 执行,不论该阶段的运行结果如何。
    3. 保存对 Jenkinsfile 的修改并将其提交到你的本地 simple-java-maven-app Git仓库。例如,在 simple-java-maven-app 目录下,运行以下命令: git stage . 继续运行 git commit -m "Add 'Test' stage"

    4. 再次回到Jenkins,如果有必要的话重新登录,进入Jenkins的Blue Ocean界面。

    5. 点击左上方的 Run 然后快速点击右下方出现的 OPEN 链接, 观察Jenkins运行你修改过的流水线项目。 如果你不能点击 OPEN 链接,点击Blue Ocean主界面的 top 行来使用这一特性。 注意: 你会发现本次运行Jenkins不再需要下载Maven Docker镜像。Jenkins只需要从之前下载的Maven镜像运行 一个新的容器。另外,如果最近一次运行 流水线 后,Docker没有重启, 那么在 "Build" 阶段无需下载Maven工件。因此,你的流水线再次运行时速度会更快。 如果你修改过的流水线运行成功,Blue Ocean界面看起来会像下面这样。注意增加的 "Test" 阶段。 你可以点击之前的 "Build" 阶段来获取阶段输出结果。

      Test stage runs successfully (with output)

    6. 点击右上方的 X 回到Blue Ocean主界面。

    为你的流水线增加deliver阶段

    1. 回到你的文本编辑器/IDE,打开你的 Jenkinsfile

    2. 复制以下声明式流水线代码,并粘贴到 JenkinsfileTest 阶段的下方:

              stage('Deliver') {
                  steps {
                      sh './jenkins/scripts/deliver.sh'
                  }
              }
      

      最终的代码为:

      pipeline {
          agent {
              docker {
                  image 'maven:3-alpine'
                  args '-v /root/.m2:/root/.m2'
              }
          }
          stages {
              stage('Build') {
                  steps {
                      sh 'mvn -B -DskipTests clean package'
                  }
              }
              stage('Test') {
                  steps {
                      sh 'mvn test'
                  }
                  post {
                      always {
                          junit 'target/surefire-reports/*.xml'
                      }
                  }
              }
              stage('Deliver') { 
                  steps {
                      sh './jenkins/scripts/deliver.sh' 
                  }
              }
          }
      }
      
       定义了一个名为 Deliver 的stage,之后会出现在Jenkins UI上。
        这里的 sh step (参考 steps 章节)执行位于 jenkins/scripts 目录下的shell脚本 deliver.sh, 该目录位于 simple-java-maven-app 仓库根目录下。deliver.sh 文件所做动作包含在其自身文本内容中。 一般的原则是,尽量保持你的流水线代码(即 Jenkinsfile)越简洁越好,将更复杂的构建步骤放在多个独立的shell脚本中 (尤其对于那些包含2个以上steps的stage)。这最终会使得维护你的流水线代码变得更容易,特别是当你的流水线变得越来越复杂的时候。
    3. 保存对 Jenkinsfile 的修改并将其提交到你的本地 simple-java-maven-app Git仓库。例如,在 simple-java-maven-app 目录下,运行以下命令: git stage . 继续运行 git commit -m "Add 'Deliver' stage"

    4. 再次回到Jenkins,如果有必要的话重新登录,进入Jenkins的Blue Ocean界面。

    5. 点击左上方的 Run 然后快速点击右下方出现的 OPEN 链接, 观察Jenkins运行你修改过的流水线项目。 如果你不能点击 OPEN 链接,点击Blue Ocean主界面的 top 行来使用这一特性。 如果你修改过的流水线运行成功,Blue Ocean界面看起来会像下面这样。注意增加的 "Deliver" 阶段。 你可以点击之前的 "Test" 和 "Build" 阶段来获取阶段输出结果。

      Deliver stage runs successfully

      以下是 "Deliver" 阶段的输出应该是什么样子,向你展示最终Java应用程序的执行结果。

      Deliver stage output only

    6. 点击右上方的 X 回到Blue Ocean主界面,列表显示流水线历史运行记录,按时间顺序倒序排列。 Main Blue Ocean interface with all previous runs displayed

    总结

    做得好!您刚刚使用Jenkins用Maven构建了一个简单的Java应用程序!

    您在上面创建的 "Build", "Test" 和 "Deliver" 阶段是使用Jenkins中的Maven构建更复杂的Java应用程序的基础,以及与其他技术栈集成的Java和Maven应用程序。

    由于Jenkins具有极高的可扩展性,因此可以对其进行修改和配置,以处理构建协调和自动化的几乎任何方面。

    要详细了解Jenkins可以做什么,请查看:

    使用npm构建Node.js和React应用

    Table of Contents

    本教程将展示Jenkins如何使用 Node Package Manager (npm)去组合构建简单的 Node.jsReact 应用 .

    如果你是一个对CI/CD概念不了解的 Node.js 和 React 开发者, 或者你熟悉这些概念却不知道如何使用Jenkins完成构建,那么本教程很适合你。 示例Node.js和React(你可以从示例仓库中获取)生成一个网页,该网页含有 "Welcome to React" 内容且伴随有一个检查应用程序满意度的测试。

    耗时: 本教程需要 20-40 分钟来完成 (假设你的机器已经满足 配置要求 ). 确切的耗时取决于你机器的性能, 以及你是否完成过在Docker中运行Jenkins 请参考:..[另一个教程]。

    你可以在任何时候停止本教程,并从你离开的地方继续。

    若你已经完成了另一个教程,可以跳过配置要求在Docker中运行Jenkins章节, 继续阅读fork示例仓库(确保你本地安装了Git)。 如果你需要重启Jenkins,请参考停止和重启Jenkins.

    配置要求

    对于本教程,您将需要:

    • 安装有macOS,Linux或Windows操作系统的机器,并拥有以下配置:

      • 最小256MB内存, 推荐512MB以上。

      • 10GB硬盘空间, 用于安装Jenkins,您的Docker镜像和容器。

    • 安装有以下软件:

      • Docker - 在安装Jenkins页面的安装Docker章节阅读更多信息。 注意: 如果您使用Linux,本教程假定您没有以root用户的身份运行Docker命令,而是使用单个用户帐户访问本教程中使用的其他工具。

      • Git 和 optionally GitHub Desktop.

    在 Docker中运行Jenkins

    在本教程中, 将Jenkins作为 Docker 容器并从 jenkinsci/blueocean Docker 镜像中运行。

    要在 Docker中运行Jenkins, 请遵循下面的macOS 和 LinuxWindows相关文档说明进行操作。 .

    你可以在 DockerInstalling Jenkins 页面的 Downloading and running Jenkins in Docker部分阅读更多有关Docker容器和镜像概念的信息。

    在 macOS 和 Linux 系统上

    1. 打开终端窗口

    2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

      docker run \
        --rm \
        -u root \
        -p 8080:8080 \
        -v jenkins-data:/var/jenkins_home \ 
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v "$HOME":/home \ 
        jenkinsci/blueocean
      
       将容器中的 /var/jenkins_home 目录映射到 Docker volume ,并将其命名为 jenkins-data。如果该卷不存在, 那么 docker run 命令会自动为你创建卷。
        将主机上的$HOME 目录 (即你的本地)映射到 (通常是 /Users/ 目录) 到容器的 /home 目录。

      Note: 如果复制或粘贴上面的命令片段不起作用, 尝试复制和粘贴这个没有注释的版本:

      docker run \
        --rm \
        -u root \
        -p 8080:8080 \
        -v jenkins-data:/var/jenkins_home \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -v "$HOME":/home \
        jenkinsci/blueocean
      
    3. 继续 安装向导

    在 Windows 系统

    1. 打开命令提示窗口。

    2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

      docker run ^
        --rm ^
        -u root ^
        -p 8080:8080 ^
        -v jenkins-data:/var/jenkins_home ^
        -v /var/run/docker.sock:/var/run/docker.sock ^
        -v "%HOMEPATH%":/home ^
        jenkinsci/blueocean
      

      对这些选项的解释, 请参考上面的 macOS 和 Linux 说明。

    3. 继续安装向导

    访问 Jenkins/Blue Ocean Docker 容器

    如果你有一些使用 Docker 的经验,希望或需要使用 docker exec 命令通过一个终端/命令提示符来访问 Jenkins/Blue Ocean Docker 容器, 你可以添加如 --name jenkins-tutorials 选项(与上面的 docker run ), 这将会给Jenkins/Blue Ocean Docker容器一个名字 "jenkins-tutorials"。

    这意味着你可以通过 docker exec 命令访问Jenkins/Blue Ocean 容器(通过一个单独的终端 /命令提示窗口) ,例如:

    docker exec -it jenkins-tutorials bash
    

    安装向导

    在你访问 Jenkins之前, 你需要执行一些快速的 "一次性" 步骤。

    解锁 Jenkins

    当你第一次访问一个新的 Jenkins 实例时, 要求你使用自动生成的密码对其进行解锁。

    1. 当在终端/命令提示窗口出现两组星号时, 浏览 http://localhost:8080 并等待 Unlock Jenkins 页面出现。

      Unlock Jenkins page

    2. 再次从终端/命令提示窗口, 复制自动生成的字母数字密码(在两组星号之间)。 Copying initial admin password

    3. Unlock Jenkins 页面, 粘贴该密码到 Administrator password 字段并点击 Continue

    使用插件自定义 Jenkins

    解锁 Jenkins后, Customize Jenkins 页面出现。

    在该页面,点击 Install suggested plugins

    安装向导显示了正在配置的Jenkins的进程,以及建议安装的插件。这个过程肯需要几分钟。

    创建第一个管理员用户

    最后, Jenkins 要求创建你的第一个管理员用户。

    1. Create First Admin User 页面出现, 在相应的字段中指定你的详细消息并点击 Save and Finish

    2. Jenkins is ready 页面出现, 点击 Start using Jenkins Notes:

      • 该页面可能表明 Jenkins is almost ready! 如果相反, 点击 Restart.

      • 如果该页面在一分钟后没有自动刷新, 使用你的web浏览器手动刷新。

    3. 如果需要,登录 Jenkins , 你就可以开始使用 Jenkins了!

    停止和重启 Jenkins

    在本教程的其余部分, 你可以通过在终端/命令提示窗口输入 Ctrl-C停止 Jenkins/Blue Ocean Docker 容器,你可以从中运行<>的 docker run ... 命令。

    要重启Jenkins/Blue Ocean Docker 容器:

    1. 在上面的 macOS,LinuxWindows上运行相同的 docker run ... 命令 。 Note: 如果有更新的话,该进程会更新 jenkinsci/blueocean Docker 镜像。

    2. 浏览http://localhost:8080

    3. 等待直到登录页面出现并登陆。

    Fork 和 clone GitHub 示例仓库

    通过将应用程序源代码所在的示例仓库fork到你自己的Github账号中, 并clone到本地, 你就可以获取一个"Welcome to React"简单Node.js和React应用程序。

    1. 请确保你登陆了你的GitHub账户。如果你还没有Github账户,你可以在 GitHub网站 免费注册一个账户。.

    2. 将示例仓库 simple-node-js-react-npm-app fork到你的账户的Github仓库中。在此过程中,如果你需要帮助, 请参考 Fork A Repo 文档。

    3. 将你的GitHub账户中的 simple-node-js-react-npm-app 仓库clone到你的本地机器。 根据你的情况完成以下步骤之一(其中 `` 是你的操作系统用户账户名称):

      • 在GitHub网站上,点击绿色的 Clone or download 按钮,再点击 Open in Desktop.

        1. 在Github桌面版中,在点击 Clone a Repository 对话框上的 Clone 按钮之前,确保 Local Path 的配置为:

          • macOS 系统配置为 /Users//Documents/GitHub/simple-node-js-react-npm-app

          • Linux 系统配置为 /home//GitHub/simple-node-js-react-npm-app

          • Windows 配置为 C:\Users\\Documents\GitHub\simple-node-js-react-npm-app

      • 其他情况:

        1. 打开一个终端/命令提示行,并且cd 进入正确的目录:

          • macOS 系统路径为 /Users//Documents/GitHub/

          • Linux 系统路径为 /home//GitHub/

          • Windows 系统路径为 C:\Users\\Documents\GitHub\ (建议使用 Git bash 命令而不是通常的 Microsoft 命令提示符)

        2. 运行以下的命令完成仓库的clone: git clone https://github.com/YOUR-GITHUB-ACCOUNT-NAME/simple-node-js-react-npm-app 其中 YOUR-GITHUB-ACCOUNT-NAME 是你的GitHub账户用户。

    在Jenkins中创建流水线项目

    1. 回到Jenkin,再次登录并点击 Welcome to Jenkins! 下的 create new jobs + Note: 如果没有看到上述内容,请点击左上角的 New Item

    2. Enter an item name 域, 填写你的新的流水线项目的名称 (比如simple-node-js-react-npm-app)。

    3. 向下滚动并单击 Pipeline, 然后点击页面末尾的 OK

    4. ( Optional )在下一页中,在 Description 字域为你的流水线项目做一个简短的描述(比如. An entry-level Pipeline demonstrating how to use Jenkins to build a simple Node.js and React application with npm.)

    5. 点击页面顶部的 Pipeline 选项,向下滚动到 Pipeline 部分.

    6. Definition 域,选择 Pipeline script from SCM 选项。此选项指示Jenkins从源代码管理(SCM)仓库获取你的流水线, 这里的仓库就是你clone到本地的Git仓库。

    7. SCM 域中,选择 Git

    8. Repository URL 域中,填写你本地仓库的 目录路径, 这是从你主机上的用户账户home目录映射到Jenkins容器的 /home 目录:

      • macOS系统 - /home/Documents/GitHub/simple-node-js-react-npm-app

      • Linux系统 - /home/GitHub/simple-node-js-react-npm-app

      • Windows系统 - /home/Documents/GitHub/simple-node-js-react-npm-app

    9. 点击 Save 保存你的流水线项目。你现在可以开始创建你的 Jenkinsfile,这些文件会被添加到你的本地仓库。

    将你的初始流水线创建为Jenkinsfile

    现在你已准备好创建你的流水线,它将使用Jenkins中的Maven自动构建你的Node.js 和 React 应用。 你的流水线将被创建为 Jenkinsfile,它将被提交到你本地的Git仓库(simple-java-maven-app)。

    这是 "Pipeline-as-Code" 的基础,它将持续交付流水线作为应用程序的一部分,与其他代码一样进行版本控制和审查。 了解更多信息请阅读 流水线以及用户手册中的 使用Jenkinsfile 章节。

    首先,创建一个初始流水线来下载 Docker镜像,并将其作为Docker容器运行(这将构建你的简单Java应用)。 同时添加一个“构建”阶段到流水线中,用于协调整个过程。

    1. 使用你最常用的文本编辑器或者IDE,在你本地的 simple-java-maven-app Git仓库的根目录创建并保存一个名为 Jenkinsfile 的文本文件。

    2. 复制以下声明式流水线代码并粘贴到 Jenkinsfile 文件中:

      pipeline {
          agent {
              docker {
                  image 'node:6-alpine' 
                  args '-p 3000:3000' 
              }
          }
          stages {
              stage('Build') { 
                  steps {
                      sh 'npm install' 
                  }
              }
          }
      }
      
       这里的 image 参数(参考 agent 章节的 docker 参数) 是用来下载 maven:3-apline Docker镜像 (如果你的机器还没下载过它)并将该镜像作为单独的容器运行。这意味着:你将在Docker中本地运行相互独立的Jenkins和Node容器。Node容器成为了Jenkins用来运行你的流水线项目的 agent 。然而, 这个容器寿命较短 - 它的寿命周期只是你的流水线执行的持续时间 。
        这里的 args 参数使Node容器(暂时的) 可通过端口3000进行访问。它的意义在于解释你clone的仓库的 jenkins/scripts/deliver.sh 域, 在本教程的后续部分将介绍这一内容。
        定义出现在Jenkins UI中名为Buildstage (指令)
        这里的 sh 步骤 (参考 steps 章节) 执行 npm 命令确保运行你的应用程序的所需的所有依赖被下载到 node_modules 工作区目录 (在Jenkins容器的 /var/jenkins_home/workspace/simple-node-js-react-npm-app 目录中).
    3. 保存并提交你编辑的 Jenkinsfile 到你本地的 simple-node-js-react-npm-app Git 仓库。 比如.在 simple-node-js-react-npm-app 目录中,运行命令: git add . 然后 git commit -m "Add initial Jenkinsfile"

    4. 再次回到Jenkins, 如果有必要的话再次登录,点击左边的 Open Blue Ocean 进入 Jenkins的Blue Ocean 界面.

    5. This job has not been run 消息框, 点击 Run, 然后快速的点击在右下的 OPEN 链接,查看Jenkins构建你的流水线项目. 如果你点击不了 OPEN 链接, 点击Blue Ocean的主界面的一行来使用这一特性。+ Note: 你可能需要几分钟完成第一次的运行。 在clone你本地的 simple-node-js-react-npm-app Git 仓库后, Jenkins进行了以下动作:

      1. 将项目加入队列等待在agent上的运行。 ..下载 Node容器镜像并将它运行在Docker的一个容器中.

        Downloading Node Docker image

      2. 在Node容器中运行 Build 阶段 (在 Jenkinsfile中定义) 。 在这期间, npm 会下载运行你的Nod.js和React应用所需的一些依赖,这些依赖最终会被保存在 node_modules 工作区目录 (在Jenkins的主目录中).

        Downloading <em>npm</em> dependencies

      如果Jenkins成功构建了你的应用,Blue Ocean的界面就会变绿。

      Initial Pipeline runs successfully

    6. 点击右上角的 X 返回到Blue Ocean的主界面.

      Main Blue Ocean interface

    向流水线添加Test阶段

    1. 回到文本编辑器/IDE,打开Jenkinsfile

    2. Jenkinsfileagent部分复制并粘贴下面的声明式语法:

          environment {
              CI = 'true'
          }
      

      以及在 Build 阶段复制并粘贴以下内容 :

              stage('Test') {
                  steps {
                      sh './jenkins/scripts/test.sh'
                  }
              }
      

      最终的代码为:

      pipeline {
          agent {
              docker {
                  image 'node:6-alpine'
                  args '-p 3000:3000'
              }
          }
          environment {
              CI = 'true' 
          }
          stages {
              stage('Build') {
                  steps {
                      sh 'npm install'
                  }
              }
              stage('Test') { 
                  steps {
                      sh './jenkins/scripts/test.sh' 
                  }
              }
          }
      }
      
       这里的 environment 指令 设置环境变量 CI 为布尔值 true, 它对管道中的所有步骤都是有用的。 当 test.shnpm test 命令 (在定义在流水线的下一步的 Test 阶段运行) 检测到环境变量 CI值为 true时, 该命令在 "non-watch" (i.e. non-interactive) 模式下运行。在"watch" 模式下, npm test 期望用户的输入,它能够无限期地停止 CI/CD 应用的运行。 作为在Jenkins的流水线中指定 environment 指令的替代选择, 你也可以在package.json域中指定该环境变量的值(通过 npm test 命令) 通过以下方式:在jenkins/scripts/test.sh 取消 npm install --save-dev cross-env 命令 ( 在Test 阶段安装 cross-env 依赖)。了解更多请参考 test.sh 文件.在 package.json 文件中修改以下行 (在 simple-node-js-react-npm-app 仓库的根目录下) 从"test": "react-scripts test --env=jsdom","test": "cross-env CI=true react-scripts test --env=jsdom",
        定义名为 Teststage (指令), 它出现在Jenkins UI中. <3> sh 步骤 (参考 steps 章节) 运行 shell 脚本 test.sh,该脚本位于 simple-node-js-react-npm-app 仓库的 jenkins/scripts 目录。 test.sh 文件本身对其进行了解释. 在通用原则下, 最好让你的流水线代码 (也就是 Jenkinsfile) 尽可能的整洁,并且将更复杂的构建脚本放在一个独立的像 test.sh 文件一样的shell脚本文件里。这最终会促进你的流水线的维护,尤其是在它更复杂的情况下。
    3. 保存并提交你编辑的 Jenkinsfile 到你本地的 simple-node-js-react-npm-app Git 仓库。比如在 simple-node-js-react-npm-app 仓库, 运行命令: git stage . 然后 git commit -m "Add 'Test' stage"

    4. 再次回到Jenkins , 如果必要的话再次登录并进入 Jenkins的 Blue Ocean 界面。

    5. 点击左上方的 Run , 然后快速的点击出现在右下方的 OPEN 链接 观察 Jenkins 运行你改进之后的流水线项目。如果点击不了 OPEN 链接, 点击Blue Ocean 界面的top 行使用这一特性。 Note: 你在这次运行中会注意到 Jenkins 不再需要下载 Node Docker 镜像。 而是, Jenkins 只需要从之前下载的Node镜像中运行一个新的容器 。 并且, 从现在开始, 在"Build"阶段不再需要下载 (新的) npm 依赖。 因此, 在接下来的时间运行流水线会更快些。 如果改进后的流水线运行成功, Blue Ocean 界面应该是这样的。另外要注意 "Test" 阶段。你可以点击之前的 "Build" 阶段来循环的 访问该阶段的输出。

      Test stage runs successfully (with output)

    6. 点击右上方的 X 回到 Blue Ocean 主界面。

    给流水线添加最终交付阶段

    1. 回到文本编辑器/IDE,打开 Jenkinsfile

    2. JenkinsfileTest 阶段下方复制并粘贴以下的声明式流水线语法:

              stage('Deliver') {
                  steps {
                      sh './jenkins/scripts/deliver.sh'
                      input message: 'Finished using the web site? (Click "Proceed" to continue)'
                      sh './jenkins/scripts/kill.sh'
                  }
              }
      

      最终的代码如下:

      pipeline {
          agent {
              docker {
                  image 'node:6-alpine'
                  args '-p 3000:3000'
              }
          }
          environment { 
              CI = 'true'
          }
          stages {
              stage('Build') {
                  steps {
                      sh 'npm install'
                  }
              }
              stage('Test') {
                  steps {
                      sh './jenkins/scripts/test.sh'
                  }
              }
              stage('Deliver') { 
                  steps {
                      sh './jenkins/scripts/deliver.sh' 
                      input message: 'Finished using the web site? (Click "Proceed" to continue)' 
                      sh './jenkins/scripts/kill.sh' 
                  }
              }
          }
      }
      
       environment 指令 不会出现在你的流水线中,如果你在 package.json above 指定 CI 环境变量。
        定义一个新的 Deliver 阶段,它出现在 Jenkins UI中。
        sh 步骤 (参考 steps 章节) 运行 shell 脚本 deliver.sh,该脚本位于 simple-node-js-react-npm-app 仓库的 jenkins/scripts 目录。 deliver.sh 文件对它进行了解释。
        input 步骤 (由 Pipeline: Input Step 插件提供) 中止运行构建并提示用户(带有自定义消息) 进行或中止。
        sh 步骤运行 shell 脚本 kill.sh, 该脚本也位于 jenkins/scripts 目录。 kill.sh 文件进行了解释。
    3. 保存并提交你编辑的 Jenkinsfile 到你的本地 simple-node-js-react-npm-app Git 仓库. 比如在 simple-node-js-react-npm-app 仓库, 运行命令: git stage . 然后 git commit -m "Add 'Deliver' stage"

    4. 再次回到 Jenkins , 如果有必要的话再次登录并进入 Jenkins的 Blue Ocean 主界面。

    5. 点击左上方的 Run t, 然后快速的点击出现在右下方的 OPEN ,查看 Jenkins 运行你改进后的流水线项目。 如果你点击不了 OPEN 链接, 点击Blue Ocean界面的 top 行 来使用.这一特性。 如果你成功运行了流水线, Blue Ocean 界面应该是这样的. 另外注意 "Deliver" 阶段。 点击之前的 "Test" 和 "Build" 阶段循环的访问这些阶段的输出。

      Deliver stage pauses for user input

    6. 观察 "Deliver" 阶段 (必要的时候点击它), 然后点击 绿色的 ./jenkins/scripts/deliver.sh 步骤扩展它的内容并向下滚动直到看见 http://localhost:3000 链接。

      Deliver stage output only

    7. 点击 http://localhost:3000 链接在一个新的浏览器选项卡查看你的 Node.js 和 React 应用的运行(在开发模式下) 。 你会 看到一个标题为 Welcome to React 的网页/站点。 Tip: 如果你觉得有些冒险, 你可以尝试访问你的Jenkins Docker 终端/命令提示符 , 然后使用 vi 编辑器, 调整并保存 App.js 源文件,查看出现在 the Welcome to React 页面上的结果。 为此, 运行下面的命令:

      docker exec -it <docker-container-name> bash 
      cd /var/jenkins_home/workspace/simple-node-js-react-npm-app/src 
      vi App.js 
      
       这个命令可以访问到你的Jenkins Docker容器的终端/命令提示符 。 使用命令 docker ps 可以获得 ` 。 另外, 他就是jenkins-tutorials(如果你在之前运行容器 [above](https://www.jenkins.io/zh/doc/tutorials/build-a-node-js-and-react-app-with-npm/#run-jenkins-in-docker) 的时候在命令中指定了它 - 比如--name jenkins-tutorials`).
        在容器中, 更该目录为 Node.js 和 React 源目录 (在 Jenkins 工作区目录).
        使用vi编辑器访问, 编辑和保存改变你的应用的 App.js 文件 。
    8. 当你查看完页面/站点, 点击 Proceed 按钮以完成 流水线的执行。

      Deliver stage runs successfully

    9. 点击右上方的 X 返回 Blue Ocean 的主界面, 它按时间顺序的反序的方式列出了流水线的历史运行记录。

      Main Blue Ocean interface with all previous runs displayed

    总结

    做得好!您刚刚使用Jenkins通过npm构建了一个简单的Node.js 和 React 应用程序!

    您在上面创建的 "Build", "Test" 和 "Deliver" 阶段是使用Jenkins中的Maven构建更复杂的 Node.js 和 React应用程序以及与其他技术栈集成的Node.js 和React应用程序的基础。

    由于Jenkins具有极高的可扩展性,因此可以对其进行修改和配置,以处理构建协调和自动化的几乎任何方面。

    要详细了解Jenkins可以做什么,请查看:

     

使用PyInstaller构建Python应用

Table of Contents

本教程将向你展示如何使用Jenkins编排构建一个使用 PyInstaller管理的简单Python应用程序。

如果你是一个 Python 开发者,对CI/CD概念不了解 或者你熟悉这些概念却不知道如何使用Jenkins完成构建,那么本教程很适合你。

示例Python应用(你可以从GitHub的示例仓库中获取)是一个输出两个值的和的命令行工具“add2vals”。如果至少有一个值是字符串,那么“add2vals”就会将这两个值都当做字符串并将其连接起来。 “cal”库“add2”函数(“add2vals”导入)伴随着一组单元测试。 这些测试是用pytest测试,以检查这个函数是否像预期那样工作并将测试结果保存到Junit XML报告中。

"add2vals"工具通过PyInstaller进行交付,PyInstaller将该工具转换成一个Linux的独立的可执行的文件, 你可以在没有Python的情况下通过Jenkins下载并执行该命令行。

Note: 与本文档的其他教程不同, 本教程需要下载大约500MB的Docker镜像数据。

Duration: 本教程需要花费20-40分钟的时间完成 (假设你已满足下文的 配置要求 )。 确切的耗时取决于你机器的性能, 以及你是否完成过在Docker中运行Jenkins 请参考另一个教程

你可以在任何时间停止该教程,并从你离开的地方继续。

如果你已经运行了 其他教程, 你可以跳过下面的 配置要求在Docker中运行 Jenkins 章节继续 fork示例仓库. (确保你已在本地安装了 Git 。) 如果你要重启 Jenkins, 只需遵照下面的重启指令 停止和重启 Jenkins 然后继续.。

配置要求

对于本教程,您将需要:

  • 安装有macOS,Linux或Windows操作系统的机器,并拥有以下配置:

    • 最小256MB内存, 推荐512MB以上。

    • 10GB硬盘空间, 用于安装Jenkins,您的Docker镜像和容器。

  • 安装有以下软件:

    • Docker - 在安装Jenkins页面的安装Docker章节阅读更多信息。 注意: 如果您使用Linux,本教程假定您没有以root用户的身份运行Docker命令,而是使用单个用户帐户访问本教程中使用的其他工具。

    • Git and optionally GitHub Desktop

在 Docker中运行Jenkins

在本教程中, 将Jenkins作为 Docker 容器并从 jenkinsci/blueocean Docker 镜像中运行。

要在 Docker中运行Jenkins, 请遵循下面的macOS 和 LinuxWindows相关文档说明进行操作。 .

你可以在 DockerInstalling Jenkins 页面的 Downloading and running Jenkins in Docker部分阅读更多有关Docker容器和镜像概念的信息。

在 macOS 和 Linux 系统上

  1. 打开终端窗口

  2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

    docker run \
      --rm \
      -u root \
      -p 8080:8080 \
      -v jenkins-data:/var/jenkins_home \ 
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v "$HOME":/home \ 
      jenkinsci/blueocean
    
     将容器中的 /var/jenkins_home 目录映射到 Docker volume ,并将其命名为 jenkins-data。如果该卷不存在, 那么 docker run 命令会自动为你创建卷。
      将主机上的$HOME 目录 (即你的本地)映射到 (通常是 /Users/ 目录) 到容器的 /home 目录。

    Note: 如果复制或粘贴上面的命令片段不起作用, 尝试复制和粘贴这个没有注释的版本:

    docker run \
      --rm \
      -u root \
      -p 8080:8080 \
      -v jenkins-data:/var/jenkins_home \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v "$HOME":/home \
      jenkinsci/blueocean
    
  3. 继续 安装向导

在 Windows 系统

  1. 打开命令提示窗口。

  2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

    docker run ^
      --rm ^
      -u root ^
      -p 8080:8080 ^
      -v jenkins-data:/var/jenkins_home ^
      -v /var/run/docker.sock:/var/run/docker.sock ^
      -v "%HOMEPATH%":/home ^
      jenkinsci/blueocean
    

    对这些选项的解释, 请参考上面的 macOS 和 Linux 说明。

  3. 继续安装向导

访问 Jenkins/Blue Ocean Docker 容器

如果你有一些使用 Docker 的经验,希望或需要使用 docker exec 命令通过一个终端/命令提示符来访问 Jenkins/Blue Ocean Docker 容器, 你可以添加如 --name jenkins-tutorials 选项(与上面的 docker run ), 这将会给Jenkins/Blue Ocean Docker容器一个名字 "jenkins-tutorials"。

这意味着你可以通过 docker exec 命令访问Jenkins/Blue Ocean 容器(通过一个单独的终端 /命令提示窗口) ,例如:

docker exec -it jenkins-tutorials bash

安装向导

在你访问 Jenkins之前, 你需要执行一些快速的 "一次性" 步骤。

解锁 Jenkins

当你第一次访问一个新的 Jenkins 实例时, 要求你使用自动生成的密码对其进行解锁。

  1. 当在终端/命令提示窗口出现两组星号时, 浏览 http://localhost:8080 并等待 Unlock Jenkins 页面出现。

    Unlock Jenkins page

  2. 再次从终端/命令提示窗口, 复制自动生成的字母数字密码(在两组星号之间)。 Copying initial admin password

  3. Unlock Jenkins 页面, 粘贴该密码到 Administrator password 字段并点击 Continue

使用插件自定义 Jenkins

解锁 Jenkins后, Customize Jenkins 页面出现。

在该页面,点击 Install suggested plugins

安装向导显示了正在配置的Jenkins的进程,以及建议安装的插件。这个过程肯需要几分钟。

创建第一个管理员用户

最后, Jenkins 要求创建你的第一个管理员用户。

  1. Create First Admin User 页面出现, 在相应的字段中指定你的详细消息并点击 Save and Finish

  2. Jenkins is ready 页面出现, 点击 Start using Jenkins Notes:

    • 该页面可能表明 Jenkins is almost ready! 如果相反, 点击 Restart.

    • 如果该页面在一分钟后没有自动刷新, 使用你的web浏览器手动刷新。

  3. 如果需要,登录 Jenkins , 你就可以开始使用 Jenkins了!

停止和重启 Jenkins

在本教程的其余部分, 你可以通过在终端/命令提示窗口输入 Ctrl-C停止 Jenkins/Blue Ocean Docker 容器,你可以从中运行<>的 docker run ... 命令。

要重启Jenkins/Blue Ocean Docker 容器:

  1. 在上面的 macOS,LinuxWindows上运行相同的 docker run ... 命令 。 Note: 如果有更新的话,该进程会更新 jenkinsci/blueocean Docker 镜像。

  2. 浏览http://localhost:8080

  3. 等待直到登录页面出现并登陆。

Fork 和 clone GitHub上的示例仓库

通过应用的源代码的示例仓库 fork 到你自己的GitHub账号中,然后在本地clone这个fork的方式,从GitHub上获取 "add" Python 应用。

  1. 确保你拥有 GitHub 账号。 如果没有GitHub账号, 在 GitHub 网站注册一个免费的账号。

  2. 在 GitHub上Fork simple-python-pyinstaller-app 到你本地的 GitHub 账号。在这个过程中如果你需要帮助, 请参考GitHub网站的 Fork A Repo 文档了解更多信息。

  3. Clone 你 fork的 simple-python-pyinstaller-app 仓库 (在 GitHub 上) 到你本地的机器。要开始这个过程, 请执行以下操作 (你的操作系统的用户账号为 `` ):

    • 如果你的机器上安装了 GitHub 桌面应用程序:

      1. 在 GitHub上, 点击你fork的仓库的 Clone or download 按钮, 然后 Open in Desktop.

      2. 再 GitHub 桌面, 在点击 Clone a Repository 对话框的击 Clone 之前, 确保 Local Path 是:

        • macOS操作系统 /Users//Documents/GitHub/simple-python-pyinstaller-app

        • Linux操作系统 /home//GitHub/simple-python-pyinstaller-app

        • Windows操作系统 C:\Users\\Documents\GitHub\simple-python-pyinstaller-app

    • 另外:

      1. 打开一个终端/命令行提示符 , cd 到对应的目录 :

        • macOS操作系统 - /Users//Documents/GitHub/

        • Linux操作系统 - /home//GitHub/

        • Windows操作系统 - C:\Users\\Documents\GitHub\ (通过使用 Git bash 命令行窗口,而不是通用的 Microsoft 命令提示符)

      2. 运行一下命令来继续/完成 clone 你 fork 到的仓库 git clone https://github.com/YOUR-GITHUB-ACCOUNT-NAME/simple-python-pyinstaller-app 你的GitHub账号的名称是 YOUR-GITHUB-ACCOUNT-NAME

使用Jenkins构建你的流水线项目

  1. 回到 Jenkins, 如果需要的话再次登录并点击 Welcome to Jenkins! 下的 create new jobs + Note: 如果你没有看到上述按钮, 点击左上的 New Item

  2. Enter an item name 域中, 指定你新的 Pipeline 项目的名称 (比如 simple-python-pyinstaller-app)。

  3. 向下滚动并点击 Pipeline, 点击页面底部的 OK

  4. ( Optional ) 在下一页的 Description 域中填写你的 Pipeline 的描述 (比如 An entry-level Pipeline demonstrating how to use Jenkins to build a simple Python application with PyInstaller.)

  5. 点击页面顶部的 Pipeline 选项卡 向下滚动到 Pipeline 部分。

  6. Definition 域中, 选择 Pipeline script from SCM 选项。 该选项命令 Jenkins 从源控制管理(SCM)获取你的流水线, 这会是你clone到本地的 Git 仓库。

  7. 从 the SCM 域中, 选择 Git

  8. Repository URL 域中, 填写你本地clone的仓库 above的目录路径, 从你的主机的用户账户/主目录, 映射到Jenkins容器的 /home 目录 - 即

    • macOS - /home/Documents/GitHub/simple-python-pyinstaller-app

    • Linux - /home/GitHub/simple-python-pyinstaller-app

    • Windows - /home/Documents/GitHub/simple-python-pyinstaller-app

  9. 点击 Save 保存你的新的流水线项目。你现在准备生成你的 Jenkinsfile,检查你clone到本地 的Git 仓库。

将初始流水线创建为 Jenkinsfile

你现在准备构建你的流水,它将在Jenkins中使用PyInstaller自动构建你的 Python 应用。你的流水线将会被创建作为 Jenkinsfile, 它将会被提交到你clone到本地的 Git 仓库 (simple-python-pyinstaller-app)。

这是 "流水线即代码"的基础, 他将连续支付流水线作为应用程序的一部,像其他代码一样进行版本化和审查。 了解更多在 用户手册的PipelineUsing a Jenkinsfile 章节。

首先, 创建一个带有 "Build" 阶段的初始流水线, 该阶段为你的应用执行整个生产过程的第一部分。 "Build" 部分 下载一个 Python Docker 镜像并将它作为 Docker 容器运行, 它将 你的简单的 Python 应用编译成字节码。

  1. 使用你最称手的文本编辑器或 IDE, 在你的本地 simple-python-pyinstaller-app Git仓库的根目录下生成并保存一个新的名为 Jenkinsfile的文本文件。

  2. 复制并粘贴下面的声明式流水线代码到你空的 Jenkinsfile文件中:

    pipeline {
        agent none 
        stages {
            stage('Build') { 
                agent {
                    docker {
                        image 'python:2-alpine' 
                    }
                }
                steps {
                    sh 'python -m py_compile sources/add2vals.py sources/calc.py' 
                }
            }
        }
    }
    
     流水线代码块顶部的 agent 部分指定的的 none 参数意味着不会为 整个流水线的执行分配全局代理 ,并且每个 stage 指令必须制定自己的 agent 部分。
      定义名为Buildstage (指令) ,它出现在 Jenkins UI中。
      image 参数 (参考 agent 部分的 docker 参数) 下载 python:2-alpine Docker image (如果他在你的主机上不可用) 并将它作为一个独立的容器运行。 这意味着:你将拥有独立的运行在Docker的Jenkins 和 Python 容器。Python 容器成为 Jenkins 用来运行你流水线项目的 Build 阶段的 agent 。 然而, 这个容器寿命较短 - 他的生命周期只是 你的 Build 阶段的执行的时间. <4> sh 步骤 (参考 steps 章节) 运行 Python 命令将你的应用和它的 calc 库 转换成字节码文件 (每个都有 .pyc 扩展), 被放在sources 工作区目录 (在Jenkins容器的 /var/jenkins_home/workspace/simple-python-pyinstaller-app 目录下)。
  3. 保存并提交你编辑的 Jenkinsfile 到本地 simple-python-pyinstaller-app Git 仓库。 比如在 simple-python-pyinstaller-app 仓库, 运行命令: git add . 然后 git commit -m "Add initial Jenkinsfile"

  4. 再次回到 Jenkins , 如果需要的话再次登录并点击左边的 Open Blue Ocean 来访问 Jenkins的 Blue Ocean 界面。

  5. This job has not been run 消息框, 点击 Run, 然后快速的点击出现在右下方的 OPEN 链接观察Jenkins 运行你的流水线项目. 如果你不能点击 OPEN 链接, 点击 Blue Ocean 主界面的行来使用这一特性。 Note: 完成第一次的运行你需要等几分钟。 在对你本地的 simple-python-pyinstaller-app Git 仓库进行clone后, Jenkins:

    1. 最初将这个项目在代理上排队运行。

    2. 下载 Python Docker 镜像并在 Docker上的容器中运行它.

      Downloading Python Docker image

    3. 在 Python 容器运行 Build 阶段 (定义在 Jenkinsfile文件中)。 在这期间, Python使用 py_compile 组件将你的Python应用的代码和它的 calc 库编译成字节码, 它被保存在 sources 工作区目录(在 Jenkins 的主目录里)。

    如果Jenkins编译Python应用成功,Blue Ocean界面会变成绿色 。

    Initial Pipeline runs successfully

  6. 点击右上方的 X 回到 Blue Ocean 主界面。

    Main Blue Ocean interface

为你的流水线添加测试阶段

  1. 回到你的文本编辑器/IDE ,打开Jenkinsfile 文件。

  2. 复制并粘贴下面的声明式流水线语法到JenkinsfileBuild阶段下面:

            stage('Test') {
                agent {
                    docker {
                        image 'qnib/pytest'
                    }
                }
                steps {
                    sh 'py.test --verbose --junit-xml test-reports/results.xml sources/test_calc.py'
                }
                post {
                    always {
                        junit 'test-reports/results.xml'
                    }
                }
            }
    

    结果是:

    pipeline {
        agent none
        stages {
            stage('Build') {
                agent {
                    docker {
                        image 'python:2-alpine'
                    }
                }
                steps {
                    sh 'python -m py_compile sources/add2vals.py sources/calc.py'
                }
            }
            stage('Test') { 
                agent {
                    docker {
                        image 'qnib/pytest' 
                    }
                }
                steps {
                    sh 'py.test --verbose --junit-xml test-reports/results.xml sources/test_calc.py' 
                }
                post {
                    always {
                        junit 'test-reports/results.xml' 
                    }
                }
            }
        }
    }
    
     定义名为Teststage (指令) ,它出现在Jenkins UI中。
      This image 参数 (参考 agent 部分的 docker 参数) 下载 qnib:pytest Docker image (如果它在你的机器上不可用)并将它作为一个独立的容器运行。 这意味着:你将拥有独立的运行在Docker的Jenkins 和 Pytest 容器。pytest 容器成为Jenkins 用来运行你流水线项目的 Test 阶段的 agent。这个容器的生命周期可以持续你的 Test 阶段的执行过程。
      这里的 sh 步骤 (参考 steps 章节) 在 sources/test_calc.py执行 pytest的 py.test 命令 , 它在"calc" 库的 add2 函数 (被 简单的 Python 应用的 add2vals使用)运行了一系列的单元测试 (定义在 test_calc.py) 。The:--verbose 选项使 py.test 在Jenkinds/Blue Ocean界面生成详细输出。--junit-xml test-reports/results.xml 选项使 py.test 生成 JUnit XML 报告,它被保存到 test-reports/results.xml (在Jenkins容器的 /var/jenkins_home/workspace/simple-python-pyinstaller-app 目录下 )。
      这里的 junit 步骤 (由 JUnit Plugin提供) 归档了 JUnit XML 报告 (由 py.test 命令生成) 并通过Jenkins界面公开结果。在 Blue Ocean, 可以通过流水线运行的 Tests 页面访问该结果。 post 部分的 always 条件包含 junit 阶段, 确保不论阶段的输出是什么,步骤 alwaysTest阶段的at the completion 被执行。
  3. 保存并提交你编辑的 Jenkinsfile 到本地的 simple-python-pyinstaller-app Git 仓库。比如在 simple-python-pyinstaller-app 目录下, 运行这些命令: git stage . 然后 git commit -m "Add 'Test' stage"

  4. 再次回到 Jenkins , 如果必要再次登录并进入 Jenkins的Blue Ocean 界面。

  5. 点击左上方的 Run , 然后快速的点击出现在右下方的 OPEN 链接来查看 Jenkins 运行你改进后的流水线项目。如果你不能点击 OPEN 链接, 点击Blue Ocean主界面的 top 行 来访问这一特性。 Note: 可能需要几分钟来下载 qnib:pytest Docker 镜像 (如果之前没做过)。 如果你改进后的流水线项目运行成功, Blue Ocean 界面将会是这样的. 另外注意 "Test" 阶段。 你可以点击之前的 "Build" 阶段循环的访问该阶段的输出。

    Test stage runs successfully (with output)

  6. 点击右上方的 X 返回到 Blue Ocean 主界面。

给你的流水线添加最终交付阶段

  1. 回到你的文本编辑器/IDE 并打开 Jenkinsfile 文件。

  2. 复制并粘贴下面的声明式流水线语法到 JenkinsfileTest 阶段下方:

            stage('Deliver') {
                agent {
                    docker {
                        image 'cdrx/pyinstaller-linux:python2'
                    }
                }
                steps {
                    sh 'pyinstaller --onefile sources/add2vals.py'
                }
                post {
                    success {
                        archiveArtifacts 'dist/add2vals'
                    }
                }
            }
    

    结果是:

    pipeline {
        agent none
        stages {
            stage('Build') {
                agent {
                    docker {
                        image 'python:2-alpine'
                    }
                }
                steps {
                    sh 'python -m py_compile sources/add2vals.py sources/calc.py'
                }
            }
            stage('Test') {
                agent {
                    docker {
                        image 'qnib/pytest'
                    }
                }
                steps {
                    sh 'py.test --verbose --junit-xml test-reports/results.xml sources/test_calc.py'
                }
                post {
                    always {
                        junit 'test-reports/results.xml'
                    }
                }
            }
            stage('Deliver') { 
                agent {
                    docker {
                        image 'cdrx/pyinstaller-linux:python2' 
                    }
                }
                steps {
                    sh 'pyinstaller --onefile sources/add2vals.py' 
                }
                post {
                    success {
                        archiveArtifacts 'dist/add2vals' 
                    }
                }
            }
        }
    }
    
     定义名为Deliverstage (指令) 它出现在Jenkins UI中。
      这里的image 参数 (参考 agent 章节的 docker 参数) 下载 cdrx/pyinstaller-linux Docker image (如果它在你的机器上不可用) 并且将它作为一个独立的容器运行。这意味着:你有一个独立的在Docker中运行的 Jenkins 和 PyInstaller (for Linux) 容器。PyInstaller 容器成为Jenkins用来运行流水线项目的 Deliver 阶段的 agent。该容器的周期持续 Deliver 阶段的执行过程。 <3> sh 步骤 (参考 steps 部分) 在你的简单的Python应用中执行 pyinstaller 命令 (在 PyInstaller 容器中)。将你的 add2vals.py Python 应用程序打包成一个 独立的可执行的文件 (via the --onefile option) 并且输出该文件到dist 工作区目录 (在 Jenkins 主目录。 虽然这一步骤有一个单一的命令组成, 在通用原则下, 你最好保持你的流水线代码 (也就是 Jenkinsfile) 尽可能的整洁并将更复杂的构建步骤 (特别是包含两个及以上步骤的阶段) 放在单独的像 deliver.sh 文件一样的shell脚本文件中。 这最终会让你的流水线代码的维护变得简单,尤其是在你的流水线更复杂的情况下。 <4> archiveArtifacts 步骤 (作为 Jenkins 核心的一部分被提供) 对独立可执行文件进行归档 (由 Jenkins 主工作目录下的dist/add2valspyinstaller 命令生成) 并通过aJenkins界面公开该文件。 在Blue Ocean, 像这样的存档组件可以通过流水线运行 Artifacts 页面进行访问。 post 部分的success 条件 c包含 archiveArtifacts 步骤, 确保步骤被执行 at the completion of the Deliver stage only if this stage completed successfully.
  3. 保存并提交你编辑的 Jenkinsfile 到本地的 simple-python-pyinstaller-app Git 仓库。 比如在 simple-python-pyinstaller-app 仓库里, 运行这些命令: git stage . 然后 git commit -m "Add 'Deliver' stage"

  4. 再次回到 Jenkins, 如果必要的话再次登录并进入 Jenkins的 Blue Ocean 界面。

  5. 点击左上方的 Run, 然后快速的点击出现在右下方的 OPEN 链接来查看 Jenkins 运行你改进后的流水线项目。 如果你点击不了 OPEN 链接, 点击Blue Ocean 界面 top 行 来使用这一特性。 Note: 可能需要几分钟来下载 cdrx/pyinstaller-linux Docker 镜像 (如果之前没有下载过)。+ 如果你改进后的流水线项目运行成功, Blue Ocean 界面应该是这样的。 另外注意 "Deliver" 阶段。 点击之前的 "Test" 和 "Build" 阶段循环的去访问这些阶段的输出。

    Deliver stage runs successfully

    "Deliver" 阶段的输出结果应该如下所示, 向你展示了 PyInstaller 将 Python 应用打包成一个简单的独立可执行文件的结果。

    Deliver stage output only

  6. 点击右上方的 X 返回到Blue Ocean 的主界面, 他按照时间顺序的反序的方式列出了你的流水线运行的历史记录。

    Main Blue Ocean interface with all previous runs displayed

跟踪 (可选)

如果你是用的是 Linux系统, 你可以尝试着运行在你本地机器上生成的带有PyInstaller的 add2vals 应用 。 要做到这一点:

  1. 从 Blue Ocean 的主界面, 访问你above的最后一次的运行的流水线 。 要做到这一点, 点击Blue Ocean的 Activity页面上的顶部行(表示最近一次的流水线运行) 。

    Main Blue Ocean interface with all previous runs displayed

  2. 在流水线运行的结果页面, 点击右上方的 Artifacts 访问 Artifacts 页面。

    Deliver stage runs successfully

  3. 在工件列表中, 点击dist/add2vals 工件项最右边的向下箭头图标下载独立可执行文件到 浏览器的 "下载" 目录中。

    Deliver stage Artifacts page

  4. 回到操作系统的终端, cd 到浏览器的 "Downloads" 目录。

  5. 使 add2vals 文件可执行 - 也就是 chmod a+x add2vals

  6. 运行命令 ./add2vals 并且追踪你的应用发出的指示。

总结

做得好!您刚刚使用Jenkins构建了一个简单的Python 应用程序!

您在上面创建的 "Build", "Test" 和 "Deliver" 阶段是在Jenkins中构建更复杂的 Python应用程序以及与其他技术栈集成的Python应用程序的基础。

由于Jenkins具有极高的可扩展性,因此可以对其进行修改和配置,以处理构建协调和自动化的几乎任何方面。

要详细了解Jenkins可以做什么,请查看:

使用Blue Ocean生成Pipeline

Table of Contents

该教程展示如何使用Jenkins的 Blue Ocean 特性生成一个流水线,该流水线将协调构建一个简单的应用程序。

在学习本教程前, 建议您先从Tutorials overview 页面至少浏览一组入门教程来熟悉CI/CD 概念 (与你 最熟悉的技术栈有) 以及这些概念是如何在Jenkins中实现的。 Jenkins.

本教程使用与Build a Node.js and React app with npm 教程相同的应用程序 . 因此, 你这次将完全通过Blue Ocean构建相同的应用程序。 自从 Blue Ocean 提供了简化的 Git处理经验, 你将直接与 GitHub上的仓库进行交互 (相对于该存储库的本地clone)。

Duration: 本教程需花费 20-40 分钟 (假设你已经 完成下述的 配置要求 )。 确切的时间取决于你的机器的运行速度 和是否你已经在另一个教程run Jenkins in Docker

你可以随时停止本教程,并且从你离开的地方继续 。

如果你已经完成 另一个教程, 你可以跳过下面的 配置要求Run Jenkins in Docker部分并继续 fork示例仓库。如果你需要重启Jenkins,只需遵循停止和重启 Jenkins中的重启指示然后继续。

配置要求

对于本教程,您将需要:

  • 安装有macOS,Linux或Windows操作系统的机器,并拥有以下配置:

    • 最小256MB内存, 推荐512MB以上。

    • 10GB硬盘空间, 用于安装Jenkins,您的Docker镜像和容器。

  • 安装有以下软件:

    • Docker - 在安装Jenkins页面的安装Docker章节阅读更多信息。 注意: 如果您使用Linux,本教程假定您没有以root用户的身份运行Docker命令,而是使用单个用户帐户访问本教程中使用的其他工具。

在 Docker中运行Jenkins

在本教程中, 将Jenkins作为 Docker 容器并从 jenkinsci/blueocean Docker 镜像中运行。

要在 Docker中运行Jenkins, 请遵循下面的macOS 和 LinuxWindows相关文档说明进行操作。 .

你可以在 DockerInstalling Jenkins 页面的 Downloading and running Jenkins in Docker部分阅读更多有关Docker容器和镜像概念的信息。

在 macOS 和 Linux 系统上

  1. 打开终端窗口

  2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

    docker run \
      --rm \
      -u root \
      -p 8080:8080 \
      -v jenkins-data:/var/jenkins_home \ 
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v "$HOME":/home \ 
      jenkinsci/blueocean
    
     将容器中的 /var/jenkins_home 目录映射到 Docker volume ,并将其命名为 jenkins-data。如果该卷不存在, 那么 docker run 命令会自动为你创建卷。
      将主机上的$HOME 目录 (即你的本地)映射到 (通常是 /Users/ 目录) 到容器的 /home 目录。

    Note: 如果复制或粘贴上面的命令片段不起作用, 尝试复制和粘贴这个没有注释的版本:

    docker run \
      --rm \
      -u root \
      -p 8080:8080 \
      -v jenkins-data:/var/jenkins_home \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v "$HOME":/home \
      jenkinsci/blueocean
    
  3. 继续 安装向导

在 Windows 系统

  1. 打开命令提示窗口。

  2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

    docker run ^
      --rm ^
      -u root ^
      -p 8080:8080 ^
      -v jenkins-data:/var/jenkins_home ^
      -v /var/run/docker.sock:/var/run/docker.sock ^
      -v "%HOMEPATH%":/home ^
      jenkinsci/blueocean
    

    对这些选项的解释, 请参考上面的 macOS 和 Linux 说明。

  3. 继续安装向导

访问 Jenkins/Blue Ocean Docker 容器

如果你有一些使用 Docker 的经验,希望或需要使用 docker exec 命令通过一个终端/命令提示符来访问 Jenkins/Blue Ocean Docker 容器, 你可以添加如 --name jenkins-tutorials 选项(与上面的 docker run ), 这将会给Jenkins/Blue Ocean Docker容器一个名字 "jenkins-tutorials"。

这意味着你可以通过 docker exec 命令访问Jenkins/Blue Ocean 容器(通过一个单独的终端 /命令提示窗口) ,例如:

docker exec -it jenkins-tutorials bash

安装向导

在你访问 Jenkins之前, 你需要执行一些快速的 "一次性" 步骤。

解锁 Jenkins

当你第一次访问一个新的 Jenkins 实例时, 要求你使用自动生成的密码对其进行解锁。

  1. 当在终端/命令提示窗口出现两组星号时, 浏览 http://localhost:8080 并等待 Unlock Jenkins 页面出现。

    Unlock Jenkins page

  2. 再次从终端/命令提示窗口, 复制自动生成的字母数字密码(在两组星号之间)。 Copying initial admin password

  3. Unlock Jenkins 页面, 粘贴该密码到 Administrator password 字段并点击 Continue

使用插件自定义 Jenkins

解锁 Jenkins后, Customize Jenkins 页面出现。

在该页面,点击 Install suggested plugins

安装向导显示了正在配置的Jenkins的进程,以及建议安装的插件。这个过程肯需要几分钟。

创建第一个管理员用户

最后, Jenkins 要求创建你的第一个管理员用户。

  1. Create First Admin User 页面出现, 在相应的字段中指定你的详细消息并点击 Save and Finish

  2. Jenkins is ready 页面出现, 点击 Start using Jenkins Notes:

    • 该页面可能表明 Jenkins is almost ready! 如果相反, 点击 Restart.

    • 如果该页面在一分钟后没有自动刷新, 使用你的web浏览器手动刷新。

  3. 如果需要,登录 Jenkins , 你就可以开始使用 Jenkins了!

停止和重启 Jenkins

在本教程的其余部分, 你可以通过在终端/命令提示窗口输入 Ctrl-C停止 Jenkins/Blue Ocean Docker 容器,你可以从中运行<>的 docker run ... 命令。

要重启Jenkins/Blue Ocean Docker 容器:

  1. 在上面的 macOS,LinuxWindows上运行相同的 docker run ... 命令 。 Note: 如果有更新的话,该进程会更新 jenkinsci/blueocean Docker 镜像。

  2. 浏览http://localhost:8080

  3. 等待直到登录页面出现并登陆。

Fork GitHub上的示例仓库

Fork GitHub上的示例 "Welcome to React" Node.js 和 React 应用到你自己的 GitHub 账户 。

  1. 确保你有 GitHub 账户。 如果没有, 在 GitHub 网站注册一个免费账号。

  2. 在GitHub Fork creating-a-pipeline-in-blue-ocean 到本地的 GitHub 账号。 在这个过程中如果需要帮助, 请参考GitHub网站的 Fork A Repo 文档 了解更多信息。 Note: 这是不同于使用npm构建 Node.js 和 React 应用程序 教程的另一个仓库。 尽管这些仓库包含相同的应用程序代码, 但请确保在继续之前正确的fork 和使用 。

在Blue Ocean创建你的流水线项目

  1. 回到Jenkins并进入Blue Ocean 界面。要做到这一点, 你应该:

    • 浏览 http://localhost:8080/blue 并登陆

    • 已浏览 http://localhost:8080/且登录后在左侧点击 Open Blue Ocean

  2. 在Blue Ocean界面中心的 Welcome to Jenkins , 点击 Create a new Pipeline 来启动流水线创建向导。 Note: 如果你没有看到这个框, 点击右上方的 New Pipeline

  3. Where do you store your code?, 点击 GitHub

  4. Connect to GitHub, 点击 Create an access key here。这将在一个新的浏览器选项卡中打开 GitHub。 Note: 如果你之前配置了 Blue Ocean,使用个人的访问令牌连接到GitHub, then Blue Ocean 将直接带你到 below的第9步。

  5. 在新的选项卡中, 登录到 GitHub 账户 (如果需要) 并进入 GitHub的 New Personal Access Token 页面, 为你的 GitHub 访问令牌 (e.g. Blue Ocean)指定一个简短的 Token description Note: 访问令牌通常是一个字母数字的字符串 ,它代表你的 GitHub 账户具有访问各种 GitHub 特性 和区域的特权。该访问令牌将具有预选的适当权限, 该权限为Blue Ocean 需要访问你的GitHub账号并与其交互。

  6. 向下滚动到页面的底部 (保留所有的 Select scopes 选项 的默认设置) 并点击 Generate token

  7. 在生成的Personal access tokens 页面上, 复制新生成的访问令牌。

  8. 回到Blue Ocean, 粘贴访问令牌到 Your GitHub access token 域并点击 Connect。 +

    Connecting to GitHub Jenkins现在在访问你的 GitHub 账户 (由你的访问令牌提供).

  9. Which organization does the repository belong to?, 点击你的 GitHub 账号 (你abovefork仓库的地方 ).

  10. Choose a repository, 点击fork的仓库的 creating-a-pipeline-in-blue-ocean

  11. 点击 Create Pipeline. Blue Ocean 检测到在存储库的master 主分支的根级别上没有 Jenkinsfile 文件 然后就帮你创建一个。 (因此, 你要点击在页面的尾部另一个 Create Pipeline 来继续。) Note: 在, 通过Blue Ocean创建的流水线项目实际上是 "多分支流水线"。 因此, Jenkins 在你的存储库的任何分支上至少找到一个Jenkinsfile文件。

创建你的初始流水线

  1. 在创建流水线项目之后 (above), 在流水线编辑器中, 从右边的 Pipeline Settings*面板中的*Agent*下拉框中选择 *docker。 +

    Initial to GitHub

  2. 在出现的 ImageArgs 域中, 分别指定node:6-alpine-p 3000:3000

    Configuring the agent Note: 对这些值的解释, 请参考“Create your initial Pipeline…​” section of the Build a Node.js and React app 教程的声明式流水线的注释 12

  3. 在主流水线编辑器中, 点击 + 图标, 它会打开右侧的新阶段面板。 Add <em>Build</em> stage

  4. 在该面板中, 在 Name your stage*域中输入 Build,然后点击下面的 *Add Step 按钮, 它会打开 Choose step type 面板。

    Adding the Build stage

  5. 在这个面板中,点击列表顶部附近的 Shell Script (选择该步骤类型), 它打开 Build / Shell Script 面板, 在这儿你可以输入该步骤的值。 Choosing a step type Tip: 最常用的步骤类型出现在最靠近列表顶部的地方。要想在这个列表中找到其他的步骤, 你可以使用 Find steps by name 选项筛选这个列表。

  6. Build / Shell Script 面板, 指定 npm install

    Specifying a shell step value Note: 对该步骤的解释, 请参考 “Create your initial Pipeline…​” section of the Build a Node.js and React app 教程的声明式流水线的注解 4

  7. ( Optional ) 点击左上的箭头图标 Return from step icon 回到主流水线编辑器。

  8. 点击右上方的 Save 按钮 开始保存你的带有"Build" 阶段的新流水线 。

  9. Save Pipeline 对话框, 在 Description 域输入命令信息 (比如 Add initial Pipeline (Jenkinsfile))。

    Save Pipeline dialog box

  10. 保留所有其他选项, 点击 Save & run ,Jenkins 就会继续构建你的流水线。

  11. 当出现Blue Ocean 的主界面时, 点击该行来查看 Jenkins 构建你的流水线项目。+ Note: 你可能需要几分钟来完成第一次的运行。 在此期间, Jenkins 进行了如下动作:

    1. 将你的流水线作为 Jenkinsfile 提交到仓库的唯一分支 (也就是 master)。

    2. 最初让项目在代理上排队构建。

    3. 下载 Node Docker 镜像并在Docker的一个容器上运行。

    4. 在Node容器中执行 Build 阶段 (定义在 Jenkinsfile)。(在此期间, npm 下载了一些需要的依赖来运行你的Node.js 和 React 应用程序, 他最终被保存在 本地的Jenkins主目录的 node_modules 目录中).

      Downloading <em>npm</em> dependencies

    如果Jenkins成功构建了你的应用程序,Blue Ocean 界面会变成绿色。

    Initial Pipeline runs successfully

  12. 点击右上方的 X 回到 Blue Ocean 的主界面。

    Main Blue Ocean interface Note: 再继续之前, 你可以检查到Jenkins已为你在你fork的GitHub仓库创建了 Jenkinsfile (在仓库的唯一的 master 分支)。

给你的流水线添加测试阶段

  1. 在Blue Ocean 界面, 点击右上方的 Branches 访问你的仓库的分支页面, 在这儿你可以访问 master 分支。+

    Repository branches page

  2. 点击 master 分支的 "Edit Pipeline" 图标 Edit Pipeline on branch 打开该分支的流水线编辑器。

  3. 在主流水线编辑器中, 点击在above创建的Build阶段的右侧的 + 图标,打开右侧的新阶段面板。 Add <em>Test</em> stage

  4. 在这个面板中, 在 Name your stage*域输入 Test ,点击下面的 *Add Step 按钮来打开 Choose step type 面板。

  5. 在这个面板中, 点击列表顶部附近的 Shell Script

  6. 在生成的 Test / Shell Script 面板, 指定 ./jenkins/scripts/test.sh ,然后点击左上方的箭头图标 Return from step icon 返回到流水线阶段编辑器。

  7. 在面板的右下方, 点击 Settings 以显示面板的这一部分。

  8. 点击Environment 标题右边的 + 图标 (你将配置一个环境变量)。

  9. 在出现的 NameValue 域中, 分别指定 CI and true。+ Environment directive Note: 对该指令以及它的步骤的解释, 请参考“Add a test stage…​” section of the Build a Node.js and React app 教程的生命是流水线的注解 13

  10. ( Optional ) 点击左上方的箭头图标 Return from step icon 回到主流水线编辑器 。

  11. 点击右上方的 Save 按钮开始保存你的带有新得"Test"阶段的流水线。

  12. Save Pipeline 对话框的Description域, 输入提交信息(比如 Add 'Test' stage)。

  13. 保留所有其它选项, 点击 Save & run , Jenkins 就会构建你改进后的流水线。

  14. 当Blue Ocean的主界面出现时, 点击 top 行来查看Jenkins 构建你的流水线项目。 Note: 你会注意到在这次运行中Jenkins 不再需要下载 Node Docker 镜像。 Jenkins 只是需要从之前下载过的Node镜像中运行一个新的容器。因此, 在接下来的时间运行你的流水线会更快些。 如果你改进后的流水巷运行成功, Blue Ocean界面应如下图所示。注意另外的"Test" 阶段。你可以点击之前的 "Build" 阶段来循环的访问这些阶段的输出。

    Test stage runs successfully (with output)

  15. 点击右上方的 X 回到 Blue Ocean 的主界面。

给你的流水线添加最终交付阶段

  1. 在 Blue Ocean 的主界面, 点击右上方的 Branches 以访问你仓库的 master 分支。

  2. 点击 master 分支的 "编辑流水线" 图标 Edit Pipeline on branch 为该分支打开流水线编辑器。

  3. 在主流水线编辑器中, 点击在above创建的Test阶段右侧的 + 图标来打开新阶段面板。 Add <em>Deliver</em> stage

  4. 在这个面板中的 Name your stage 域, 输入 Deliver 并点击下面的 Add Step 按钮打开 Choose step type 面板。

  5. 在该面板中, 点击列表顶部附近的 Shell Script

  6. 在生成的 Deliver / Shell Script 面板, 指定 ./jenkins/scripts/deliver.sh ,然后点击左上的箭头图标 Return from step icon 回到流水线阶段编辑器。

    Add next step Note: 对该步骤的解释, 请参考deliver.sh文件,它位于你在GitHub fork的仓库的 jenkins/scripts 中。

  7. 再次点击 Add Step 按钮。

  8. Choose step type 面板的 Find steps by name 域输入 input

    Choosing the input step type

  9. 点击过滤后的 Wait for interactive input 步骤类型。

  10. 在生成的 Deliver / Wait for interactive input 面板,在 Message 域指定 Finished using the web site? (Click "Proceed" to continue),然后点击左上方的箭头图标 Return from step icon 回到流水线阶段编辑器。

    Specifying input step message value Note: 对该步骤的解释, 请参考“Add a final deliver stage…​” section of the Build a Node.js and React app 教程的声明式流水线的注释 4

  11. 点击 Add Step 按钮 (最后一次)。

  12. 点击列表顶部附近的 Shell Script

  13. 在生成的 Deliver / Shell Script 面板, 指定 ./jenkins/scripts/kill.sh. Note: 对该步骤的解释,请参考 kill.sh 文件,它 位于你在GitHub上fork的仓库的 jenkins/scripts 中。

  14. ( Optional ) 点击左上方的图标按钮 Return from step icon回到主流水线编辑器。

  15. 点击右上方的 Save 按钮开始保存你的带有新"Deliver" 阶段的流水线。

  16. Save Pipeline 对话框的 Description 域填写提交信息 (比如 Add 'Deliver' stage)。

  17. 保留所有其它选项, 点击 Save & run ,Jenkins 就会对你改进后的流水线进行构建。

  18. 当Blue Ocean主界面出现时, 点击 top行来查看Jenkins 构建你的流水线项目。+ 如果你改进后的流水巷线运行成功, Blue Ocean 界面应如下图所示。注意另外的 "Deliver" 阶段。 点击之前的"Test" 和 "Build" 阶段循环的访问这些阶段的输出。

    Deliver stage pauses for user input

  19. 确保你正在查看 "Deliver" 阶段 (如果必要的话点击它), 探后点击绿色的 ./jenkins/scripts/deliver.sh 步骤来扩展它的内容并向下滚动直到你看到 http://localhost:3000 链接。 Deliver stage output only

  20. 点击 http://localhost:3000 链接查看你的 Node.js 和 React 应用程序在一个新的web浏览器选项卡中运行 (在开发模式下)。 你将会看到一个标题为Welcome to React的网页/站点。

  21. 当你查看完该网页/站点时, 点击 Proceed 按钮以完成流水线的执行。

    Deliver stage runs successfully

  22. 点击右上方的 X 回到Blue Ocean 的主界面, 它以时间顺序的反序的方式列出了你的流水线运行的历史记录。

    Main Blue Ocean interface with all previous runs displayed

跟踪 (可选)

如果你检查在你fork的creating-a-pipeline-in-blue-ocean 仓库的根目录下的Blue Ocean生成的 Jenkinsfile 的内容 , 注意 environment 指令的位置。 该指令在"Test" 阶段的位置意味着环境变量 CI (它的值为true) 只是在"Test"阶段的范围内可用的变量。

你可以在Blue Ocean中设置该指令以便于它的环境变量在整个流水线中都是可用的(和 使用npm构建Node.js 和 React 应用程序 教程中一样)。要做到这一点:

  1. 从Blue Ocean的主界面, 点击右上方的 Branches来访问仓库的 master 分支。

  2. 点击 master 分支的"编辑流水线" 图标 Edit Pipeline on branch为该分支打开流水线编辑器。

  3. 在主流水线编辑器中, 点击 你在 above创建的Test 阶段 开始编辑它。

  4. 在右侧的阶段面板中, 点击 Settings 来显示面板的这一部分。

  5. 点击 CI环境变量(你之前创建的)右边的减 (-) 图标来删除它。

  6. 点击左上的箭头图标 Return from step icon 返回主流水线编辑器。

  7. Pipeline Settings 面板,点击Environment标题右边的 + 图标 (你将为此配置一个 global 环境指令)。

  8. 在出现的 NameValue 域中, 分别指定 CItrue

  9. 点击右上的Save 按钮开始保存你的迁移了环境指令的流水线。

  10. Save Pipeline 对话框的Description域指定提交消息(比如 Make environment directive global)。

  11. 保留所有的其他设置, 点击 Save & run ,Jenkins 继续去构建你的改进后的流水线。

  12. 当出现Blue Ocean 的主界面时, 点击 top 行来查看Jenkins 构建你的流水线项目。 你应该看到与当你添加最终交付阶段(above)完成后相同的构建工程。 然而, 当你再次检查 Jenkinsfile , 你会注意到 environment 指令是 agent 部分的兄弟。

结束语

做得好!您刚刚使用Jenkins的Blue Ocean特性以及npm构建了一个简单的Node.js 和React应用程序!

您在上面创建的 "Build", "Test" 和 "Deliver" 阶段是在Jenkins中使用技术栈构建其他应用程序的基础,包括更复杂的应用程序以及将多个技术栈组合在一起的应用程序。

由于Jenkins具有极高的可扩展性,因此可以对其进行修改和配置,以处理构建协调和自动化的几乎任何方面。

要详细了解Jenkins可以做什么,请查看:

构建多分支流水线项目

Table of Contents

本教程向你展示如何使用Jenkins协调一个用 Node Package Manager (npm) 管理的简单 Node.jsReact 项目, 并同时 为开发和产品环境交付不同的结果。

在开始本教程之前,建议你前往 教程概览 页面,并至少完成一个 介绍教程, 从而让你熟悉持续集成/持续交付概念(不同于你以往熟悉的技术栈)和这些概念在Jenkins中实现方式, 以及Jenkins流水线的基本知识。

本教程你将使用与 构建npm管理的Node.js和React应用 教程相同的应用。然而这一次,项目的交付会根据Jenkins构建不同的Git分支而有所区别。 也就是说,所构建的分支决定你的流水线会执行哪一个交付阶段。

耗时: 假如你的机器符合配置要求,完成本教程需要30-50分钟。 准确的耗时取决于你机器的性能, 以及你是否完成过在Docker中运行Jenkins教程,请参考另一个教程.

你可以在任何时候停止本教程,并从你离开的地方继续。

若你已经完成了另一个教程,可以跳过配置要求在Docker中运行Jenkins章节, 继续阅读fork示例仓库(确保你本地安装了Git)。 如果你需要重启Jenkins,请参考停止和重启Jenkins.

配置要求

对于本教程,您将需要:

  • 安装有macOS,Linux或Windows操作系统的机器,并拥有以下配置:

    • 最小256MB内存, 推荐512MB以上。

    • 10GB硬盘空间, 用于安装Jenkins,您的Docker镜像和容器。

  • 安装有以下软件:

    • Docker - 在安装Jenkins页面的安装Docker章节阅读更多信息。 注意: 如果您使用Linux,本教程假定您没有以root用户的身份运行Docker命令,而是使用单个用户帐户访问本教程中使用的其他工具。

    • GitGitHub Desktop.

在 Docker中运行Jenkins

在本教程中, 将Jenkins作为 Docker 容器并从 jenkinsci/blueocean Docker 镜像中运行。

要在 Docker中运行Jenkins, 请遵循下面的macOS 和 LinuxWindows相关文档说明进行操作。 .

你可以在 DockerInstalling Jenkins 页面的 Downloading and running Jenkins in Docker部分阅读更多有关Docker容器和镜像概念的信息。

在 macOS 和 Linux 系统上

  1. 打开终端窗口

  2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

    docker run \
      --rm \
      -u root \
      -p 8080:8080 \
      -v jenkins-data:/var/jenkins_home \ 
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v "$HOME":/home \ 
      jenkinsci/blueocean
    
     将容器中的 /var/jenkins_home 目录映射到 Docker volume ,并将其命名为 jenkins-data。如果该卷不存在, 那么 docker run 命令会自动为你创建卷。
      将主机上的$HOME 目录 (即你的本地)映射到 (通常是 /Users/ 目录) 到容器的 /home 目录。

    Note: 如果复制或粘贴上面的命令片段不起作用, 尝试复制和粘贴这个没有注释的版本:

    docker run \
      --rm \
      -u root \
      -p 8080:8080 \
      -v jenkins-data:/var/jenkins_home \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v "$HOME":/home \
      jenkinsci/blueocean
    
  3. 继续 安装向导

在 Windows 系统

  1. 打开命令提示窗口。

  2. 使用下面的 docker run 命令运行 jenkinsci/blueocean 镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):

    docker run ^
      --rm ^
      -u root ^
      -p 8080:8080 ^
      -v jenkins-data:/var/jenkins_home ^
      -v /var/run/docker.sock:/var/run/docker.sock ^
      -v "%HOMEPATH%":/home ^
      jenkinsci/blueocean
    

    对这些选项的解释, 请参考上面的 macOS 和 Linux 说明。

  3. 继续安装向导

访问 Jenkins/Blue Ocean Docker 容器

如果你有一些使用 Docker 的经验,希望或需要使用 docker exec 命令通过一个终端/命令提示符来访问 Jenkins/Blue Ocean Docker 容器, 你可以添加如 --name jenkins-tutorials 选项(与上面的 docker run ), 这将会给Jenkins/Blue Ocean Docker容器一个名字 "jenkins-tutorials"。

这意味着你可以通过 docker exec 命令访问Jenkins/Blue Ocean 容器(通过一个单独的终端 /命令提示窗口) ,例如:

docker exec -it jenkins-tutorials bash

安装向导

在你访问 Jenkins之前, 你需要执行一些快速的 "一次性" 步骤。

解锁 Jenkins

当你第一次访问一个新的 Jenkins 实例时, 要求你使用自动生成的密码对其进行解锁。

  1. 当在终端/命令提示窗口出现两组星号时, 浏览 http://localhost:8080 并等待 Unlock Jenkins 页面出现。

    Unlock Jenkins page

  2. 再次从终端/命令提示窗口, 复制自动生成的字母数字密码(在两组星号之间)。 Copying initial admin password

  3. Unlock Jenkins 页面, 粘贴该密码到 Administrator password 字段并点击 Continue

使用插件自定义 Jenkins

解锁 Jenkins后, Customize Jenkins 页面出现。

在该页面,点击 Install suggested plugins

安装向导显示了正在配置的Jenkins的进程,以及建议安装的插件。这个过程肯需要几分钟。

创建第一个管理员用户

最后, Jenkins 要求创建你的第一个管理员用户。

  1. Create First Admin User 页面出现, 在相应的字段中指定你的详细消息并点击 Save and Finish

  2. Jenkins is ready 页面出现, 点击 Start using Jenkins Notes:

    • 该页面可能表明 Jenkins is almost ready! 如果相反, 点击 Restart.

    • 如果该页面在一分钟后没有自动刷新, 使用你的web浏览器手动刷新。

  3. 如果需要,登录 Jenkins , 你就可以开始使用 Jenkins了!

停止和重启 Jenkins

在本教程的其余部分, 你可以通过在终端/命令提示窗口输入 Ctrl-C停止 Jenkins/Blue Ocean Docker 容器,你可以从中运行<>的 docker run ... 命令。

要重启Jenkins/Blue Ocean Docker 容器:

  1. 在上面的 macOS,LinuxWindows上运行相同的 docker run ... 命令 。 Note: 如果有更新的话,该进程会更新 jenkinsci/blueocean Docker 镜像。

  2. 浏览http://localhost:8080

  3. 等待直到登录页面出现并登陆。

Fork 和 clone GitHub示例仓库

通过将应用程序源代码所在的示例仓库fork到你自己的Github账号中, 并clone到本地, 你就可以获取一个"Welcome to React"简单Node.js和React应用程序。

  1. 请确保你登陆了你的GitHub账户。如果你还没有Github账户,你可以在 GitHub网站 免费注册一个账户。

  2. 将示例仓库 building-a-multibranch-pipeline-project fork到你的账户的Github仓库中。在此过程中,如果你需要帮助, 请参考 Fork A Repo 文档。

  3. 将你的GitHub账户中的 simple-java-maven-app 仓库clone到你的本地机器。 根据你的情况完成以下步骤之一(其中 `` 是你的操作系统用户账户名称):

    • 如果你的机器安装了Github Desktop:

      1. 在GitHub网站上,点击绿色的 Clone or download 按钮,再点击 Open in Desktop.

      2. 在Github桌面版中,在点击 Clone a Repository 对话框上的 Clone 按钮之前,确保 Local Path 的配置为:

        • macOS 系统配置为 /Users//Documents/GitHub/building-a-multibranch-pipeline-project

        • Linux 系统配置为 /home//GitHub/building-a-multibranch-pipeline-project

        • Windows 系统配置为 C:\Users\\Documents\GitHub\building-a-multibranch-pipeline-project

    • 其他情况:

      1. 打开一个终端/命令提示符,并且 cd 进入正确的目录路径:

        • macOS 系统路径为 /Users//Documents/GitHub/

        • Linux 系统路径为 /home//GitHub/

        • Windows 系统路径为 C:\Users\\Documents\GitHub\ (推荐使用Git bash命令行,而不是通常的Microsoft命令提示符)

      2. 运行以下命令完成仓库的clone: git clone https://github.com/YOUR-GITHUB-ACCOUNT-NAME/building-a-multibranch-pipeline-project 其中 YOUR-GITHUB-ACCOUNT-NAME 是你的Github账户的名称。

在你的仓库中创建开发和生产分支

在Jenkins中创建流水线项目之前,在你的本地Git仓库中创建"development"和 "production"分支。 你将创建一个单独的Jenkinsfile(最初是在 master 分支,但最终其上的代码会复制到其他分支), 该Jenkinsfile的各个阶段会根据Jenkins所构建的分支不同而被选择性的执行。

building-a-multibranch-pipeline-project 目录路径下(即你的本地clone仓库)

  1. 运行以下命令来创建以上分支(从 master 分支的内容复制):

    • git branch development 以及

    • git branch production

  2. 检查这些分支被成功创建,运行命令 git branch,结果为:

      development
    * master
      production
    
  3. 如果符号*(标识当前分支)未处于 master 的位置,运行命令 git checkout master 以确保 master 是当前分支。

在Blue Ocean中创建你的流水线项目

当你在Blue Ocean中创建 any 流水线项目是 , Jenkins 实际上在后台创建了一个多分支管道项目 。 如果你在Blue Ocean创建了一个流水线项目后,访问 Jenkins的经典界面; 你会看到Jenkins 将你的项目创建为一个 "多分支流水线" 项目。

  1. 回到Jenkins并进入 Blue Ocean 界面。 要做到这点, 确保:

    • 浏览 http://localhost:8080/blue 并登陆+ 或

    • 浏览 http://localhost:8080/, 登录后点击右侧的 Open Blue Ocean

  2. 在Blue Ocean界面中心的 Welcome to Jenkins 框, 点击 Create a new Pipeline 开始流水线构建向导。 Note: 如果你没有看到这个框, 点击右上方的 New Pipeline

  3. Where do you store your code?,点击 Git (not GitHub).

  4. Repository URL 域 (在 Connect to a Git repository里), 指定你aboveclone到本地的仓库的目录路径, 他来自你主机上的 用户账号/主目录 , 映射到Jenkins容器的 /home d目录 - 即

    • macOS - /home/Documents/GitHub/building-a-multibranch-pipeline-project

    • Linux - /home/GitHub/building-a-multibranch-pipeline-project

    • Windows - /home/Documents/GitHub/building-a-multibranch-pipeline-project

  5. 点击k Save 保存你新建的流水线项目。 Blue Ocean 在每个分支中检测 Jenkinsfile "流水线存根" 的存在并运行每条流水线以对抗其各自的分支, 它的构建结果显示在Blue Ocean主界面的 Activity 页面上。+

    Main Blue Ocean interface

 流水线存根包含一条流水线的基本要求 - 即 agentstages 部分, 以及 stage 指令。为什么 building-a-multibranch-pipeline-project 仓库的原因包括Jenkinsfile 流水线存根,它的存在的作用是:在 Blue Ocean中创建流水线项目后能够立刻检测到(即 Jenkinsfile) , 这使得这些分支可以通过Blue Ocean进行访问。如果你在Blue Ocean中构建了一个流水线项目,但在你的仓库的一个或多个分支上没有一个 Jenkinsfile, 随后添加Jenkinsfile 到这些分支中,然后在Blue Ocean中访问这些分支 任一个:在多分支流水线项目中使用 Scan Multibranch Pipeline Now 特性 (可通过 Jenkins的 经典界面进行访问), 或者在 Git 仓库中实现webhooks。
   

将你的带有build 和 test 阶段的初始流水线创建为Jenkinsfile

现在,你已经准备好在Jenkins中创建你的能够自动构建 Node.js 和React 应用程序的流水。 你的流水线将被创建为 Jenkinsfile, 它会提交你本地的Git仓库(building-a-multibranch-pipeline-project)的 master 分支 。

首先, 创建一个初始流水线来下载 Node Docker 镜像并将它作为Docket容器运行,它会构建简单的Node.js 和 React 应用程序。还会添加 "Build" 阶段到流水线,开始编排整个过程和"Test" 阶段 ,检查应用程序呈现的结果是否令人满意。

  1. 使用你最称手的文本编辑器或 IDE, 在本地 building-a-multibranch-pipeline-project Git 仓库的根目录下打开现有的 Jenkinsfileclear 它的内容。 Note: 确保在你的仓库的master 分支上执行了该步骤。

  2. 复制并粘贴下面的声明式流水线代码到空的 Jenkinsfile文件中:

    pipeline {
        agent {
            docker {
                image 'node:6-alpine'
                args '-p 3000:3000 -p 5000:5000' 
            }
        }
        environment {
            CI = 'true'
        }
        stages {
            stage('Build') {
                steps {
                    sh 'npm install'
                }
            }
            stage('Test') {
                steps {
                    sh './jenkins/scripts/test.sh'
                }
            }
        }
    }
    
     args 使 Node 容器 (临时的) 可以通过 3000 和 5000端口进行访问。它的意义在于解释了你clone的仓库的 jenkins/scripts/deliver-for-deployment.shjenkins/scripts/deploy-for-production.sh 文件, 这将在本教程的后续部分中介绍。
       

    Note:Jenkinsfile中其他组件的解释, 请参考使用npm构建Node.js和React应用教程的“Create your initial Pipeline…”“Add a test stage…”章节的声明式流水线的注解。 .

  3. 保存并提交你编辑的 Jenkinsfile 文件到本地的 building-a-multibranch-pipeline-project Git 仓库。 比如在 building-a-multibranch-pipeline-project 目录下, 运行下面的命令: git stage . 然后 git commit -m "Add initial Jenkinsfile with 'Test' stage"

  4. 再次回到Jenkins, 必要的话再次登录并进入 Jenkins的Blue Ocean的界面。

  5. 点击右上方的 Branches 进入你的流水线项目的分支列表。 Branches page

  6. 点击你的流水线项目的 master 分支的运行图标 Run icon , 然后快速的点击出现在右下方的 OPEN 链接来查看Jenkins 使用改进后的 Jenkinsfile构建 master 分支。 如果你点击不了OPEN 链接, 点击Blue Ocean Activity 页面 的top 行来使用这一特性。 在几分钟内, 如果Jenkins成功的从你的 master分支构建了 Node.js 和 React 应用程序,Blue Ocean界面就会变成绿色。

    Build and test stages run successfully with output

  7. 点击右上方的 X 回到Blue Ocean 界面的 Activity 页面。

给你的流水线添加deliver和 deploy 阶段

接下来, 添加 "交付开发" 和 "部署生产" 阶段到你的流水线,Jenkins将会根据Jenkins所在的分支选择性的执行。

这将 "流水线即代码" 概念提升到一个新的级别, 在这个级别中, 一个单一的 Jenkinsfile 文件描述了在Jenkins中你的仓库的每个分支的整个项目的构建, 测试, 交付和部署过程。 了解更多在用户手册的 流水线使用Jenkinsfile章节。

  1. 回到你的文本编辑器/IDE,打开Jenkinsfile 文件。

  2. 立刻复制并粘贴下面的声明式流水线语法到Jenkinsfile文件的 Test 阶段下面:

            stage('Deliver for development') {
                when {
                    branch 'development'
                }
                steps {
                    sh './jenkins/scripts/deliver-for-development.sh'
                    input message: 'Finished using the web site? (Click "Proceed" to continue)'
                    sh './jenkins/scripts/kill.sh'
                }
            }
            stage('Deploy for production') {
                when {
                    branch 'production'
                }
                steps {
                    sh './jenkins/scripts/deploy-for-production.sh'
                    input message: 'Finished using the web site? (Click "Proceed" to continue)'
                    sh './jenkins/scripts/kill.sh'
                }
            }
    

    结果如下:

    pipeline {
        agent {
            docker {
                image 'node:6-alpine'
                args '-p 3000:3000 -p 5000:5000'
            }
        }
        environment {
            CI = 'true'
        }
        stages {
            stage('Build') {
                steps {
                    sh 'npm install'
                }
            }
            stage('Test') {
                steps {
                    sh './jenkins/scripts/test.sh'
                }
            }
            stage('Deliver for development') {
                when {
                    branch 'development' 
                }
                steps {
                    sh './jenkins/scripts/deliver-for-development.sh'
                    input message: 'Finished using the web site? (Click "Proceed" to continue)'
                    sh './jenkins/scripts/kill.sh'
                }
            }
            stage('Deploy for production') {
                when {
                    branch 'production'  
                }
                steps {
                    sh './jenkins/scripts/deploy-for-production.sh'
                    input message: 'Finished using the web site? (Click "Proceed" to continue)'
                    sh './jenkins/scripts/kill.sh'
                }
            }
        }
    }
    
     when 指令 (和它们的branch 条件一起)决定是否 stages (包括这些 when 指令) 会被执行。 如果 branch 条件的值(即模式) 与Jenkins运行构建的分支名匹配, 包含 whenbranch 概念的stage 就会被执行。
       

    Notes:

  3. 保存并提交你编辑的 Jenkinsfile 到本地的 building-a-multibranch-pipeline-project Git 仓库。 比如在 building-a-multibranch-pipeline-project 目录, 运行命令: git stage . 然后 git commit -m "Add 'Deliver...' and 'Deploy...' stages"

  4. 再次回到Jenkins, 如果必要重新登录并进入Jenkins的Blue Ocean界面。

  5. 点击右上方的 Branches 来访问你的流水线项目的分支列表。

  6. 点击你的流水线项目的master分支的运行图标 Run icon ,然后快速的点击出现在右下方的 OPEN 链接查看Jenkins使用改进过的 Jenkinsfile构建 master 分支。I如果你点击不了 OPEN 链接, 点击Blue Ocean Activity 页面的 top 行来访问这一特性。 注意Jenkins是如何跳过你添加的最后两个阶段, 由于你正在运行构建的分支 (master) 在这些阶段不满足 when 指令的 branch 条件。

    Complete Pipeline runs successfully on the <em>master</em> branch

  7. C点击右上方的 X 回到Blue Ocean界面的 Activity 页面。

Pull 更新的 Jenkinsfile 到其他的仓库分支中

现在你已经有一个完整的 Jenkinsfile 文件可以在Jenkins中构建你的应用, 你可以 pull 该文件从你本地仓库的 master 分支到它的 developmentproduction 分支。 在你本地仓库的 building-a-multibranch-pipeline-project 目录下:

  1. 运行下面的命令来来pull从masterdevelopment的改变:

    • git checkout development 然后

    • git pull . master

  2. 还可以运行线面的命令将更改从 master pull到 production:

    • git checkout production 然后

    • git pull . master

    现在你的 developmentproduction 分支拥有你在 master 分支上对 Jenkinsfile 的所有修改。

在development分支上运行流水线

  1. 再次回到 Jenkins, 需要的话再次登录并进入 Jenkins的Blue Ocean界面。

  2. 点击右上的 Branches 进入流水线项目的分支列表。

  3. 点击流水线项目development 分支的运行图标 Run icon, 然后快速的点击出现在右下方的 OPEN 链接来查看Jenkins 使用改进后的 Jenkinsfile构建 development 分支。 如果你点击不了 OPEN 链接, 点击Blue Ocean的 Activity 页面上的 top 行来访问这一特性。

  4. 在几分钟,当构建停止时, 确保你正在查看 Deliver for development 阶段 (如果需要点击它), 然后点击顶部绿色的Shell Script 步骤来扩展它的内容 并向下滚动直到你看见 http://localhost:3000 链接。

    Shell Script step <em>Deliver for development</em> stage opened Note: 由于你正在不同的分支上构建应用程序, npm install 步骤需要几分钟为npm下载运行Node.js 和 React 应用所需的一些依赖 (保存在Jenkins主目录的node_modules 目录下)。由于这次的Jenkins构建是你的流水线项目在 development 分支上的第一次运,并且每个分支都会在Jenkins的主目录中有他自己的工作区目录(包括他自己的node_modules 目录),这些依赖被再次下载。

  5. 点击 http://localhost:3000 链接查看Node.js 和 React 应用在开发模式下在一个新的web浏览器选项卡中运行 (使用 npm start 命令) 。 你应该会看到一个标题为 Welcome to React的页面/站点。

  6. 当你查看完页面/站点, 在Blue Ocean点击 Proceed 按钮完成流水线的执行。 如果Jenkins成功在development 分支上构建Node.js 和 React 应用程序,Blue Ocean界面就会变成绿色。注意 Deliver for development 阶段是如何被执行的 ,而Deploy for production 阶段却没有执行。

    Complete Pipeline runs successfully on the <em>development</em> branch

  7. 点击右上方的 X 回到Blue Ocean界面的Activity 页面。

在production分支上运行流水线

  1. 点击右上方的 Branches 来访问你的流水线项目的分支列表。

  2. 点击你的流水线项目的production分支的运行图标 Run icon, 然后快速的点击出现在右下方的 OPEN 链接查看Jenkins使用改进后的 Jenkinsfile构建production 分支。如果 你不能点击 OPEN 链接, 点击Blue Ocean Activity 页面的 top 行来访问这一特性。

  3. 在几分钟内,当构建停止时, 确保你正在查看 Deploy for production 阶段 (如果必要点击它), 然后点击顶部绿色的Shell Script 步骤来扩展它的内容并向下滚动直到你看到http://localhost:5000 链接。 Shell Script step <em>Deploy for production</em> stage opened

  4. 点击 http://localhost:5000 链接在一个新的web浏览器选项卡中查看你的Node.js 和 React应用。他将会在生产模式下从你的源代码的生产构建开始运行(使用 npm run build 命令生产)。 同样的, 你会看到一个标题为Welcome to React的页面/站点 然而, 这一次, 该应用程序的内容是由 npm serve module提供的,并且很可能会继续在你浏览器的后台运行。

  5. 当你查看完网页/站点, 在Blue Ocean中点击 Proceed 按钮 完成流水线的执行。 如果Jenkins 从production分支成功 production构建你的Node.js 和 React 应用,Blue Ocean界面就会变成绿色。 注意 Deploy for production 阶段是如何被执行的,而 Deliver for development 阶段被跳过。

    Complete Pipeline runs successfully on the <em>production</em> branch

  6. 点击右上方的 X 回到Blue Ocean界面的 Activity p页面。+ Note: 由于你的浏览器很可能会继续运行npm serve 模块提供的应用内容, 在Jenkins关闭serve 进程后,你的浏览器仍然会长时间显示你在http://localhost:5000查看过的内容 。 在below阅读更多关于如何从你的浏览器清除应用程序和它的内容。

跟踪 (可选)

本节将向你介绍使用Jenkins的一种类似的开发工作流程,在它们被部署到生产 (从 production 分支)前,从development分支经由master 分支对你的应用程序 (即 App.js 源文件) 进行更改。

  1. 在你本地仓库的 building-a-multibranch-pipeline-project 目录下, 运行命令 git checkout development 更改 development 分支。

  2. 回到你的文本编辑器/IDE,打开你本地的building-a-multibranch-pipeline-project Git仓库的 src目录下的 App.js 文件。

  3. 立刻复制并粘贴下面的HTML语法到App.js文件的To get started… 行下面:

              <br/>
              This is a new line I added.
    

    结果如下:

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    
    class App extends Component {
      render() {
        return (
          <div className="App">
            <header className="App-header">
              <img src={logo} className="App-logo" alt="logo" />
              <h1 className="App-title">Welcome to React</h1>
            </header>
            <p className="App-intro">
              To get started, edit <code>src/App.js</code> and save to reload.
              <br/>
              This is a new line I added.
            </p>
          </div>
        );
      }
    }
    
    export default App;
    
  4. 保存并提交你编辑的 App.js 文件到你本地的 building-a-multibranch-pipeline-project Git仓库。 比如在 building-a-multibranch-pipeline-project 目录下, 运行命令: git stage . 然后 git commit -m "Update 'App.js'"

  5. 回到Blue Ocean, 在 development 分支运行你的流水线 (如 above所述) 并通过 http://localhost:3000检查结果以查看新添加的行。

  6. 假设你对该更改感到满意, 在你本地仓库的 building-a-multibranch-pipeline-project 目录下, 运行下面一系列的命令 pull 你的更改到 production 分支 (via the master 分支):

    • git checkout master 然后

    • git pull . development 然后

    • git checkout production 接着

    • git pull . master

  7. 回到 Blue Ocean, 这次在 production分支运行你的流水线 (和你在 <>中做的一样) 并通过 http://localhost:5000 检查结果,以查看你新添加的行 。 Notes:

    • 由于你的浏览器很可能会缓存 npm serve 模块的内容, 你需要刷新你的浏览器页面以查看你的更改。

    • 在一个真正的软件开发环境中,对于大型团队来说, 在云或web托管的 Git 服务上 (如 GitHub或BitBucket)使用pull请求,更有可能在分支之间pull变更。

从你的浏览器中清除应用程序

你的浏览器很有可能继续运行由npm serve module提供的应用的内容, 这意味着在 Jenkins 中止 serve 进程后,你的浏览器仍然会长时间显示你在http://localhost:5000查看的内容。 从浏览器中清除应用程序以及内容:

在Chrome

  1. 在你浏览器的 URL 域输入以下内容: chrome://serviceworker-internals/

  2. 将 "ServiceWorker" 条目定位到 http://localhost:5000

  3. 点击 Unregister 按钮。

在Firefox

  1. 在你浏览器的 URL 域输入以下内容: about:serviceworkers

  2. 将 "Registered Service Worker" 条目定位到 http://localhost:5000

  3. 点击 Unregister 按钮。

结束语

做得好!您刚刚使用Jenkins通过npm构建了一个有选择的运行阶段的多分支流水线项目!

本教程展现了Jenkins 使用一个 Jenkinsfile 在你的仓库的多个分支中编排不同的构建和交付结果的能力。

由于Jenkins具有极高的可扩展性,因此可以对其进行修改和配置,以处理构建协调和自动化的几乎任何方面。

要详细了解Jenkins可以做什么,请查看:

 

 

用户手册概述

本页提供Jenkins用户手册文档概述

如果您是初次使用Jenkins,请参阅 安装Jenkins 以了解如何在支持的平台上安装Jenkins

如果您已经是Jenkins用户 (任何技能水平) 想要进一步了解Jenkins的使用, 请参阅 使用 Jenkins. 或者参阅PipelineBlue Ocean 独立章节以获取关于Jenkins核心特性的更多信息

如果您是Jenkins管理员,想要了解有关管理Jenkins节点和实例的更多信息,请参阅 管理 Jenkins.

如果您是系统管理员,想要了解如何备份、恢复和维护Jenkins服务器和节点,请参阅 Jenkins 系统管理.


索引

安装Jenkins ⇒

安装Jenkins

Table of Contents

本节的步骤适用于单个/本地机器上的Jenkins新安装。

Jenkins通常作为一个独立的应用程序在其自己的流程中运行, 内置Java servlet 容器/应用程序服务器(Jetty)。

Jenkins也可以运行在不同的Java servlet容器((如Apache TomcatGlassFish))中作为servlet运行.但是设置这些类型的安装的说明超出了本页的范围

注意:尽管此页面重点关注Jenkins的本地安装,但此内容也可用于帮助在生产环境中设置Jenkins。

系统要求

最低推荐配置:

  • 256MB可用内存

  • 1GB可用磁盘空间(作为一个Docker容器运行jenkins的话推荐10GB)

为小团队推荐的硬件配置:

  • 1GB+可用内存

  • 50 GB+ 可用磁盘空间

软件配置:

  • Java 8—无论是Java运行时环境(JRE)还是Java开发工具包(JDK)都可以。

注意: 如果将Jenkins作为Docker 容器运行,这不是必需的

安装平台

本节介绍如何在不同的平台和操作系统上安装/运行Jenkins。

Docker

Docker是一个在称为“容器”(或Docker容器)的孤立环境中可运行应用程序的平台。 像Jenkins这样的应用程序可以作为只读的“镜像”(或Docker镜像)下载, 每个镜像都作为容器在Docker中运行。Docker容器实际上是Docker镜像的“运行实例”。 从这个角度来看,镜像永久存储(只要镜像更新发布),而容器暂时存储。 在Docker文档的入门指南,Getting Started, Part 1: Orientation and setup页面中阅读有关这些概念的更多信息 。

Docker的基础平台和容器设计意味着可以在任何支持的操作系统(macOS,Linux和Windows) 或云服务(AWS和Azure)上运行单个Docker镜像(对于任何给定的应用程序,如Jenkins)。

安装Docker

要在您的操作系统上安装Docker,请访问 Docker store网站并单击适用于您的操作系统或云服务的Docker Community Edition框。 按照其网站上的安装说明进行操作。

Jenkins也可以在Docker企业版上运行,您可以通过 Docker商店网站上的Docker EE访问它。

[ CAUTION]

如果您要在基于Linux的操作系统上安装Docker,请确保配置Docker,以便它可以作为非root用户进行管理。 在Docker的Post-installation steps for Linux网页中了解更多关于它 的文档。 如何将Docker配置为默认启动的方式也可在此文档中查找。

在Docker中下载并运行Jenkins

几个可用的Jenkins Docker镜像.

建议使用的Docker映像是jenkinsci/blueocean image(来自 the Docker Hub repository)。 该镜像包含当前的长期支持 (LTS) 的Jenkins版本 (可以投入使用) ,捆绑了所有Blue Ocean插件和功能。这意味着你不需要单独安装Blue Ocean插件。

 jenkinsci/blueocean每次发布Blue Ocean新版本时,都会发布新镜像。您可以在标签 page页上看到以前发布的镜像版本列表 。您还可以使用其他Jenkins Docker镜像(在Docker Hub上可通过jenkins/jenkins获取)。 但是,这些不会随Blue Ocean的发布而提供,需要通过 Jenkins中的Manage Jenkins > Manage Plugins页面进行安装。 在Blue Ocean入门中了解更多信息。
   
在macOS和Linux上
  1. 打开一个终端窗口。

  2. 下载 jenkinsci/blueocean 镜像并使用以下docker run 命令将其作为Docker中的容器运行 :

    docker run \
      -u root \
      --rm \  
      -d \ 
      -p 8080:8080 \ 
      -p 50000:50000 \ 
      -v jenkins-data:/var/jenkins_home \ 
      -v /var/run/docker.sock:/var/run/docker.sock \ 
      jenkinsci/blueocean 
    
     (可选) jenkinsci/blueocean 关闭时自动删除Docker容器(下图为实例)。如果您需要退出Jenkins,这可以保持整洁。
      (可选)jenkinsci/blueocean 在后台运行容器(即“分离”模式)并输出容器ID。如果您不指定此选项, 则在终端窗口中输出正在运行的此容器的Docker日志。
      映射(例如“发布”)jenkinsci/blueocean 容器的端口8080到主机上的端口8080。 第一个数字代表主机上的端口,而最后一个代表容器的端口。因此,如果您为此选项指定 -p 49000:8080 ,您将通过端口49000访问主机上的Jenkins。
      (可选)将 jenkinsci/blueocean 容器的端口50000 映射到主机上的端口50000。 如果您在其他机器上设置了一个或多个基于JNLP的Jenkins代理程序,而这些代理程序又与 jenkinsci/blueocean 容器交互(充当“主”Jenkins服务器,或者简称为“Jenkins主”), 则这是必需的。默认情况下,基于JNLP的Jenkins代理通过TCP端口50000与Jenkins主站进行通信。 您可以通过“ 配置全局安全性” 页面更改Jenkins主服务器上的端口号。如果您要将您的Jenkins主机的JNLP代理端口的TCP端口 值更改为51000(例如),那么您需要重新运行Jenkins(通过此 docker run …命令)并指定此“发布”选项 -p 52000:51000,其中最后一个值与Jenkins master上的这个更改值相匹配,第一个值是Jenkins主机的主机上的端口号, 通过它,基于JNLP的Jenkins代理与Jenkins主机进行通信 - 例如52000。
      (可选,但强烈建议)映射在容器中的/var/jenkins_home 目录到具有名字 jenkins-datavolume。 如果这个卷不存在,那么这个 docker run 命令会自动为你创建卷。 如果您希望每次重新启动Jenkins(通过此 docker run ... 命令)时保持Jenkins状态,则此选项是必需的 。 如果你没有指定这个选项,那么在每次重新启动后,Jenkins将有效地重置为新的实例。 注意: 所述的 jenkins-data 卷也可以 docker volume create命令创建: docker volume create jenkins-data 代替映射 /var/jenkins_home 目录转换为Docker卷,还 可以将此目录映射到计算机本地文件系统上的目录。 例如,指定该选项 -v $HOME/jenkins:/var/jenkins_home 会将容器的 /var/jenkins_home 目录映射 到 本地计算机上目录中的 jenkins 子目录, 该$HOME目录通常是 /Users//jenkins/home/<your-username>/jenkins
      (可选 /var/run/docker.sock 表示Docker守护程序通过其监听的基于Unix的套接字。 该映射允许 jenkinsci/blueocean 容器与Docker守护进程通信, 如果 jenkinsci/blueocean 容器需要实例化其他Docker容器,则该守护进程是必需的。 如果运行声明式管道,其语法包含agent部分用 docker例如, agent { docker { ... } } 此选项是必需的。 在Pipeline Syntax 页面上阅读更多关于这个的信息 。
      jenkinsci/blueocean Docker镜像本身。如果此镜像尚未下载,则此 docker run 命令 将自动为您下载镜像。此外,如果自上次运行此命令后发布了此镜像的任何更新, 则再次运行此命令将自动为您下载这些已发布的镜像更新。 注意:这个Docker镜像也可以使用以下 docker pull命令独立下载(或更新) : docker pull jenkinsci/blueocean 注意: 如果复制并粘贴上面的命令片段不起作用,请尝试在此处复制并粘贴此无注释版本:docker run \ -u root \ --rm \ -d \ -p 8080:8080 \ -p 50000:50000 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ jenkinsci/blueocean
  3. 继续按照Post-installation setup wizard安装。

在Windows上
  1. 打开命令提示符窗口。

  2. 下载 jenkinsci/blueocean 镜像并使用以下 docker run 命令将其作为Docker中的容器运行 :

    docker run ^
      -u root ^
      --rm ^
      -d ^
      -p 8080:8080 ^
      -p 50000:50000 ^
      -v jenkins-data:/var/jenkins_home ^
      -v /var/run/docker.sock:/var/run/docker.sock ^
      jenkinsci/blueocean
    

    有关这些选项的解释,请参阅上面的在macOS和Linux上

  3. 继续按照Post-installation setup wizard安装。

访问Jenkins / Blue Ocean Docker容器

如果您对Docker有一些经验,并且您希望或需要 jenkinsci/blueocean 通过 命令提示符通过终端/命令提示符访问docker exec ,则可以添加一个选项 --name jenkins-blueocean(如 docker run 所述),这会为 jenkinsci/blueocean 容器命名为 "jenkins-blueocean" 。

这意味着你可以使用如下命令访问容器(通过单独的终端/命令提示符窗口) :

docker exec -it jenkins-blueocean bash

通过Docker日志访问Jenkins控制台日志

您可能需要访问Jenkins控制台日志。例如,在解锁 Jenkins 作为安装后设置向导的一部分时。

如果没有指定分离模式选项 -ddocker run ... 命令以上, 那么Jenkins控制台日志是通过终端方便/命令从中运行此Docker命令提示符窗口。

否则,您可以通过访问Jenkins控制台日志 Docker logs中 的 jenkinsci/blueocean ,使用以下命令:

docker logs 

Your ` can be obtained using the [docker ps](https://docs.docker.com/engine/reference/commandline/ps/) command. If you specified the--name jenkins-blueoceanoption in thedocker run ...command above (see also [Accessing the Jenkins/Blue Ocean Docker container](https://www.jenkins.io/zh/doc/book/installing/#accessing-the-jenkins-blue-ocean-docker-container)), you can simply use thedocker logs` command:

您的 ` 可以使用[docker ps](https://docs.docker.com/engine/reference/commandline/ps/) 命令获得 。如果您在上述docker run ...命令中指定了--name jenkins-blueocean参数(请参阅[访问Jenkins/Blue Ocean Docker容器](https://www.jenkins.io/zh/doc/book/installing/#accessing-the-jenkins-blue-ocean-docker-container)) ,则只需使用以下docker logs` 命令:

docker logs jenkins-blueocean

访问Jenkins主目录

例如,您可能需要访问Jenkins主目录,以查看 workspace 子目录中Jenkins版本的详细信息。

如果您将Jenkins主目录( /var/jenkins_home )映射到您计算机 本地文件系统上的一个目录(如上面的 docker run ... 命令 ), 那么您可以通过计算机常用的终端/命令提示符访问此目录的内容。

否则,如果您在 docker run ... 命令里指定了 -v jenkins-data:/var/jenkins_home 选项, 则可以 jenkinsci/blueocean 使用以下 docker exec 命令通过容器的终端/命令提示符访问Jenkins主目录的内容:

docker exec -it  bash

上面所提到, 您的 ` 可以使用来获得 [docker ps](https://docs.docker.com/engine/reference/commandline/ps/) 命令。如果您在docker run ...中指定了--name jenkins-blueocean该选项(也可参照 [访问Jenkins / Blue Ocean Docker容器](https://www.jenkins.io/zh/doc/book/installing/#accessing-the-jenkins-blue-ocean-docker-container))), 则只需使用以下docker exec` 命令:

docker exec -it jenkins-blueocean bash

WAR文件

Jenkins的Web应用程序ARchive(WAR)文件版本可以安装在任何支持Java的操作系统或平台上。

要下载并运行Jenkins的WAR文件版本,请执行以下操作:

  1. 最新的稳定Jenkins WAR包 下载到您计算机上的相应目录。

  2. 在下载的目录内打开一个终端/命令提示符窗口到。

  3. 运行命令java -jar jenkins.war

  4. 浏览http://localhost:8080并等到Unlock Jenkins页面出现。

  5. 继续使用Post-installation setup wizard后面步骤设置向导。

最新的稳定Jenkins WAR包下载到您计算机上的相应目录。

Notes:

  • 不像在Docker中下载和运行有Blue Ocean的Jenkins,这个过程不会自动安装Blue Ocean功能, 这将分别需要在jenkins上通过 Manage Jenkins > Manage Plugins安装。 在Getting started with Blue Ocean有关于安装Blue Ocean的详细信息 。.

  • 您可以通过--httpPort在运行java -jar jenkins.war命令时指定选项来更改端口。例如,要通过端口9090访问Jenkins,请使用以下命令运行Jenkins: java -jar jenkins.war --httpPort=9090

苹果系统

从网站安装的话使用这个包:

Jenkins 也可以使用brew以下方式安装:

  • 安装最新版本

brew install jenkins
  • 安装 LTS 版本

brew install jenkins-lts

Linux

Debian/Ubuntu

在基于Debian的发行版(如Ubuntu)上,您可通过apt安装Jenkins

an apt repository可获得最新版本,较老但稳定的LTS版本在this apt repository这里可获得

wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

安装这个软件包将会:

  • 将Jenkins设置为启动时启动的守护进程。查看/etc/init.d/jenkins获取更多细节

  • 创建一个'jenkins'用户来运行此服务

  • 直接将控制台日志输出到文件/var/log/jenkins/jenkins.log。如果您正在解决Jenkins问题,请检查此文件

  • /etc/default/jenkins`为启动填充配置参数,例如JENKINS_HOME

  • 将Jenkins设置为在端口8080上进行监听。使用浏览器访问此端口以开始配置

 如果你的/etc/init.d/jenkins文件无法启动Jenkins,编辑/etc/default/jenkins, 修改 ----HTTP_PORT=8080--------HTTP_PORT=8081---- 在这里,“8081”也可被换为其他可用端口。
   

Windows

从网站安装的话, 请使用安装程序:

其他操作系统

OpenIndiana Hipster

在运行OpenIndiana Hipster的系统上 , 可以使用Image Packaging System (IPS)将Jenkins安装在本地或全局区域中 。

 免责声明:这个平台不是由Jenkins团队正式支持的,使用它需要您自担风险。 本节中描述的打包和集成由OpenIndiana Hipster团队维护,捆绑通用的jenkins.war 到该操作环境中工作。
   

对于运行每周最新的版本包作为独立服务器这种常见情景,只需执行:

pkg install jenkins
svcadm enable jenkins

上面命令将会发生:

  • 创建一个jenkins用户来运行该服务并拥有其下的目录结构/var/lib/jenkins

  • Pull the OpenJDK8 and other packages required to execute Jenkins, including the jenkins-core-weekly package with the latest jenkins.war

     长期支持(LTS)的Jenkins版本目前不支持基于OpenZFS的系统,因此目前没有提供包安装
       
  • 将Jenkins设置为SMF服务实例(svc:/network/http:jenkins),然后可以使用上面的svcadm命令启用它。

  • 设置Jenkins监听8080端口。

  • 配置log输出文件/var/svc/log/network-http:jenkins.log,由SMF管理.

一旦jenkins运行,看log(/var/svc/log/network-http:jenkins.log), 一般在 /var/lib/jenkins/home/secrets/initialAdminPassword里可以获取jenkins初始化的管理员密码. 然后进入localhost:8080 to complete configuration of the Jenkins instance来完成Jenkins实例的配置。 Jenkins instance>>.

要更改服务的属性(如环境变量JENKINS_HOME 或用于Jetty Web服务器的端口号),请使用svccfg

svccfg -s svc:/network/http:jenkins editprop
svcadm refresh svc:/network/http:jenkins

您还可以参考/lib/svc/manifest/network/jenkins-standalone.xml 获取有关当前支持的SMF服务可调参数的更多详细信息和评论。 请注意,由packaging创建的jenkins用户帐户有特殊的特权,允许绑定1024以下的端口号。

可用于OpenIndiana特定版本的Jenkins相关软件包的当前状态可以通过查询:

pkg info -r '*jenkins*'

升级包可以通过更新整个操作环境来执行pkg update,或者专门针对Jenkins核心软件进行更新:

pkg update jenkins-core-weekly
 更新软件包的过程将重新启动当前运行的Jenkins进程。 如果确定需要更新,请确保在更新之前准备好关闭并完成所有正在运行的作业
   

Solaris, OmniOS, SmartOS, and other siblings

一般来说,应该满足:安装Java 8和download jenkins.war, 并运行它作为一个独立的进程或应用服务器,比如Apache Tomcat

一些注意事项:

  • Headless JVM and fonts: For OpenJDK builds on minimalized-footprint systems, there may be issues running the headless JVM, because Jenkins needs some fonts to render certain pages. Headless模式JVM和字体:为了OpenJDK构建在占用空间最小的系统上, 请看链接issues running the headless JVM, 因为Jenkins需要一些字体来渲染某些页面。

  • ZFS相关的JVM崩溃:当Jenkins在SunOS系统上运行时,它会通过使用bundledlibzfs.jar映射从Java到主机操作系统提供的libzfs.so尝试加载集成高级ZFS功能。 不幸的是,该库是为了在操作系统中构建和捆绑的二进制实用程序,同时与它一起制作, 并不是作为一个稳定界面显示给消费者的。作为Solaris遗留的分支, 包括ZFS以及随后的OpenZFS计划的发展,许多不同的二进制功能签名由不同的主机操作系统提供。 当Jenkinslibzfs.jar调用错误的签名时,整个JVM进程崩溃jenkins.war自从发布2.55(至今尚未在任何LTS中)以来,提出并整合了一个解决方案。 使管理员能够配置哪些功能签名应该用于已知具有不同变体的每个功能, 将其应用于其应用程序服务器初始化选项,然后运行和更新通用而不需要进一步的解决方法。 有关更多详细信息,请参阅 the libzfs4j Git repository, 包括尝试使用脚本并“锁定”您特定分发所需的配置(特别是如果您的内核更新带来新的不兼容libzfs.so)。

另外请注意,OpenZFS计划的分支可能会在各种BSD,Linux和macOS发行版上提供ZFS。 一旦Jenkins支持检测ZFS功能,而不是依赖于SunOS检查,则应考虑上述与Jenkins集成ZFS的注意事项。

安装后设置向导

下载安装并运行Jenkins后,即将开始进入安装向导。

此安装向导会引导您完成几个快速“一次性”步骤来解锁Jenkins, 使用插件对其进行自定义,并创建第一个可以继续访问Jenkins的管理员用户。

解锁 Jenkins

当您第一次访问新的Jenkins实例时,系统会要求您使用自动生成的密码对其进行解锁。

  1. 浏览到 http://localhost:8080(或安装时为Jenkins配置的任何端口),并等待 解锁 Jenkins 页面出现。

Unlock Jenkins page

  1. 从Jenkins控制台日志输出中,复制自动生成的字母数字密码(在两组星号之间)。

Copying initial admin password

  1. 解锁Jenkins 页面上,将此 密码 粘贴到管理员密码字段中,然后单击 继续

Notes:

  • 如果您以分离模式在Docker中运行Jenkins,则可以从Docker日志(above) 访问Jenkins控制台日志。

  • Jenkins控制台日志显示可以获取密码的位置(在Jenkins主目录中)。 必须在新Jenkins安装中的安装向导中输入此密码才能访问Jenkins的主UI。 如果您在设置向导中跳过了后续的用户创建步骤, 则此密码还可用作默认admininstrator帐户的密码(使用用户名“admin”)

自定义jenkins插件

解锁 Jenkins之后,在 Customize Jenkins 页面内, 您可以安装任何数量的有用插件作为您初始步骤的一部分。

两个选项可以设置:

  • 安装建议的插件 - 安装推荐的一组插件,这些插件基于最常见的用例.

  • 选择要安装的插件 - 选择安装的插件集。当你第一次访问插件选择页面时,默认选择建议的插件。

 如果您不确定需要哪些插件,请选择 安装建议的插件 。 您可以通过Jenkins中的Manage Jenkins > Manage Plugins 页面在稍后的时间点安装(或删除)其他Jenkins插件 。
   

设置向导显示正在配置的Jenkins的进程以及您正在安装的所选Jenkins插件集。这个过程可能需要几分钟的时间

创建第一个管理员用户

最后,在customizing Jenkins with plugins之后,Jenkins要求您创建第一个管理员用户。 . 出现“ 创建第一个管理员用户 ”页面时, 请在各个字段中指定管理员用户的详细信息,然后单击 保存完成 。 . 当 Jenkins准备好了 出现时,单击开始使用 Jenkins

Notes: * 这个页面可能显示 Jenkins几乎准备好了! 相反,如果是这样,请单击 重启 。 * 如果该页面在一分钟后不会自动刷新,请使用Web浏览器手动刷新页面。如果需要,请使用您刚刚创建的用户的凭据登录到Jenkins,并准备好开始使用Jenkins!

 从这时起,Jenkins用户界面只能通过提供有效的用户名和密码凭证来访问。
   

⇐ 用户手册概述

索引

使用 Jenkins ⇒

 

使用 Jenkins

子章节

本章节包含一般Jenkins用户(任何技能水平)关于Jenkins使用的主题, 这些用例不包含Jenkins核心特性:Pipeline和Blue Ocean

如果您想要通过JenkinsFile或者Blue Ocean 创建、配置Pipeline项目,或者希望了解更多Jenkins核心特性,请参阅 PipelineBlue Ocean 章节.

如果您是 Jenkins 管理员,想要了解有关管理Jenkins节点和实例的更多信息,请参阅 管理 Jenkins.

如果您是系统管理员,想要了解如何备份、恢复和维护Jenkins服务器和节点,请参阅 Jenkins 系统管理.

有关Jenkins用户手册内容概述,请参照 用户手册概述


⇐ 安装Jenkins

索引

使用 credentials ⇒

 

使用 credentials

Table of Contents

许多三方网站和应用可以与Jenkins交互,如Artifact仓库,基于云的存储系统和服务等

此类应用的系统管理员可以在应用程序中配置 credentials 供Jenkins使用,通常将访问控制应用于这些 credentials, 以“锁定”Jenkins可用的应用程序功能区域。一旦Jenkins管理员(即管理Jenkins站点的用户) 在Jenkins中添加/配置这些 credentials,Pipeline项目就可以使用 credentials 与三方应用交互

注意: 在当前和相关页面描述的Jenkins credentials功能由 Credentials Binding 插件提供。

存储在Jenkins中的credentials可以被使用:

Jenkins可以存储以下类型的credentials:

  • Secret text - API token之类的token (如GitHub个人访问token),

  • Username and password - 可以为独立的字段,也可以为冒号分隔的字符串:username:password(更多信息请参照 处理 credentials),

  • Secret file - 保存在文件中的加密内容

  • SSH Username with private key - SSH 公钥/私钥对,

  • Certificate - a PKCS#12 证书文件 和可选密码

  • Docker Host Certificate Authentication credentials.

Credential 安全

为了最大限度地提高安全性,在Jenins中配置的 credentials 以加密形式存储在Jenkins 主节点上(用Jenkins ID加密),并且只能通过 credentials ID在Pipeline项目中获取

这最大限度地减少了向Jenkins用户公开credentials真实内容的可能性,并且阻止了将credentials复制到另一台Jenkins实例

配置 credentials

本节介绍在Jenkins中配置 credentials 的过程

Jenkins用户可以把credentials添加到Jenkins中,该用户具有 Credentials > Create 权限 (通过 基于Matrix的安全设置 )。这些权限可以由具有 管理员 权限的用户配置. Read more 在 授权 部分的 安全管理中了解更多信息

如果Jenkins的 配置全局安全性授权 设置为默认值,那么任何Jenkins用户都可以添加和配置credentials, 设置页面将被置为默认: 登录用户可以执行任何设置 或者 任何人都可以执行任何设置

添加新的global credentials

要向Jenkins实例添加新的全局credentials

  1. 如果需要,请确保您已经登录到Jenkins (作为拥有 Credentials > Create 权限的用户).

  2. 从Jenkins主页(即Jenkins经典UI的仪表板) 点击左侧的 Credentials > System

  3. System 中, 点击 Global credentials (无限制) 链接以访问默认域。

  4. 点击左侧的 添加 Credentials 注意: 如果此默认域中没有 credentials,你也可以点击 添加某些 credentials 链接 (与点击 添加 Credentials 相同).

  5. Kind 字段中,选择要添加的 credentials类型

  6. Scope 字段中,选择:

    • Global - 如果要添加的credential用于管道项目/项目,选择此项将crendential应用于管道项目/项目“对象”及其所有子对象

    • System - 如果要添加的credential用于Jenkins实例本身与系统管理功能(例如电子邮件认证,代理连接等)交互。 选择此选项会将crendential的应用于单个对象。

  7. 将credentials 本身添加到所选择的credentials类型的相应字段中:

    • Secret text - 复制加密文本到 Secret 字段中

    • Username and password - 在对应字段指定credential 的 UsernamePassword

    • Secret file - 点击 File 字段旁边的 Choose file 按钮以选择要上传到Jenkins的加密文件

    • SSH Username with private key - 在对应字段中指定 Username, Private Key 和 可选的 Passphrase 注意: 直接 选择 回车 可以让您复制私钥的文本并将其粘贴到生成的秘钥文本框中

    • Certificate - 指定 证书 和可选的 密码 。选择 上传 PKCS#12 证书 ,您可以通过 上传证书 按钮将证书作为文件上传

    • Docker Host Certificate Authentication - 将相应的详细信息复制到c Client Key, Client CertificateServer CA Certificate 字段。.

  8. ID 字段中,指定一个有意义的credential ID - 例如 jenkins-user-for-xyz-artifact-repository 。 您可以使用大写或小写字母作为凭证ID,也可以使用任何有效的分隔符。但是,为了Jenkins实例上所有用户利益,最好使用统一的约定来指定credential ID 注意: 该字段是可选的。 如果您没有指定值, Jenkins 则Jenkins会分配一个全局唯一ID(GUID)值。请记住,一旦设置了credential ID,就不能再进行更改。

  9. 为credential指定可选的 说明

  10. 点击 OK 保存 credentials.


⇑ 使用 Jenkins

索引

流水线 ⇒

 

流水线

子章节

Table of Contents

This chapter covers all recommended aspects of Jenkins Pipeline functionality, including how to:

有关Jenkins用户手册的内容的概述, 请前往 用户手册概述

什么是Jenkins的流水线?

Jenkins 流水线 (或简单的带有大写"P"的"Pipeline") 是一套插件,它支持实现和集成 continuous delivery pipelines 到Jenkins。

continuous delivery (CD) pipeline是你的进程的自动表达,用于从版本控制向用户和客户获取软件。 你的软件的每次的变更 (在源代码控制中提交)在它被释放的路上都经历了一个复杂的过程 on its way to being released. 这个过程包括以一种可靠并可重复的方式构建软件, 以及通过多个测试和部署阶段来开发构建好的软件 (c成为 "build") 。

流水线提供了一组可扩展的工具,通过 Pipeline domain-specific language (DSL) syntax. [1]对从简单到复杂的交付流水线 "作为代码" 进行建模。

对Jenkins 流水线的定义被写在一个文本文件中 (成为 Jenkinsfile),该文件可以被提交到项目的源代码的控制仓库。 [2] 这是"流水线即代码"的基础; 将CD 流水线作为应用程序的一部分,像其他代码一样进行版本化和审查。 创建 Jenkinsfile并提交它到源代码控制中提供了一些即时的好处:

  • 自动地为所有分支创建流水线构建过程并拉取请求。

  • 在流水线上代码复查/迭代 (以及剩余的源代码)。

  • 对流水线进行审计跟踪。

  • 该流水线的真正的源代码 [3], 可以被项目的多个成员查看和编辑。

While定义流水线的语法, 无论是在 web UI 还是在 Jenkinsfile 中都是相同的, 通常认为在Jenkinsfile 中定义并检查源代码控制是最佳实践。

声明式和脚本化的流水线语法

Jenkinsfile 能使用两种语法进行编写 - 声明式和脚本化。

声明式和脚本化的流水线从根本上是不同的。 声明式流水线的是 Jenkins 流水线更近的特性:

  • 相比脚本化的流水线语法,它提供更丰富的语法特性,

  • 是为了使编写和读取流水线代码更容易而设计的。

然而,写到Jenkinsfile中的许多单独的语法组件(或者 "步骤"), 通常都是声明式和脚本化相结合的流水线。 在下面的 [pipeline-concepts] 和 [pipeline-syntax-overview] 了解更多这两种语法的不同。

Why Pipeline?

本质上,Jenkins 是一个自动化引擎,它支持许多自动模式。 流水线向Jenkins中添加了一组强大的工具, 支持用例 简单的持续集成到全面的CD流水线。通过对一系列的相关任务进行建模, 用户可以利用流水线的很多特性:

  • Code: 流水线是在代码中实现的,通常会检查到源代码控制, 使团队有编辑, 审查和迭代他们的交付流水线的能力。

  • Durable: 流水线可以从Jenkins的主分支的计划内和计划外的重启中存活下来。

  • Pausable: 流水线可以有选择的停止或等待人工输入或批准,然后才能继续运行流水线。

  • Versatile: 流水线支持复杂的现实世界的 CD 需求, 包括fork/join, 循环, 并行执行工作的能力。

  • Extensible:流水线插件支持扩展到它的DSL [1]的惯例和与其他插件集成的多个选项。

然而, Jenkins一直允许以将自由式工作链接到一起的初级形式来执行顺序任务, [4] 流水线使这个概念成为了Jenkins的头等公民。

构建一个的可扩展的核心Jenkins值, 流水线也可以通过 Pipeline Shared Libraries 的用户和插件开发人员来扩展。 [5]

下面的流程图是一个 CD 场景的示例,在Jenkins中很容易对该场景进行建模:

Pipeline Flow

流水线概念

下面的概念是Jenkins流水线很关键的一方面 , 它与流水线语法紧密相连 (参考 overview below).

流水线

流水线是用户定义的一个CD流水线模型 。流水线的代码定义了整个的构建过程, 他通常包括构建, 测试和交付应用程序的阶段 。

另外 , pipeline 块是 声明式流水线语法的关键部分.

节点

节点是一个机器 ,它是Jenkins环境的一部分 and is capable of执行流水线。

另外, node块是 脚本化流水线语法的关键部分.

阶段

stage 块定义了在整个流水线的执行任务的概念性地不同的的子集(比如 "Build", "Test" 和 "Deploy" 阶段), 它被许多插件用于可视化 或Jenkins流水线目前的 状态/进展. [6]

步骤

本质上 ,一个单一的任务, a step 告诉Jenkins 在特定的时间点要做what (或过程中的 "step")。 举个例子,要执行shell命令 ,请使用 sh 步骤: sh 'make'。当一个插件扩展了流水线DSL, [1] 通常意味着插件已经实现了一个新的 step

流水线语法概述

下面的流水线代码骨架说明了声明式流水线语法脚本化流水线语法之间的根本差异。

请注意 阶段 and 步骤 (上面的) 都是声明式和脚本化流水线语法的常见元素。

声明式流水线基础

在声明式流水线语法中, pipeline 块定义了整个流水线中完成的所有的工作。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any 
    stages {
        stage('Build') { 
            steps {
                // 
            }
        }
        stage('Test') { 
            steps {
                // 
            }
        }
        stage('Deploy') { 
            steps {
                // 
            }
        }
    }
}
 在任何可用的代理上,执行流水线或它的任何阶段。
  定义 "Build" 阶段。
  执行与 "Build" 阶段相关的步骤。
  定义"Test" 阶段。
  执行与"Test" 阶段相关的步骤。
  定义 "Deploy" 阶段。
  执行与 "Deploy" 阶段相关的步骤。

脚本化流水线基础

在脚本化流水线语法中, 一个或多个 node 块在整个流水线中执行核心工作。 虽然这不是脚本化流水线语法的强制性要求, 但它限制了你的流水线的在node块内的工作做两件事:

  1. 通过在Jenkins队列中添加一个项来调度块中包含的步骤。 节点上的执行器一空闲, 该步骤就会运行。

  2. 创建一个工作区(特定为特定流水间建立的目录),其中工作可以在从源代码控制检出的文件上完成。 Caution: 根据你的 Jenkins 配置,在一系列的空闲后,一些工作区可能不会自动清理 。参考 JENKINS-2111 了解更多信息。

Jenkinsfile (Scripted Pipeline)

node {  
    stage('Build') { 
        // 
    }
    stage('Test') { 
        // 
    }
    stage('Deploy') { 
        // 
    }
}
 在任何可用的代理上,执行流水线或它的任何阶段。
  定义 "Build" 阶段。 stage 块 在脚本化流水线语法中是可选的。 然而, 在脚本化流水线中实现 stage 块 ,可以清楚的显示Jenkins UI中的每个 stage 的任务子集。
  执行与 "Build" 阶段相关的步骤。
  定义 "Test" 阶段。
  执行与 "Test" 阶段相关的步骤。
  定义 "Deploy" 阶段。
  执行与 "Deploy" 阶段相关的步骤。

流水线示例

这有一个使用声明式流水线的语法编写的 Jenkinsfile 文件 - 可以通过点击下面 Toggle Scripted Pipeline 链接来访问它的等效的脚本化语法:

Jenkinsfile (Declarative Pipeline)

pipeline { 
    agent any 
    stages {
        stage('Build') { 
            steps { 
                sh 'make' 
            }
        }
        stage('Test'){
            steps {
                sh 'make check'
                junit 'reports/**/*.xml' 
            }
        }
        stage('Deploy') {
            steps {
                sh 'make publish'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

 pipeline 是声明式流水线的一种特定语法,他定义了包含执行整个流水线的所有内容和指令的 "block" 。
  agent是声明式流水线的一种特定语法,它指示 Jenkins 为整个流水线分配一个执行器 (在节点上)和工作区。
  stage 是一个描述 stage of this Pipeline的语法块。在 Pipeline syntax 页面阅读更多有关声明式流水线语法的stage块的信息。如 above所述, 在脚本化流水线语法中,stage 块是可选的。
  steps 是声明式流水线的一种特定语法,它描述了在这个 stage 中要运行的步骤。
  sh 是一个执行给定的shell命令的流水线 step (由 Pipeline: Nodes and Processes plugin提供) 。
  junit 是另一个聚合测试报告的流水线 step (由 JUnit plugin提供)。
  node 是脚本化流水线的一种特定语法,它指示 Jenkins 在任何可用的代理/节点上执行流水线 (和包含在其中的任何阶段)这实际上等效于 声明式流水线特定语法的agent

Pipeline Syntax 页面阅读了解更多流水线语法的相关信息。


1. Domain-specific language

2. Source control management

3. Single source of truth

4. Additional plugins have been used to implement complex behaviors utilizing Freestyle Jobs such as the Copy Artifact, Parameterized Trigger, and Promoted Builds plugins

5. GitHub Organization Folder plugin

6. Blue Ocean, 流水线: 阶段查看插件


⇐ 使用 Jenkins

索引

流水线入门 ⇒

流水线入门

Table of Contents

正如 前文 提到的,Jenkins 流水线是一套插件,它支持实现和集成持续交付流水线到 Jenkins。流水线提供了一组可扩展的工具,用于通过流水线 DSL 将简单到复杂的交付流水线建模为“代码”。 [1]

本节描述了如何在 Jenkins 中开始创建你的流水线并介绍创建和存储 Jenkinsfile 的各种方式。

配置要求

为了使用 Jenkins 流水线,你需要:

  • Jenkins 2.x 或以上版本(旧版本到 1.642.3 可能可以,但不建议)

  • 流水线插件,[2] 作为“建议插件”的一部分安装(在安装 Jenkins 后,运行 Post-installation setup wizard 时指定)。

Managing Plugins 中阅读了解更多与安装和管理插件有关的信息。

定义流水线

声明式和脚本式流水线都是 DSL 语言,[1]用来描述软件交付流水线的一部分。 脚本式流水线是用一种限制形式的 Groovy 语法编写的。

本文档将根据需要介绍 Groovy 语法的相关部分,所以虽然理解 Groovy 对使用流水线有所帮助,但并不是必须的。

流水线可以通过以下任一方式来创建:

  • 通过 Blue Ocean - 在 Blue Ocean 中设置一个流水线项目后,Blue Ocean UI 会帮你编写流水线的 Jenkinsfile 文件并提交到源代码管理系统。

  • 通过经典 UI - 你可以通过经典 UI 在 Jenkins 中直接输入基本的流水线。

  • 在源码管理系统中定义 - 你可以手动编写一个 Jenkinsfile 文件,然后提交到项目的源代码管理仓库中。[3]

使用两种方式定义流水线的语法是相同的。尽管 Jenkins 支持在经典 UI 中直接进入流水线,但通常认为最好的实践是在 Jenkinsfile 文件中定义流水线,Jenkins 之后会直接从源代码管理系统加载。

通过 Blue Ocean

如果你刚接触 Jenkins 流水线,Blue Ocean UI 可以帮助你 设置流水线项目,并通过图形化流水线编辑器为你自动创建和编写流水线(即 Jenkinsfile)。

作为在 Blue Ocean 中设置流水线项目的一部分,Jenkins 给你项目的源代码管理仓库配置了一个安全的、经过身份验证的适当的连接。因此,你通过 Blue Ocean 的流水线编辑器在 Jenkinsfile 中做的任何更改都会自动的保存并提交到源代码管理系统。

了解更多 Blue Ocean 相关信息请前往 Blue Ocean 章节和 Blue Ocean 入门页面。

通过经典 UI

使用经典 UI 创建的 Jenkinsfile 由 Jenkins 自己保存(在 Jenkins 的主目录下)。

想要通过 Jenkins 经典 UI 创建一个基本流水线:

  1. 如果有要求的话,确保你已登录进 Jenkins。

  2. 从Jenkins 主页(即 Jenkins 经典 UI 的工作台),点击左上的 新建任务

    Classic UI left column

  3. 输入一个任务名称字段,填写你新建的流水线项目的名称。 警告:Jenkins 使用这个项目名称在磁盘上创建目录。建议不要在项目名称中使用空格,因为这样做可能会触发在脚本中不能正确处理目录路径中的空格的bug。

  4. 向下滚动并点击 流水线,然后点击页面底部的 确定 打开流水线配置页(已选中 General 选项)。

    Enter a name, click <strong>Pipeline</strong> and then click <strong>OK</strong>

  5. 点击页面顶部的 流水线 选项卡让页面向下滚动到 流水线 部分。 注意:如果你在源代码管理系统中定义了 Jenkinsfile, 请按照下面的在源码管理系统中定义的说明。

  6. 流水线 部分, 确保 定义 字段显示 Pipeline script 选项。

  7. 将你的流水线代码输入到 脚本 文本区域。 例如,复制并粘贴下面的声明式示例流水线代码(在 Jenkinsfile ( …​ ) 标题下)或者它的脚本化的版本到 脚本 文本区域。(下面的声明式示例将在整个过程的其余部分使用。)

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any 
        stages {
            stage('Stage 1') {
                steps {
                    echo 'Hello world!' 
                }
            }
        }
    }
    

    Toggle Scripted Pipeline (Advanced)

     agent 指示 Jenkins 为整个流水线分配一个执行器(在 Jenkins 环境中的任何可用代理/节点上)和工作区。
      echo 写一个简单的字符串到控制台输出。
      node 与上面的 agent 做了同样的事情。

    Example Pipeline in the classic UI

    注意:你也可以从 脚本 文本区域右上方的 try sample Pipeline… 选项选择脚本式流水线的示例。注意该区域没有可用的声明式流水线示例。

  8. 点击 保存 打开流水线项目视图页面。

  9. 在该页面, 点击左侧的 立即构建 运行流水线。

    Classic UI left column on an item

  10. 在左侧的 Build History 下面,点击 #1 来访问这个特定流水线运行的详细信息。

  11. 点击 Console Output 来查看流水线运行的全部输出。下面的输出显示你的流水线已成功运行。

    <strong>Console Output</strong> for the Pipeline

    注意:

    • 你也可以通过点击构建号左边的彩色地球仪从工作台直接访问控制台输出(例如 #1)。

    • 通过经典的 UI 定义流水线可以很方便的测试流水线代码片段,也可以处理简单的或不需要从源代码仓库中检出/克隆的流水线。正如上面提到的,和通过 Blue Ocean(上面)或在版本管理系统中(下面)定义的 Jenkinsfile 不同,在流水线项目的 脚本 文本区域输入的 Jenkinsfile 由 Jenkins 自己存储在 Jenkins 主目录下。因此,为了更好地控制和扩展你的流水线,尤其是源代码管理系统中那些复杂的项目,建议使用 Blue Ocean源码管理系统来定义你的 Jenkinsfile 文件。

在源码管理系统中

复杂的流水线很难在流水线配置页面 经典 UI脚本文本区域进行编写和维护。

为简化操作,流水线的 Jenkinsfile 可以在文本编辑器或集成开发环境(IDE)中进行编写并提交到源码管理系统 [3](可选择性地与需要 Jenkins 构建的应用程序代码放在一起)。然后 Jenkins 从源代码管理系统中检出 Jenkinsfile 文件作为流水线项目构建过程的一部分并接着执行你的流水线。

要使用来自源代码管理系统的 Jenkinsfile 文件配置流水线项目:

  1. 按照 通过经典 UI上面的步骤定义你的流水线直到第5步(在流水线配置页面访问流水线部分)。

  2. 定义 字段选择 Pipeline script from SCM 选项。

  3. SCM 字段,选择包含 Jenkinsfile 文件的仓库的源代码管理系统的类型。

  4. 填充对应仓库的源代码管理系统的字段。 Tip: 如果你不确定给定字段应填写什么值,点击它右侧的 ? 图标以获取更多信息。

  5. 脚本路径 字段,指定你的 Jenkinsfile 文件的位置(和名称)。这个位置是 Jenkins 检出/克隆包括 Jenkinsfile 文件的仓库的位置,它应该与仓库的文件结构匹配。该字段的默认值采取名称为 "Jenkinsfile" 的 Jenkinsfile 文件并位于仓库的根路径。

当你更新指定的仓库时,只要流水线配置了版本管理系统的轮询触发器,就会触发一个新的构建。

 由于流水线代码(特别是脚本式流水线)是使用类似 Groovy 的语法编写的, 如果你的IDE不能正确的使用语法高亮显示你的 Jenkinsfile,可以尝试在 Jenkinsfile 文件的顶部插入行 #!/usr/bin/env groovy 纠正这个问题。 [4] [5]
   

内置文档

流水线拥有内置文档的特性可以让创建各种复杂的流水线变得更容易。该内置文档基于 Jenkins 实例中安装的插件自动生成和更新。

该内置文档可以在 ${YOUR_JENKINS_URL}/pipeline-syntax 全局地找到。对于任何已配置的流水线项目,这个文档也被链接到侧栏的流水线语法

Classic UI left column on an item

片段生成器

内置的“片段生成器”工具有助于为各个步骤创建代码段,发现插件提供的新步骤,或者为特定的步骤尝试不同的参数。

片段生成器由 Jenkins 实例中可用的步骤动态添加。可用的步骤的数量依赖于安装的插件,这些插件显式地公开了流水线中使用的步骤。

要使用代码生成器生成一个步骤的片段:

  1. 从已配置好的流水线导航到 流水线语法 链接(见上),或访问 ${YOUR_JENKINS_URL}/pipeline-syntax

  2. 示例步骤 下拉菜单中选择需要的步骤。

  3. 使用 示例步骤 下拉菜单的动态填充区来配置已选的步骤。

  4. 点击 生成流水线脚本 生成一个能够被复制并粘贴到流水线中的流水线片段。

Snippet Generator

要访问所选步骤的附加信息和/或文档,请点击帮助图标(上图中的红色箭头所示)。

全局变量参考

对于只展示步骤的片段生成器的补充,流水线还提供了一个内置的“全局变量参考”。和片段生成器一样,它也是由插件动态添加。但和片段生成器不一样的是,全局变量参考只包含由流水线或插件提供的可用于流水线的变量文档。

流水线默认提供的变量是:

  • env

    可以从脚本式流水线中访问的环境变量,例如: env.PATHenv.BUILD_ID。 访问内置的全局变量参考页面 ${YOUR_JENKINS_URL}/pipeline-syntax/globals 以获取完整的,最新的,可用于流水线的环境变量列表。

  • params

    将为流水线定义的所有参数作为 Map,例如:params.MY_PARAM_NAME

  • currentBuild

    可用于发现当前正在执行的流水线的信息, 比如 currentBuild.resultcurrentBuild.displayName 等属性。参考内置的全局变量参考页面 ${YOUR_JENKINS_URL}/pipeline-syntax/globals 以获取完整的,最新的,currentBuild 的属性列表。

声明式指令生成器

片段生成器可以帮助生成脚本式流水线的步骤或者声明式流水线的 stage 中的 steps 代码块,但是其并没有包含用于定义声明式流水线的 section(节段)directive(指令)。声明式指令生成器(Declarative Directive Generator)这个工具可以做到这点。和 片段生成器类似,指令生成器允许你选择声明式的指令,对其以一种方式进行配置,然后生成这个指令的配置,让你将其用于声明式流水线。

要使用声明式指令生成器生成一个声明式的指令:

  1. 从已配置好的流水线导航到 Pipeline Syntax/流水线语法 链接(见上),然后点击侧栏的 Declarative Directive Generator,或直接访问 ${YOUR_JENKINS_URL}/directive-generator

  2. 在下拉菜单中选择需要的指令。

  3. 使用下拉菜单下面动态生成的区域配置已选的指令。

  4. 点击 Generate Declarative Directive 生成一个能够被复制到流水线中的指令配置。

指令生成器可以生成嵌套的指令配置,比如在 when 指令内的条件,但是它不能生成流水线步骤。对于包含步骤的指令内容,比如 stage 内的 stepspost 内的条件如 alwaysfailure,指令生成器添加一个占位符注释。你仍然需要手动添加步骤到流水线中。

Jenkinsfile (Declarative Pipeline)

stage('Stage 1') {
    steps {
        // One or more steps need to be included within the steps block.
    }
}

延伸阅读

本节仅仅介绍了 Jenkins 流水线可以做的事情的皮毛,但是应该为你开始测试 Jenkins 实例提供了足够的基础。

在下一节中,使用 Jenkinsfile,会讨论更多的流水线步骤以及实现成功的,真实世界的 Jenkins 流水线模式。

其它资源


1. Domain-specific language

2. Pipeline plugin

3. Source control management

4. Shebang (general definition)

5. Shebang line (Groovy syntax)


⇑ 流水线

索引

使用 Jenkinsfile ⇒

 

使用 Jenkinsfile

Table of Contents

本节基于 流水线入门 所涵盖的信息,介绍更多有用的步骤、常见的模式,并且演示 Jenkinsfile 的一些特例。

创建一个检入到源码管理系统中 [1] 的 Jenkinsfile 带来了一些直接的好处:

  • 流水线上的代码评审/迭代

  • 对流水线进行审计跟踪

  • 流水线的单一可信数据源 [2],能够被项目的多个成员查看和编辑。

流水线支持 两种语法:声明式(在 Pipeline 2.5 引入)和脚本式流水线。 两种语法都支持构建持续交付流水线。两种都可以用来在 web UI 或 Jenkinsfile 中定义流水线,不过通常认为创建一个 Jenkinsfile 并将其检入源代码控制仓库是最佳实践。

创建 Jenkinsfile

正如 在 SCM 中定义流水线中所讨论的,Jenkinsfile 是一个文本文件,它包含了 Jenkins 流水线的定义并被检入源代码控制仓库。下面的流水线实现了基本的三阶段持续交付流水线。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo 'Building..'
            }
        }
        stage('Test') {
            steps {
                echo 'Testing..'
            }
        }
        stage('Deploy') {
            steps {
                echo 'Deploying....'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

不是所有的流水线都有相同的三个阶段,但为大多数项目定义这些阶段是一个很好的开始。下面这一节将在 Jenkins 的测试安装中演示一个简单流水线的创建和执行。

 假设已经为项目设置了一个源代码控制仓库并在 Jenkins 下的 these instructions中定义了一个流水线。
   

使用文本编辑器,最好支持 Groovy 语法高亮,在项目的根目录下创建一个 Jenkinsfile

上面的声明式流水线示例包含了实现持续交付流水线的最小必要结构。agent指令是必需的,它指示 Jenkins 为流水线分配一个执行器和工作区。没有 agent 指令的话,声明式流水线不仅无效,它也不可能完成任何工作!默认情况下,agent 指令确保源代码仓库被检出并在后续阶段的步骤中可被使用。

一个合法的声明式流水线还需要 stages 指令steps 指令,因为它们指示 Jenkins 要执行什么,在哪个阶段执行。

想要使用脚本式流水线的更高级用法,上面例子中的 node 是关键的第一步,因为它为流水线分配了一个执行者和工作区。实际上,没有 node,流水线无法工作!在 node 内,业务的第一步是检出这个项目的源代码。由于 Jenkinsfile 已经从源代码控制中直接拉取出来,流水线提供了一个快速且简单的方式来访问正确的源代码修订版本。

Jenkinsfile (Scripted Pipeline)

node {
    checkout scm 
    /* .. snip .. */
}
 checkout 步骤将会从源代码控制中检出代码;scm 是一个特殊的变量, 它指示 checkout 步骤克隆触发流水线运行的特定修订版本。
   

构建

对于许多项目来说,流水线“工作”的开始就是“构建”阶段。通常流水线的这个阶段包括源代码的组装、编译或打包。Jenkinsfile 文件不能替代现有的构建工具,如 GNU/Make、Maven、Gradle 等,而应视其为一个将项目的开发生命周期的多个阶段(构建、测试、部署等)绑定在一起的粘合层。

Jenkins 有许多插件可以用于调用几乎所有常用的构建工具,不过这个例子只是从 shell 步骤(sh)调用 makesh 步骤假设系统是基于 Unix/Linux 的,对于基于 Windows 的系统可以使用 bat 替代。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'make' 
                archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true 
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

 sh 步骤调用 make 命令,只有命令返回的状态码为零时才会继续。任何非零的返回码都将使流水线失败。
  archiveArtifacts 捕获符合模式(**/target/*.jar)匹配的交付件并将其保存到 Jenkins master 节点以供后续获取。
 制品归档不能替代外部制品库(例如 Artifactory 或 Nexus),而只应当认为用于基本报告和文件存档。
   

测试

运行自动化测试是任何成功的持续交付过程的重要组成部分。因此,Jenkins 有许多测试记录,报告和可视化工具,这些都是由各种插件提供的。最基本的,当测试失败时,让 Jenkins 记录这些失败以供汇报以及在 web UI 中可视化是很有用的。下面的例子使用由 JUnit 插件提供的 junit 步骤。

在下面的例子中,如果测试失败,流水线就会被标记为“不稳定”,这通过 web UI 中的黄色球表示。基于测试报告的记录,Jenkins 还可以提供历史趋势分析和可视化。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any

    stages {
        stage('Test') {
            steps {
                /* `make check` 在测试失败后返回非零的退出码;
                * 使用 `true` 允许流水线继续进行
                */
                sh 'make check || true' 
                junit '**/target/*.xml' 
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

 使用内联的 shell 条件(sh 'make || true')确保 sh 步骤总是看到退出码是零,使 junit 步骤有机会捕获和处理测试报告。在下面处理故障一节中,对它的替代方法有更详细的介绍。
  junit 捕获并关联与包含模式(\**/target/*.xml)匹配的 JUnit XML 文件。

部署

部署可以隐含许多步骤,这取决于项目或组织的要求,并且可能是从发布构建的交付件到 Artifactory 服务器,到将代码推送到生产系统的任何东西。 在示例流水线的这个阶段,“Build(构建)” 和 “Test(测试)” 阶段都已成功执行。从本质上讲,“Deploy(部署)” 阶段只有在之前的阶段都成功完成后才会进行,否则流水线会提前退出。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any

    stages {
        stage('Deploy') {
            when {
              expression {
                currentBuild.result == null || currentBuild.result == 'SUCCESS' 
              }
            }
            steps {
                sh 'make publish'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

 流水线访问 currentBuild.result 变量确定是否有任何测试的失败。在这种情况下,值为 UNSTABLE
   

假设在示例的 Jenkins 流水线中所有的操作都执行成功,那么每次流水线的成功运行都会在 Jenkins 中存档相关的交付件、上面报告的测试结果以及所有控制台输出。

脚本式流水线包含条件测试(如上所示),循环,try/catch/finally 块甚至函数。下一节将会详细的介绍这个高级的脚本式流水线语法。

使用 Jenkinsfile 工作

接下来的章节提供了处理以下事项的细节:

  • Jenkinsfile 中的流水线特有语法

  • 流水线语法的特性和功能,这对于构建应用程序或流水线项目非常重要。

字符串插值

Jenkins 使用与 Groovy 相同的规则进行字符串插值。 Groovy 的字符串插值支持可能会使很多新手感到困惑。尽管 Groovy 支持使用单引号或双引号声明一个字符串,例如:

def singlyQuoted = 'Hello'
def doublyQuoted = "World"

只有后面的字符串才支持基于美元符($)的字符串插值,例如:

def username = 'Jenkins'
echo 'Hello Mr. ${username}'
echo "I said, Hello Mr. ${username}"

其结果是:

Hello Mr. ${username}
I said, Hello Mr. Jenkins

理解如何使用字符串插值对于使用一些流水线的更高级特性是至关重要的。

使用环境变量

Jenkins 流水线通过全局变量 env 提供环境变量,它在 Jenkinsfile 文件的任何地方都可以使用。Jenkins 流水线中可访问的完整的环境变量列表记录在 ${YOUR_JENKINS_URL}/pipeline-syntax/globals#env,并且包括:

  • BUILD_ID

    当前构建的 ID,与 Jenkins 版本 1.597+ 中创建的构建号 BUILD_NUMBER 是完全相同的。

  • BUILD_NUMBER

    当前构建号,比如 “153”。

  • BUILD_TAG

    字符串 jenkins-${JOB_NAME}-${BUILD_NUMBER}。可以放到源代码、jar 等文件中便于识别。

  • BUILD_URL

    可以定位此次构建结果的 URL(比如 http://buildserver/jenkins/job/MyJobName/17/

  • EXECUTOR_NUMBER

    用于识别执行当前构建的执行者的唯一编号(在同一台机器的所有执行者中)。这个就是你在“构建执行状态”中看到的编号,只不过编号从 0 开始,而不是 1。

  • JAVA_HOME

    如果你的任务配置了使用特定的一个 JDK,那么这个变量就被设置为此 JDK 的 JAVA_HOME。当设置了此变量时,PATH 也将包括 JAVA_HOME 的 bin 子目录。

  • JENKINS_URL

    Jenkins 服务器的完整 URL,比如 https://example.com:port/jenkins/ (注意:只有在“系统设置”中设置了 Jenkins URL 才可用)。

  • JOB_NAME

    本次构建的项目名称,如 “foo” 或 “foo/bar”。

  • NODE_NAME

    运行本次构建的节点名称。对于 master 节点则为 “master”。

  • WORKSPACE

    workspace 的绝对路径。

引用或使用这些环境变量就像访问 Groovy Map 的 key 一样, 例如:

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}"
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

设置环境变量

在 Jenkins 流水线中,取决于使用的是声明式还是脚本式流水线,设置环境变量的方法不同。

声明式流水线支持 environment 指令,而脚本式流水线的使用者必须使用 withEnv 步骤。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    environment { 
        CC = 'clang'
    }
    stages {
        stage('Example') {
            environment { 
                DEBUG_FLAGS = '-g'
            }
            steps {
                sh 'printenv'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

 用在最高层的 pipeline 块的 environment 指令适用于流水线的所有步骤。
  定义在 stage 中的 environment 指令只适用于 stage 中的步骤。

动态设置环境变量

环境变量可以在运行时设置,然后给 shell 脚本(sh)、Windows 批处理脚本(batch)和 Powershell 脚本(powershell)使用。各种脚本都可以返回 returnStatusreturnStdout

下面是一个使用 sh(shell)的声明式脚本的例子,既有 returnStatus 也有 returnStdout

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any 
    environment {
        // 使用 returnStdout
        CC = """${sh(
                returnStdout: true,
                script: 'echo "clang"'
            )}""" 
        // 使用 returnStatus
        EXIT_STATUS = """${sh(
                returnStatus: true,
                script: 'exit 1'
            )}"""
    }
    stages {
        stage('Example') {
            environment {
                DEBUG_FLAGS = '-g'
            }
            steps {
                sh 'printenv'
            }
        }
    }
}
 agent 必须设置在流水线的最高级。如果设置为 agent none 会失败。
  使用 returnStdout 时,返回的字符串末尾会追加一个空格。可以使用 .trim() 将其移除。

处理凭据

Jenkins 中配置的凭据可以在流水线中处理以便于立即使用。请前往 使用凭据页面阅读更多关于在 Jenkins 中使用凭据的信息。

Secret 文本,带密码的用户名,Secret 文件

Jenkins 的声明式流水线语法有一个 credentials() 辅助方法(在environment 指令中使用),它支持 secret 文本带密码的用户名,以及 secret 文件凭据。如果你想处理其他类型的凭据,请参考其他凭据类型一节(见下)。

Secret 文本

下面的流水线代码演示了如何使用环境变量为 secret 文本凭据创建流水线的示例。

在该示例中,将两个 secret 文本凭据赋予各自的环境变量来访问 Amazon Web 服务(AWS)。这些凭据已在 Jenkins 中配置了各自的凭据 ID jenkins-aws-secret-key-idjenkins-aws-secret-access-key

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent {
        // 此处定义 agent 的细节
    }
    environment {
        AWS_ACCESS_KEY_ID     = credentials('jenkins-aws-secret-key-id')
        AWS_SECRET_ACCESS_KEY = credentials('jenkins-aws-secret-access-key')
    }
    stages {
        stage('Example stage 1') {
            steps {
                // 
            }
        }
        stage('Example stage 2') {
            steps {
                // 
            }
        }
    }
}
 你可以在该阶段的步骤中用语法 $AWS_ACCESS_KEY_ID$AWS_SECRET_ACCESS_KEY 来引用两个凭据环境变量(定义在流水线的 environment 指令中)。比如,在这里,你可以使用分配给这些凭据变量的 secret 文本凭据对 AWS 进行身份验证。 为了保持这些凭据的安全性和匿名性,如果任务试图从流水线中显示这些凭据变量的值(如 echo $AWS_SECRET_ACCESS_KEY),Jenkins 只会返回 “” 来降低机密信息被写到控制台输出和任何日志中的风险。凭据 ID 本身的任何敏感信息(如用户名)也会以 “” 的形式返回到流水线运行的输出中。 这只能降低意外暴露的风险。它无法阻止恶意用户通过其他方式获取凭据的值。使用凭据的流水线也可能泄漏这些凭据。不要允许不受信任的流水线任务使用受信任的凭据。
  在该流水线示例中,分配给两个 AWS_... 环境变量的凭据在整个流水线的全局范围内都可访问,所以这些凭据变量也可以用于该阶段的步骤中。然而,如果流水线中的 environment 指令被移动到一个特定的阶段(比如下面的 带密码的用户名流水线示例),那么这些 AWS_... 环境变量就只能作用于该阶段的步骤中。
带密码的用户名

下面的流水线代码片段展示了如何创建一个使用带密码的用户名凭据的环境变量的流水线。

在该示例中,带密码的用户名凭据被分配了环境变量,用来使你的组织或团队以一个公用账户访问 Bitbucket 仓库;这些凭据已在 Jenkins 中配置了凭据 ID jenkins-bitbucket-common-creds

当在 environment 指令中设置凭据环境变量时:

environment {
    BITBUCKET_COMMON_CREDS = credentials('jenkins-bitbucket-common-creds')
}

这实际设置了下面的三个环境变量:

  • BITBUCKET_COMMON_CREDS - 包含一个以冒号分隔的用户名和密码,格式为 username:password

  • BITBUCKET_COMMON_CREDS_USR - 附加的一个仅包含用户名部分的变量。

  • BITBUCKET_COMMON_CREDS_PSW - 附加的一个仅包含密码部分的变量。

 按照惯例,环境变量的变量名通常以大写字母中指定,每个单词用下划线分割。 但是,你可以使用小写字母指定任何合法的变量名。请记住, credentials() 方法(见上)所创建的附加环境变量总是会有后缀 _USR_PSW(即以下划线后跟三个大写字母的格式)。
   

下面的代码片段完整的展示了示例流水线:

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent {
        // 此处定义 agent 的细节
    }
    stages {
        stage('Example stage 1') {
            environment {
                BITBUCKET_COMMON_CREDS = credentials('jenkins-bitbucket-common-creds')
            }
            steps {
                // 
            }
        }
        stage('Example stage 2') {
            steps {
                // 
            }
        }
    }
}
 下面的凭据环境变量(定义在流水线的 environment 指令中)可以在该阶段的步骤中使用,并且可以使用下面的语法引用:$BITBUCKET_COMMON_CREDS``$BITBUCKET_COMMON_CREDS_USR``$BITBUCKET_COMMON_CREDS_PSW比如,在这里你可以使用分配给这些凭据变量的用户名和密码向 Bitbucket 验证身份。 为了维护这些凭据的安全性和匿名性,如果任务试图从流水线中显示这些凭据变量的值,那么上面的 Secret 文本 描述的行为也同样适用于这些带密码的用户名凭据变量类型。 同样,这只能降低意外暴露的风险。它无法阻止恶意用户通过其他方式获取凭据的值。使用凭据的流水线也可能泄漏这些凭据。不要允许不受信任的流水线任务使用受信任的凭据。
  在该流水线示例中,分配给三个 COMMON_BITBUCKET_CREDS... 环境变量的凭据仅作用于 Example stage 1,所以在 Example stage 2 阶段的步骤中这些凭据变量不可用。然而,如果马上把流水线中的 environment 指令移动到 pipeline 块中(正如上面的 Secret 文本流水线示例一样),这些 COMMON_BITBUCKET_CREDS... 环境变量将应用于全局并可以在任何阶段的任何步骤中使用。
Secret 文件

就流水线而言,secret 文件的处理方式与 Secret 文本 完全相同。

实际上,secret 文本和 secret 文件凭据之间的唯一不同是,对于 secret 文本,凭据本身直接输入到 Jenkins 中,而 secret 文件的凭据则原样保存到一个文件中,之后将传到 Jenkins。

与 secret 文本不同的是,secret 文件适合:

  • 太笨拙而不能直接输入 Jenkins

  • 二进制格式,比如 GPG 文件

其他凭据类型

如果你需要在流水线中设置除了 secret 文本、带密码的用户名、secret 文件(见上)以外的其他凭据——即 SSH 秘钥或证书,那么请使用 Jenkins 的片段生成器特性,你可以通过 Jenkins 的经典 UI 访问它。

要从你的流水线项目访问片段生成器

  1. 从 Jenkins 主页(即 Jenkins 的经典 UI 工作台)点击流水线项目的名字。

  2. 在左侧,点击流水线语法并确保 Snippet Generator/片段生成器的链接在右上角粗体显示(如果没有,点击它的链接)。

  3. 示例步骤字段中,选择 withCredentials: Bind credentials to variables

  4. 绑定下面,点击新增并从下拉框中选择:

    • SSH User Private Key - 要处理 SSH 公私钥对凭据,你可以提供:

      • Key 文件变量 - 将要绑定到这些凭据的环境变量的名称。Jenkins 实际上将此临时变量分配给 SSH 公私钥对身份验证过程中所需的私钥文件的安全位置。

      • 密码变量可选)- 将要被绑定到与 SSH 公私钥对相关的 密码 的环境变量的名称。

      • 用户名变量可选)- 将要绑定到与 SSH 公私钥对相关的用户名的环境变量的名称。

      • 凭据 - 选择存储在 Jenkins 中的 SSH 公私钥对证书。该字段的值是凭据 ID,Jenkins 将其写入生成的代码片段中。

    • Certificate - 要处理 PKCS#12 证书,你可以提供:

      • 密钥库变量 - 将要绑定到这些凭据的环境变量的名称。Jenkins 实际上将这个临时变量分配给要求进行身份验证的证书密钥库的安全位置。

      • 密码变量可选) - 将会被绑定到与证书相关的密码的环境变量的名称。

      • 别名变量可选) - 将会被绑定到与证书相关的唯一别名的环境变量的名称。

      • 凭据 - 选择存储在 Jenkins 中的证书。该字段的值是凭据 ID,Jenkins 将其写入生成的代码片段中。

    • Docker client certificate - 用于处理 Docker 主机证书的身份验证。

  5. 点击 生成流水线脚本,Jenkins 会为你指定的凭据生成一个 withCredentials( ... ) { ... } 的流水线步骤片段,你可以将其复制并粘贴到你的声明式或脚本化流水线代码中。 注意:

    • 凭据 字段(见上)显示的是 Jenkins 中配置的证书的名称。然而,这些值在点击 生成流水线脚本 之后会被转换成证书 ID。

    • 要在一个 withCredentials( ... ) { ... } 流水线步骤组合多个证书,请查看 在一个步骤中组合使用凭据(见下)的详细信息。

SSH User Private Key 示例

withCredentials(bindings: [sshUserPrivateKey(credentialsId: 'jenkins-ssh-key-for-abc', \
                                             keyFileVariable: 'SSH_KEY_FOR_ABC', \
                                             passphraseVariable: '', \
                                             usernameVariable: '')]) {
  // some block
}

可选的 passphraseVariableusernameVariable 定义可以在最终的流水线代码中删除。

Certificate 示例

withCredentials(bindings: [certificate(aliasVariable: '', \
                                       credentialsId: 'jenkins-certificate-for-xyz', \
                                       keystoreVariable: 'CERTIFICATE_FOR_XYZ', \
                                       passwordVariable: 'XYZ-CERTIFICATE-PASSWORD')]) {
  // some block
}

可选的 aliasVariablepasswordVariable 变量定义可以在最终的流水线代码中删除。

下面的代码片段展示了一个完整的示例流水线,实现了上面的 SSH User Private KeyCertificate 片段:

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent {
        // define agent details
    }
    stages {
        stage('Example stage 1') {
            steps {
                withCredentials(bindings: [sshUserPrivateKey(credentialsId: 'jenkins-ssh-key-for-abc', \
                                                             keyFileVariable: 'SSH_KEY_FOR_ABC')]) {
                  // 
                }
                withCredentials(bindings: [certificate(credentialsId: 'jenkins-certificate-for-xyz', \
                                                       keystoreVariable: 'CERTIFICATE_FOR_XYZ', \
                                                       passwordVariable: 'XYZ-CERTIFICATE-PASSWORD')]) {
                  // 
                }
            }
        }
        stage('Example stage 2') {
            steps {
                // 
            }
        }
    }
}
 在该步骤中,你可以使用语法 $SSH_KEY_FOR_ABC 引用凭据环境变量。比如,在这里你可以使用配置的 SSH 公私钥对证书对 ABC 应用程序进行身份验证,它的 SSH User Private Key 文件被分配给 $SSH_KEY_FOR_ABC
  在该步骤中,你可以使用语法 $CERTIFICATE_FOR_XYZ$XYZ-CERTIFICATE-PASSWORD 引用凭据环境变量。比如,在这里你可以使用配置的证书凭据对 XYZ 应用程序进行身份验证。证书 Certificate 的秘钥存储文件和密码分别被分配给 $CERTIFICATE_FOR_XYZ$XYZ-CERTIFICATE-PASSWORD 变量。
  在流水线示例中,分配给 $SSH_KEY_FOR_ABC$CERTIFICATE_FOR_XYZ$XYZ-CERTIFICATE-PASSWORD 的环境变量的凭据只适用于它们各自 withCredentials( ... ) { ... } 步骤中,所以这些凭据变量在 Example stage 2 阶段的步骤中不可用。

为了维护这些证书的安全性和匿名性,如果你试图从 withCredentials( ... ) { ... } 步骤中检索这些凭据变量的值,在 Secret 文本 示例(见上)中的相同行为也适用于这些 SSH 公私钥对证书和凭据变量类型。

 片段生成器示例步骤中使用 withCredentials: Bind credentials to variables 选项时,只有当前流水线项目有访问权限的凭据才可以从凭据字段中选择。 虽然你可以为你的流水线手动编写 withCredentials( ... ) { ... } 步骤( 如上所示),但更建议使用 片段生成器 来防止指定超出该流水线访问范围的证书,可以避免运行步骤时失败。你也可以用 片段生成器 来生成处理 secret 文本,带密码的用户名以及 secret 文件的 withCredentials( ... ) { ... } 步骤。但是,如果你只需要处理这些类型的证书的话,为了提高你流水线代码的可读性,更建议你使用在上面一节中描述的相关过程。在 Groovy 中使用单引号而不是双引号来定义脚本(sh 的隐式参数)。单引号将使 secret 被 shell 作为环境变量展开。双引号可能不太安全,因为这个 secret 是由 Groovy 插入的,所以一般操作系统的进程列表(以及 Blue Ocean 和经典 UI 中的流水线步骤树)会意外地暴露它:node { withCredentials([string(credentialsId: 'mytoken', variable: 'TOKEN')]) { sh /* 错误! */ """ set +x curl -H 'Token: $TOKEN' https://some.api/ """ sh /* 正确 */ ''' set +x curl -H 'Token: $TOKEN' https://some.api/ ''' } }
   
在一个步骤中组合使用凭据

使用 片段生成器,你可以在单个 withCredentials( ... ) { ... } 步骤中提供多个可用凭据,操作如下:

  1. 从 Jenkins 的主页中(即 Jenkins 的经典 UI 工作台)点击流水线项目的名称。

  2. 在左侧,点击 流水线语法 确保片段生成器链接在左上加粗显示(如果没有,点击该链接)。

  3. 示例步骤 字段,选择 withCredentials: Bind credentials to variables

  4. 点击 绑定 下的 新增

  5. 从下拉列表中选择要添加到 withCredentials( ... ) { ... } 步骤的凭据类型。

  6. 指定凭据绑定的细节。请在操作过程中阅读其他凭据类型

  7. 重复“点击 新增 …”将每个(组)凭据添加到 withCredentials( ... ) { ... } 步骤。

  8. 点击 生成流水线脚本 生成最终的 withCredentials( ... ) { ... } 步骤片段。

处理参数

声明式流水线支持参数开箱即用,允许流水线在运行时通过parameters 指令接受用户指定的参数。配置脚本式流水线的参数是通过 properties 步骤实现的,可以在代码生成器中找到。

如果你使用 Build with Parameters 选项将流水线配置为接受参数,这些参数将作为 params 变量的成员被访问。

假设在 Jenkinsfile 中配置了名为 “Greeting” 的字符串参数,它可以通过 ${params.Greeting} 访问该参数:

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    parameters {
        string(name: 'Greeting', defaultValue: 'Hello', description: 'How should I greet the world?')
    }
    stages {
        stage('Example') {
            steps {
                echo "${params.Greeting} World!"
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

处理故障

声明式流水线默认通过 post 节段支持强大的故障处理,它允许声明许多不同的 “post 条件”,比如: alwaysunstablesuccessfailurechanged流水线语法 提供了关于如何使用各种 post 条件的更多细节。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                sh 'make check'
            }
        }
    }
    post {
        always {
            junit '**/target/*.xml'
        }
        failure {
            mail to: team@example.com, subject: 'The Pipeline failed :('
        }
    }
}

Toggle Scripted Pipeline (Advanced)

然而脚本化的流水线依赖于 Groovy 的内置的 try/catch/finally 语义来处理流水线运行期间的故障。

在上面的测试示例中, sh 步骤被修改为永远不会返回非零的退出码(sh 'make check || true')。虽然这种方法合法,但意味着接下来的阶段需要检查 currentBuild.result 来了解测试是否失败。

该问题的另一种处理方式是使用一系列的 try/finally 块,它保留了流水线中前面的失败退出的行为,但仍然给了 junit 捕获测试报告的机会。

使用多个代理

在之前所有的示例中都只使用了一个代理。这意味着 Jenkins 会分配一个可用的执行者而无论该执行者是如何打标签或配置的。流水线不仅可以覆盖这种行为,还允许在 Jenkins 环境中使用 同一个 Jenkinsfile 中的多个代理,这将有助于更高级的用例,例如跨多个平台的执行构建/测试。

在下面的示例中,“Build” 阶段将会在一个代理中执行,并且构建结果将会在后续的 “Test” 阶段被两个分别标记为 “linux” 和 “windows” 的代理重用。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent none
    stages {
        stage('Build') {
            agent any
            steps {
                checkout scm
                sh 'make'
                stash includes: '**/target/*.jar', name: 'app' 
            }
        }
        stage('Test on Linux') {
            agent { 
                label 'linux'
            }
            steps {
                unstash 'app' 
                sh 'make check'
            }
            post {
                always {
                    junit '**/target/*.xml'
                }
            }
        }
        stage('Test on Windows') {
            agent {
                label 'windows'
            }
            steps {
                unstash 'app'
                bat 'make check' 
            }
            post {
                always {
                    junit '**/target/*.xml'
                }
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

 stash 步骤允许捕获与包含模式(\**/target/*.jar)匹配的文件,以便在同一个流水线中重用。一旦流水线执行完成,就会从 Jenkins master 中删除暂存文件。
  agent/node 中的参数允许使用任何可用的 Jenkins 标签表达式。参考 流水线语法 部分了解更多信息。
  unstash 将会从 Jenkins master 中取回命名的 “stash” 到流水线的当前工作区中。
  bat 脚本允许在基于 Windows 的平台上执行批处理脚本。

可选的步骤参数

流水线遵循 Groovy 语言允许在方法周围省略括号的惯例。

许多流水线步骤也使用命名参数语法作为在 Groovy 中创建的 Map(使用语法 [key1: value1, key2: value2] )的简写 。下面的语句有着相同的功能:

git url: 'git://example.com/amazing-project.git', branch: 'master'
git([url: 'git://example.com/amazing-project.git', branch: 'master'])

为了方便,当调用只有一个参数的步骤时(或仅一个强制参数),参数名称可以省略,例如:

sh 'echo hello' /* short form  */
sh([script: 'echo hello'])  /* long form */

高级脚本式流水线

脚本式流水线是一种基于 Groovy 的领域特定语言 [3] ,大多数 Groovy 语法都可以无需修改,直接在脚本式流水线中使用。

并行执行

上面这节中的示例跨两个不同的平台串联地运行测试。在实践中,如果执行 make check 需要30分钟来完成,那么 “Test” 阶段就需要 60 分钟来完成!

幸运的是,流水线有一个内置的并行执行部分脚本式流水线的功能,通过贴切的名为 parallel 的步骤实现。

使用 parallel 步骤重构上面的示例:

Jenkinsfile (Scripted Pipeline)

stage('Build') {
    /* .. snip .. */
}

stage('Test') {
    parallel linux: {
        node('linux') {
            checkout scm
            try {
                unstash 'app'
                sh 'make check'
            }
            finally {
                junit '**/target/*.xml'
            }
        }
    },
    windows: {
        node('windows') {
            /* .. snip .. */
        }
    }
}

测试不再在标记为 “linux” 和 “windows” 节点中串联地执行,而是并行执行。


1. en.wikipedia.org/wiki/Source_control_management

2. en.wikipedia.org/wiki/Single_Source_of_Truth

3. en.wikipedia.org/wiki/Domain-specific_language


⇐ 流水线入门

⇑ 流水线

索引

分支和pull请求 ⇒

 

分支和pull请求

Table of Contents

previous section 中,实现了一个能够检入到源代码控制中的 Jenkinsfile。 本节将介绍在Jenkinsfile的基础上构建的 Multibranch 流水线的概念,用来在Jenkins中提供更动态和自动的功能。

创建多分支流水线

Multibranch Pipeline 项目类型能够 在同一个项目的不同分支上实现不同的Jenkinsfile。 在多分支流水线项目中, Jenkins 自动的发现, 管理和执行在源代码控制中包含Jenkinsfile的分支的流水线。

这消除了手动创建和管理流水线的需要。

创建多分支流水线:

  • 点击Jenkins主页上的 New Item

Classic UI left column

  • 为你的流水线输入一个名称, 选择 Multibranch Pipeline 并点击 OK

 Jenkins 使用流水线的名称在磁盘上创建目录。 包含空格的流水线名称可能会在脚本中出现不希望在路径中出现空格的bug。
   

Enter a name, select *Multibranch Pipeline*, and click *OK*

  • 添加 Branch Source (比如, Git) 并输入仓库的位置。

Add a Branch Source

Add the URL to the project repository

  • Save 该多分支流水线项目。

Save是, Jenkins 自动的扫描指定的存储库并为包含Jenkinsfile的仓库的每个分支创建合适的项目。默认情况下, Jenkins 不会自动的重新索引分支添加或删除的仓库(除非使用 组织文件夹), 所以周期性地重新索引有助于配置多分支流水线:

Setting up branch re-indexing

附加的环境变量

多分支流水线通过env 全局变量公开了额外的与分支构建相关的信息 , 比如:

  • BRANCH_NAME

    该流水线正在执行的流水线的名称, 比如 master

  • CHANGE_ID

    对应于某种形式的更改请求的标识符, 比如在 全局变量引用中列出了附加的环境变量的pull请求。

支持Pull请求

在 "GitHub" 或 "Bitbucket" 分支源, 可以使用多分支流水线来验证 pull/change 请求。 该功能分别由 GitHub 分支源Bitbucket 分支源 插件提供。有关于如何使用这些插件的更多信息,请参考他们的文档。

使用组织文件夹

组织文件夹使Jenkins 能够监视整个 GitHub 组织或 Bitbucket 团队/P项目 并自动地为仓库创建一个新的多分支流水线,该流水线包括分支和含有Jenkinsfile文件的pull请求。

目前, 该功能只存在于 GitHub 和 Bitbucket, 该功能由 GitHub 组织文件夹Bitbucket 分支源 插件提供。


⇐ 使用 Jenkinsfile

⇑ 流水线

索引

在流水线中使用Docker ⇒

在流水线中使用Docker

Table of Contents

许多组织使用 Docker 在机器之间统一构建和测试环境, 并为部署应用程序提供有效的机制。从流水线版本 2.5 或以上开始, 流水线内置了与Jenkinsfile中的Docker进行交互的的支持。

虽然本节将介绍基础知识在 Jenkinsfile中使用Docker的基础,但它不会涉及 Docker 的基本原理, 可以参考 Docker入门指南

自定义执行环境

设计流水线的目的是更方便地使用 Docker镜像作为单个 Stage或整个流水线的执行环境。 这意味着用户可以定义流水线需要的工具,而无需手动配置代理。 实际上,只需对 Jenkinsfile进行少量编辑,任何 packaged in a Docker container的工具, 都可轻松使用。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent {
        docker { image 'node:7-alpine' }
    }
    stages {
        stage('Test') {
            steps {
                sh 'node --version'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

当流水线执行时, Jenkins 将会自动地启动指定的容器并在其中执行指定的步骤:

[Pipeline] stage
[Pipeline] { (Test)
[Pipeline] sh
[guided-tour] Running shell script
+ node --version
v7.4.0
[Pipeline] }
[Pipeline] // stage
[Pipeline] }

容器的缓存数据

许多构建工具都会下载外部依赖并将它们缓存到本地以便于将来的使用。 由于容器最初是由 "干净的" 文件系统构建的, 这导致流水线速度变慢, 因为它们不会利用后续流水线运行的磁盘缓存。 on-disk caches between subsequent Pipeline runs.

流水线支持 向Docker中添加自定义的参数, 允许用户指定自定义的 Docker Volumes 装在, 这可以用于在流水线运行之间的 agent上缓存数据。下面的示例将会在 流水线运行期间使用 maven container缓存 ~/.m2, 从而避免了在流水线的后续运行中重新下载依赖的需求。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent {
        docker {
            image 'maven:3-alpine'
            args '-v $HOME/.m2:/root/.m2'
        }
    }
    stages {
        stage('Build') {
            steps {
                sh 'mvn -B'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

使用多个容器

代码库依赖于多种不同的技术变得越来越容易。比如, 一个仓库既有基于Java的后端API 实现 and 有基于JavaScript的前端实现。 Docker和流水线的结合允许 Jenkinsfile 通过将 agent {} 指令和不同的阶段结合使用 multiple 技术类型。

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent none
    stages {
        stage('Back-end') {
            agent {
                docker { image 'maven:3-alpine' }
            }
            steps {
                sh 'mvn --version'
            }
        }
        stage('Front-end') {
            agent {
                docker { image 'node:7-alpine' }
            }
            steps {
                sh 'node --version'
            }
        }
    }
}

Toggle Scripted Pipeline (Advanced)

使用Dockerfile

对于更需要自定义执行环境的项目, 流水线还支持从源仓库的Dockerfile 中构建和运行容器。 与使用"现成" 容器的 previous approach 不同的是 , 使用 agent { dockerfile true } 语法从 Dockerfile 中构建一个新的镜像而不是从 Docker Hub中拉取一个。

重复使用上面的示例, 使用一个更加自定义的 Dockerfile:

Dockerfile

FROM node:7-alpine

RUN apk add -U subversion

通过提交它到源仓库的根目录下, 可以更改 Jenkinsfile 文件,来构建一个基于该 Dockerfile 文件的容器然后使用该容器运行已定义的步骤:

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent { dockerfile true }
    stages {
        stage('Test') {
            steps {
                sh 'node --version'
                sh 'svn --version'
            }
        }
    }
}

agent { dockerfile true } 语法支持大量的其它选项,这些选项的更详细的描述请参考 流水线语法 部分。

Using a Dockerfile with Jenkins Pipeline

https://www.youtube.com/embed/Pi2kJ2RJS50?rel=0

指定Docker标签

的了 agent 都能够运行基于Docker的流水线。 对于有macOS, Windows, 或其他代理的Jenkins环境, 不能运行Docker守护进程, 这个默认设置可能会有问题。 流水线在 Manage Jenkins 页面和 文件夹级别提供一个了全局选项,用来指定运行基于Docker的流水线的代理 (通过 标签)。

Configuring the Pipeline Docker Label

脚本化流水线的高级用法

运行 "sidecar" 容器

在流水线中使用Docker可能是运行构建或一组测试的所依赖的服务的有效方法。类似于 sidecar 模式, Docker 流水线可以"在后台"运行一个容器 , 而在另外一个容器中工作。 利用这种sidecar 方式, 流水线可以为每个流水线运行 提供一个"干净的" 容器。

考虑一个假设的集成测试套件,它依赖于本地 MySQL 数据库来运行。使用 withRun 方法, 在 Docker Pipeline 插件中实现对脚本化流水线的支持, Jenkinsfile 文件可以运行 MySQL作为sidecar :

node {
    checkout scm
    /*
     * In order to communicate with the MySQL server, this Pipeline explicitly
     * maps the port (`3306`) to a known port on the host machine.
     */
    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw" -p 3306:3306') { c ->
        /* Wait until mysql service is up */
        sh 'while ! mysqladmin ping -h0.0.0.0 --silent; do sleep 1; done'
        /* Run some tests which require MySQL */
        sh 'make check'
    }
}

该示例可以更进一步, 同时使用两个容器。 一个 "sidecar" 运行 MySQL, 另一个提供执行环境, 通过使用Docker 容器链接

node {
    checkout scm
    docker.image('mysql:5').withRun('-e "MYSQL_ROOT_PASSWORD=my-secret-pw"') { c ->
        docker.image('mysql:5').inside("--link ${c.id}:db") {
            /* Wait until mysql service is up */
            sh 'while ! mysqladmin ping -hdb --silent; do sleep 1; done'
        }
        docker.image('centos:7').inside("--link ${c.id}:db") {
            /*
             * Run some tests which require MySQL, and assume that it is
             * available on the host name `db`
             */
            sh 'make check'
        }
    }
}

上面的示例使用 withRun公开的项目, 它通过 id 属性具有可用的运行容器的ID。使用该容器的 ID, 流水线通过自定义 Docker 参数生成一个到inside() 方法的链。

The id property can also be useful for inspecting logs from a running Docker container before the Pipeline exits:

sh "docker logs ${c.id}"

构建容器

为了构建 Docker 镜像,Docker 流水线 插件也提供了一个 build() 方法用于在流水线运行期间从存储库的Dockerfile 中创建一个新的镜像。

使用语法 docker.build("my-image-name") 的主要好处是, 脚本化的流水线能够使用后续 Docker流水线调用的返回值, 比如:

node {
    checkout scm

    def customImage = docker.build("my-image:${env.BUILD_ID}")

    customImage.inside {
        sh 'make test'
    }
}

该返回值也可以用于通过 push() 方法将Docker 镜像发布到 Docker Hub, 或 custom Registry,比如:

node {
    checkout scm
    def customImage = docker.build("my-image:${env.BUILD_ID}")
    customImage.push()
}

镜像 "tags"的一个常见用法是 为最近的, 验证过的, Docker镜像的版本,指定 latest 标签。 push() 方法接受可选的 tag 参数, 允许流水线使用不同的标签 push customImage , 比如:

node {
    checkout scm
    def customImage = docker.build("my-image:${env.BUILD_ID}")
    customImage.push()

    customImage.push('latest')
}

在默认情况下, build() 方法在当前目录构建一个 Dockerfile。提供一个包含 Dockerfile文件的目录路径作为build() 方法的第二个参数 就可以覆盖该方法, 比如:

node {
    checkout scm
    def testImage = docker.build("test-image", "./dockerfiles/test") 

    testImage.inside {
        sh 'make test'
    }
}
 从在 ./dockerfiles/test/Dockerfile中发现的Dockerfile中构建test-image
   

通过添加其他参数到 build() 方法的第二个参数中,传递它们到 docker build。 当使用这种方法传递参数时, 该字符串的最后一个值必须是Docker文件的路径。

该示例通过传递 -f标志覆盖了默认的 Dockerfile :

node {
    checkout scm
    def dockerfile = 'Dockerfile.test'
    def customImage = docker.build("my-image:${env.BUILD_ID}", "-f ${dockerfile} ./dockerfiles") 
}
 从在./dockerfiles/Dockerfile.test发现的Dockerfile构建 my-image:${env.BUILD_ID}
   

使用远程 Docker 服务器

默认情况下, Docker Pipeline 插件会与本地的Docker的守护进程通信, 通常通过 /var/run/docker.sock访问。

要选择一个非默认的Docker 服务器, 比如 Docker 集群, 应使用withServer() 方法。

通过传递一个URI, 在Jenkins中预先配置的 Docker Server Certificate Authentication的证书ID, 如下:

node {
    checkout scm

    docker.withServer('tcp://swarm.example.com:2376', 'swarm-certs') {
        docker.image('mysql:5').withRun('-p 3306:3306') {
            /* do things */
        }
    }
}
 inside()build() 不能正确的在Docker集群服务器中工作。对于inside() 工作, Docker 服务器和Jenkins 代理必须使用相同的文件系统, 这样才能安装工作区。目前,Jenkins 插件和Docker CLI 都不会自动的 检查服务器远程运行的情况; 典型的症状是嵌套的sh命令的错误,比如cannot create /…@tmp/durable-…/pid: Directory nonexistent当 Jenkins 检查到代理本身在 Docker 容器中运行时, 它会自动地传递 --volumes-from 参数到 inside 容器,确保它能够和代理共享工作区。另外,Docker集群的一些版本不支持自定义注册。
   

使用自定义注册表

默认情况下, Docker 流水线 集成了 Docker Hub默认的 Docker注册表。 .

为了使用自定义Docker 注册吧, 脚本化流水线的用户能够使用 withRegistry() 方法完成步骤,传入自定义注册表的URL, 比如:

node {
    checkout scm

    docker.withRegistry('https://registry.example.com') {

        docker.image('my-custom-image').inside {
            sh 'make test'
        }
    }
}

对于需要身份验证的Docker 注册表, 从Jenkins 主页添加一个 "Username/Password" 证书项, 并使用证书ID 作为 withRegistry()的第二个参数:

node {
    checkout scm

    docker.withRegistry('https://registry.example.com', 'credentials-id') {

        def customImage = docker.build("my-image:${env.BUILD_ID}")

        /* Push the container to the custom Registry */
        customImage.push()
    }
}

⇐ 分支和pull请求

⇑ 流水线

索引

扩展共享库 ⇒

扩展共享库

Table of Contents

由于流水线被组织中越来越多的项目所采用,常见的模式很可能会出现。 在多个项目之间共享流水线有助于减少冗余并保持代码 "DRY" [1]。

流水线支持创建 "共享库" ,可以在外部源代码控制仓库中定义并加载到现有的流水线中。

定义共享库

共享库通过名称,源代码检索方法,比如 SCM,以及可选的默认版本定义。名称应该是一个简短的标识符,因为它将在脚本中使用。

该 SCM 可以理解该版本的任何内容;比如,分支、标签和提交哈希值,这些都适用于 Git。你还可以声明脚本是否需要显式地请求该库 (下面详细说明),或者在默认情况下是否存在该库。此外,如果你在 Jenkins 配置中指定了版本,则可以阻止脚本选择 不同的 版本。

指定 SCM 最好的方式是使用一个专门更新的 SCM 插件,以支持新的 API 检出任意命名的版本 (Modern SCM 选项)。 在撰写本文时,最新版本的 Git 和 Subversion 插件支持这种模式;其他人应该遵循。

如果你的 SCM 插件没有被集成, 你可以选择 Legacy SCM 并选择提供的任何东西。 在这种情况下, 你需要包含 ${library.yourLibName.version} 在 SCM 的配置中, 所以在检出插件期间,将会扩展该变量来选择需要的版本比如,对于 Subversion ,你可以设置 Repository URLhttps://svnserver/project/${library.yourLibName.version} 然后使用诸如 trunkbranches/devtags/1.0 的版本。

目录结构

共享库的目录结构如下:

(root)
+- src                     # Groovy source files
|   +- org
|       +- foo
|           +- Bar.groovy  # for org.foo.Bar class
+- vars
|   +- foo.groovy          # for global 'foo' variable
|   +- foo.txt             # help for 'foo' variable
+- resources               # resource files (external libraries only)
|   +- org
|       +- foo
|           +- bar.json    # static helper data for org.foo.Bar

src 目录应该看起来像标准的 Java 源目录结构。当执行流水线时,该目录被添加到类路径下。

vars 目录定义可从流水线访问的全局变量的脚本。 每个 *.groovy 文件的基名应该是一个 Groovy (~ Java) 标识符, 通常是 camelCased。 匹配 *.txt, 如果存在, 可以包含文档, 通过系统的配置标记格式化从处理 (所以可能是 HTML, Markdown 等,虽然 txt 扩展是必需的)。

这些目录中的 Groovy 源文件 在脚本化流水线中的 “CPS transformation” 一样。

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

根目录下的其他目录被保留下来以便于将来的增强。

全局共享库

有几个地方可以定义共享库, 这取决于用例。 Manage Jenkins » Configure System » Global Pipeline Libraries 必要时可以配置许多库。

Add a Global Pipeline Library

由于这些库将是全局可用的, 系统中的任何流水线都可以使用这些库中实现的功能。

这些库被认为是 "可信的:"他们可以在 Java,Groovy, Jenkins 内部 API, Jenkins 插件, 或第三方库中运行任何方法。 这允许你定义将单个不安全的API封进一个更高级别的包装中以便于在流水线中使用的库。 请注意 anyone able to push commits to this SCM repository could obtain unlimited access to Jenkins。 你需要 Overall/RunScripts 权限来配置这些库 (通常这些权限会授予 Jenkins 管理员)。

文件夹级别的共享库

创建的任何文件夹都可以有一个与之关联的共享库。该机制允许将特定库的范围扩展到文件夹或子文件夹的所有流水线。

基于文件夹的库不被认为是 "可信的:" 他们在 Groovy 沙箱中运行,就像典型的流水线一样。

自动分享库

其他插件可能会添加定义库的方法on the fly。比如, GitHub 分支源 插件提供了 "GitHub 组织文件夹" 项,它允许脚本使用一个不被信任的库, 比如 github.com/someorg/somerepo 而不需要任何额外的配置。在这种情况下, 指定的 GitHub 仓库将会从 master 分支加载, 使用匿名检出。

使用库

标记为 Load implicitly 的共享库允许流水线立即使用任何此库定义的类或全局变量。为了访问其他共享库, Jenkinsfile 需要使用 @Library 注解, 指定库的名字:

Configuring a Global Pipeline Library

@Library('my-shared-library') _
/* Using a version specifier, such as branch, tag, etc */
@Library('my-shared-library@1.0') _
/* Accessing multiple libraries with one statement */
@Library(['my-shared-library', 'otherlib@abc1234']) _

该注解可以在脚本的 Groovy 允许注解的任何地方。当引用类库时 (在 src/ 目录下), 通常注释会进入 import 语句:

@Library('somelib')
import com.mycorp.pipeline.somelib.UsefulClass
 对于只定义了全局变量 (vars/)的共享库, 或者只需要一个全局变量的 Jenkinsfile 文件, annotation 模式 @Library('my-shared-library') _ 有助于保持代码简洁。 从本质上说, 并不是注释一个不必要的 import 语句, 符号 _ 是带注释的。不建议 import 一个全局变量/函数, 由于这将强制编译器 将字段和方法解释为 static。 即使他们是要实例化的。 该例中的Groovy编译器 可以产生困惑人的错误消息。
   

在脚本的 compilation 期间, 在库执行之前,它被解析和加载。这允许 Groovy 编译器理解在静态类型检查中使用的符号的意义, 并允许他们在脚本的类型声明中被使用,比如:

@Library('somelib')
import com.mycorp.pipeline.somelib.Helper

int useSomeLib(Helper helper) {
    helper.prepare()
    return helper.count()
}

echo useSomeLib(new Helper('some text'))

Global Variables however, are resolved at runtime.

Loading libraries dynamically

作为 Pipeline: Shared Groovy Libraries 2.7 版本插件, 在脚本中有一个加载库(非隐式)的新选项t: 在构建期间的任何时间, dynamically加载库的library步骤。

如果你只对使用全局变量/方法 (从 vars/ 目录)感兴趣, 那么语法非常简单:

library 'my-shared-library'

此后, 该脚本可以访问该库的任何全局变量。

使用 src/ 目录下的类也是可行的, 但更复杂。 然而,在编译之前,@Library 注释准备了脚本的 “类路径”, 当遇到一个 library 步骤时,脚本已经被编译了。 因此,你不能 import 或 “静态地” 引用库中的类型。

但是你可以动态的使用类库(不用类型检查), 通过library 步骤返回值中完全限定的名称访问它们。 使用类似于Java的语法调用static 方法:

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

你也可以访问 static 字段, 并调用构造方法就像他们是名为 newstatic 方法:

def useSomeLib(helper) { // dynamic: cannot declare as Helper
    helper.prepare()
    return helper.count()
}

def lib = library('my-shared-library').com.mycorp.pipeline // preselect the package

echo useSomeLib(lib.Helper.new(lib.Constants.SOME_TEXT))

库版本

配置共享库的 "默认版本" 是在 "隐式加载" 被检查时使用,或者一个流水线通过名称引用了该库, 比如 @Library('my-shared-library') _。如果not 定义“默认版本”,流水线必须制定一个版本,比如 @Library('my-shared-library@master') _

如果在共享库的配置中启用了“允许默认版本被覆盖”, @Library 注解也可以覆盖为该库定义的默认版本。这同样允许在需要时从不同的版本加载一个“隐式加载”的库。

当使用 library 步骤你也可以指定一个版本:

library 'my-shared-library@master'

由于这是一个常规步骤,该版本可以被 computed, 而不是像注释那样的常量;比如:

library "my-shared-library@$BRANCH_NAME"

使用与多分支 Jenkinsfile 文件相同的 SCM 分支加载一个库。 作为另一个示例, 你可以通过参数选择一个库:

properties([parameters([string(name: 'LIB_VERSION', defaultValue: 'master')])])
library "my-shared-library@${params.LIB_VERSION}"

注意 library 步骤不会被用来覆盖隐式加载的库的版本。 在脚本启动时已经加载了它,并且一个给定名称的库不会被加载两次。

检索方法

指定 SCM 最好的方式是使用一个专门更新的 SCM 插件,以支持新的 API 检出任意命名的版本 (Modern SCM 选项)。 在撰写本文时,最新版本的 Git 和 Subversion 插件支持这种模式

Configuring a 'Modern SCM' for a Pipeline Library

遗留 SCM

还没有更新到支持共享库所需的新特性的 SCM 插件, 仍然可以通过 Legacy SCM 选项被使用。 在这种情况下, 包括 ${library.yourlibrarynamehere.version} 任何 分支/标签/引用 都可以配置为 SCM 插件。这确保在检出库的源代码期间, SCM 插件会扩展改该变量来检出库的合适的版本。

Configuring a 'Legacy SCM' for a Pipeline Library

动态检索

如果你在 library 步骤只指定了库的名称(optionally with version after @) , Jenkins 将查找该名称的预配置库。 (或者在github.com/owner/repo 自动库中,加载该文件)。 但是你也可以动态的指定检索方法, 在这种情况下不需要在Jenkins库中预定义库。 这是一个例子:

library identifier: 'custom-lib@master', retriever: modernSCM(
  [$class: 'GitSCMSource',
   remote: 'git@git.mycorp.com:my-jenkins-utils.git',
   credentialsId: 'my-private-key'])

最好为你的SCM的精确语法引用 Pipeline Syntax

注意,在这些情况下,库的版本 must 指定。

写库

在基本级别, 任何有效的 Groovy 代码 都可以使用。 不同的数据结构, 实用方法等, 比如:

// src/org/foo/Point.groovy
package org.foo;

// point in 3D space
class Point {
  float x,y,z;
}

访问步骤

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

// src/org/foo/Zot.groovy
package org.foo;

def checkOutFrom(repo) {
  git url: "git@github.com:jenkinsci/${repo}"
}

return this

这可以从一个脚本化流水线中调用:

def z = new org.foo.Zot()
z.checkOutFrom(repo)

该方法有一定的局限性; 比如, 它避免了父类的声明。

此外,在构造函数中, 或只是在一个方法中使用 this可以将一组 steps 显式地传递给类库:

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}"
  }
}

当在类上保存状态时, 如上图, 类 must 实现 Serializable 接口。确保使用类的流水线可以在Jenkins中适当的挂起和恢复, 如下所示。

@Library('utils') import org.foo.Utilities
def utils = new Utilities(this)
node {
  utils.mvn 'clean package'
}

如果该库需要访问全局变量, 比如 env, 则应该以类似的方式显式地传递给类库或方法。

而不是将大量的数据从脚本化流水线传递到库中。

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}"
  }
}

上面的示例显示传递给 static 方法的脚本,该方法从脚本化流水线中调用:

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

定义全局变量

在内部, vars目录中的脚本根据需求以单例的方式实例化,这允许在单个.groovy 文件中定义多个方法。例如:

vars/log.groovy

def info(message) {
    echo "INFO: ${message}"
}

def warning(message) {
    echo "WARNING: ${message}"
}

Jenkinsfile

@Library('utils') _

log.info 'Starting'
log.warning 'Nothing to do!'

声明式流水线不允许在script指令之外使用全局变量 (JENKINS-42360)。

Jenkinsfile

@Library('utils') _

pipeline {
    agent none
    stage ('Example') {
        steps {
             script { 
                 log.info 'Starting'
                 log.warning 'Nothing to do!'
             }
        }
    }
}
 script指令在声明式流水线中访问全局变量。
   
 定义在共享库的变量只会在Jenkins加载后显示在 Global Variables Reference (再 Pipeline Syntax下面) ,并将该库作为成功的流水线运行的一部分。
   
 Avoid preserving state in global variables避免使用交互或保存状态的方法来定义全局变量。 使用静态类或实例化一个类的局部变量。=== 定义自定义步骤共享库也可以定义全局变量,和定义内置步骤的操作类似, 比如 shgit。定义在共享库中 的全局变量must 必须以全小写或 "camelCased" 命名以便于能够在流水线中正确的加载。 [2]例如, 要定义 sayHello, 需要创建 vars/sayHello.groovy文件并实现call 方法。call 方法 允许全局变量以一种类似于步骤的方式被调用:// vars/sayHello.groovy def call(String name = 'human') { // Any valid steps can be called from this code, just like in other // Scripted Pipeline echo "Hello, ${name}." }然后流水线就能引用或调用该变量:sayHello 'Joe' sayHello() /* invoke with default arguments */如果用块调用, call 方法会接收一个 Closure。 应明确定义类型来说明该步骤的意义, 例如:// vars/windows.groovy def call(Closure body) { node('windows') { body() } }然后流水线就能使用这个变量,就像内置的步骤一样,它接收一个块:windows { bat "cmd /?" }=== 定义更结构化的 DSL如果你有很多类似的流水线, 全局变量机制提供了一个便利的工具来构建更高级别的获取相似度的 DSL。 比如, 所有的Jenkins插件用同样的方式构建和测试, 所以我们可能会写一个名为 buildPlugin的步骤:// vars/buildPlugin.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 将会大大简化:Jenkinsfile (Scripted Pipeline)buildPlugin name: 'git'还有一个使用 Groovy的 Closure.DELEGATE_FIRST“构建模式” 技巧, 它允许 Jenkinsfile 看起来更像一个配置文件,而不是程序, 但它更复杂,容易出错,不推荐使用。=== 使用第三方库在trusted 库代码中使用 @Grab 注释,可以使用第三方库, 它通常在 Maven Central中找到。详情请参阅 Grape documentation, 但简单地说:@Grab('org.apache.commons:commons-math3:3.4.1') import org.apache.commons.math3.primes.Primes void parallelize(int count) { if (!Primes.isPrime(count)) { error "${count} was not prime" } // … }在默认情况下,第三方库会被缓存到Jenkins主机的 ~/.groovy/grapes/ 文件中。=== 加载资源外部库可以使用libraryResource 步骤从 resources/ 目录加载附属的 文件。参数是相对路径名, 类似于Java资源加载:def request = libraryResource 'com/mycorp/pipeline/somelib/request.json'该文件做为字符串被加载,适合传递给某些 API或使用 writeFile保存到工作区。建议使用一个独特的包结构,这样你就不会意外地与另一个库发生冲突。=== 事前测试库的变更如果你在构建一个不被信任的库时注意到一个错误, 只需点击 Replay 链接尝试编辑它的一个或多个源文件, 查看是否构建结果和预期一样。 一旦你对该结果感到满意, 就可以从构建的状态页追踪diff链接, 并将其应用到库的仓库并提交。(即使请求库的版本是一个分支, 而不是像标记一样的固定版本, 重放构建将会使用与原始构建完全相同的修订: 库源不会被再次检出)。目前,Replay 不支持受信任的库,在 Replay期间也不支持修改资源文件。=== 定义声明式流水线从2017年9月下旬发布的声明式 1.2开始, 你也可以在你的共享库里定义声明式流水线。下面是一个示例, 它将会执行一个不同的流水线,这取决于构建号是奇数还是偶数:// vars/evenOrOdd.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 @Library('my-shared-library') _ evenOrOdd(currentBuild.getNumber())只有整个 流水线s can be defined in shared libraries as of this time. This can only be done in vars/*.groovy, 和 call方法。在单个构建中只有一个声明式流水线可以执行,如果你尝试执行第二个, 你的构建就会失败。
   

1. en.wikipedia.org/wiki/Don't_repeat_yourself

2. gist.github.com/rtyler/e5e57f075af381fce4ed3ae57aa1f0c2

流水线开发工具

Table of Contents

Jenkins 流水线包括 内置文档代码生成器 ,是开发流水线的关键资源。它们提供了详细的帮助和信息,这些帮助和信息被定制到当前安装的Jen在本节中, 我们将讨论可能有助于Jenkins流水线开发的其他工具和资源。

Blue Ocean 编辑器

Blue Ocean Pipeline Editor 提供 WYSIWYG 方法来创建声明式流水线。 该编辑器提供了所有阶段,并行分支和流水线中步骤的构造视图。 编辑器验证了流水线的更改, 在它们被提交之前消除了许多错误。在后台,它仍然生成声明式的流水线代码。

命令行流水线linter

Jenkins可以验证或者 "lint", 在实际运行它之前,从命令行发出声明式流水线。 这可以通过使用 Jenkins CLI 命令或用适当的参数创建一个 HTTP POST请求来完成。 建议使用 SSH interface 来运行linter。请参阅 Jenkins CLI 文档 了解如何正确配置Jenkins以获取安全命令行访问的详细信息 。

Linting via the CLI with SSH

# ssh (Jenkins CLI)
# JENKINS_SSHD_PORT=[sshd port on master]
# JENKINS_HOSTNAME=[Jenkins master hostname]
ssh -p $JENKINS_SSHD_PORT $JENKINS_HOSTNAME declarative-linter < Jenkinsfile

Linting via HTTP POST using curl

# curl (REST API)
# Assuming "anonymous read access" has been enabled on your Jenkins instance.
# JENKINS_URL=[root URL of Jenkins master]
# JENKINS_CRUMB is needed if your Jenkins master has CRSF protection enabled as it should
JENKINS_CRUMB=`curl "$JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"`
curl -X POST -H $JENKINS_CRUMB -F "jenkinsfile=<Jenkinsfile" $JENKINS_URL/pipeline-model-converter/validate

示例

下面是正在运行流水线linter的两个示例。 第一个示例显示传递一个无效的 Jenkinsfile时的输出,这是 agent 声明中缺失的部分。

Jenkinsfile

pipeline {
  agent
  stages {
    stage ('Initialize') {
      steps {
        echo 'Placeholder.'
      }
    }
  }
}

Linter output for invalid Jenkinsfile

# pass a Jenkinsfile that does not contain an "agent" section
ssh -p 8675 localhost declarative-linter < ./Jenkinsfile
Errors encountered validating Jenkinsfile:
WorkflowScript: 2: Not a valid section definition: "agent". Some extra configuration is required. @ line 2, column 3.
     agent
     ^

WorkflowScript: 1: Missing required section "agent" @ line 1, column 1.
   pipeline &#125;
   ^

在第二个示例中, Jenkinsfile 已被更新,它的内容包含agent上 丢失的any。 linter 现在报告说流水线是有效的。

Jenkinsfile

pipeline {
  agent any
  stages {
    stage ('Initialize') {
      steps {
        echo 'Placeholder.'
      }
    }
  }
}

Linter output for valid Jenkinsfile

ssh -p 8675 localhost declarative-linter < ./Jenkinsfile
Jenkinsfile successfully validated.

"replay" Pipeline Runs with Modifications

典型的流水线将在经典的 Jenkins web UI中被定义, 或者提交一个 Jenkinsfile i到源代码控制。 不幸的是, 这两种方法都不适合于流水线的快速迭代或原型开发。 "Replay" 特性允许快速修改和执行现有流水线,而不需要修改流水线配置或创建新的提交。

用法

使用"Replay" 特性:

  1. 在构建历史中选择一个之前已完成的运行。

    Previous Pipeline Run

  2. 点击右侧菜单的 "Replay" 。

    Replay Left-menu Button

  3. 修改并点击 "Run"。在该示例中, 将 "ruby-2.3" 改为 "ruby-2.4"。

    Replay Left-menu Button

  4. 检查更改的结果

一旦你满意本次更改, 你可以使用回放来再次查看他们, 复制他们到你的流水线作业或 Jenkinsfile中, 然后使用平常的工程流程提交它们。

特性

  • Can be called multiple times on the same run - 允许对不同的更改进行简单的并行测试。

  • Can also be called on Pipeline runs that are still in-progress - 只要流水线包含语法正确的 Groovy 并且能够启动,就可以回放。

  • Referenced Shared Library code is also modifiable - 如果一个流水线运行引用了一个 Shared Library, 那么共享库中的代码也将作为回放页面的一部分显示和修改。

限制

  • Pipeline runs with syntax errors cannot be replayed - 意思是他们的代码不能被查看,任何在他们里面的改变都不能被检索。 当使用回放进行更重要的修改时, 在运行之前保存你的变更到一个Jenkins之外的文件或编辑器中。 参考JENKINS-37589

  • Replayed Pipeline behavior may differ from runs started by other methods - 对于不属于多分支流水线的流水线,原始运行和回放运行的 提交信息可能会不同。 参考 JENKINS-36453

IDE 集成

Eclipse Jenkins 编辑器

Eclipse 市场存在一个名为 Jenkins Editor的Eclipse插件。 这个特殊的文本编辑器提供了一些定义流水线的特性,比如:

  • 通过 Jenkins Linter Validation验证流水线脚本。 失败会显示为Eclipse标记。

  • 带有专用图标的大纲(用于声明式 Jenkins 流水线 )

  • 语法 / 关键字高亮

  • Groovy 验证

 Jenkins 编辑器插件是一个不被Jenkins项目支持的第三方工具。
   

流水线单元测试框架

 流水线单元测试框架是一个不被Jenkins项目支持的第三方工具。
   

流水线单元测试框架 允许在运行流水线和共享库之前对他们进行 单元测试。它提供了一个模拟执行环境,其中实际的流水线步骤被模拟对象所替换,你可以使用模拟对象来检查预期的行为。 新而粗糙的边缘周围, 但有希望。 该项目的 README包含示例和使用说明。

流水线语法

Table of Contents

本节是建立在 流水线入门内容的基础上,而且,应当被当作一个参考。 对于在实际示例中如何使用流水线语法的更多信息, 请参阅本章在流水线插件的2.5版本中的 使用 Jenkinsfile部分, 流水线支持两种离散的语法,具体如下对于每种的优缺点, 参见语法比较

正如 本章开始讨论的, 流水线最基础的部分是 "步骤"。基本上, 步骤告诉 Jenkins 要做什么,以及作为声明式和脚本化流水线语法的基本构建块。

对于可用步骤的概述, 请参考 流水线步骤引用,它包含了一个构建到流水线的步骤和 插件提供的步骤的全面的列表。

声明式流水线

声明式流水线是最近添加到 Jenkins 流水线的 [1],它在流水线子系统之上提供了一种更简单,更有主见的语法。

所有有效的声明式流水线必须包含在一个 pipeline 块中, 比如:

pipeline {
    /* insert Declarative Pipeline here */
}

在声明式流水线中有效的基本语句和表达式遵循与 Groovy的语法同样的规则, 有以下例外:

  • 流水线顶层必须是一个 block, 特别地: pipeline { }

  • 没有分号作为语句分隔符,,每条语句都必须在自己的行上。

  • 块只能由 节段, 指令, 步骤, 或赋值语句组成。 *属性引用语句被视为无参方法调用。 例如, input被视为 input()

节段

声明式流水线中的节段通常包含一个或多个 指令步骤

代理

agent 部分指定了整个流水线或特定的部分, 将会在Jenkins环境中执行的位置,这取决于 agent 区域的位置。该部分必须在 pipeline 块的顶层被定义, 但是 stage 级别的使用是可选的。

RequiredYes
Parameters Described below
Allowed In the top-level pipeline block and each stage block.
参数

为了支持作者可能有的各种各样的用例流水线, agent 部分支持一些不同类型的参数。这些参数应用在pipeline块的顶层, 或 stage 指令内部。

  • any

    在任何可用的代理上执行流水线或阶段。例如: agent any

  • none

    当在 pipeline 块的顶部没有全局代理, 该参数将会被分配到整个流水线的运行中并且每个 stage 部分都需要包含他自己的 agent 部分。比如: agent none

  • label

    在提供了标签的 Jenkins 环境中可用的代理上执行流水线或阶段。 例如: agent { label 'my-defined-label' }

  • node

    agent { node { label 'labelName' } }agent { label 'labelName' } 一样, 但是 node 允许额外的选项 (比如 customWorkspace )。

  • docker

    使用给定的容器执行流水线或阶段。该容器将在预置的 node上,或在匹配可选定义的label 参数上,动态的供应来接受基于Docker的流水线。 docker 也可以选择的接受 args 参数,该参数可能包含直接传递到 docker run 调用的参数, 以及 alwaysPull 选项, 该选项强制 docker pull ,即使镜像名称已经存在。 比如: agent { docker 'maven:3-alpine' }agent { docker { image 'maven:3-alpine' label 'my-defined-label' args '-v /tmp:/tmp' } }

  • dockerfile

    执行流水线或阶段, 使用从源代码库包含的 Dockerfile 构建的容器。为了使用该选项, Jenkinsfile 必须从多个分支流水线中加载, 或者加载 "Pipeline from SCM." 通常,这是源代码仓库的根目录下的 Dockerfile : agent { dockerfile true }. 如果在另一个目录下构建 Dockerfile , 使用 dir 选项: agent { dockerfile {dir 'someSubDir' } }。如果 Dockerfile 有另一个名称, 你可以使用 filename 选项指定该文件名。你可以传递额外的参数到 docker build ... 使用 additionalBuildArgs 选项提交, 比如 agent { dockerfile {additionalBuildArgs '--build-arg foo=bar' } }。 例如, 一个带有 build/Dockerfile.build 的仓库,期望一个构建参数 version: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' } }

常见选项

有一些应用于两个或更多 agent 的实现的选项。他们不被要求,除非特别规定。

  • label

    一个字符串。该标签用于运行流水线或个别的 stage。该选项对 node, dockerdockerfile 可用, node要求必须选择该选项。

  • customWorkspace

    一个字符串。在自定义工作区运行应用了 agent 的流水线或个别的 stage, 而不是默认值。 它既可以是一个相对路径, 在这种情况下,自定义工作区会存在于节点工作区根目录下, 或者一个绝对路径。比如:agent { node { label 'my-defined-label' customWorkspace '/some/other/path' } }该选项对 node, dockerdockerfile 有用 。

  • reuseNode

    一个布尔值, 默认为false。 如果是true, 则在流水线的顶层指定的节点上运行该容器, 在同样的工作区, 而不是在一个全新的节点上。这个选项对 dockerdockerfile 有用, 并且只有当 使用在个别的 stageagent 上才会有效。

示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent { docker 'maven:3-alpine' } 
    stages {
        stage('Example Build') {
            steps {
                sh 'mvn -B clean verify'
            }
        }
    }
}
 在一个给定名称和标签(maven:3-alpine)的新建的容器上执行定义在流水线中的所有步骤 。
   
阶段级别的 agent 部分

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent none 
    stages {
        stage('Example Build') {
            agent { docker 'maven:3-alpine' } 
            steps {
                echo 'Hello, Maven'
                sh 'mvn --version'
            }
        }
        stage('Example Test') {
            agent { docker 'openjdk:8-jre' } 
            steps {
                echo 'Hello, JDK'
                sh 'java -version'
            }
        }
    }
}
 在流水线顶层定义 agent none 确保 an Executor 没有被分配。 使用 agent none 也会强制 stage 部分包含他自己的 agent 部分。
  使用镜像在一个新建的容器中执行该阶段的该步骤。
  使用一个与之前阶段不同的镜像在一个新建的容器中执行该阶段的该步骤。

post

post 部分定义一个或多个steps ,这些阶段根据流水线或阶段的完成情况而 运行(取决于流水线中 post 部分的位置). post 支持以下 post-condition 块中的其中之一: always, changed, failure, success, unstable, 和 aborted。这些条件块允许在 post 部分的步骤的执行取决于流水线或阶段的完成状态。

RequiredNo
Parameters None
Allowed In the top-level pipeline block and each stage block.
Conditions
  • always

    无论流水线或阶段的完成状态如何,都允许在 post 部分运行该步骤。

  • changed

    只有当前流水线或阶段的完成状态与它之前的运行不同时,才允许在 post 部分运行该步骤。

  • failure

    只有当前流水线或阶段的完成状态为"failure",才允许在 post 部分运行该步骤, 通常web UI是红色。

  • success

    只有当前流水线或阶段的完成状态为"success",才允许在 post 部分运行该步骤, 通常web UI是蓝色或绿色。

  • unstable

    只有当前流水线或阶段的完成状态为"unstable",才允许在 post 部分运行该步骤, 通常由于测试失败,代码违规等造成。通常web UI是黄色。

  • aborted

    只有当前流水线或阶段的完成状态为"aborted",才允许在 post 部分运行该步骤, 通常由于流水线被手动的aborted。通常web UI是灰色。

示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
    post { 
        always { 
            echo 'I will always say Hello again!'
        }
    }
}
 按照惯例, post 部分应该放在流水线的底部。
  Post-condition 块包含与 steps 部分相同的steps

stages

包含一系列一个或多个 stage 指令, stages 部分是流水线描述的大部分"work" 的位置。 建议 stages 至少包含一个 stage 指令用于连续交付过程的每个离散部分,比如构建, 测试, 和部署。

RequiredYes
Parameters None
Allowed Only once, inside the pipeline block.
示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages { 
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}
 stages 部分通常会遵循诸如 agent, options 等的指令。
   

steps

steps 部分在给定的 stage 指令中执行的定义了一系列的一个或多个steps

RequiredYes
Parameters None
Allowed Inside each stage block.
示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example') {
            steps { 
                echo 'Hello World'
            }
        }
    }
}
 steps 部分必须包含一个或多个步骤。
   

指令

environment

environment 指令制定一个 键-值对序列,该序列将被定义为所有步骤的环境变量,或者是特定于阶段的步骤, 这取决于 environment 指令在流水线内的位置。

该指令支持一个特殊的助手方法 credentials() ,该方法可用于在Jenkins环境中通过标识符访问预定义的凭证。对于类型为 "Secret Text"的凭证, credentials() 将确保指定的环境变量包含秘密文本内容。对于类型为 "SStandard username and password"的凭证, 指定的环境变量指定为 username:password ,并且两个额外的环境变量将被自动定义 :分别为 MYVARNAME_USRMYVARNAME_PSW

RequiredNo
Parameters None
Allowed Inside the pipeline block, or within stage directives.
示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    environment { 
        CC = 'clang'
    }
    stages {
        stage('Example') {
            environment { 
                AN_ACCESS_KEY = credentials('my-prefined-secret-text') 
            }
            steps {
                sh 'printenv'
            }
        }
    }
}
 顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤。
  在一个 stage 中定义的 environment 指令只会将给定的环境变量应用于 stage 中的步骤。
  environment 块有一个 助手方法 credentials() 定义,该方法可以在 Jenkins 环境中用于通过标识符访问预定义的凭证。

options

options 指令允许从流水线内部配置特定于流水线的选项。 流水线提供了许多这样的选项, 比如 buildDiscarder,但也可以由插件提供, 比如 timestamps.

RequiredNo
Parameters None
Allowed Only once, inside the pipeline block.
可用选项
  • buildDiscarder

    为最近的流水线运行的特定数量保存组件和控制台输出。例如: options { buildDiscarder(logRotator(numToKeepStr: '1')) }

  • disableConcurrentBuilds

    不允许同时执行流水线。 可被用来防止同时访问共享资源等。 例如: options { disableConcurrentBuilds() }

  • overrideIndexTriggers

    允许覆盖分支索引触发器的默认处理。 如果分支索引触发器在多分支或组织标签中禁用, options { overrideIndexTriggers(true) } 将只允许它们用于促工作。否则, options { overrideIndexTriggers(false) } 只会禁用改作业的分支索引触发器。

  • skipDefaultCheckout

    agent 指令中,跳过从源代码控制中检出代码的默认情况。例如: options { skipDefaultCheckout() }

  • skipStagesAfterUnstable

    一旦构建状态变得UNSTABLE,跳过该阶段。例如: options { skipStagesAfterUnstable() }

  • checkoutToSubdirectory

    在工作空间的子目录中自动地执行源代码控制检出。例如: options { checkoutToSubdirectory('foo') }

  • timeout

    设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线。例如: options { timeout(time: 1, unit: 'HOURS') }

  • retry

    在失败时, 重新尝试整个流水线的指定次数。 For example: options { retry(3) }

  • timestamps

    预谋所有由流水线生成的控制台输出,与该流水线发出的时间一致。 例如: options { timestamps() }

Example

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    options {
        timeout(time: 1, unit: 'HOURS') 
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}
 指定一个小时的全局执行超时, 在此之后,Jenkins 将中止流水线运行。
   
 一个完整的可用选项列表正在等待完成第 INFRA-1503次。
   
阶段选项

stageoptions 指令类似于流水线根目录上的 options 指令。然而, stage -级别 options 只能包括 retry, timeout, 或 timestamps 等步骤, 或与 stage 相关的声明式选项,如 skipDefaultCheckout

stage, options 指令中的步骤在进入 agent 之前被调用或在 when 条件出现时进行检查。

可选的阶段选项
  • skipDefaultCheckout

    agent 指令中跳过默认的从源代码控制中检出代码。例如: options { skipDefaultCheckout() }

  • timeout

    设置此阶段的超时时间, 在此之后, Jenkins 会终止该阶段。 例如: options { timeout(time: 1, unit: 'HOURS') }

  • retry

    在失败时, 重试此阶段指定次数。 例如: options { retry(3) }

  • timestamps

    预谋此阶段生成的所有控制台输出以及该行发出的时间一致。例如: options { timestamps() }

示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example') {
            options {
                timeout(time: 1, unit: 'HOURS') 
            }
            steps {
                echo 'Hello World'
            }
        }
    }
}
 指定 Example 阶段的执行超时时间, 在此之后,Jenkins 将中止流水线运行。
   

参数

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

RequiredNo
Parameters None
Allowed Only once, inside the pipeline block.
可用参数
  • 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}"
            }
        }
    }
}
 一份完整的可用参数列表正在等待 INFRA-1503的完成。
   

触发器

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

RequiredNo
Parameters None
Allowed Only once, inside the pipeline block.
  • 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 指令中。

RequiredAt least one
Parameters One mandatory parameter, a string for the name of the stage.
Allowed Inside the stages section.
示例

Jenkinsfile (Declarative Pipeline)

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

工具

定义自动安装和放置 PATH 的工具的一部分。如果 agent none 指定,则忽略该操作。

RequiredNo
Parameters None
Allowed Inside the pipeline block or a stage block.
支持工具
  • maven

  • jdk

  • gradle

示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    tools {
        maven 'apache-maven-3.0.1' 
    }
    stages {
        stage('Example') {
            steps {
                sh 'mvn --version'
            }
        }
    }
}
 The tool name must be pre-configured in Jenkins under Manage JenkinsGlobal Tool Configuration.
   

input

stageinput 指令允许你使用 input step提示输入。 在应用了 options 后,进入 stageagent 或评估 when 条件前, stage 将暂停。 如果 input 被批准, stage 将会继续。 作为 input 提交的一部分的任何参数都将在环境中用于其他 stage

配置项
  • message

    必需的。 这将在用户提交 input 时呈现给用户。

  • id

    input 的可选标识符, 默认为 stage 名称。

  • ok

    input表单上的"ok" 按钮的可选文本。

  • submitter

    可选的以逗号分隔的用户列表或允许提交 input 的外部组名。默认允许任何用户。

  • submitterParameter

    环境变量的可选名称。如果存在,用 submitter 名称设置。

  • parameters

    提示提交者提供的一个可选的参数列表。 更多信息参见 [parameters]

示例

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example') {
            input {
                message "Should we continue?"
                ok "Yes, we should."
                submitter "alice,bob"
                parameters {
                    string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
                }
            }
            steps {
                echo "Hello, ${PERSON}, nice to meet you."
            }
        }
    }
}

when

when 指令允许流水线根据给定的条件决定是否应该执行阶段。 when 指令必须包含至少一个条件。 如果 when 指令包含多个条件, 所有的子条件必须返回True,阶段才能执行。 这与子条件在 allOf 条件下嵌套的情况相同 (参见下面的示例)。

使用诸如 not, allOf, 或 anyOf 的嵌套条件可以构建更复杂的条件结构 can be built 嵌套条件可以嵌套到任意深度。

RequiredNo
Parameters None
Allowed Inside a stage directive
内置条件
  • branch

    当正在构建的分支与模式给定的分支匹配时,执行这个阶段, 例如: when { branch 'master' }。注意,这只适用于多分支流水线。

  • environment

    当指定的环境变量是给定的值时,执行这个步骤, 例如: when { environment name: 'DEPLOY_TO', value: 'production' }

  • expression

    当指定的Groovy表达式评估为true时,执行这个阶段, 例如: when { expression { return params.DEBUG_BUILD } }

  • not

    当嵌套条件是错误时,执行这个阶段,必须包含一个条件,例如: when { not { branch 'master' } }

  • allOf

    当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件,例如: when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }

  • anyOf

    当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件,例如: when { anyOf { branch 'master'; branch 'staging' } }

在进入 stageagent 前评估 when

默认情况下, 如果定义了某个阶段的代理,在进入该stageagent 后该 stagewhen 条件将会被评估。但是, 可以通过在 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'
            }
        }
    }
}

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
                environment name: 'DEPLOY_TO', value: 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                allOf {
                    branch 'production'
                    environment name: 'DEPLOY_TO', value: 'production'
                }
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
                anyOf {
                    environment name: 'DEPLOY_TO', value: 'production'
                    environment name: 'DEPLOY_TO', value: 'staging'
                }
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                expression { BRANCH_NAME ==~ /(production|staging)/ }
                anyOf {
                    environment name: 'DEPLOY_TO', value: 'production'
                    environment name: 'DEPLOY_TO', value: 'staging'
                }
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

Jenkinsfile (Declarative Pipeline)

pipeline {
    agent none
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            agent {
                label "some-label"
            }
            when {
                beforeAgent true
                branch 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

并行

声明式流水线的阶段可以在他们内部声明多隔嵌套阶段, 它们将并行执行。 注意,一个阶段必须只有一个 stepsparallel 的阶段。 嵌套阶段本身不能包含进一步的 parallel 阶段, 但是其他的阶段的行为与任何其他 stage 相同。任何包含 parallel 的阶段不能包含 agenttools 阶段, 因为他们没有相关 steps

另外, 通过添加 failFast true 到包含 parallelstage 中, 当其中一个进程失败时,你可以强制所有的 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"
                    }
                }
            }
        }
    }
}

步骤

声明式流水线可能使用在 流水线步骤引用中记录的所有可用的步骤, 它包含一个完整的步骤列表, 其中添加了下面列出的步骤,这些步骤只在声明式流水线中 only supported

脚本

script 步骤需要 [scripted-pipeline]块并在声明式流水线中执行。 对于大多数用例来说,应该声明式流水线中的“脚本”步骤是不必要的, 但是它可以提供一个有用的"逃生出口"。 非平凡的规模和/或复杂性的 script 块应该被转移到 共享库

示例

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"
                    }
                }
            }
        }
    }
}

脚本化流水线

脚本化流水线, 与[declarative-pipeline]一样的是, 是建立在底层流水线的子系统上的。与声明式不同的是, 脚本化流水线实际上是由 Groovy构建的通用 DSL [2]。 Groovy 语言提供的大部分功能都可以用于脚本化流水线的用户。这意味着它是一个非常有表现力和灵活的工具,可以通过它编写持续交付流水线。

流控制

脚本化流水线从 Jenkinsfile 的顶部开始向下串行执行, 就像 Groovy 或其他语言中的大多数传统脚本一样。 因此,提供流控制取决于 Groovy 表达式, 比如 if/else 条件, 例如:

Jenkinsfile (Scripted Pipeline)

node {
    stage('Example') {
        if (env.BRANCH_NAME == 'master') {
            echo 'I only execute on the master branch'
        } else {
            echo 'I execute elsewhere'
        }
    }
}

另一种方法是使用Groovy的异常处理支持来管理脚本化流水线流控制。当 步骤 失败 ,无论什么原因,它们都会抛出一个异常。处理错误的行为必须使用Groovy中的 try/catch/finally 块 , 例如:

Jenkinsfile (Scripted Pipeline)

node {
    stage('Example') {
        try {
            sh 'exit 1'
        }
        catch (exc) {
            echo 'Something failed, I should sound the klaxons!'
            throw
        }
    }
}

步骤

正如 本章开始所讨论的, 流水线最基础的部分是"步骤"。从根本上说, 步骤告诉 Jenkins要做 what ,并作为声明式和脚本化流水线已发的基本构建块。

脚本化流水线 not 不引入任何特定于其语法的步骤; 流水线步骤引用 包括流水线和插件提供的步骤的完整列表。

区别普通 Groovy

为了提供 durability, 这意味着运行流水线可以在Jenkins master 重启后继续运行,脚本化的流水线序列化数据到主服务器。由于这个设计需求, 一些Groovy 习惯用语,比如 collection.each { item -> /* perform operation */ } 都不完全支持。详情参见 JENKINS-27421JENKINS-26481

语法比较

当Jenkins 流水线第一次构建时, Groovy 被选为基础。 Jenkins长期使用嵌入式 Groovy引擎来为管理员和用户提供 高级脚本功能。另外, Jenkins流水线的实现者发现 Groovy是 构建现在成为 "脚本化流水线" DSL的坚实基础 [2]。

由于它是一个功能齐全的编程环境, 脚本化流水线为Jenkins用户提供了 大量的灵活性性和可扩展性。 Groovy学习曲线通常不适合给定团队的所有成员, 因此创造了声明式流水线来为编写Jenkins流水线提供一种更简单、更有主见的语法。

两者本质上是相同的流水线子系统。 underneath. 他们都是 "流水线即代码" 的持久实现。它们都能够使用构建到流水线中或插件提供的步骤。它们都能够使用 共享库

但是它们的区别在于语法和灵活性。 声明式限制了用户使用更严格和预定义的结构, 使其成为更简单的持续交付流水线的理想选择。 脚本化提供了很少的限制, 以至于对脚本和语法的唯一限制往往是由Groovy子集本身定义的,而不是任何特定于流水线的系统, 这使他成为权利用户和那些有更复杂需求的人的理想选择。 顾名思义, 声明式流水线鼓励 声明式编程模型。 [3] 而脚本化流水线遵循一个更命令式的编程模型 [4]


1. Version 2.5 of the "Pipeline plugin" introduces support for Declarative Pipeline syntax

2. Domain-specific language

3. Declarative Programming

4. Imperative Programming

规模 Pipelines

Table of Contents

流水线的主要瓶颈之一是它 FREQUENTLY 将临时数据写入磁盘,以便于运行流水线能够处理意外的Jenkins重启或系统崩溃。对于许多用户来说,这种持久性是有用,但是它的性能成本是一个问题。

流水线现在包含了一些特性,通过减少写入磁盘的数据的量以及写入磁盘的频率 使用户提高耐用的性能-- 以一个小的成本。在一些特殊情况下,如果Jenkins突然关闭,用户没有获得写入数据的机会,就可能无法恢复或可视化正在运行的流水线。 由于这些设置包括速度与持久性的权衡,他们最初是选择性加入的。 为了启用性能优化模式, 用户需要明确设置流水线的 Speed/Durability Setting 。 如果没有明确的选择, 流水线目前默认为 "最大持久性" 设置并像过去一样写入磁盘中。 在相同的插件版本中有一些 I/O 优化, 但好处要小得多。

如何设置速度/持久性设置?

有 3 种方式配置持久性设置:

  1. Globally, 在 "管理Jenkins" > "系统配置"下你可以选择一个全局默认 durability设置 , 标记 "流水线速度/持久性设置"。 你可以使用下面这些更具体的设置覆盖这些内容。

  2. Per pipeline job: 在作业配置的顶部, 标记 "自定义流水线速度/持久性级别" - 它会覆盖全局设置。或者, 使用 "属性" 步骤 - 该设置将会应用到该步骤执行后的下一次运行(相同的结果)。

  3. Per-branch for a multibranch project: 配置自定义分支属性策略 (在SCM下)并为自定义流水线速度/持久性级别添加属性。它会覆盖全局设置。 你还可以使用 "属性" 步骤来覆盖设置,但请记住,你可能需要再次运行该步骤来撤销该设置。

持久性设置将会影响下一次适用的流水线运行, 而不是立即。 该设置将会显示在日志中。

更高性能的持久性设置能帮助我吗?

  • 是的, 如果你的 Jenkins 实例使用 NFS,磁存储, 同时运行许多流水线, 或者显示高的 iowait.

  • 是的, 如果你运行带有许多步骤(超过几百个)的流水线。

  • 是的, 如果你的流水线存储大型文件或复杂数据到脚本的变量中, 保存这些变量在将来使用的范围内, 然后运行步骤。 这听起来很奇怪,但是发生的比你想象的要多。

    • 例如: 带有一个大的 XML/JSON文件的readFile 步骤 ,或者使用来自解析 One of the Utility Steps这样的文件的配置信息。

    • 另一个常见的模式是包含来自许多分支 (日志, 结果, 或统计数据)的数据的"summary" 对象。由于你将经常通过添加/附加或 Map.put() 操作添加它,通常这是可见的。

    • 数据的大数组或配置信息的 Map是这种情况的另一个常见示例。

  • 不, 如果你的流水线花费几乎所有的时间等待shell/批处理脚本完成。这不是万能的 "go fast" 按钮!

  • 不, 如果流水线将大量数据写入日志(日志记录不变)。

  • 不, 如果你不使用流水线, 或者你的系统被其他因素加载。

  • 不, 如果你没有为流水线启用更高性能的模式。

为什么放弃持久性设置"权衡?"

Stability of Jenkins ITSELF is not changed regardless of this setting - 它只适用于流水线。最坏的情况是类似于自由构建—运行不能持久存储数据的流水线可能无法恢复或显示在 Blue Ocean/阶段视图等,但会显示日志。这 only 影响到运行的流水线,而且只有当Jenkins被突然关闭,并且在它们完成之前没有优雅地关闭。

"graceful" shutdown是Jenkins完全关闭进程的地方, 比如访问 http://[jenkins-server]/退出, 或者使用正常的服务关闭脚本(如果 Jenkins健壮)。 发送一个 SIGTERM/SIGINT 到 Jenkins会触发一个优雅的关闭。 注意:运行流水线不需要完成(你不需要use /safeExit来关闭)。

"dirty" shutdown 是当 Jenkins没有进行正常的关机过程时。如果进程被强制终止,就会发生这种情况。最常见的原因是使用 SIGKILL 终止 Jenkins 进程或杀死运行Jenkins的容器/VM 。只要Jenkins 进程能够恢复,,简单的停止或暂停容器/VM 不会造成这种情况。 由于灾难性的系统操作故障(包括 Linux OOMKiller攻击Jenkins的java 进程以释放内存),脏关闭也有可能会发生。

Atomic writes: except "最大持久性"之外的所有设置都避免了原子写入 --这意味着如果操作系统运行Jenkins失败, 写到磁盘的缓存数据不会被刷新, 它将会丢失。 这种情况非常少见, 容器或虚拟化操作停止操作系统或断开存储可能会造成这种情况。 通常这些数据会被很快地刷新到磁盘, 所以数据丢失的窗口是简短的。 在 Linux 上,刷新到磁盘可以通过运行’sync’强制执行。在一些汉奸的情况下,这也会导致无法加载的构建。

使用持久性配置的配置要求

  • Jenkins LTS 2.73+ 或以上版本 (或者 weekly 2.62+)

  • 下面的all流水线插件 , 至少安装指定的最低版本:

    • 流水线: API (workflow-api) v2.25

    • 流水线: Groovy (workflow-cps) v2.43

    • 流水线: Job (workflow-job) v2.17

    • 流水线: Supporting APIs (工作流支持) v2.17

    • 流水线: 多分支 (工作流多分支) v2.17 - 可选, 只需要为多分支流水线启动该设置。

  • 重启主机来使用更新的插件 - 注意: 你需要使用这些所有插件。

持久性配置是什么?

  • P性能优化模式 ("PERFORMANCE_OPTIMIZED") - Greatly 减少磁盘 I/O。 如果流水线没有完成 ,Jenkins 没有优雅地关闭, 它们可能会像上面的自由式项目一样丢失数据 — 在上面查看细节。

  • 最大持久性 ("MAX_SURVIVABILITY") - 像之前的流水线中所做的那样, 最慢的选项。 使用它来运行你最重要的流水线。

  • 不那么持久, 晒微快一些("SURVIVABLE_NONATOMIC") -每一步都写入数据,但是避免了原子写入。 这比更大耐久性模块要快, 尤其是在网络文件系统上。它带有一个额外的风险(在上面的 "为什么我放弃了: 原子写入"有详细说明)。

推荐的最佳实践和持久性配置

  • 对大多数流水线使用 "性能优化" 模式 ,尤其是基本的构建测试流水线或任何可以在需要时再次运行的东西。

  • 使用 "最大持久性" 和 "不那么持久" 的流水线模式 ,你需要你需要有保证的执行记录(auditing). 这些记录运行在每一步。

  • 当流水线修改关键基础设施的状态时,使用 "最大持久性" 和 "不那么持久"。比如, 用于产品部署。

  • 为持久性设置设置"性能优化"的全局默认值 (见上文), 然后 在特定的流水线作业或多分支流水线的分支 ("主分支" 或发布分支)中设置 "最大持久性"。

  • 你可以强制地让流水线暂停来保存数据。

其他规模建议

  • Whenever possible, run Jenkins with fast SSD-backed storage and not hard drives. This can make a *huge* difference.

  • 一般来说,将工具和作业联系起来。当使用构建代理运行一个复杂的过程时, 写一个简短的 Shell/Batch/Groovy/Python 脚本。 Good examples 包括处理数据, 与REST API交互, 和 解析/模板 大型的 XML 或 JSON 文件。 shbat 有助于调用这些步骤, 尤其是 returnStdout: true 返回该脚本的输出并将其保存为变量(脚本化流水线)。

    • 流水线 DSL 不是为任意的网络和计算任务 - 它是为CI/CD 脚本编写的。

  • 如果条件允许 ,使用流水线插件和脚本安全的最新版本,这些包含了定期的性能提高。

  • 尝试通过减少运行的步骤数量和使用更简单的 Groovy 代码来简化脚本化流水线的代码。

  • 如果可以的话,合并相同类型的顺序步骤, 比如通过使用 Shell步骤 来调用helper脚本而不是运行多个步骤。

  • 尝试通过流水线限制写入日志的数据量。如果你正在编写几MB的日志数据, 比如来自构建工具, 将它写入到外部文件, 压缩它, 并将它存档为构建组件。

  • 在使用超过6MB堆的Jenkins时,使用 建议的垃圾收集调优选项 来减少垃圾收集的暂停时间和开销。

Blue Ocean

子章节

Table of Contents

本章节涵盖了Blue Ocean 功能的所有方面,包括:

本章节使用与所有技能水平的Jenkins用户,但初学者可能需要参阅 Pipeline 的某些章节,以了解Blue Ocean章节 包含的一些主题。

有关Jenkins用户手册的概述,请参阅 用户手册概述.

什么是 Blue Ocean?

Blue Ocean 重新思考Jenkins的用户体验,从头开始设计Jenkins Pipeline, 但仍然与自由式作业兼容,Blue Ocean减少了混乱而且进一步明确了团队中每个成员 Blue Ocean 的主要特性包括:

  • 持续交付(CD)Pipeline的 复杂可视化 ,可以让您快速直观地理解管道状态。

  • Pipeline 编辑器 - 引导用户通过直观的、可视化的过程来创建Pipeline,从而使Pipeline的创建变得平易近人。

  • 个性化 以适应团队中每个成员不同角色的需求。

  • 在需要干预和/或出现问题时 精确定位 。 Blue Ocean 展示 Pipeline中需要关注的地方, 简化异常处理,提高生产力

  • 本地集成分支和合并请求, 在与GitHub 和 Bitbucket中的其他人协作编码时实现最大程度的开发人员生产力。

开始使用 Blue Ocean, 请参照 Getting started with Blue Ocean.

 

 

常见问题

为什么需要 Blue Ocean?

世界已经从开发者的纯粹功能性工具转向了开发人员工具,成为“开发者体验”的一部分, 也就是说,它不再是单一的工具,而是开发者全天使用的许多工具,以及它们如何协同工作以实现对开发人员有利的 工作流程-这就是“开发者体验”

像Heroku,Atlassian和Github这样的开发工具公司已经提高了业界认为的良好开发者体验的标准,开发人员也越来越期望获得优秀的设计 。近年来,开发者越来越被那些不仅功能强大,而且能够无缝地融入工作流程中,使用起来很愉悦的工具所吸引。这种转变代表了更高的设计 和用户体验标准。Jenkins需要改善以达到这个更高的标准。

创建可视化CD pipeline 对于很多Jenkins用户来说非常有价值,为了满足他们的需求,Jenkins社区已经创建了超过5个插件。 这表明需要重新审视目前Jenkins如何表达这些概念,并将交付pipeline视为Jenkins用户体验的中心主题。

这不仅仅是持续交付概念,而且是开发人员每天使用的工具 - Github,Bitbucket,Slack,HipChat,Puppet或Docker。 它不仅仅是Jenkins - 而是涵盖了多种工具的,围绕Jenkins的开发者工作流程。

新团队几乎没有时间积累自己的Jenkins经验 - 他们希望更快地发布更好的软件来缩短上市时间。 总结以上经验,Jenkins体验是我们可以与Jenkins用户和贡献者社区共同努力的方式。随着时间的推移,开发者对良好用户体验变化的期望和 Bule Ocean的使命将是Jenkins做出回应。

Jenkins社区已经倾注了大量的汗水和眼泪到构建现有最具技术优势和可扩展性的软件自动化工具。现在如果不采取任何行动,想改变 开发者体验,怕是只能邀请其他人 - 闭源 - 来做了。

 

 

名字由来?

Blue Ocean 这个名字来自书籍 Blue Ocean Strategy 它不是在有争议的空间内查看战略问题,而是在更大的无争议的空间中查看问题。简单来说, 引用冰球传奇人物 Wayne Gretzky的话: “滑到冰球将要到达的位置,而不是冰球的位置”。

Blue Ocean 支持自由风格作业吗?

Blue Ocean 旨在为pipeline 提供绝佳的体验,并与您已在Jenkins实例上配置的任何自由式作业兼容。但是,您将不会受益于为 管道构建的任何功能 - 例如:管道可视化

由于 Blue Ocean的设计是可扩展的,Jenkins社区有可能在未来扩展蓝海以支持其他作业类型

这对于 Jenkins 经典UI来说意味着什么?

随着Blue Ocean的成熟,用户回到经典UI的理由将越来越少。阅读 in Pipeline入门中关于经典UI的更多信息。

例如,Blue Ocean的早期版本主要针对pipeline 作业。您能够在Blue Ocean中看到您现有的非Pipeline作业,但可能在一段时间 内无法在Blue Ocean UI中配置他们。这意味着用户将不得不跳转到经典UI来配置pipeline以外的pipeline/item 作业。.

可能会有更多了例子,这就是经典用户界面被长期保留很重要的原因。

这对插件来说意味着什么?

可扩展性是Jenkins的核心特性,因此,扩展Blue Ocean UI非常重要。 <ExtensionPoint name=..>可以被用作Blue Ocean的标记,为插件流出位置来作用于Blue Ocean UI(即插件可以拥有自己的Blue Ocean 扩展点,就像现在在Jenkins里面一样),到目前为止,Blue Ocean 本身也是基于这些扩展点实现的。

扩展程序通常由插件提供,但是,插件开发者需要引入一些额外的javaScript 以关联Blue Ocean扩展点,为 Blue Ocean用户体验做出贡献。

目前使用了哪些技术?

Blue Ocean 本身是Jenkins插件的集合。有一个关键的差别 - Blue Ocean 为HTTP请求提供了自己的端点, 并通过不同的路径提供了HTML / JavaScript,而没有现有的Jenkins UI标记/脚本。 React.js 和 ES6 用于提供Blue Ocean的JavaScript 组件。受到这个优秀的开源项目的启发 (在博客 Building Plugins for React Apps 中了解更多内容), `` 允许来自任何Jenkins插件的扩展(仅限于JavaScript),并且它们是否能够正确加载是完全独立的。

从哪里可以找到源码

源代码可以在GitHub上找到

加入社区

通过以下方式加入社区:

  1. Gitter联系社区和开发者团队 blueocean plugin

  2. blueocean-plugin component in JIRA请求功能或报告错误。

  3. Jenkins 用户邮件列表订阅并提问。

  4. 开发者? 我们已经 标记了一些 对于Blue Ocean开发者来说很好的 问题 。不要忘记Gitter聊天和自我介绍

Blue Ocean 入门

Table of Contents

本节将介绍如何开始使用BlueOcean。介绍如何 安装和配置Blue Ocean进入Blue Ocean UI返回 Jenkins 经典 UI.

安装 Blue Ocean

Blue Ocean 可以用以下方式安装:

在已有Jenkins实例上安装

在大多数平台安装Jenkins时,默认情况下不安装 Blue Ocean 插件 及其所有其他依赖插件(组成Blue Ocean“插件套件”)。

要在现有的Jenkins实例上安装Blue Ocean插件套件,您的Jenkins实例必须运行Jenkins 2.7.x或更高版本。

任何拥有 Administer 权限(通过 基于Matrix 安全设置)的Jenkins用户都可以在Jenkins实例上安装插件 。 拥有次权限的Jenkins用户还可以配置系统上其他用户的权限。在 管理安全性授权 部分了解更多信息

要将Blue Ocean安装到您的Jenkins实例:

  1. 如果需要,请确保您已经登录到jenkins(作为具有 管理员 权限的用户).

  2. 从Jenkins主页(即Jenkins经典用户界面的仪表板),单机左侧的 管理Jenkins ,然后单击中心的 管理插件

  3. 点击 可用的 选项卡,然后在 过滤 文本框键入 blue ocean ,将过两次插件列表为名称/描述包含“blue”和“ocean”的插件名单。

    Blue Ocean plugins filtered

  4. 选择 安装 列顶部附近的 Blue Ocean 插件复选框,然后单击 立刻下载并在重启后安装 按钮(推荐)或 安装而不重新启动按钮 注意:

    • 无需选择此过滤列表中其他插件的复选框,因为 Blue Ocean 插件具有其他插件的依赖关系(构成Blue Ocean的插件套件),当您点击安装, 其他插件将被自动选择和安装。

    • 如果你选择 安装不重启 按钮, 你可能需要重启Jenkins来获取Blue Ocean的完整功能。

阅读 管理 插件 页面中有关如何安装和管理插件的更多信息 。

Blue Ocean 在安装后不需要额外的配置,现有的pipeline 和其他项目(如自由风格作业)将照常运行。

但是,请注意, 首次使用特定的 Git 服务(即GitHub,Bitbucket或普通Git服务器)在 Blue Ocean中创建pipeline 时,Blue Ocean会提示您输入credentials 以访问Git服务器上的存储库。在Blue Ocean可以将 Jenkinsfile 写入存储库之前

作为Jenkins-Docker镜像的一部分

Blue Ocean套件也与Jenkins捆绑在一起,作为Jenkins Docker镜像 (jenkinsci/blueocean)的一部分,该镜像可以从 Docker Hub 存储库获得。

参阅 安装 Jenkins 页面的 Docker 部分获取更多信息

访问 Blue Ocean

一旦Jenkins环境安装了Blue Ocean,登录到Jenkins经典UI 后,您可以通过点击左侧的 打开Blue Ocean 来访问Blue Ocean页面。

Open Blue Ocean link

或者,您可以在您的Jenkins url后面追加 /blue 直接访问Blue Ocean - 如 http://jenkins-server-url/blue.

如果您的Jenkins实例:

  • 已经存在pipeline或其他项目,则显示 Blue Ocean 仪表板

  • 是新的或者没有配置项目,则Blue Ocean 会显示 Welcome to Jenkins 对话框,其中包含了 Create a new Pipeline 按钮。您可以使用 该按钮开始创建新的pipeline 项目。参阅 创建 Pipeline获取更多信息

    <em>Welcome to Jenkins - Create a New Pipeline message box</em>

导航栏

Blue Ocean 用户界面顶部有一个导航栏,可以让您访问Blue Ocean 的不同视图和其他功能。

导航栏分为两部分 - 占据了Blue Ocean视图顶部大部分的公共部分和下面的上下文相关部分。上下文部分取决于您正在查看的Blue Ocean界面。

导航栏的公共部分包含以下按钮:

  • Jenkins 图标 - 点击返回 Dashboard,如果您正在该页面,则重新加载。

  • Pipelines - 也会将您带到仪表板,如果您已经在查看仪表板,则不会执行任何操作。 当您查看 Pipeline 运行细节 页面时,此按钮有不同的用途。

  • Administration - 点击进入经典UI的 管理Jenkins 页面 注意: 如果您的Jenkins用户没有 Administer 权限 (通过 基于Matrix安全性设置). 参阅 管理 安全性授权 部分获取更多信息

  • Go to classic 图标 - 点击返回经典Jenkins界面。 参阅 切换到经典界面获取更多信息

  • Logout - 注销当前Jenkins用户并返回Jenkins登录界面

使用标准导航栏的视图会在其下方添加另一栏,并带有该视图特定的选项。一些视图将普通的导航栏替换为特别适合该视图的导航栏。

切换到经典界面

Blue Ocean 不支持一些用户需要的Jenkins遗留或管理的功能。

如果您需要放弃Blue Ocean用户体验来访问这些功能,请单击Blue Ocean navigation bar公共部分顶部的 转到经典图标。

Go to classic icon

点击此按钮即可进入Jenkins经典用户界面的等效界面,或者Blue Ocean中与经典界面最相似的界面

创建流水线

Table of Contents

Blue Ocean 能够更容易的在Jenkins中创建一个流水线。

流水线可以由源代码控制中存在的Jenkinsfile 生成, 或者使用 Blue Ocean 流水线编辑器 生成一个新的流水线(作为 Jenkinsfile 会提交到源代码控制中)。

配置流水线项目

要在 Blue Ocean中开始配置你的流水线项目, 在 Blue Ocean Dashboard的右上方, 点击 New Pipeline 按钮。

<em>New Pipeline Button</em>

如果你的Jenkins 实例是新生成的或者没有流水线项目或其他的配置项(仪表盘是空的), Blue Ocean显示 Welcome to Jenkins 消息框 ,你可以点击 Create a new Pipeline 按钮来开始配置你的流水线项目。

<em>Welcome to Jenkins - Create a New Pipeline message box</em>

现在,你要从下面选择一个创建你的流水线项目:

Git仓库

要为git仓库创建你的流水线项目, 点击 Where do you store your code?*下的 *Git 按钮。

<em>Where do you store your code</em>

Connect to a Git repository 部分, 在Repository URL字段输入你的Git仓库的 URL 。

<em>Connect to a Git repository</em>

现在,你要指定 本地远程 仓库,构建你的流水线项目。

本地仓库

如果你的 URL 是本地目录路径 (比如以一个正斜杠 /开头 比如/home/cloned-git-repos/my-git-repo.git),你要继续点击 Create Pipeline 按钮。

之后,Blue Ocean 会扫描你本地仓库的分支来获得 Jenkinsfile,并将为每个包含Jenkinsfile的分支运行流水线。 如果 Blue Ocean 找不到任何 Jenkinsfile, 将提示你开始通过流水线编辑器创建一个。

远程仓库

由于流水线编辑器将经过编辑的流水线作为 Jenkinsfile 保存到 Git 仓库, Blue Ocean 只支持通过SSH协议连接到远程Git仓库。

如果你的 URL 是远程 Git 仓库的路径, 当你开始输入URL时, 你可以从以下两种方式开始:

  • ssh:// - 例如 ssh://gituser@git-server-url/git-server-repos-group/my-git-repo.git

  • user@host:path/to/git/repo.git - 例如 gituser@git-server-url:git-server-repos-group/my-git-repo.git,

Blue Ocean 自动生成一个 SSH 公共/私有密钥对 (或提供已存在的一个) 作为你当前/登录的 Jenkins 用户。该凭证自动地注册,为该Jenkins用户提供以下详细信息:

  • Domain: blueocean-private-key-domain

  • ID: jenkins-generated-ssh-key

  • Name: (jenkins-generated-ssh-key)

你要确保 SSH 公共/私有秘钥对在继续之前已经被注册到你的Git服务器。如果没有, 遵循下面的 2 个步骤。否则, 继续

  1. 配置这个密钥对的 SSH 公钥组件(你可以从 Blue Ocean界面复制粘贴),用于远程 Git 服务器的用户账户(比如在机器的gituser/.ssh目录的 authorized_keys 文件中)。 Note: 该进程允许 Jenkins 用户访问你的Git服务器的用户账户 (比如 gituser)能够访问到的仓库。了解更多请参考Pro Git documentationSetting Up the Server

  2. 完成后, 回到Blue Ocean 界面。

点击Create Pipeline 按钮。

之后,Blue Ocean 会扫描过本地仓库的分支来获得 Jenkinsfile 并开始为每个包含 Jenkinsfile的分支运行流水线。 如果 Blue Ocean 找不到任何 Jenkinsfile, 将会提示你通过 流水线编辑器开始创建一个。

GitHub仓库

要为gitHuB上的存储库直接创建流水线项目, 点击*Where do you store your code?下的 *GitHub 按钮。

<em>Where do you store your code</em>

Connect to GitHub 部分的Your GitHub access token字段, 输入你的 GitHub 访问令牌。+ 如果你之前配置过 Blue Ocean,使用个人的访问令牌连接到 GitHub , Blue Ocean 直接带你到下面的 选择 GitHub 账户/组织和存储库步骤。

<em>Connect to GitHub</em>

如果你没有 GitHub 访问令牌, 点击 Create an access key here 链接打开 New personal access token 页面。

创建访问令牌

  1. 在一个新的选项卡中, 登录 GitHub 账户 (如果需要的话) 并且在 GitHub的 New Personal Access Token 页面,为你的GirHub访问令牌 (e.g. Blue Ocean)输入一个简短的 Token description Note: 访问令牌通常是一个字母数字字符串,它通过你的GitHub 账户对你的GitHub账户访问各种特性和区域的权限进行相应的处理。新的访问令牌过程 (通过上面的 Create an access key here 链接触发) 具有预选的合适权限, Blue Ocean 需要访问你的GitHub账户并与其进行交互。

  2. 向下滚动直到页面的末尾,然后点击 Generate token

  3. 在生成的 Personal access tokens 页面, 复制新生成的访问令牌。

  4. 回到Blue Ocean, 粘贴访问令牌到 Your GitHub access token*字段并点击 *Connect 你当前/登陆的Jenkins用户现在可以访问 GitHub a账户 (由你的访问令牌提供), 所以你现在可以 选择 GitHub 账户/组织和存储库 Jenkins 为Jenkins用户注册了带有以下详细信息的凭证:

    • Domain: blueocean-github-domain

    • ID: github

    • Name: /****** (GitHub Access Token)

选择 GitHub 账户/组织和存储库

此时, Blue Ocean 提示你选择 GitHub 账户或你所在的组织, 以及它包含的用于构建你流水线项目的存储库

  1. Which organization does the repository belong to? 部分, 点击:

    • 你的 GitHub 账户为你自己的 GitHub 仓库中的或GitHub的其他地方创建流水线项目。

    • 你所在的组织为组织内的GitHub仓库创建流水线项目。

  2. Choose a repository 部分, 点击存储库 (在你 GitHub 账户或组织内) ,从而构建你的流水线项目。 Tip:*如果你的仓库的列表很长, 你可以使用 *Search 选项来筛选这个列表。

    <em>Choose a repository</em>

  3. 点击 Create Pipeline Blue Ocean 将会扫描你本地仓库的分支来获得 Jenkinsfile 并为每个包含 Jenkinsfile 的分支运行流水线。 如果Blue Ocean 找不到任何 Jenkinsfile, 会提示你通过 流水线编辑器 (通过再次点击 Create Pipeline)创建一个。 Note: U在引擎下, 通过Blue Ocean创建的流水线项目实际上是 "多分支流水线"。因此, Jenkins在你仓库的任何分支中寻找至少一个Jenkinsfile 。

Bitbucket Cloud的存储库

为了直接在Bitbucket Cloud上为Git 或 Mercurial 存储库创建流水线项目, 点击 Where do you store your code?**Bitbucket Cloud 按钮

<em>Where do you store your code</em>

Connect to Bitbucket 部分的UsernamePassword字段, 分别输入 Bitbucket 邮箱地址和密码。注意:

  • 如果你之前配置过 Blue Ocean,使用你的email地址和密码连接到Bitbucket , Blue Ocean就会直接将你带到下面的 选择Bitbucket 账户/团队和存储库步骤。

  • 如果你输入这些凭证, Jenkins就会为Jenkins用户使用下面的信息进行注册:

    • Domain: blueocean-bitbucket-cloud-domain

    • ID: bitbucket-cloud

    • Name: /****** (Bitbucket server credentials)

<em>Connect to Bitbucket</em>

点击 Connect,你当前/登陆的Jenkins用户将会访问 你的Bitbucket 账户。现在,你可以 选择Bitbucket 账户/团队和存储库

选择 Bitbucket 账户/团队和仓库

在这里, Blue Ocean提示你选择 Bitbucket 账户或你所在的团队, 以及它包含的构建你的流水线项目的仓库。

  1. Which team does the repository belong to? 部分, 点击:

    • Bitbucket 账户为你的或从Bitbucket的其他地方fork的 Bitbucket 仓库创建流水线项目。

    • 你所在的团队为该团队内的仓库创建流水线项目。

  2. Choose a repository 部分, 点击存储库 (在你的 Bitbucket 账户或团队中) 来构建你的流水线项目。 Tip: 如过你的仓库列表太长,你可以使用 Search 选项过滤该列表。

    <em>Choose a repository</em>

  3. 点击 Create Pipeline Blue Ocean就会扫描你本地仓库的分支来获取 Jenkinsfile, 并为每一个含有 Jenkinsfile 的分支开始运行流水线。 如果Blue Ocean找不到任何 Jenkinsfile, 会提示你 通过 流水线编辑器 (通过再次点击 Create Pipeline )创建一个。+ Note: 在引擎下, 通过 Blue Ocean创建的流水线项目实际上是 "多分支流水线"。因此, Jenkins 在存储库的任何分支中寻找至少一个Jenkinsfile。

仪表盘

Table of Contents

Blue Ocean的 "Dashboard" 是当你打开 Blue Ocean时的 默认视图,他显示了在Jenkins实例上配置的所有的流水线项目的示例。

该仪表盘由顶部的蓝色 导航条 , [流水线列表, 和 link:#favorites-list收藏列表组成。

Overview of the Dashboard

导航条

仪表盘包括了界面顶部的 导航条

该导航条被分为两部分 - 顶部的公共部分和下面的上下文部分。 上下文部分根据你当前正在查看的Blue Ocean页面而改变。

在查看仪表盘时, 导航条的上下文部分包括:

  • Search pipelines 字段, 筛选 流水线列表 以显示包含你输入到该字段的文本的项。

  • New Pipeline 按钮, 开始 创建流水线 进程。

流水线列表

"流水线" 列表是仪表盘的默认列表,在一次访问 Blue Ocean时, 它是显示在仪表盘上的唯一列表。

该列表显示了配置在Jenkins实例上的每个人流水线的总体状态(也可以包含其他的流水线项目)。对于本列表的某一项, 下列信息表示:

  • 项目的 NAME,

  • 项目的 HEALTH,

  • 通过或失败的流水线的源代码控制仓库的 BRANCH*数和pull请求 (*PR) 数,

  • 一个星号表明该项目的默认/主分支石佛营以手动的添加到当前Jenkins 用户的收藏列表

点击一个项目的星将在下面的内容中切换:

  • 添加项目的存储库的默认分支到你当前用户的收藏列表中 (使用一个实心的 "★"表示),

  • 从该列表中移除默认分支 (使用空心的 "☆"表示)。

在流水线列表中点击一个项会显示项目的 活动视图

收藏列表

当至少一个流水线/项目出现在用户的最喜欢列表中时,Favorites 列表出现在仪表盘的默认 [pipelines-list]的上方。

该列表为[pipelines-list]中的可访问项的核心子集提供了关键信息和操作。 该关键信息包括 项目及其仓库分支的当前 运行状态,以及项目运行的其他细节,包括分支名称, 提交哈希的初始部分和最后一次运行的时间。 在这个列表中的项目还包括可点击的图标,在仓库分支上运行或重新运行该项目。

如果你要定期检查该项目的分支,你应该只在你的收藏列表中添加一个项目(或仓库的特定分支)。 添加项目的指定分支到收藏列表可以通过项目的 活动视图来完成。

当包含由当前用户编辑更改的运行时,Blue Ocean 自动添加分支和PR到该列表。

你也可以通过点击该列表中的实心的 "★"手动的从收藏列表中移除项。当这个列表在的最后一项被移除时, 该列表将从界面中移除。

在收藏列表中点击一个项可以打开在存储库分支或PR所示的最新运行的 流水线运行细节

健康图标

Blue Ocean 使用天气图标代表一个流水线/项目或它的一个存储库的分支的整体健康状况, 这取决于最近通过的构建的数量。

仪表盘上的健康图标代表这个流水线的健康, 而 活动视图中的分支选项中的健康图标代表每个分支的健康。

IconHealth
Sunny Sunny, more than 80% of Runs passing
Partially Sunny Partially Sunny, 61% to 80% of Runs passing
Cloudy Cloudy, 41% to 60% of Runs passing
Raining Raining, 21% to 40% of Runs passing
Storm Storm, less than 21% of Runs passing

运行状态

Blue Ocean使用始终如一的图标集代表流水线/项目或它的一个仓库的分支的运行状态。

IconStatus
In Progress In Progress
Passed Passed
Unstable Unstable
Failed Failed
Aborted Aborted

活动视图

Table of Contents

Blue Ocean 额的活动视图显示了与流水线相关的所有活动。

Overview of the Activity View

导航条

活动视图包括顶部的标准导航条,下面是一个本地导航栏 本地导航条包括:

活动

活动视图的默认选项卡, "活动" 选项卡, 显示最新完成或正在运行的运行的列表。 列表中的每一行都显示了运行的 状态, id 号,提交信息, 持续时间, 和运行完成时的状态。 点击Run将会启动该运行的 流水线运行详情。 "In Progress" 运行可以通过点击这个列表中的 "Stop" 符号 (一个圆里面的正方形 "◼" )来中止。 已经完成的运行可以通过点击 "Re-run" 符号(一个逆时针方向的 "↺")来重新运行。 该列表可通过点击列表头部的 "branch"下拉列表中的分支或 pull 请求来筛选。

该列表不允许被编辑或标记为喜欢的运行。 这些操作可以从"branches" 选项卡中完成。

分支

"Branches" 选项卡显示了在当前流水线已完成或正在运行的所有分支的列表。 列表的每一行都代表了源代码控制中的一个分支, [1] 根据最近的运行, 最近运行的状态, id号, 提交信息, 持续时间, 和运行完成时的状态显示 分支的总体健康状态

Branches Tab of Activity View

点击该列表的一个分支, 为最近完成或在进行中的该分支中的运行提供 流水线运行细节。 "In Progress" runs 可以通过点击 "Stop" 符号 (在一个圆中的 "◼" )从列表中中止。 Pull 请求的最近一次的完成可以通过点击"Play" 符号(一个圆中的 "▶" ) 进行再次运行。 单击"Edit" 符号 (类似于铅笔 "✎")为该分支上的流水线打开 流水线编辑器。 点击 "Favorite" 符号 (一个星的轮廓 "☆")添加分支到收藏列表,为该用户显示在 仪表盘的 "Favorites" 列表z中 。 一个已被收藏的分支会显示一个实心的 "★" 点击它就可以从收藏中移除该分支。

Pull请求

"Pull Requests"选项卡显示了当前已完成或正在运行的流水线的所有pull请求的列表 。 (一些源代码控制系统称之为从 "Merge Requests",而另一些根本不支持这些)。 列表的每一行代表源控制代码的一个pull请求, 显示最新运行的状态, id 号, 提交信息, 持续时间, 以及运行完成时的状态。

Activity Pull Requests view

Blue Ocean显示从分支中分离的 pull请求, 但是其他情况下的 Pull 请求列表的行为和分支列表相似。 单击该列表中的 pull 请求,为pull请求已完成或正在运行的运行提供了 流水线运行详情。 "In Progress" 运行可以通过点击 "Stop" 符号(一个圆中的 "◼")从列表中中止。

最新完成的Pull请求可以通过点击 "Play" 符号 (一个圆中的三角形 "▶")来再次运行。 Pull 请求不显示 "健康图标",不能被编辑或标记为喜欢。

 默认情况下, 当Pull Request 被关闭, Jenkins 将会从Jenkins 中移除流水线(稍后将被清理), 并且不再访问Jenkins来运行该pull请求。 这可以通过更改底层多分支流水线作业的配置来改变。
   

1. en.wikipedia.org/wiki/Source_control_management

流水线运行细节视图

Table of Contents

Blue Ocean 流水线运行细节视图显示了与单个流水线运行相关的信息并允许以后编辑或回放运行。 下面是运行细节视图部分的详细概述。

Overview of the Pipeline Run Details

  1. Run Status - 此图标, 以及顶部菜单栏的背景色,表明了流水线运行的状态。

  2. Pipeline Name - 运行的流水线的名称。

  3. Run Number - 流水线运行的ID号。 对于流水线的每个分支(和 Pull 请求),ID号是唯一的。

  4. Tab Selector - 查看该运行的一个细节 选项卡。 默认值是"Pipeline"。

  5. Re-run Pipeline - 再次执行运行的流水线。

  6. Edit Pipeline - 在 Pipeline Editor中打开运行的流水线。

  7. Go to Classic - 转换到该运行细节的 "经典" UI 视图。

  8. Close Details - 这将关闭细节视图并使用户回到该流水线的 活动视图

  9. Branch or Pull Request - 该运行的分支或pull请求。

  10. Commit Id - 提交本次运行的ID。

  11. Duration - 本次运行的持续时间。

  12. Completed Time - 多久之前运行完成。

  13. Change Author - 更改的作者姓名。

  14. Tab View - 显示所选选项卡的信息。

流水线运行状态

Blue Ocean 可以很容易的查看当前流水线运行的状态,通过顶部菜单栏颜色的改变来匹配状态: 蓝色表示 "In progress", 绿色表示 "Passed", 黄色表示 "Unstable", 红色表示 "Failed", 灰色表示 "Aborted"。

特例

Blue Ocean 在源代码控制中使用流水线进行优化,但它也可以显示其他类型项目的细节。 Blue Ocean 为所有支持的项目类型提供了同样的选项卡 , 但这些选项卡可能显示不同的信息。

源代码控制之外的流水线

对于不基于源代码控制的流水线, Blue Ocean 仍然会显示 "提交 Id", "分支", 和 "更改", 但是这些字段都是空白的。 在这种情况下, 顶部菜单栏不包含 "Edit" 选项。

自由式项目

对于自由式项目, Blue Ocean 仍然提供相同的选项卡, 但是流水线选项卡只显示控制台日志输出。 "Rerun"或 "Edit"选项也没有显示在顶部菜单栏中。

矩阵项目

在Blue Ocean中不支持矩阵项目。 查看矩阵项目将重定向到该项目的 "经典UI" 视。

选项卡

运行细节视图的每个选项卡都提供了运行的特定方面的信息。

流水线

这是默认选项卡并给出了该流水线运行的留的总体视图 他显示每个阶段河道并行分支, 这些阶段中的步骤, 以及这些步骤的控制台输出。上面的概述图像显示了一个成功的流水线运行。 如果运行中的某个步骤失败, 该选项将自动默认显示来自失败步骤的控制台日志。 下图显示了一个失败的运行。

Failed Run

变化

List of Changes for a Run

测试

"Tests" 选项卡显示有关此次运行的测试结果的信息。 该选项卡只包含测试结果发布步骤的信息, 如 "Publish JUnit test results" (junit) 步骤。 如果没有结果被记录 这个表会说, 如果所有的测试通过, 该选项会报告通过测试的总数。 在失败的情况下。选项卡将会显示从失败中获取的如下日志细节。

Test Results for Unstable Run

当先前的运行失败,而当前运行修复这些失败时, 该选项卡会注意到固定的文本并显示它们的日志。

Test Results for Fixed Run

工件

"Artifacts" 选项卡显示使用"Archive Artifacts" (archive)步骤保存的任何工件的列表。 单击列表中的项并下载它。 运行中的完整输出日志可以从这个列表中下载。

List of Artifacts from a Run

流水线编辑器

Table of Contents

流水线编辑器是任何人在Jenkins中开始构建流水线的最简单的方式。这也是现有的Jenkins用户 开始采用流水线的很好的方式。

该编辑器允许用户创建和编辑声明式流水线, 添加可同时运行的阶段和并行任务, 这取决于它们的需要。完成后, 编辑器将流水线作为Jenkinsfile保存到源代码控制仓库中。如果流水线需要再次更改, Blue Ocean 可以轻松的返回到视图编辑器来随时修改流水线。

Pipeline Editor

启动编辑器

要使用编辑器,用户首先要 在Blue Ocean中创建流水线 或者在Jenkins中已创建一个或多个现有的流水线。 如果编辑现有的流水线, 该流水线的凭证必须允许push更改到目标仓库。

编辑器可通过以下方式启动:

  • 仪表板的 "New Pipeline" 按钮

  • 单个运行的活动视图

  • 流水线运行细节

限制

  • 只能是基于SCM的声明式流水线

  • 凭证必须有写权限

  • 没有与声明式流水线完全对等

  • 流水线重新排序,删除评论

导航栏

流水线编辑器包括顶部的标准导航栏, 下面是一个本地导航栏。 本地导航栏包括:

  • Pipeline Name -这将包括分支依赖或者方式

  • Cancel - 放弃对流水线所做的更改

  • Save - 打开 保存流水线对话框

流水线设置

默认情况下, 编辑器右侧显示 "Pipeline Settings"。 该表单可以通过点击 Stage editor的任何地方来访问, 这不是一个阶段,也不是"Add Stage" 按钮。

代理

"Agent" 吧部分控制流水线将要使用的代理。 这与 "agent" 指令相同。

环境

"Environment" 允许我们为流水线设置一个环境变量, 这与"environment" 指令相。

阶段编辑器

左侧的编辑器屏幕包括阶段编辑器, 用于创建流水线的各个阶段。

Stage editor simple

可以通过点击现有阶段右侧的 "+" 按钮,将阶段添加到流水线中。 Parallel stages can be added 通过点击现有阶段下面的 "+" 按钮,将并行阶段添加到流水线中。 可以使用 阶段配置表中的上下文菜单删除阶段。

一旦设置完毕,该阶段编辑器就会显示每个阶段的名称。 包含不完整或无效信息的阶段将显示一个警告符号。 流水线可以在编辑时显示验证错,但是直到错误被修复前不能保存。

Stage editor with error

阶段配置

在阶段配置器中选择一个阶段, 将打开右侧的 "Stage Configuration" 表。 在这里,我们可以改变阶段的名称, 删除该阶段,并添加步骤到阶段。

Stage Configuration

阶段的名称可以在阶段配置表的顶部配置。 上下文菜单(右上角的三个点)可以用来删除当前阶段。 点击 "Add step"将会显示可用步骤类型的列表 ,顶部有一个搜索栏。 步骤可以使用上下文的 在步骤配置表中的上下文菜单删除。 添加步骤或选择一个现有的步骤将打开 步骤配置表中

Step list filtered by <em>file</em>

步骤配置

从阶段配置表中选择一个步骤将打开步骤配置表。

Step configuration for JUnit step

这张表将根据步骤类型而有所不同, 它包含了所需的任何字段或控件。 步骤的名称不能被更改。 上下文菜单 (右上角的三个点), 可以用来删除当前步骤。 包含不完整或无效信息的字段将会显示一个警告符号。 流水线可以在编辑时显示验证错,但是直到错误被修复前不能保存。

Step configuration with error

保存流水线对话框

为了运行, 必须在源代码控制中保存对流水线的更改。 "Save Pipeline" 对话框控制源代码控制的更改保存。

Save Pipeline Dialog

可以添加或保留对更改的有用描述。该对话框也支持保存相同的分支或进入一个新的分支来保存。 点击 "Save & run" 将会把流水线的任何更改保存为新的提交, 将启动一个基于这些更改的新的流水线运行, 并且导航到该流水线的 活动视图

 

管理Jenkins

子章节

本章将介绍如何管理和配置Jenkins 管理器和节点。

本章是为 Jenkins 管理员提供的。经验丰富的用户可能会发现这些信息是有用的, 但是只有在某种程度上,他们理解到的东西是不可能达到管理员所能够做到的。 各个部分可能会假设你对前面的信息有所了解, 但是这些假设将会被显式的调用和相互引用。

如果你是一个系统管理员,想要学习如何备份, 恢复, 维护Jenkins服务器和节点maintain as Jenkins servers and nodes, 请参考 Jenkins System Administration

有关Jenkins用户手册内容的概述, 请参考 用户户手册概述. 但是只有经验到达一定程度上,他们才会理解本章讲的是什么并且不可能让管理员去做

配置系统

 这仍然是一项正在进行的工作
   

管理安全

Table of Contents

从公司内部网的工作站, 到连接到公共互联网的高性能服务器,Jenkins无处不在。 为了安全支持这一广泛的安全和威胁配置文件的传播, Jenkins提供了许多配置选项 来启用, 编辑, 或禁用各种安全特性。

在Jenkins 2.0中,许多安全选项默认是启用的,以确保Jenkins环境保持安全,除非管理员明确禁用某些保护。

本节将介绍管理员可用的各种安全选项 , 解释所提供的保护, 并权衡禁用其中的一些选项。

启用安全

当启用了 Enable Security c复选框时, 这是Jenkins 2.0以来的默认值, 用户可以使用用户名和密码登录, 以执行匿名用户无法执行的操作。 哪些操作需要用户登录 取决于所选择的授权策略和它的配置; 默认情况下匿名用户没有权限, 已登录用户完全控制。 对于任何非本地(测试)Jenkins环境,该复选框应该 always 启用。

web UI的启用安全部分允许Jenkins 管理员启用, 配置,或禁用应用于整个Jenkins环境的关键安全特性。

Configure Global Security - Enable Security

JNLP TCP 端口

Jenkins 使用TCP 端口通过JNLP协议与启用的代理通信,比如基于 Windows的代理。 在 Jenkins 2.0中,默认这个端口是禁用的。

对于希望使用基于JNLP的代理的管理员, 两个端口选项是:

  1. Random: JNLP 端口是随机选择的,来避免在 Jenkins 主机上繁盛冲突。 随机 JNLP端口的缺点是他们是在Jenkins主机的引导下选择的, 这使得管理允许JNLP通信的防火墙规则变得困难。

  2. Fixed: JNLP端口由Jenkins管理员选择的,并且在Jenkins主机的重新引导下是一致的。这使得管理基于JNLP代理连接到主服务器的防火墙规则变得容易。

访问控制

访问控制是保护Jenkins环境免受未经授权使用的主要机制。配置的两个方面对于在Jenkins中配置访问控制 是必要的:

  1. Security Realm 告诉Jenkins环境如何以及从何处获取用户(或身份)信息。 也别称为 "认证"。

  2. Authorization 配置,他告诉 Jenkins 环境, 哪些用户和/或组可以访问Jenkins的哪些方面, 以及何种程度。

使用安全与和授权配置,可以在Jenkins中配置非常轻松地或非常严格的身份认证和授权方案。

此外, 一些插件比如 基于角色的授权策略 插件可以扩展Jenkins的访问控制功能,以支持更加微妙的身份认证和授权方案。

安全域

默认情况下, Jenkins包含了对几个不同安全域的支持:

  • Delegate to servlet container

    对于委托认证运行Jenkins主机的servlet容器, 比如 Jetty。如果使用该选项, 请参考servlet 容器的 身份验证文档。

  • Jenkins’ own user database

    使用Jenkins自己内置的用户数据存储来进行身份验证,而不是委托给外部系统。 这是Jenkins 2.0或后来安装的Jenkins默认启用的,适用于小环境。

  • LDAP

    间所有的身份认证委托给配置的LDAP 服务器, 包括用户和组。对于已经配置了外部身份提供者比如LDAP的组织的大型安装,该选项更为常见。 这也支持活动目录安装。

 LDAP plugin提供的该特性 可能不会安装到你的实例中。
   
  • Unix user/group database

    将身份验证委托给Jenkins主机上的底层Unix OS-级别的用户数据库。 该模式允许 重用Unix组进行授权。 比如, Jenkins 能够配置为 "在 developers组中的所有人都有管理员访问权限" 来支持该特性, Jenkins 依赖于可能需要在Jenkins环境外配置的 PAM

 Unix 允许用户和组拥有相同的名称。为了消除歧义, 使用@ 前缀强制将名称结束为一个组。比如, @dev意味着 dev 组而不是 dev 用户。
   

插件能够提供额外的安全域,这可能有助于 将Jenkins合并到现有的身份系统中, 比如:

授权

安全域或身份认证, 指示 who 可以访问 Jenkins 环境。另一个难题是 Authorization, 它指示 在what 地方他们可以访问Jenkins环境。默认情况下, Jenkins 支持几种不同的授权选项:

  • Anyone can do anything

    每个人都能完全控制Jenkins, 包括没有登陆的匿名用户。 Do not use this setting ,除了在本地测试Jenkins主机。

  • Legacy mode

    与Jenkins <1.164的行为完全相同。也就是说, 如果一个用户拥有 "admin" 角色, 就会被授予对系统的完全控制, 负责 (包括匿名用户) 只会拥有读访问权限。 除了在本地测试Jenkins主机,Do not use this setting

  • Logged in users can do anything

    在该模式下, 每个登陆的用户对Jenkins完全控制。根据一个高级选项, 匿名用户获取Jenkins的访问权限, 或者根本无法访问。该模式有助于强制用户在操作前进行登录, 以便于对用户的行为进行审计跟踪。

  • Matrix-based security

    该授权方案对允许用户和组在Jenkins环境下能够进行哪些操作进行细粒度控制(见下面的屏幕截图)。

  • Project-based Matrix Authorization Strategy

    此授权方案是基于矩阵的安全性的扩展, 它允许为在项目配置屏幕中的 each project分别定义额外的访问控制列表 (ACL)。它允许特定的用户和组访问特定的项目, 而不是Jenkins 环境中的所有项目。 基于项目的矩阵授权定义的ACL是附加的,在配置全局安全屏幕中定义的访问授权将与 指定项目的ACL相结合。

 基于矩阵的安全性和基于项目的矩阵授权策略由 Matrix Authorization Strategy Plugin插件提供,它可能不会安装在你的Jenkins中。
   

对于大多数的Jenkins环境, 基于矩阵的安全性提供了最大的安全和灵活性,因此建议将它作为 "生产"环境的起点。

Configure Global Security - Enable Security - Matrix authorization

Figure 1. Matrix-based security

上面显示的表格可以非常宽,因为每一列表示由Jenkins核心或插件提供的权限。将鼠标悬停在权限上将显示更多关于该权限的信息。

表中的每一行都代表了一个用户或组(也成为 "角色")。其中包括名为"匿名" 和 "身份验证" 的特殊条目。 "匿名" 条目表示授予访问Jenkins环境的所有未经身份验证的用户的权限。而 "身份验证' 可用于 授予访问Jenkins环境的所有已经通过身份验证的用户的权限。

在矩阵中授予的权限是附加的。比如,如果一个用户 "kohsuke" 是在 "开发者" 组和 "管理员"组, 那么授予"kohsuke" 的权限将会是授予 "kohsuke", "开发者", "管理员", "身份验证", 和 "匿名"的所有这些权限的联合。

标记格式化程序

Jenkins允许用户输入大量不同的配置字段和文本域,这些字段和文本域会导致用户, 无心或恶意的, 输入不安全的HTML 和/或 JavaScript。

默认情况下,Markup Formatter 配置将被设置为 Plain Text ,以避免诸如 <& 对其各自的字段实体的不安全字符。

使用 Safe HTML 标记格式化程序允许用户和管理员向项目描述和其他地方注入有用的和信息的HTML 片段。

跨站请求伪造

跨站请求伪造(或 CSRF/XSRF) [1] 是一个漏洞,允许未经身份验证的第三方通过模拟另一个身份验证的用户对web应用程序执行请求。 在Jenkins环境中,CSRF 攻击允许恶意的参与者删除项目, 修改构建, 或修改Jenkins的系统配置。为了防范这些漏洞, 从2.0开始,CSRF 保护已经默认启用了所有的Jenkins版本。

Configure Global Security - Prevent Cross Site Request Forgery exploits

当启用该选项时, Jenkins 会检查 在Jenkins环境中可能更改数据的任何请求的CSRF 令牌, 或 "crumb"。它包含对远程API的任何表单提交和调用,包含使用 "Basic"身份验证的表单。

strongly recommended 启用 enabled该选项, 包括在私有的, 完全可信的网络上运行的实例。

说明

CSRF 保护 may 会导致更高级别的Jenkins用法的挑战, 比如:

  • 一些Jenkins特性, 像远程 API, 当启用该选项时更加难以使用。参考 Remote API文档了解更多信息。

  • 通过配置差的反向代理访问Jenkins可能会导致从请求中删掉CSRF HTTP 头, 从而导致保护操作失败。

  • 过时的插件, 没有经过 CSRF 保护的测试,可能无法正常工作。

关于CSRF 攻击的信息可以在 on the OWASP website中找到。

代理/主机访问控制

概念上讲, Jenkins主服务和代理可以被看作一个聚合系统,它在多个离散的进程和机器上执行。 这允许代理请求主进程获取信息,例如,文件的内容等。

对于更大的或成熟的Jenkins 环境,Jenkins管理员可能会启用其他团队或组织提供的代理, 但是,一个统一的代理/主信任模型是不够的。

代理/主机访问系统被引入 [2],允许Jenkins管理员在Jenkins主机和连接代理之间添加更细粒度的访问控制定义 。

Configure Global Security - Enable Agent ⇒ Master Access Control

在Jenkins 2.0中,默认这个子系统是打开的。

自定义访问

对于高级用户,他们可能希望允许从代理到Jenkins主机的某些访问模式, Jenkins 允许管理员从内置的访问控制规则中创建特定的豁免。

Configure Global Security - Enable Agent ⇒ Master Access Control - Editing Rules

通过遵循上面高亮的链接, 管理员可以编辑 CommandsFile Access代理/主机访问控制规则。

命令

Jenkins中的"命令" 和它的插件是由他们的完全限定类名来标识的。这些请求的大多数都是通过一个主请求来执行的, 但是其中一些是通过一个代理的请求来执行。

这个子系统尚未更新的插件可能不会对每个命令所属的类别进行分类, 当主机执行未明确允许的命令的代理请求时, Jenkins会出错,并拒绝执行命令。

在这种情况下, Jenkins管理员可以 "白名单" [3]某些命令,以便在主服务器上执行。

Configure Global Security - Enable Agent ⇒ Master Access Control - Editing Rules - Command Whitelisting

高级

管理员也可以通过在JENKINS_HOME/secrets/whitelisted-callables.d/目录下创建带有.conf扩展名的文件来白名单类。 这些 .conf 文件的内容应该在单独的行上列出命令名。

目录中的所有 .conf 文件的内容将由Jenkins读取并合并,在目录中创建一个 列出所有已知的安全命令的default.conf 文件。 default.conf 在每一次的Jenkins中都将被重写。

Jenkins也管理名为 gui.conf的文件, 在 whitelisted-callables.d 目录, 通过web UI添加的命令被写入。 为了禁用管理员从web UI中改变白名单命令的能力, 在目录中放一个 gui.conf 文件,并改变它的权限,这样操作系统用户就不能写入Jenkins了。

文件访问规则

文件访问规则可用于验证从代理到主服务器的文件访问请求。每个文件访问规则都是一个三元组,其中必须包含以下元素:

  1. allow / deny: 如果以下两个参数与当前正在考虑的请求匹配, allow 条目将允许执行请求,而 deny 条目将拒绝被拒绝的请求, 无论后面的规则会说什么。

  2. operation: 请求的操作类型。 存在以下 6个值。 该操作也可以通过逗号分隔符组合这些值。 all 的值表示,所有列出的操作是允许或拒绝的。

    • read: 读取文件内容或列出目录条目

    • write: 写文件内容

    • mkdirs: 创建一个新的目录

    • create: 在现有目录中创建一个文件

    • delete: 删除一个文件或目录

    • stat: 读取一个文件/目录的元数据, 比如时间戳, 长度, 文件访问模式。

  3. file path: 指定与此规则匹配的文件路径的正则表达式。除了基本的正则表达式语法, 它还支持以下标记:

    • ` 可以作为前缀来匹配主机的JENKINS_HOME` 目录。

    • ` 可以作为前缀来匹配构建记录目录, 比如/var/lib/jenkins/job/foo/builds/2014-10-17_12-34-56`。

    • ` 与timestamp格式的构建ID匹配, 如2014-10-17_12-34-56`。

规则是有序的, 并按顺序执行。以最早匹配为准。 比如, 以下的规则允许访问JENKINS_HOME中除了 secrets 文件夹以外的所有文件 :

# To avoid hassle of escaping every '\' on Windows, you can use / even on Windows.
deny all <JENKINS_HOME>/secrets/.*
allow all <JENKINS_HOME>/.*

次序是非常重要的! 下面的规则写错了,因为第二个规则永远不会匹配, 并且允许所有的代理访问JENKINS_HOME下的所有文件和文件夹:

allow all <JENKINS_HOME>/.*
deny all <JENKINS_HOME>/secrets/.*
高级

管理员还可以通过在JENKINS_HOME/secrets/filepath-filters.d/目录中创建带有.conf.扩展名的文件来添加文件访问规则。 Jenkins自身在该目录下生成 30-default.conf 文件, 它包含了Jenkins项目认为的在兼容性和安全性之间的最佳平衡的默认值。 要禁用该内置的默认, 请用一个空的文件置换 30-default.conf ,这样操作系统用户就无法写入。

在每个引导中, Jenkins 会读取filepath-filters.d目录中按字母顺序排列的所有的 .conf 文件, 以指示其负载顺序的方式命名文件是很好的做法。

Jenkins 还管理 50-gui.conf, 在 filepath-filters/ 目录中, 通过web UI添加的文件访问规则被写入。 为了禁用管理员从web UI中改变文件访问规则的能力, 在目录中放一个 50-gui.conf 文件,并改变它的权限,这样操作系统用户就不能写入Jenkins了。

禁用

虽然不推荐, 但如果Jenkins环境中的所有代理都被认为是和主机一样程度的"信任的" , 代理/主机访问控制特性有可能被禁用。 此外, Jenkins环境中的所有用户都应该拥有和所有已配置项目一样的访问级别。

管理员可以在web UI中通过在Configure Global Security 页面上取消选中该复选框,来禁用代理/主机访问控制。或者,管理员可以在JENKINS_HOME/secrets中创建一个名为 slave-to-master-security-kill-switch 内容为 true的文件并重启Jenkins。

 随着环境的发展,大多数Jenkins环境会随着时间的推移而增长,要求他们的信任模型不断演化。请考虑定期进行 "检查" ,来检查是否禁用的安全设置应该被重新启用。
   

1. www.owasp.org/index.php/Cross-Site_Request_Forgery

2. Starting with 1.587, and 1.580.1, releases

3. en.wikipedia.org/wiki/Whitelist

 

管理工具

Table of Contents

 这仍然是一项正在进行的工作
   

Built-in tool providers

Ant

Ant build step

Git

JDK

Maven

 

管理插件

Table of Contents

插件是为了适应组织或用户的需求,增强Jenkins环境的功能的主要手段。有 上千的插件可以安装在Jenkins主机上,来集成不同的构建工具, 云提供程序, 分析工具等。

插件以及它们的依赖能够自动地从更新中心下载。更新中心 是一个由Jenkins项目运营的服务,它提供了一个开源插件的清单,这些插件是由Jenkins社区的成员共同开发和维护的。

这一节将涵盖从管理Jenkins web UI中的插件的基础到修改master’s文件系统的所有内容。

安装插件

Jenkins 提供了几个不同的的方法在主机上安装插件:

  1. 在web UI使用 "插件管理器"。

  2. 使用Jenkins CLI install-plugin 命令。

每个方法都会导致由Jenkins加载插件,但是需要不同的级别的访问和权衡才能使用。

这两种方法要求 Jenkins 主机能够从更新中心下载元数据, 无论是由Jenkins项目运营的主更新中心 [1], 或是自定义更新中心。

插件被打包成独立的 .hpi 文件, 它含有所有必需的代码, 图像, 和其他插件成功运行所需要的资源。

从web UI

安装插件最简单,最普遍的方式是 通过 Manage Jenkins > Manage Plugins 视图, 该视图可用于Jenkins环境的管理员。 在 Available 选项卡下, 插件可以从已配置的更新中心检索和考虑:

Available tab in the Plugin Manager

大多数插件都能安装并立即使用,通过勾选插件旁边的框并点击 Install without restart

 如果可用插件的列表是空的, 那么主机可能配置不正确或者没有从更新中心下载插件元数据。 点击 Check now 按钮将会强制 Jenkins尝试连接其配置的更新中心。
   

使用Jenkins CLI

管理员也可以使用 Jenkins CLI ,它提供了一个安装插件的命令。 管理Jenkins环境或配置管理代码的脚本,可能需要安装插件,而不是在web UI中直接用户交互。 Jenkins CLI 允许命令行用户或自动化工具下载插件和它的依赖。

java -jar jenkins-cli.jar -s http://localhost:8080/ install-plugin SOURCE ... [-deploy] [-name VAL] [-restart]

Installs a plugin either from a file, an URL, or from update center.

 SOURCE    : If this points to a local file, that file will be installed. If
             this is an URL, Jenkins downloads the URL and installs that as a
             plugin.Otherwise the name is assumed to be the short name of the
             plugin in the existing update center (like "findbugs"),and the
             plugin will be installed from the update center.
 -deploy   : Deploy plugins right away without postponing them until the reboot.
 -name VAL : If specified, the plugin will be installed as this short name
             (whereas normally the name is inferred from the source name
             automatically).
 -restart  : Restart Jenkins upon successful installation.

高级安装

更新中心只允许安装最新发布的插件版本。在需要旧版本插件的情况下, Jenkins管理员可以下载一个旧的 .hpi 存档,并手动安装到Jenkins主机上。 install that on the Jenkins master.

从web UI

假设已经下载了 .hpi 文件, 已登录的 Jenkins 管理员可能 从 web UI中上传文件:

  1. 在web UI中导航到 Manage Jenkins > Manage Plugins 页面。

  2. 点击 Advanced 选项卡。

  3. 选择Upload Plugin 部分下面的.hpi文件。

  4. Upload 插件文件。

Advanced tab in the Plugin Manager

一旦插件文件被上传,Jenkins主机必须手动重启,以便更改生效。 ==== 在 master

假设系统管理员已经明确下载了 .hpi 文件, 管理员可以手动将 .hpi f文件放置在 文件系统的特定位置。

复制下载的 .hpi 文件到Jenkins主机的 JENKINS_HOME/plugins 目录(例如, 在 Debian系统 JENKINS_HOME 通常是 /var/lib/jenkins)。

在插件加载前重启服务器,确保它在Jenkins环境中可用。

 更新站点中插件目录的名称 [1] 并不总是和插件显示的名称相同。 搜索 plugins.jenkins.io 为需要的插件提供合适到.hpi文件的链接。
   

更新插件

Manage Plugins页面的Updates 选项卡中列出的更新,可以通过选中想要更新的插件的复选框并点击Download now and install after restart按钮来安装。

Updates tab in the Plugin Manager

默认情况下, Jenkins主服务器会每隔24小时检查一次从更新中心检查更新。要手动触发更新检查, 只需点击Updates选项卡上的 Check now 按钮。

删除插件

当一个插件不再在Jenkins环境中使用时, 从Jenkins服务器中删除插件是很谨慎的。这提供了很多好处,比如减少引导或运行时的内存开销, 减少web UI中的配置选项, 并消除未来与新插件更新的冲突。

卸载插件

卸载插件最简单的方式是导航到Manage Plugins 页面的 Installed 选项卡。从那里, Jenkins 会自动决定哪些插件是安全的卸载, 哪些不是其他插件的依赖,并提供一个这样做的按钮。

Installed tab in the Plugin Manager

也可以通过移除主机上 JENKINS_HOME/plugins 目录的对应的 .hpi文件来卸载插件。该插件会一直工作直到主机被重启。

 如果插件的 .hpi 文件被移除,但其他插件需要该插件,Jenkins 主机可能无法正确引导。
   

卸载插件 not 删除插件创建的配置。如果有现有的工作/节点/视图/构建/等由插件创建的配置n, 在启动时,Jenkins会警告 有些配置不能被完全加载,忽略不识别的数据。

由于配置将被保留直到它们被覆盖, 重装插件将会导致这些配置值重新出现。

删除旧数据

Jenkins提供了一个工具,它能够清除未安装插件的配置。 导航到 Manage Jenkins ,然后点击 Manage Old Data 来检查并清除旧数据。

禁用插件

禁用插件是让插件不再工作的一种更温和的方式。 Jenkins将继续确认插件已安装, b但是它不会启动该插件, 也不会看到插件的扩展。

Jenkins管理员可以通过在Manage Plugins页面的Installed 选项卡上取消复选框来禁用插件 (见下面)。

Installed tab in the Plugin Manager

enkins管理员可以通过在Jenkins主机上创建一个文件来禁用插件,比如: JENKINS_HOME/plugins/PLUGIN_NAME.hpi.disabled.

禁用插件创建的配置就像插件被卸载一样, 它们在引导时引起了警告,但被忽略掉。

固定的插件

 Jenkins 2.0中删除了固定插件特性。之后的版本没有捆绑插件,而是提供了一个安装最有用插件的向导。
   

pinned plugins 的概念适用于在Jenkins 1.x中绑定的插件, 例如 Matrix Authorization plugin

默认情况下, 当Jenkins升级时, 其绑定的插件就会覆盖当前在JENKINS_HOME中安装的插件版本。

然而, 手动更新捆绑插件时, Jenkins会将该插件标记为特定的版本。在文件系统中, Jenkins 创建了一个名为 JENKINS_HOME/plugins/PLUGIN_NAME.hpi.pinned的空文件,来表示固定。

在Jenkins启动期间,固定插件永远不会被绑定插件覆盖。(如果固定的插件比当前捆绑的插件老,新版本的Jenkins就会发出警告)。 将一个绑定的插件更新到更新中心提供的版本是安全的。 通常获取最新的特性并修复是必要的。 绑定的版本偶尔会更新, 但不是一致的。

插件管理允许插件被显式的释放。 JENKINS_HOME/plugins/PLUGIN_NAME.hpi.pinned 文件也能手动创建/删除,以控制固定行为。如果pinned 文件存在, Jenkins将使用用户指定的任何插件。 如果文件不存在, Jenkins 将在启动时将插件恢复到默认版本。


1. updates.jenkins.io

 

Jenkins CLI

Table of Contents

Jenkins有一个内置的命令行界面,允许用户和管理员从脚本或shell环境中访问Jenkins。这可以方便的编写日常任务, 批量更新, 故障排除等等。

可以通过SSH 或 Jenkins CLI客户端访问命令行界面, Jenkins分布式的的.jar 文件。

 由于安全原因,not recommended使用 Jenkins 2.53 及以下和Jenkins LTS 2.46.1 及以下分布式的CLI 客户端: 虽然目前没有已知的漏洞,但之前有几个漏洞被报告并修补过, 而且它使用的Jenkins远程协议 很容易受到远程代码执行bug的影响,is inherently vulnerable to remote code execution bugs, 甚至是 “预认证” 漏洞 (匿名用户能够物理访问Jenkins 网络)。Jenkins 2.5 及以上和Jenkins LTS 2.46.2 及以上分发的客户端被认为在它的默认 (-http) 或 -ssh 模式是安全的,如使用标准 ssh 命令。
   

通过SSH使用 CLI

在新的Jenkins安装中, SSH 服务默认禁用。 管理员可以选择设置一个特定的端口,或让Jenkins在 配置全局安全 页面选择一个随机的端口。

为了确定随机分配的SSH端口,请检查Jenkins URL返回的头,例如:

% curl -Lv https://JENKINS_URL/login 2>&1 | grep 'X-SSH-Endpoint'
< X-SSH-Endpoint: localhost:53801
%

使用随机 SSH 端口 (本例中为53801 ), 和配置的 [Authentication], 任何现代的 SSH 客户端都可以安全的执行 CLI 命令。

身份验证

无论哪个在Jenkins 主机身份验证的用户,为了access CLI,都必须具有 Overall/Read 权限。根据执行的命令,用户可能需要其他的权限。

身份认证依赖于 基于SSH公共/私有密钥对身份认证。要为合适的用户添加 SSH 公共密钥, 导航到 https://JENKINS_URL/user/USERNAME/configure 并将 SSH 公共密钥粘贴到合适的文本域。

Adding public SSH keys for a user

常用命令

Jenkins 有许多内置的 CLI 命令,这些命令可以在任何 Jenkins 环境中找到, 比如 buildlist-jobs。插件也提供 CLI 命令; 为了确定给定Jenkins环境中可用命令的完整列表, 执行CLI help 命令:

% ssh -l kohsuke -p 53801 localhost help

下面的命令列表并不全面, 但他是Jenkins CLI 使用的起点。

build

最常见和有用的 CLI命令之一是 build, 它允许用户触发拥有权限的任何作业或流水线。

最基本的调用将简单的触发 作业或流水线并退出, 但是通过额外的选项,用户也可以传递参数, 轮询 SCM, 甚至可以跟踪触发的构建或流水线的运行的控制台输出。

% ssh -l kohsuke -p 53801 localhost help build

java -jar jenkins-cli.jar build JOB [-c] [-f] [-p] [-r N] [-s] [-v] [-w]
Starts a build, and optionally waits for a completion.  Aside from general
scripting use, this command can be used to invoke another job from within a
build of one job.  With the -s option, this command changes the exit code based
on the outcome of the build (exit code 0 indicates a success) and interrupting
the command will interrupt the job.  With the -f option, this command changes
the exit code based on the outcome of the build (exit code 0 indicates a
success) however, unlike -s, interrupting the command will not interrupt the
job (exit code 125 indicates the command was interrupted).  With the -c option,
a build will only run if there has been an SCM change.
 JOB : Name of the job to build
 -c  : Check for SCM changes before starting the build, and if there's no
       change, exit without doing a build
 -f  : Follow the build progress. Like -s only interrupts are not passed
       through to the build.
 -p  : Specify the build parameters in the key=value format.
 -s  : Wait until the completion/abortion of the command. Interrupts are passed
       through to the build.
 -v  : Prints out the console output of the build. Use with -s
 -w  : Wait until the start of the command
% ssh -l kohsuke -p 53801 localhost build build-all-software -f -v
Started build-all-software #1
Started from command line by admin
Building in workspace /tmp/jenkins/workspace/build-all-software
[build-all-software] $ /bin/sh -xe /tmp/hudson1100603797526301795.sh
+ echo hello world
hello world
Finished: SUCCESS
Completed build-all-software #1 : SUCCESS
%

console

同样有用的是console 命令, 它检索指定的构建或流水线运行的控制台输出。当没有提供构建编号时, console 命令将会输出最后完成的构建的控制台输出。

% ssh -l kohsuke -p 53801 localhost help console

java -jar jenkins-cli.jar console JOB [BUILD] [-f] [-n N]
Produces the console output of a specific build to stdout, as if you are doing 'cat build.log'
 JOB   : Name of the job
 BUILD : Build number or permalink to point to the build. Defaults to the last
         build
 -f    : If the build is in progress, stay around and append console output as
         it comes, like 'tail -f'
 -n N  : Display the last N lines
% ssh -l kohsuke -p 53801 localhost console build-all-software
Started from command line by kohsuke
Building in workspace /tmp/jenkins/workspace/build-all-software
[build-all-software] $ /bin/sh -xe /tmp/hudson1100603797526301795.sh
+ echo hello world
yes
Finished: SUCCESS
%

who-am-i

who-am-i 有助于列出当前用户的可用凭证和权限。这对调试时由于没有某些权限而缺少 CLI 命令的情况很有帮助。

% ssh -l kohsuke -p 53801 localhost help who-am-i

java -jar jenkins-cli.jar who-am-i
Reports your credential and permissions.
% ssh -l kohsuke -p 53801 localhost who-am-i
Authenticated as: kohsuke
Authorities:
  authenticated
%

使用 CLI 客户端

尽管基于SSH的CLI快速且覆盖了大多数需求, 但是Jenkins分布式的CLI客户端是更好的选择。 例如, CLI客户端的默认传输是 HTTP,这意味着不需要在防火墙中打开其他端口以供其使用。

下载客户端

CLI 客户端可以直接在URL /jnlpJars/jenkins-cli.jar从Jenkins主机下载, 实际上 https://JENKINS_URL/jnlpJars/jenkins-cli.jar

.jar 用于 Jenkins的不同版本时, 在使用时出现兼容性问题, 请重新从Jenkins主机下载最新的 .jar文件。

使用客户端

调用客户端的一般语法如下:

java -jar jenkins-cli.jar [-s JENKINS_URL] [global options...] command [command options...] [arguments...]

JENKINS_URL 可以通过环境变量 $JENKINS_URL来指定。 其他通用选项的摘要可以通过运行客户端来显示,而不需要任何参数。

客户端连接模式

在2.54+ / 2.46.2+ 客户端,有三种基本模式可以使用 , 可通过全局变量选择: -http; -ssh; 和 -remoting

HTTP 连接模式

这是2.54 和 2.46.2的默认模式, 不过你可以明确地传递 -http 选项。

身份认证最好使用 -auth 选项, 它接受 username:apitoken 参数。 从/me/configure获取你的API令牌:

java -jar jenkins-cli.jar [-s JENKINS_URL] -auth kohsuke:abc1234ffe4a command ...

(实际上也接受密码, 但这是不鼓励的)

你还可以在带 @的参数之前从文件加载相关的内容:

java -jar jenkins-cli.jar [-s JENKINS_URL] -auth @/home/kohsuke/.jenkins-cli command ...

一般来说,不需要特别的参数配置来启动基于 HTTP的CLI 连接。 如果你在HTTP 反向代理后台运行Jenkins, e确保它不缓存请求或响应体。

 Jenkins 2.54及以上的CLI的HTTP连接模式不能在使用mod_proxy的Apache HTTP 反向代理服务器上正常工作。工作区包括使用不同的反向代理,如 Nginx 或 HAProxy, 或在可能的情况下使用 SSH 连接模式。参考 JENKINS-47279.
   

SSH连接模式

身份验证是通过 SSH 密钥对进行的。你还必须选择Jenkins用户ID:

java -jar jenkins-cli.jar [-s JENKINS_URL] -ssh -user kohsuke command ...

在这种模式下, 客户机基本上像一个本地 ssh 命令。

默认情况下,客户端尝试连接在 JENKINS_URL使用的相同主机上的SSH端口。 如果Jenkins在 HTTP 反向代理的后面, 这通常不会起作用, 所以用系统属性 -Dorg.jenkinsci.main.modules.sshd.SSHD.hostName=ACTUALHOST运行Jenkins, 为SSH端点定义一个主机名或IP地址

远程连接模式

这是客户端支持从pre-2.54 / pre-2.46.2 Jenkins 服务器下载的唯一模式 (引入 -remoting 选项之前)。 由于安全和性能原因它被弃用了。 也就是说, 某些命令或命令模式 only 能在远程模式下运行, 通常是由于命令功能包括在客户端机器上运行的服务器提供的代码。

该模式在服务器端被禁用,用于2.54+ 和 2.46.2的新的安装。 如果你必须使用它, 并接受风险, 可在 配置全局安全性中启用。

身份验证最好通过 SSH 密钥对进行。 login命令和 --username / --password 命令(注意: not global) 选项也是可用的; 由于无法使用非基于密码的安全域,这些命令是无效的。 如果匿名用户缺乏整体或工作对权限,那么某些命令参数无法得到适当的解析,并且在脚本中保存人工选择的密码用于使用被认为是不安全的。

注意,此模式有两种传输方式: 通过HTTP, 或通过 专用的TCP 套接。 如果TCP 端口可用 并且看起来有效, 客户端将使用此传输。 如果TCP 端口被禁用, 或者这样一个端口被广告但不接受连接 (例如,你使用带有防火墙的 HTTP 反向代理), 客户端将会自动地退回到效率较低的HTTP传输。

基于远程的客户端的常见问题

在运行CLI客户端时可能会遇到很多常见问题。

操作超时

如果你在服务器上使用防火墙请检查 HTTP 或 TCP 端口是否打开。你可以在Jenkins配置中配置它的值。 默认情况下,它将设置一个随机的端口。

% java -jar jenkins-cli.jar -s JENKINS_URL help
Exception in thread "main" java.net.ConnectException: Operation timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:432)
    at java.net.Socket.connect(Socket.java:529)
    at java.net.Socket.connect(Socket.java:478)
    at java.net.Socket.<init>(Socket.java:375)
    at java.net.Socket.<init>(Socket.java:189)
    at hudson.cli.CLI.<init>(CLI.java:97)
    at hudson.cli.CLI.<init>(CLI.java:82)
    at hudson.cli.CLI._main(CLI.java:250)
    at hudson.cli.CLI.main(CLI.java:199)
No X-Jenkins-CLI2-Port

进入 Manage Jenkins > Configure Global Security 并选择TCP port for JNLP agents下面的 "Fixed" 或 "Random"。

java.io.IOException: No X-Jenkins-CLI2-Port among [X-Jenkins, null, Server, X-Content-Type-Options, Connection,
        X-You-Are-In-Group, X-Hudson, X-Permission-Implied-By, Date, X-Jenkins-Session, X-You-Are-Authenticated-As,
        X-Required-Permission, Set-Cookie, Expires, Content-Length, Content-Type]
    at hudson.cli.CLI.getCliTcpPort(CLI.java:284)
    at hudson.cli.CLI.<init>(CLI.java:128)
    at hudson.cli.CLIConnectionFactory.connect(CLIConnectionFactory.java:72)
    at hudson.cli.CLI._main(CLI.java:473)
    at hudson.cli.CLI.main(CLI.java:384)
    Suppressed: java.io.IOException: Server returned HTTP response code: 403 for URL: http://citest.gce.px/cli
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1840)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
        at hudson.cli.FullDuplexHttpStream.<init>(FullDuplexHttpStream.java:78)
        at hudson.cli.CLI.connectViaHttp(CLI.java:152)
        at hudson.cli.CLI.<init>(CLI.java:132)
        ... 3 more
服务器密钥未验证

你可能会得到以下的错误并找到一个关于 mismatched keys的日志条目:

org.apache.sshd.common.SshException: Server key did not validate
    at org.apache.sshd.client.session.AbstractClientSession.checkKeys(AbstractClientSession.java:523)
    at org.apache.sshd.common.session.helpers.AbstractSession.handleKexMessage(AbstractSession.java:616)
    ...

这意味着你的SSH 配置不承认服务器提供的公钥。 当你在开发模式下运行Jenkins,应用程序的多个实例会随着时间的推移运行在同一个SSH端口上。 在开发环境中, 访问你的 ~/.ssh/known_hosts (或 C:/Users//.ssh/known_hosts )并删除与你当前 SSH 端口对应的行 (比如 [localhost]:3485)。 在生产环境中, 如果服务器的公钥在最近发生改变,请与Jenkins管理员联系。 如果是这样, a请管理员执行上面描述的步骤。

UsernameNotFoundException

如果你的客户端显示如下的堆栈跟踪:

org.acegisecurity.userdetails.UsernameNotFoundException: <name_you_used>
    ...

这意味着SSH密钥被识别并对存储的用户进行了验证,但是用户名对当前应用程序正在使用的安全域无效 。 这可能发生在最初使用Jenkins数据库时, 配置了你的用户, 然后切换到另一个安全域 (如 LDAP等) ,在该安全域中,你定义的用户还不存在。

要解决这个问题, 就要确保你的用户在你配置的安全域中存在。

故障诊断日志

为了获取认证过程的更多信息:

  1. 进入 Manage Jenkins > System Log > Add new log recorder

  2. 输入你想要的名称,点击 Ok

  3. 点击 Add

  4. 输入 org.jenkinsci.main.modules.sshd.PublicKeyAuthenticatorImpl (或者输入 PublicKeyAuth ,然后选择全名)

  5. 设置等级为ALL

  6. hudson.model.User重复之前的三个步骤。

  7. 点击Save

当你尝试身份验证时, 你可以刷新页面并查看内部发生了什么。

 

进程内的脚本批准

Table of Contents

Jenkins和许多插件都允许用户in Jenkins执行 Groovy脚本。 这些脚本功能的提供者是:

为了保护Jenkins不执行恶意脚本,这些插件在 Groovy 沙箱中执行用户提供的脚本,这限制了可访问的内部API。然后管理员可以使用由 Script Security plugin提供"In-process Script Approval"页面,来管理Jenkins环境中不安全的方法(如果有的话)。

Entering the In-process Script Approval configuration

开始

脚本安全插件 是由 Post-install Setup Wizard自动安装的, 尽管最初没有附加的脚本或操作被批准使用。

 这个插件的旧版本可能不能安全使用。 请查看 the Script Security plugin page列出的安全警告, 来确保 Script Security plugin 是最新的。
   

进程内脚本的安全性由两个不同的机制提供: Groovy 沙箱脚本批准。第一种, Groovy 沙箱, 是 Jenkins 流水线默认的机制,允许用户提供的脚本化和声明式流水线在没有管理员干预的情况下执行。第二种, 脚本批准, 允许管理员批准或否认非沙箱脚本, 或允许沙箱脚本执行其他方法。

对于大多数实例, Groovy 沙箱和已批准方法签名的 脚本安全的内置列表 的结合足够了。 强烈建议,如果绝对必要,管理员脱离这些默认值。

Groovy 沙箱

为了减少管理员的人工干预, 大多数脚本默认在 Groovy沙箱运行, 包括所有的 Jenkins 流水线。 沙箱只允许 Groovy的方法的子集被认为足够安全,无需预先批准就可以执行"不被信任的" 访问。 使用Groovy沙箱的脚本 all 受到同样的限制, 因此 , 由管理员编写的流水线将受到非管理员用户授权的限制。

当一个脚本试图使用沙箱未授权的特性或方法时, 脚本会立刻停止, 如下图所示

Sandbox method rejection

Figure 1. Unauthorized method signature rejected at runtime via Blue Ocean

上面的流水线将不会执行直到管理员通过 In-process Script Approval 页面 批准方法签名

除了添加批准的方法签名之外, 用户还可以完全禁用 Groovy 沙箱,如下所示。 禁用 Groovy 沙箱要求 entire 脚本必须经过管理员的审核和 手动批准

Creating a Scripted Pipeline and unchecking 'Use Groovy Sandbox'

Figure 2. Disabling the Groovy Sandbox for a Pipeline

脚本批准

管理员对整个脚本或方法签名的手动批准, 为管理员提供了额外的灵活性,来支持进程内脚本的更高级的用法。 当 Groovy 沙箱 被禁用, 或内置列表外的方法被调用时, 脚本安全插件将 检查管理员管理的批准脚本和方法列表。

对于希望在 Groovy 沙箱外执行的脚本, 管理员必须批准In-process Script Approval 页面内的 entire 脚本 :

Approving an unsandboxed Scripted Pipeline

Figure 3. Approving an unsandboxed Scripted Pipeline

对于使用Groovy 沙箱的脚本, 但是希望执行当前未批准的方法签名,也会被Jenkins停止,并要求管理员在脚本被允许执行之前批准指定的方法签名:

Approving a new method signature

Figure 4. Approving a new method signature

批准假设权限检查

脚本批准提供了三个选项: 批准, 否认, 和 "批准假设权限检查" 。虽然前两者的目的是不言而喻的, 第三种需要对内部数据脚本能够访问的内容和在如何在Jenkins函数内部检查权限进行一些额外的了解。

考虑访问方法 hudson.model.AbstractItem.getParent()的脚本,它本身是无害的,它将返回一个包含当前执行的流水线或任务的文件夹和根项的对象。 Following that 方法调用, 执行 hudson.model.ItemGroup.getItems(),它将列出文件夹或根项中的项, 需要 Job/Read 权限。

这可能意味着批准 hudson.model.ItemGroup.getItems() 方法签名将允许脚本绕过内置的权限检查。

通常更可取的是,点击 Approve assuming permissions check ,这将造成脚本审批引擎允许方法 签名,假设运行该脚本的用户具有执行该方法的权限, 比如示例中的 Job/Read 权限。

系统管理

子章节

本章适用于Jenkins服务器和节点的系统管理员。它将涵盖系统维护主题,包括安全性,监控和备份/恢复。

没有参与系统级任务的用户会发现这章的使用受限。个别部分可能会假设对前一部分的信息有所了解,但这些假设将被明确地调出并交叉引用。

如果您是Jenkins管理员,想要了解有关管理Jenkins节点和实例的更多信息,请参阅 管理Jenkins.

有关Jenkins用户手册中内容的概述,请参阅 用户手册概览.

安全

Table of Contents

 这仍然是一项正在进行中的工作。
   

在Jenkins 1.x的默认配置中, Jenkins 不执行任何安全检查。这意味着 Jenkins能够启动进程并访问本地文件,任何人都可以访问Jenkins web UI和更多。

保护 Jenkins 可从两个方面着手。

  • 访问控制, 这确保用户在访问Jenkins及其活动时进行身份验证。

  • 保护Jenkins免受外部威胁

访问控制

你应该所得对 Jenkins UI 的访问以便于用户进行身份认证, 并授予一组合适的权限。 还设置主要由两个轴控制:

  • Security Realm, 他决定用户和他们的密码, 以及用户所属的组。

  • Authorization Strategy,他决定谁有权访问什么。

这两个轴是正交的, 需要单独配置。比如, 你可以选择使用外部的 LDAP 或Active 目录作为安全域, 你也可以选择 "每个人都完全访问" 模式的授权策略。或者你还可以选择让Jenkins运行 他自己的用户数据库, 并基于权限/用户矩阵执行访问控制。

保护Jenkins用户免受其他威胁

在Jenkins中有另外的安全子系统,可以保护Jenkins和Jenkins的用户免受间接攻击。

下面的主体将讨论 off by default下的特性。 我们建议你先阅读并立即行动。

下面的主题讨论默认情况下的其他安全特性。你只需要在它们造成问题的时候查看他们。

禁用安全

你可能意外的设置了安全域 / 权限,在这种情况下你可能无法重新配置Jenkins。

当出现这种情况时, 你可以通过以下步骤修复它:

  1. 停止Jenkins (最简单的方法是停止servlet容器)

  2. 进入文件系统的 $JENKINS_HOME并找到 config.xml 文件。

  3. 在编辑器中打开该文件。

  4. 在该文件中寻找 true 元素。

  5. false取代 true

  6. 删除 authorizationStrategysecurityRealm

  7. 启动Jenkins

  8. 当Jenkins回来时, 它将处于一种不安全的模式,每个人都能完全访问系统。

如果仍然不起作用, 尝试重命名或删除 config.xml

规模 Jenkins

本章将讨论与使用和管理大规模 Jenkins 配置相关的主题: 大量的用户, 节点, 代理, 文件夹, 项目, 并发作业, 作业结果和日志, 甚至大量的主服务器。

本章适合于熟悉 Jenkins的用户, 管理员, 和那些计划大规模安装的人。

如果你是Jenkins管理员想要了解更有与管理 Jenkins节点和 instances相关的信息, 请参考 管理Jenkins.

对于Jenkins用户手册内容的概述, 请参阅 用户手册概述

 

附录

本节通常是为 Jenkins 管理员和系统管理员准备的。 每一节都是与其他节不同的独立主题。 这些都是高级的主题, 涉及到终端, 也不适合其他章节的内容。

 To Contributors: 请考虑在其他地方添加一个终端。 事实上,在其他地方不适合甚至超出该手册的范围的主题。请参阅 Contributing to Jenkins 了解如何联系产品贡献者的详细信息,并讨论你想要添加的内容。
   

 

术语表

Table of Contents

一般术语

  • Agent

    代理通常是一个机器或者容器, 它连接到 Jenkins 的主服务器并在主服务器的指示下执行任务。

  • Artifact

    BuildPipeline 运行期间生成的一个不可变文件,该文件被 archived到Jenkins Master供用户在之后进行检索。

  • Build

    Project的单个执行结果

  • Cloud

    一个提供动态 Agent配置和分配的系统配置, 如由 Azure VM AgentsAmazon EC2 插件提供的配置。

  • Core

    主要的 Jenkins 应用程序 (jenkins.war) which 提供基本的 web UI, 配置, 和 Plugins构建的基础。

  • Downstream

    一个已配置的 PipelineProject,它作为一个单独的流水线或项目执行的一部分被触发。

  • Executor

    一个工作的执行位置 ,由Node上的 PipelineProject定义。一个节点可能由0或多个配置的执行器,它对应 有多少并发项目或流水线能够在此节点上执行。

  • Fingerprint

    被认为是全局唯一的一个散列,用于追踪Artifact或其他跨多个PipelinesProjects的实体的使用。

  • Folder

    用于 Pipelines 和/或 Projects的组织容器, 类似于文件系统的文件夹。

  • Item

    web UI中的一个实体, 对应于以下任一个: Folder, Pipeline, 或Project

  • Job

    一个不赞成使用的一个术语, Project的同义词。

  • Label

    用于分组Agents的用户定义的文本, 通常使用类似的功能和功能。例如, 基于 Linux代理的linux或者Docker-capable代理的docker

  • Master

    中心, 协调保存配置, 加载插件,和呈现给Jenkins各种用户界面的过程。

  • Node

    一种机器,他是Jenkins环境的一部分,能够执行 PipelinesProjectsMasterAgents 都被认为是节点。

  • Project

    应该执行的工作的用户配置描述 , 比如 构建一个软件, 等等。

  • Pipeline

    连续交付流水线的一个用户定义模型, 了解更请阅读本手册的 Pipeline chapter

  • Plugin

    Jenkins功能的扩展,由Jenkins 核心分别提供。

  • Publisher

    完成所有已配置的发布报告, 发送通知等 Steps之后Build的部分。

  • Stage

    stage 是流水线的一部分, 用于定义整个流水线的概念上不同的子集, 例如: "Build", "Test", 和 "Deploy", 他们被许多插件用于可视化或呈现Jenkins流水线状态/进展。

  • Step

    一个单一的任务; 从根本上,步骤告诉Jenkins在一个 PipelineProject中要做 what

  • Trigger

    触发一个新的 Pipeline 运行或 Build的标准。

  • Update Center

    托管了插件和插件元数据的库,用来支持在Jenkins内部安装插件。

  • Upstream

    一个已配置PipelineProject ,它 触发一个流水线或项目作为执行的一部分。

  • Workspace

    A disposable directory 在 Node文件系统的一次性目录, 其中工作可以通过 PipelineProject完成。在 BuildPipeline 运行完成之后, 工作区通常会保留在适当的位置。除非在Jenkins Master上设置了 特定的工作区清理策略。

  • 流水线语法

    Table of Contents

    本节是建立在 流水线入门内容的基础上,而且,应当被当作一个参考。 对于在实际示例中如何使用流水线语法的更多信息, 请参阅本章在流水线插件的2.5版本中的 使用 Jenkinsfile部分, 流水线支持两种离散的语法,具体如下对于每种的优缺点, 参见语法比较

    正如 本章开始讨论的, 流水线最基础的部分是 "步骤"。基本上, 步骤告诉 Jenkins 要做什么,以及作为声明式和脚本化流水线语法的基本构建块。

    对于可用步骤的概述, 请参考 流水线步骤引用,它包含了一个构建到流水线的步骤和 插件提供的步骤的全面的列表。

    声明式流水线

    声明式流水线是最近添加到 Jenkins 流水线的 [1],它在流水线子系统之上提供了一种更简单,更有主见的语法。

    所有有效的声明式流水线必须包含在一个 pipeline 块中, 比如:

    pipeline {
        /* insert Declarative Pipeline here */
    }
    

    在声明式流水线中有效的基本语句和表达式遵循与 Groovy的语法同样的规则, 有以下例外:

    • 流水线顶层必须是一个 block, 特别地: pipeline { }

    • 没有分号作为语句分隔符,,每条语句都必须在自己的行上。

    • 块只能由 节段, 指令, 步骤, 或赋值语句组成。 *属性引用语句被视为无参方法调用。 例如, input被视为 input()

    节段

    声明式流水线中的节段通常包含一个或多个 指令步骤

    代理

    agent 部分指定了整个流水线或特定的部分, 将会在Jenkins环境中执行的位置,这取决于 agent 区域的位置。该部分必须在 pipeline 块的顶层被定义, 但是 stage 级别的使用是可选的。

    RequiredYes
    Parameters Described below
    Allowed In the top-level pipeline block and each stage block.
    参数

    为了支持作者可能有的各种各样的用例流水线, agent 部分支持一些不同类型的参数。这些参数应用在pipeline块的顶层, 或 stage 指令内部。

    • any

      在任何可用的代理上执行流水线或阶段。例如: agent any

    • none

      当在 pipeline 块的顶部没有全局代理, 该参数将会被分配到整个流水线的运行中并且每个 stage 部分都需要包含他自己的 agent 部分。比如: agent none

    • label

      在提供了标签的 Jenkins 环境中可用的代理上执行流水线或阶段。 例如: agent { label 'my-defined-label' }

    • node

      agent { node { label 'labelName' } }agent { label 'labelName' } 一样, 但是 node 允许额外的选项 (比如 customWorkspace )。

    • docker

      使用给定的容器执行流水线或阶段。该容器将在预置的 node上,或在匹配可选定义的label 参数上,动态的供应来接受基于Docker的流水线。 docker 也可以选择的接受 args 参数,该参数可能包含直接传递到 docker run 调用的参数, 以及 alwaysPull 选项, 该选项强制 docker pull ,即使镜像名称已经存在。 比如: agent { docker 'maven:3-alpine' }agent { docker { image 'maven:3-alpine' label 'my-defined-label' args '-v /tmp:/tmp' } }

    • dockerfile

      执行流水线或阶段, 使用从源代码库包含的 Dockerfile 构建的容器。为了使用该选项, Jenkinsfile 必须从多个分支流水线中加载, 或者加载 "Pipeline from SCM." 通常,这是源代码仓库的根目录下的 Dockerfile : agent { dockerfile true }. 如果在另一个目录下构建 Dockerfile , 使用 dir 选项: agent { dockerfile {dir 'someSubDir' } }。如果 Dockerfile 有另一个名称, 你可以使用 filename 选项指定该文件名。你可以传递额外的参数到 docker build ... 使用 additionalBuildArgs 选项提交, 比如 agent { dockerfile {additionalBuildArgs '--build-arg foo=bar' } }。 例如, 一个带有 build/Dockerfile.build 的仓库,期望一个构建参数 version: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' } }

    常见选项

    有一些应用于两个或更多 agent 的实现的选项。他们不被要求,除非特别规定。

    • label

      一个字符串。该标签用于运行流水线或个别的 stage。该选项对 node, dockerdockerfile 可用, node要求必须选择该选项。

    • customWorkspace

      一个字符串。在自定义工作区运行应用了 agent 的流水线或个别的 stage, 而不是默认值。 它既可以是一个相对路径, 在这种情况下,自定义工作区会存在于节点工作区根目录下, 或者一个绝对路径。比如:agent { node { label 'my-defined-label' customWorkspace '/some/other/path' } }该选项对 node, dockerdockerfile 有用 。

    • reuseNode

      一个布尔值, 默认为false。 如果是true, 则在流水线的顶层指定的节点上运行该容器, 在同样的工作区, 而不是在一个全新的节点上。这个选项对 dockerdockerfile 有用, 并且只有当 使用在个别的 stageagent 上才会有效。

    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent { docker 'maven:3-alpine' } 
        stages {
            stage('Example Build') {
                steps {
                    sh 'mvn -B clean verify'
                }
            }
        }
    }
    
     在一个给定名称和标签(maven:3-alpine)的新建的容器上执行定义在流水线中的所有步骤 。
       
    阶段级别的 agent 部分

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent none 
        stages {
            stage('Example Build') {
                agent { docker 'maven:3-alpine' } 
                steps {
                    echo 'Hello, Maven'
                    sh 'mvn --version'
                }
            }
            stage('Example Test') {
                agent { docker 'openjdk:8-jre' } 
                steps {
                    echo 'Hello, JDK'
                    sh 'java -version'
                }
            }
        }
    }
    
     在流水线顶层定义 agent none 确保 an Executor 没有被分配。 使用 agent none 也会强制 stage 部分包含他自己的 agent 部分。
      使用镜像在一个新建的容器中执行该阶段的该步骤。
      使用一个与之前阶段不同的镜像在一个新建的容器中执行该阶段的该步骤。

    post

    post 部分定义一个或多个steps ,这些阶段根据流水线或阶段的完成情况而 运行(取决于流水线中 post 部分的位置). post 支持以下 post-condition 块中的其中之一: always, changed, failure, success, unstable, 和 aborted。这些条件块允许在 post 部分的步骤的执行取决于流水线或阶段的完成状态。

    RequiredNo
    Parameters None
    Allowed In the top-level pipeline block and each stage block.
    Conditions
    • always

      无论流水线或阶段的完成状态如何,都允许在 post 部分运行该步骤。

    • changed

      只有当前流水线或阶段的完成状态与它之前的运行不同时,才允许在 post 部分运行该步骤。

    • failure

      只有当前流水线或阶段的完成状态为"failure",才允许在 post 部分运行该步骤, 通常web UI是红色。

    • success

      只有当前流水线或阶段的完成状态为"success",才允许在 post 部分运行该步骤, 通常web UI是蓝色或绿色。

    • unstable

      只有当前流水线或阶段的完成状态为"unstable",才允许在 post 部分运行该步骤, 通常由于测试失败,代码违规等造成。通常web UI是黄色。

    • aborted

      只有当前流水线或阶段的完成状态为"aborted",才允许在 post 部分运行该步骤, 通常由于流水线被手动的aborted。通常web UI是灰色。

    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example') {
                steps {
                    echo 'Hello World'
                }
            }
        }
        post { 
            always { 
                echo 'I will always say Hello again!'
            }
        }
    }
    
     按照惯例, post 部分应该放在流水线的底部。
      Post-condition 块包含与 steps 部分相同的steps

    stages

    包含一系列一个或多个 stage 指令, stages 部分是流水线描述的大部分"work" 的位置。 建议 stages 至少包含一个 stage 指令用于连续交付过程的每个离散部分,比如构建, 测试, 和部署。

    RequiredYes
    Parameters None
    Allowed Only once, inside the pipeline block.
    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages { 
            stage('Example') {
                steps {
                    echo 'Hello World'
                }
            }
        }
    }
    
     stages 部分通常会遵循诸如 agent, options 等的指令。
       

    steps

    steps 部分在给定的 stage 指令中执行的定义了一系列的一个或多个steps

    RequiredYes
    Parameters None
    Allowed Inside each stage block.
    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example') {
                steps { 
                    echo 'Hello World'
                }
            }
        }
    }
    
     steps 部分必须包含一个或多个步骤。
       

    指令

    environment

    environment 指令制定一个 键-值对序列,该序列将被定义为所有步骤的环境变量,或者是特定于阶段的步骤, 这取决于 environment 指令在流水线内的位置。

    该指令支持一个特殊的助手方法 credentials() ,该方法可用于在Jenkins环境中通过标识符访问预定义的凭证。对于类型为 "Secret Text"的凭证, credentials() 将确保指定的环境变量包含秘密文本内容。对于类型为 "SStandard username and password"的凭证, 指定的环境变量指定为 username:password ,并且两个额外的环境变量将被自动定义 :分别为 MYVARNAME_USRMYVARNAME_PSW

    RequiredNo
    Parameters None
    Allowed Inside the pipeline block, or within stage directives.
    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        environment { 
            CC = 'clang'
        }
        stages {
            stage('Example') {
                environment { 
                    AN_ACCESS_KEY = credentials('my-prefined-secret-text') 
                }
                steps {
                    sh 'printenv'
                }
            }
        }
    }
    
     顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤。
      在一个 stage 中定义的 environment 指令只会将给定的环境变量应用于 stage 中的步骤。
      environment 块有一个 助手方法 credentials() 定义,该方法可以在 Jenkins 环境中用于通过标识符访问预定义的凭证。

    options

    options 指令允许从流水线内部配置特定于流水线的选项。 流水线提供了许多这样的选项, 比如 buildDiscarder,但也可以由插件提供, 比如 timestamps.

    RequiredNo
    Parameters None
    Allowed Only once, inside the pipeline block.
    可用选项
    • buildDiscarder

      为最近的流水线运行的特定数量保存组件和控制台输出。例如: options { buildDiscarder(logRotator(numToKeepStr: '1')) }

    • disableConcurrentBuilds

      不允许同时执行流水线。 可被用来防止同时访问共享资源等。 例如: options { disableConcurrentBuilds() }

    • overrideIndexTriggers

      允许覆盖分支索引触发器的默认处理。 如果分支索引触发器在多分支或组织标签中禁用, options { overrideIndexTriggers(true) } 将只允许它们用于促工作。否则, options { overrideIndexTriggers(false) } 只会禁用改作业的分支索引触发器。

    • skipDefaultCheckout

      agent 指令中,跳过从源代码控制中检出代码的默认情况。例如: options { skipDefaultCheckout() }

    • skipStagesAfterUnstable

      一旦构建状态变得UNSTABLE,跳过该阶段。例如: options { skipStagesAfterUnstable() }

    • checkoutToSubdirectory

      在工作空间的子目录中自动地执行源代码控制检出。例如: options { checkoutToSubdirectory('foo') }

    • timeout

      设置流水线运行的超时时间, 在此之后,Jenkins将中止流水线。例如: options { timeout(time: 1, unit: 'HOURS') }

    • retry

      在失败时, 重新尝试整个流水线的指定次数。 For example: options { retry(3) }

    • timestamps

      预谋所有由流水线生成的控制台输出,与该流水线发出的时间一致。 例如: options { timestamps() }

    Example

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        options {
            timeout(time: 1, unit: 'HOURS') 
        }
        stages {
            stage('Example') {
                steps {
                    echo 'Hello World'
                }
            }
        }
    }
    
     指定一个小时的全局执行超时, 在此之后,Jenkins 将中止流水线运行。
       
     一个完整的可用选项列表正在等待完成第 INFRA-1503次。
       
    阶段选项

    stageoptions 指令类似于流水线根目录上的 options 指令。然而, stage -级别 options 只能包括 retry, timeout, 或 timestamps 等步骤, 或与 stage 相关的声明式选项,如 skipDefaultCheckout

    stage, options 指令中的步骤在进入 agent 之前被调用或在 when 条件出现时进行检查。

    可选的阶段选项
    • skipDefaultCheckout

      agent 指令中跳过默认的从源代码控制中检出代码。例如: options { skipDefaultCheckout() }

    • timeout

      设置此阶段的超时时间, 在此之后, Jenkins 会终止该阶段。 例如: options { timeout(time: 1, unit: 'HOURS') }

    • retry

      在失败时, 重试此阶段指定次数。 例如: options { retry(3) }

    • timestamps

      预谋此阶段生成的所有控制台输出以及该行发出的时间一致。例如: options { timestamps() }

    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example') {
                options {
                    timeout(time: 1, unit: 'HOURS') 
                }
                steps {
                    echo 'Hello World'
                }
            }
        }
    }
    
     指定 Example 阶段的执行超时时间, 在此之后,Jenkins 将中止流水线运行。
       

    参数

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

    RequiredNo
    Parameters None
    Allowed Only once, inside the pipeline block.
    可用参数
    • 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}"
                }
            }
        }
    }
    
     一份完整的可用参数列表正在等待 INFRA-1503的完成。
       

    触发器

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

    RequiredNo
    Parameters None
    Allowed Only once, inside the pipeline block.
    • 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 指令中。

    RequiredAt least one
    Parameters One mandatory parameter, a string for the name of the stage.
    Allowed Inside the stages section.
    示例

    Jenkinsfile (Declarative Pipeline)

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

    工具

    定义自动安装和放置 PATH 的工具的一部分。如果 agent none 指定,则忽略该操作。

    RequiredNo
    Parameters None
    Allowed Inside the pipeline block or a stage block.
    支持工具
    • maven

    • jdk

    • gradle

    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
       agent any
       tools {
           maven 'apache-maven-3.0.1'
      }
       stages {
           stage('Example') {
               steps {
                   sh 'mvn --version'
              }
          }
      }
    }
     The tool name must be pre-configured in Jenkins under Manage JenkinsGlobal Tool Configuration.
       

    input

    stageinput 指令允许你使用 input step提示输入。 在应用了 options 后,进入 stageagent 或评估 when 条件前, stage 将暂停。 如果 input 被批准, stage 将会继续。 作为 input 提交的一部分的任何参数都将在环境中用于其他 stage

    配置项
    • message

      必需的。 这将在用户提交 input 时呈现给用户。

    • id

      input 的可选标识符, 默认为 stage 名称。

    • ok

      input表单上的"ok" 按钮的可选文本。

    • submitter

      可选的以逗号分隔的用户列表或允许提交 input 的外部组名。默认允许任何用户。

    • submitterParameter

      环境变量的可选名称。如果存在,用 submitter 名称设置。

    • parameters

      提示提交者提供的一个可选的参数列表。 更多信息参见 [parameters]

    示例

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example') {
                input {
                    message "Should we continue?"
                    ok "Yes, we should."
                    submitter "alice,bob"
                    parameters {
                        string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
                    }
                }
                steps {
                    echo "Hello, ${PERSON}, nice to meet you."
                }
            }
        }
    }
    

    when

    when 指令允许流水线根据给定的条件决定是否应该执行阶段。 when 指令必须包含至少一个条件。 如果 when 指令包含多个条件, 所有的子条件必须返回True,阶段才能执行。 这与子条件在 allOf 条件下嵌套的情况相同 (参见下面的示例)。

    使用诸如 not, allOf, 或 anyOf 的嵌套条件可以构建更复杂的条件结构 can be built 嵌套条件可以嵌套到任意深度。

    RequiredNo
    Parameters None
    Allowed Inside a stage directive
    内置条件
    • branch

      当正在构建的分支与模式给定的分支匹配时,执行这个阶段, 例如: when { branch 'master' }。注意,这只适用于多分支流水线。

    • environment

      当指定的环境变量是给定的值时,执行这个步骤, 例如: when { environment name: 'DEPLOY_TO', value: 'production' }

    • expression

      当指定的Groovy表达式评估为true时,执行这个阶段, 例如: when { expression { return params.DEBUG_BUILD } }

    • not

      当嵌套条件是错误时,执行这个阶段,必须包含一个条件,例如: when { not { branch 'master' } }

    • allOf

      当所有的嵌套条件都正确时,执行这个阶段,必须包含至少一个条件,例如: when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }

    • anyOf

      当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件,例如: when { anyOf { branch 'master'; branch 'staging' } }

    在进入 stageagent 前评估 when

    默认情况下, 如果定义了某个阶段的代理,在进入该stageagent 后该 stagewhen 条件将会被评估。但是, 可以通过在 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'
                }
            }
        }
    }
    

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example Build') {
                steps {
                    echo 'Hello World'
                }
            }
            stage('Example Deploy') {
                when {
                    branch 'production'
                    environment name: 'DEPLOY_TO', value: 'production'
                }
                steps {
                    echo 'Deploying'
                }
            }
        }
    }
    

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example Build') {
                steps {
                    echo 'Hello World'
                }
            }
            stage('Example Deploy') {
                when {
                    allOf {
                        branch 'production'
                        environment name: 'DEPLOY_TO', value: 'production'
                    }
                }
                steps {
                    echo 'Deploying'
                }
            }
        }
    }
    

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example Build') {
                steps {
                    echo 'Hello World'
                }
            }
            stage('Example Deploy') {
                when {
                    branch 'production'
                    anyOf {
                        environment name: 'DEPLOY_TO', value: 'production'
                        environment name: 'DEPLOY_TO', value: 'staging'
                    }
                }
                steps {
                    echo 'Deploying'
                }
            }
        }
    }
    

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent any
        stages {
            stage('Example Build') {
                steps {
                    echo 'Hello World'
                }
            }
            stage('Example Deploy') {
                when {
                    expression { BRANCH_NAME ==~ /(production|staging)/ }
                    anyOf {
                        environment name: 'DEPLOY_TO', value: 'production'
                        environment name: 'DEPLOY_TO', value: 'staging'
                    }
                }
                steps {
                    echo 'Deploying'
                }
            }
        }
    }
    

    Jenkinsfile (Declarative Pipeline)

    pipeline {
        agent none
        stages {
            stage('Example Build') {
                steps {
                    echo 'Hello World'
                }
            }
            stage('Example Deploy') {
                agent {
                    label "some-label"
                }
                when {
                    beforeAgent true
                    branch 'production'
                }
                steps {
                    echo 'Deploying'
                }
            }
        }
    }
    

    并行

    声明式流水线的阶段可以在他们内部声明多隔嵌套阶段, 它们将并行执行。 注意,一个阶段必须只有一个 stepsparallel 的阶段。 嵌套阶段本身不能包含进一步的 parallel 阶段, 但是其他的阶段的行为与任何其他 stage 相同。任何包含 parallel 的阶段不能包含 agenttools 阶段, 因为他们没有相关 steps

    另外, 通过添加 failFast true 到包含 parallelstage 中, 当其中一个进程失败时,你可以强制所有的 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"
                        }
                    }
                }
            }
        }
    }
    

    步骤

    声明式流水线可能使用在 流水线步骤引用中记录的所有可用的步骤, 它包含一个完整的步骤列表, 其中添加了下面列出的步骤,这些步骤只在声明式流水线中 only supported

    脚本

    script 步骤需要 [scripted-pipeline]块并在声明式流水线中执行。 对于大多数用例来说,应该声明式流水线中的“脚本”步骤是不必要的, 但是它可以提供一个有用的"逃生出口"。 非平凡的规模和/或复杂性的 script 块应该被转移到 共享库

    示例

    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"
                        }
                    }
                }
            }
        }
    }
    

    脚本化流水线

    脚本化流水线, 与[declarative-pipeline]一样的是, 是建立在底层流水线的子系统上的。与声明式不同的是, 脚本化流水线实际上是由 Groovy构建的通用 DSL [2]。 Groovy 语言提供的大部分功能都可以用于脚本化流水线的用户。这意味着它是一个非常有表现力和灵活的工具,可以通过它编写持续交付流水线。

    流控制

    脚本化流水线从 Jenkinsfile 的顶部开始向下串行执行, 就像 Groovy 或其他语言中的大多数传统脚本一样。 因此,提供流控制取决于 Groovy 表达式, 比如 if/else 条件, 例如:

    Jenkinsfile (Scripted Pipeline)

    node {
       stage('Example') {
           if (env.BRANCH_NAME == 'master') {
               echo 'I only execute on the master branch'
          } else {
               echo 'I execute elsewhere'
          }
      }
    }

    另一种方法是使用Groovy的异常处理支持来管理脚本化流水线流控制。当 步骤 失败 ,无论什么原因,它们都会抛出一个异常。处理错误的行为必须使用Groovy中的 try/catch/finally 块 , 例如:

    Jenkinsfile (Scripted Pipeline)

    node {
       stage('Example') {
           try {
               sh 'exit 1'
          }
           catch (exc) {
               echo 'Something failed, I should sound the klaxons!'
               throw
          }
      }
    }

    步骤

    正如 本章开始所讨论的, 流水线最基础的部分是"步骤"。从根本上说, 步骤告诉 Jenkins要做 what ,并作为声明式和脚本化流水线已发的基本构建块。

    脚本化流水线 not 不引入任何特定于其语法的步骤; 流水线步骤引用 包括流水线和插件提供的步骤的完整列表。

    区别普通 Groovy

    为了提供 durability, 这意味着运行流水线可以在Jenkins master 重启后继续运行,脚本化的流水线序列化数据到主服务器。由于这个设计需求, 一些Groovy 习惯用语,比如 collection.each { item -> /* perform operation */ } 都不完全支持。详情参见 JENKINS-27421JENKINS-26481

    语法比较

    当Jenkins 流水线第一次构建时, Groovy 被选为基础。 Jenkins长期使用嵌入式 Groovy引擎来为管理员和用户提供 高级脚本功能。另外, Jenkins流水线的实现者发现 Groovy是 构建现在成为 "脚本化流水线" DSL的坚实基础 [2]。

    由于它是一个功能齐全的编程环境, 脚本化流水线为Jenkins用户提供了 大量的灵活性性和可扩展性。 Groovy学习曲线通常不适合给定团队的所有成员, 因此创造了声明式流水线来为编写Jenkins流水线提供一种更简单、更有主见的语法。

    两者本质上是相同的流水线子系统。 underneath. 他们都是 "流水线即代码" 的持久实现。它们都能够使用构建到流水线中或插件提供的步骤。它们都能够使用 共享库

    但是它们的区别在于语法和灵活性。 声明式限制了用户使用更严格和预定义的结构, 使其成为更简单的持续交付流水线的理想选择。 脚本化提供了很少的限制, 以至于对脚本和语法的唯一限制往往是由Groovy子集本身定义的,而不是任何特定于流水线的系统, 这使他成为权利用户和那些有更复杂需求的人的理想选择。 顾名思义, 声明式流水线鼓励 声明式编程模型。 [3] 而脚本化流水线遵循一个更命令式的编程模型 [4]


    1. Version 2.5 of the "Pipeline plugin" introduces support for Declarative Pipeline syntax

    2. Domain-specific language

    3. Declarative Programming

    4. Imperative Programming

Pipeline Steps Reference

The following plugins offer Pipeline-compatible steps. Each plugin link offers more information about the parameters for each step.

Read more about how to integrate steps into your Pipeline in the Steps section of the Pipeline Syntax page.

 

Jenkins LTS 升级指导

本章节为管理员重点介绍升级 Jenkins LTS 时需要注意的重要变更。每个章节都覆盖了从上一个 LTS 发行版的升级,在版本为 x.y.1 的章节中包括了从上一个 LTS 线的升级。如果你在升级过程中跳过了一些 LTS 版本,建议阅读之间所有版本。

posted on 2022-08-10 13:50  root-123  阅读(3678)  评论(0编辑  收藏  举报