0

Background

My team wants to update several linting rules in our project, however, doing so will cause our Jenkins build pipeline which lints, tests and builds each feature branch to break. We don't want to lose the value of linting each feature branch before merging, so we agree that linting only the files that the feature branch changes is a reasonable way to introduce these new lint rules without forcing us to re-lint the whole project up-front. Given that our entire project is already linted, this seems like a reasonable move.

A while ago I wrote a git tool to do exactly this. It determines which files have changed since the feature branch diverged from master and outputs those files so they can be consumed by eslint, pycodestyle and other linters. Here's the source if you're interested in how this is done.

Problem

Jenkins declarative build process and it's GitHub Branch Source Plugin seem to have a brittle checkout behavior that can't be modified to checkout more than just the feature branch that it's called on to build.

If I call git fetch origin stage within a build step, Jenkins complains about missing credentials. I don't feel comfortable sticking in credentials into my pipeline file, I'd MUCH prefer to continue using the Git plugin to manage credentials to our private github repo and pull branches, however, I'm at a loss as to how to specify for it to fetch more than just the feature branch.

For reference, here's the relevant portions of my Jenkinsfile

As you can see, I've tried adding the GitSCM code block to no avail. I've read this medium article which solves a similar problem, but I'm not using SSH credentials and I'd prefer not to given than we're already managing credentials using the Git plugin.

pipeline {
  agent any
  tools {
    nodejs 'node12.7.0'
  }
  stages {
    stage('checkout') {
      steps {
        checkout([
          $class: 'GitSCM',
          branches: [[name: '*']],
          extensions: scm.extensions,
          userRemoteConfigs: [],
          doGenerateSubmoduleConfigurations: true
        ])
      }
    }
    stage('install') {
      steps {
        script {
          sh 'git config --add remote.origin.fetch +refs/heads/master:refs/remotes/origin/master'
          sh 'yarn install'
        }
      }
    }
    stage('lint & test') {
      failFast true
      parallel {
        stage('lint') {
          when {
            not {
              anyOf {
                branch 'stage'; branch 'int'; branch 'prod'
              }
            }
          }
          steps {
            script {
              sh """
                git submodule update --init
                yarn run lint
              """
            }
          }
        }
        ...
      }
    }
    stage('deploy') {...}
    }
  }
  post {
    failure {
      notifySlack()
    }
  }
}
CodeOcelot
  • 3,403
  • 3
  • 22
  • 23
  • If you don’t want to use SSH, you can use a `username:password` credential by specifying the appropriate credential ID from your Jenkins credential store and GitHub `http(s)://` URL with `userRemoteConfigs: [[credentialsId: '', url: '']]`. See https://stackoverflow.com/a/56581645/8895640. – Dibakar Aditya Sep 08 '19 at 14:06

2 Answers2

1

One frequent root cause - mentioned on the referenced medium article, too - is that Jenkins only checks out the current branch that needs to be build.

An easy option I just found to have other project branches available is to

  • Configure your pipeline job
  • Under Behaviors->General, add Specify ref specs
  • Optionally adjust the parameter to the refs you need, e.g. the branches to compare to. Or you can get all branches by maintaining the default +refs/heads/*:refs/remotes/@{remote}/* as shown in the screenshot: Jenkins Pipeline Job - Ref Config

P.S.: This seems to be part of the GIT Jenkins plugin, but I couldn't find it in the docs...

jkd3v
  • 11
  • 2
0

Create credential in your Jenkins with ssh key and private key, which can be added to the checkout userRemoteConfigs which will be used while checking out (Value given down just an example of one the credential id in my Jenkins environment)

userRemoteConfigs: [[credentialsId: '7969s7612-adruj-au2cd-492msa802f']]