简体   繁体   中英

Jenkins multibranch pipeline triggers pipeline on unrelated branches

I have a problem with Jenkins multibranch pipleline using JenkinsFile and the GIT plugin.

The problem is that every push to staging branch triggers the pipeline of master as well. The desired behavior is that push to staging branch only triggers the pipleine for staging, and push to master branch only triggers the pipeline for master

This is my JenkinsFile

#!/usr/bin/env bash
pipeline {
    agent any
    triggers {
        pollSCM('*/1 * * * *')
    }
    environment {
        GCLOUD_PATH="/var/jenkins_home/GoogleCloudSDK/google-cloud-sdk/bin"
    }
    stages {
        stage('Git Checkout'){
            steps{
              // Clean Workspace
              cleanWs()
              // Get source from Git
              git branch: 'staging', 
                credentialsId: ****', 
                url: 'git@github.com:***/****.git'
            }    
        }
        stage('Update Staging') {
            when {
                branch 'staging'
            }
            environment{
                INSTANCE="***"        
            }
            steps {
                sshagent(credentials : ['****']) {
                    sh 'ssh -tt -o StrictHostKeyChecking=no jenkins@"${INSTANCE}" sudo /opt/webapps/****/deploy.sh firstinstance'
                }
            }
        }
        stage('Update Production') {
            when {
                branch 'master'
            }
            environment{
                gzone="us-central1-a"
            }
            steps {
                    sh '''
                        #!/bin/bash
                        echo "${BRANCH_NAME}"
                        export instances=$("${GCLOUD_PATH}"/gcloud compute instances list --filter="status:(running) AND tags.items=web" --format="value(name)")
                        FIRST=1
                        for instance in ${instances}
                        do
                            echo "### Running Instance: ${instance} ###"
                            if [[ $FIRST == 1 ]]; then
                                echo "first instance"
                                ${GCLOUD_PATH}/gcloud compute ssh jenkins@${instance} --zone ${gzone} '--ssh-flag=-tt -i /root/.ssh/id_rsa -o StrictHostKeyChecking=no' --command="echo first"
                            else
                                ${GCLOUD_PATH}/gcloud compute ssh jenkins@${instance} --zone ${gzone} '--ssh-flag=-tt -i /root/.ssh/id_rsa -o StrictHostKeyChecking=no' --command="sudo uptime"
                            fi
                            FIRST=0
                        done
                    '''

            }
        }
    }
    post {
        success {
            cleanWs()
        }
    }

}

I'll share some logs: The is a log for master branch

http://34.69.57.212:8080/job/tinytap-server/job/master/2/pollingLog/  returns
Started on Dec 10, 2019 1:42:00 PM
Using strategy: Specific revision
[poll] Last Built Revision: Revision 12ecdbc8d2f7e7ff1f578b135ea0b23a28d7672d (master)
using credential ccb9a735-04d9-4aab-8bab-5c86fe0f363c
 > git --version # timeout=10
using GIT_ASKPASS to set credentials 
 > git ls-remote -h -- https://github.com/tinytap/tinytap-web.git # timeout=10
Found 222 remote heads on https://github.com/tinytap/tinytap-web.git
[poll] Latest remote head revision on refs/heads/master is: 12ecdbc8d2f7e7ff1f578b135ea0b23a28d7672d - already built by 1
Using strategy: Default
[poll] Last Built Revision: Revision f693e358ce14bc5dfc6111e62ed88e6dd1d0dfc9 (refs/remotes/origin/staging)
using credential 17f45a89-da78-4969-b18f-cb270a526347
 > git --version # timeout=10
using GIT_SSH to set credentials jenkins key
 > git ls-remote -h -- git@github.com:tinytap/tinytap-web.git # timeout=10
Found 222 remote heads on git@github.com:tinytap/tinytap-web.git
[poll] Latest remote head revision on refs/heads/staging is: 907899a0e7e131e9416ee65aad041c8da111e2fe
Done. Took 1 sec 
Changes found 

The is a log for master branch, but only staging had a new commit :

http://34.69.57.212:8080/job/tt-server/job/master/3/pollingLog/    returns
Started on Dec 10, 2019 1:55:00 PM
Using strategy: Specific revision
[poll] Last Built Revision: Revision 12ecdbc8d2f7e7ff1f578b135ea0b23a28d7672d (master)
using credential ****-****-****-****-5c86fe0f363c
 > git --version # timeout=10
using GIT_ASKPASS to set credentials 
 > git ls-remote -h -- https://github.com/tt/tt-web.git # timeout=10
Found 222 remote heads on https://github.com/tt/tt-web.git
[poll] Latest remote head revision on refs/heads/master is: 12ecdbc8d2f7e7ff1f578b135ea0b23a28d7672d - already built by 2
Using strategy: Default
[poll] Last Built Revision: Revision 907899a0e7e131e9416ee65aad041c8da111e2fe (refs/remotes/origin/staging)
using credential ****-****-****-****-cb270a526347
 > git --version # timeout=10
using GIT_SSH to set credentials jenkins key
 > git ls-remote -h -- git@github.com:tt/tt-web.git # timeout=10
Found 222 remote heads on git@github.com:tt/tt-web.git
[poll] Latest remote head revision on refs/heads/staging is: eab6e8bc6d8586084e9fe9856dec7fd8b31dd098
Done. Took 0.98 sec 
Changes found 

Notice "changes found" even though head did not change on master branch

Jenkins ver. 2.190.1 Git plugin ver 4.0.0 Git client plugin ver 2.9.0

I use this plugin - https://github.com/lachie83/jenkins-pipeline and it works fine for me. You need to have separate if blocks for each branch and then the stage block inside it. Example below:

#!/usr/bin/groovy

@Library('https://github.com/lachie83/jenkins-pipeline@master')

def pipeline = new io.estrado.Pipeline()
def cloud = pipeline.getCloud(env.BRANCH_NAME)
def label = pipeline.getPodLabel(cloud)

// deploy only the staging branch
if (env.BRANCH_NAME == 'staging') {
    stage ('deploy to k8s staging') {
      //Deploy to staging
    }
}
// deploy only the master branch
if (env.BRANCH_NAME == 'master') {
    stage ('deploy to k8s production') {
      //Deploy to production
    }
}

I think you have some logical omissions in your Jenkinsfile. As it currently stands, you poll SCM for changes. If any change is detected, first stage 'Git Checkout' will checkout staging branch (always). Then you have another stage which does something if the branch is 'staging' (which it is, because it's hardcoded to checkout that branch above) etc. This will be the first thing to fix - if SCM changes are detected, checkout the right branch. How - there are a few options. I usually use 'skipDefaultCheckout()' in 'options' together with explicit checkout in my first pipeline stage:

        steps {
            sshagent(['github-creds']) {
                git branch: "${env.BRANCH_NAME}", credentialsId: 'github-creds', url: 'git@github.com:x/y.git'
            }
        }

The second thing is that you try to squeeze handling two different branches into a single Jenkinsfile. This is not how it should be done. Jenkins wil use Jenkinsfile from a given branch - just make sure Jenkinsfile on staging contains what you want it to contain, same with Jenkinsfile on master.

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM