Jenkins 管道:等待另一个作业暂停
Jenkins pipeline: wait for another job to pause
我有几个测试项目(API 测试,UI Selenium 测试等),它们测试同一个应用程序。现在,应用程序的步骤。部署在每个詹金斯文件中都是重复的。
目标是有一个共同的 app-deployment 作业,它在服务器上准备应用程序:
- 从特定修订版或标签中获取;
- 定义各种环境变量,如许可证等;
- 生成 WAR 个文件;
- 将它们复制到 Tomcat 构建目录;
- 启动 Tomcat 并等待上下文准备就绪。
我不能在这之后就完成构建,因为 Jenkins 会杀死所有创建的进程,包括启动的 Tomcat。我为 Tomcat 尝试了 doNoKillMe
cookie,但这导致了与重新启动应用程序和数据库连接相关的其他几个问题。因此,当应用程序准备就绪时,我将 input
步骤与 ID 放在一起:
node {
properties([
parameters([
string(name: 'REVISION',
defaultValue: '',
),
string(name: 'TAG_NAME',
defaultValue: ''),
]),
])
withEnv(buildEnvVariables()) {
stage('Checkout') {
}
stage('Prepare file system') {
}
stage('Prepare database') {
}
stage('Builds WAR files') {
}
stage('Tomcat deploy') {
// Delete previous WAR files from Tomcat
// Copy generated files to tomcat
sh "$TOMCAT_DIR/bin/startup.sh"
waitForTokenFileOrFail()
}
input(id: 'IsBuilt', 'Application is ready... ')
}
}
现在,我希望从其他几个 testing-specific jenkins 文件中调用此作业:
node {
properties([
parameters([
string(name: 'TESTS_SUITE',
defaultValue: '',
),
string(name: 'OTHER_PARAM',
defaultValue: ''),
]),
])
withEnv(buildEnvVariables()) {
stage('Checkout') {
}
stage('Stop any running application builds') {
def jenkinsQueue = Jenkins.instance.queue
jenkinsQueue.items.findAll { it.task.name.startsWith(contextDeployBuildName) }.each {
echo "Found pending $contextDeployBuildName job. Cancelling: ${it.getId()}"
jenkinsQueue.doCancelItem(it.getId())
}
Jenkins.instance.getItemByFullName(contextDeployBuildName)
.getAllJobs().first().getBuilds()
?.each { build ->
if (build.isBuilding()) {
try {
echo "Found running $contextDeployBuildName job. Stopping: ${build.number}"
httpRequest(
httpMode: 'POST',
authentication: 'credentialsID',
url: "${JENKINS_URL}job/$contextDeployBuildName/${build.number}/stop")
} catch (any) {
println any.message
}
}
}
}
stage('Build the app') {
build(wait: true, job: contextDeployBuildName, parameters: [
string(name: 'REVISION', value: env.BRANCH_NAME),
string(name: 'TAG_NAME', value: env.TAG_NAME)])
// How to wait for a specific input/condition here???
}
stage('Run tests') {
}
stage('Report, cleanup') {
}
}
}
我正在使用带有 wait
条件的 jenkins build step
,但它似乎只能等待作业完成。忽略更改部署作业的状态(我相信,因为未触发构建侦听器):
currentBuild.rawBuild.@result = hudson.model.Result.SUCCESS
问题:
如何正确通知 testing-specific 作业有关 app-deployment 作业中的触发输入?是否有解决此类 'deployment-testing' 问题的标准方法?
目前,除了管道工具之外,我有两种丑陋的方法来检查状态:
- 等待 Tomcat/application 个文件夹中的某些特定文件
- 当触发具有指定 ID 的输入时,可以通过该 ID 访问它的页面,因此我可以 ping 输入的页面直到它 returns 200 状态而不是 404。
一些历史:几年前,有定期的 Jenkins 作业,人们过去常常将它们视为构建块并从另一个触发。这不是很方便,长话短说,管道诞生了。
管道不应该相互触发,因为如果你的两个作业之间有如此多的依赖关系,其中一个必须等待并向另一个发出信号,那么最好将它们视为单个作业的一部分管道。
代码重复是一个问题,但如果您将所有步骤视为更大管道的一部分,则可以解决该问题。与此相符(从您的代码复制粘贴到声明性管道):
pipeline {
agent any
parameters {
string(name: 'REVISION', defaultValue: '')
string(name: 'TAG_NAME', defaultValue: '')
choice(name: 'TEST_SUITE', choices: ['selenium', 'api', 'etc'])
}
stages {
stage('Checkout') {
}
stage('Prepare file system') {
}
stage('Prepare database') {
}
stage('Builds WAR files') {
}
stage('Tomcat deploy') {
agent { label "tomcat" }
steps { script {
sh "$TOMCAT_DIR/bin/startup.sh"
}}}
// start testing
stage('Testing') {
parallel {
stage('Selenium') {
when { equals expected: "selenium", actual: params.TEST_SUITE }}
agent { label "selenium-slave" }
steps {
echo "Doing selenium tests"
}
}
stage('API') {
when { equals expected: "api", actual: params.TEST_SUITE }}
agent { label "api-slave" }
steps {
echo "Doing api tests"
}
}
}
}
stage('Cleanup') {
agent { label "tomcat" }
steps { script {
sh "$TOMCAT_DIR/bin/shutdown.sh"
}}}
}
}
编辑:让你的 'start tomcat' 和 'stop tomcat' 落在完全相同的节点上可能是个问题,但是一点并行化和 post { }
块可以解决这个问题,也是。
我有几个测试项目(API 测试,UI Selenium 测试等),它们测试同一个应用程序。现在,应用程序的步骤。部署在每个詹金斯文件中都是重复的。
目标是有一个共同的 app-deployment 作业,它在服务器上准备应用程序:
- 从特定修订版或标签中获取;
- 定义各种环境变量,如许可证等;
- 生成 WAR 个文件;
- 将它们复制到 Tomcat 构建目录;
- 启动 Tomcat 并等待上下文准备就绪。
我不能在这之后就完成构建,因为 Jenkins 会杀死所有创建的进程,包括启动的 Tomcat。我为 Tomcat 尝试了 doNoKillMe
cookie,但这导致了与重新启动应用程序和数据库连接相关的其他几个问题。因此,当应用程序准备就绪时,我将 input
步骤与 ID 放在一起:
node {
properties([
parameters([
string(name: 'REVISION',
defaultValue: '',
),
string(name: 'TAG_NAME',
defaultValue: ''),
]),
])
withEnv(buildEnvVariables()) {
stage('Checkout') {
}
stage('Prepare file system') {
}
stage('Prepare database') {
}
stage('Builds WAR files') {
}
stage('Tomcat deploy') {
// Delete previous WAR files from Tomcat
// Copy generated files to tomcat
sh "$TOMCAT_DIR/bin/startup.sh"
waitForTokenFileOrFail()
}
input(id: 'IsBuilt', 'Application is ready... ')
}
}
现在,我希望从其他几个 testing-specific jenkins 文件中调用此作业:
node {
properties([
parameters([
string(name: 'TESTS_SUITE',
defaultValue: '',
),
string(name: 'OTHER_PARAM',
defaultValue: ''),
]),
])
withEnv(buildEnvVariables()) {
stage('Checkout') {
}
stage('Stop any running application builds') {
def jenkinsQueue = Jenkins.instance.queue
jenkinsQueue.items.findAll { it.task.name.startsWith(contextDeployBuildName) }.each {
echo "Found pending $contextDeployBuildName job. Cancelling: ${it.getId()}"
jenkinsQueue.doCancelItem(it.getId())
}
Jenkins.instance.getItemByFullName(contextDeployBuildName)
.getAllJobs().first().getBuilds()
?.each { build ->
if (build.isBuilding()) {
try {
echo "Found running $contextDeployBuildName job. Stopping: ${build.number}"
httpRequest(
httpMode: 'POST',
authentication: 'credentialsID',
url: "${JENKINS_URL}job/$contextDeployBuildName/${build.number}/stop")
} catch (any) {
println any.message
}
}
}
}
stage('Build the app') {
build(wait: true, job: contextDeployBuildName, parameters: [
string(name: 'REVISION', value: env.BRANCH_NAME),
string(name: 'TAG_NAME', value: env.TAG_NAME)])
// How to wait for a specific input/condition here???
}
stage('Run tests') {
}
stage('Report, cleanup') {
}
}
}
我正在使用带有 wait
条件的 jenkins build step
,但它似乎只能等待作业完成。忽略更改部署作业的状态(我相信,因为未触发构建侦听器):
currentBuild.rawBuild.@result = hudson.model.Result.SUCCESS
问题:
如何正确通知 testing-specific 作业有关 app-deployment 作业中的触发输入?是否有解决此类 'deployment-testing' 问题的标准方法?
目前,除了管道工具之外,我有两种丑陋的方法来检查状态:
- 等待 Tomcat/application 个文件夹中的某些特定文件
- 当触发具有指定 ID 的输入时,可以通过该 ID 访问它的页面,因此我可以 ping 输入的页面直到它 returns 200 状态而不是 404。
一些历史:几年前,有定期的 Jenkins 作业,人们过去常常将它们视为构建块并从另一个触发。这不是很方便,长话短说,管道诞生了。
管道不应该相互触发,因为如果你的两个作业之间有如此多的依赖关系,其中一个必须等待并向另一个发出信号,那么最好将它们视为单个作业的一部分管道。
代码重复是一个问题,但如果您将所有步骤视为更大管道的一部分,则可以解决该问题。与此相符(从您的代码复制粘贴到声明性管道):
pipeline {
agent any
parameters {
string(name: 'REVISION', defaultValue: '')
string(name: 'TAG_NAME', defaultValue: '')
choice(name: 'TEST_SUITE', choices: ['selenium', 'api', 'etc'])
}
stages {
stage('Checkout') {
}
stage('Prepare file system') {
}
stage('Prepare database') {
}
stage('Builds WAR files') {
}
stage('Tomcat deploy') {
agent { label "tomcat" }
steps { script {
sh "$TOMCAT_DIR/bin/startup.sh"
}}}
// start testing
stage('Testing') {
parallel {
stage('Selenium') {
when { equals expected: "selenium", actual: params.TEST_SUITE }}
agent { label "selenium-slave" }
steps {
echo "Doing selenium tests"
}
}
stage('API') {
when { equals expected: "api", actual: params.TEST_SUITE }}
agent { label "api-slave" }
steps {
echo "Doing api tests"
}
}
}
}
stage('Cleanup') {
agent { label "tomcat" }
steps { script {
sh "$TOMCAT_DIR/bin/shutdown.sh"
}}}
}
}
编辑:让你的 'start tomcat' 和 'stop tomcat' 落在完全相同的节点上可能是个问题,但是一点并行化和 post { }
块可以解决这个问题,也是。