Jenkins声明性管道:如何始终从Github检查最新的提交,如果已经安排了,不要安排新的工作?

xam8gpfp  于 4个月前  发布在  Git
关注(0)|答案(1)|浏览(78)

我们有一些Jenkins工作,在构建之前检查多个github仓库;一个单独的构建可能需要一个小时或更长时间。如果有什么变化,我们希望安排新的构建,但目前Jenkins正在安排太多的构建。我们已经设置了一个SCM轮询后,每10分钟,它安排一个新的运行作业每10分钟,即使已经有5个相同的作业在队列中等待.切换到git后,看起来情况变得更糟了,而svn并没有那么糟糕.
我们的愿望在我看来是卑微的:
1.如果一个工作已经在等待名单上,不要安排新的工作。
1.运行作业时,始终从所有存储库中检出最新提交,以适应所有更改。
有没有可能用Jenkins声明式管道来实现这一点?我试图通过在互联网上找到的localBranch: '**'技巧来解决2),但不确定它是否有效,也许它使1)更糟。我们的管道草图看起来像:

pipeline {
    agent {
        label 'BuildWin6'
    }
    triggers {
        pollSCM '*/10 * * * *'
    }
    
    stages {
        stage('Checkout') {
            steps {
                dir('production') {
                    checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [[$class: 'LocalBranch', localBranch: '**']], userRemoteConfigs: [[credentialsId: 'b342365f-2641-4fe7-a77d-e4378431434f', url: '[email protected]:Company/Project']]])
                }
                dir('test-core') {
                    checkout([$class: 'GitSCM', branches: [[name: '*/main']], extensions: [[$class: 'LocalBranch', localBranch: '**']], userRemoteConfigs: [[credentialsId: 'b342365f-2641-4fe7-a77d-e4378431434f', url: '[email protected]:Company/Project-test-core.git']]])
                }
            }
        }
        // ...
    }
    // ...
}

字符串
感谢任何提示!

ntjbwcob

ntjbwcob1#

我自己回答我的问题。我无法让Jenkins pipeline triggers机制做我想要的事情,无论是pollSCM还是upstream。相反,我通过试验Groovy发现它通过Hudson.instance.queue.getItems()item.getTask().getName()暴露了所需的信息。后者似乎报告了屏幕上显示的相同构建队列行,例如part of MyJobName #243,从那里我可以看到一个作业是否在构建队列中。
所以,我现在的解决方案是添加一个单独的Jenkins作业,它每10分钟运行一次,从各种repos中检查是否有新的提交,并触发所需的作业。这个触发作业必须在一个特定的单独节点上运行,该节点不运行任何其他长作业,以确保它确实每10分钟运行一次。

pipeline {
    agent {
        label 'node1'
    }
    triggers {
        cron('*/10 * * * *')
    }
    options {
        buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '1'))
    }
    
    stages {
        stage('Working') {
            steps {
                script {
                    def text = "";
                    for (job in Hudson.instance.queue.getItems()) {
                        text = text.concat("${job.getTask().getName()}\n")
                    }
                    println "Current build queue:\n${text}"
                    writeFile file: 'jenkins-queue.txt', text: "${text}"
                }
                
                sh '''
set +x
URL1='https://github.com/MyCompany/Project1'
URL2='https://github.com/MyCompany/Project2'
URL3='http://svnrepos/code/Projects/Project3/trunk/Production'
URL4='http://svnrepos/code/Projects/Project4/trunk/Production'

BRANCH1='main'
BRANCH2='main'

HASH1=`git ls-remote $URL1 $BRANCH1 | awk '{print $1}'`
HASH2=`git ls-remote $URL2 $BRANCH2 | awk '{print $1}'`
HASH3=`svn info --show-item last-changed-revision $URL3`
HASH4=`svn info --show-item last-changed-revision $URL4`

LINE="$HASH1 $HASH2 $HASH3 $HASH4"
echo "Repo state: $LINE"

if [ -z "$HASH1" ] || [ -z "$HASH2" ] || [ -z "$HASH3" ] || [ -z "$HASH4" ]; then
    echo "Could not retrieve repo state"
    exit 1
fi

JOBS="MyJobName1 MyJobName2 MyJobName3"

rm -f jenkins-trigger.txt
touch jenkins-trigger.txt

for JOB in $JOBS; do
    touch "$JOB.triggered"

    if fgrep -q "$LINE" "$JOB.triggered"; then
        echo "Job already triggered for this repo state: $JOB"
    else
        if egrep -qw "$JOB" jenkins-queue.txt; then
            echo "Job already in Jenkins build queue, marking as triggered: $JOB"
            echo "$LINE" > "$JOB.triggered"
        else
            echo "Triggering job: $JOB"
            echo "$JOB" >> jenkins-trigger.txt
            echo "$LINE" > "$JOB.triggered"
        fi
    fi
done
                '''
                
                script {
                    def text2 = readFile('jenkins-trigger.txt')
                    def lines = text2.readLines()
                    for (line in lines) {                                            
                        println "Triggering job: ${line}"
                        build(job: "${line}", wait: false)
                    }
                }
            }       
        }
    }
}

字符串
当然,中间部分也可以用Groovy编写,我敢肯定。
为了触发级联作业,前一个作业最终可以做类似的事情:

pipeline {
   // ... ...

    post {
        success {
            script {
                def triggerNextJob = true;
                for (job in Hudson.instance.queue.getItems()) {
                    def line = "${job.getTask().getName()}";
                    println "In build queue: ${line}"
                    def pos = line.indexOf("MyNextJobName1");
                    if (pos != -1) {
                        println "Next build already in queue, will not trigger: MyNextJobName1"
                        triggerNextJob = false;
                    }
                }
                if (triggerNextJob) {
                    println "Triggering next job: MyNextJobName1"
                    build(job: "MyNextJobName1", wait: false)
                }
            }
        }
    }
}

相关问题