web-dev-qa-db-fra.com

Est-il impossible de commander une autre branche dans Jenkinsfile?

J'ai deux branches sur BitBucket: master et develop. J'ai également un travail de dossier d'équipe BitBucket configuré sur mon serveur Jenkins pour construire ce référentiel. Le fichier Jenkins suivant se trouve sur la branche develop:

node {
    stage('Checkout') {
        checkout scm
    }

    stage('Try different branch') {
        sh "git branch -r"
        sh "git checkout master"
    }
}

Lorsque Jenkins l’exécute, la construction échoue lorsqu’il tente d’extraire master:

[Pipeline] stage
[Pipeline] { (Try different branch)
[Pipeline] sh
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running Shell script
+ git branch -r
  Origin/develop
[Pipeline] sh
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running Shell script
+ git checkout master
error: pathspec 'master' did not match any file(s) known to git.
[Pipeline] }

Je m'attendais à ce que la commande git branch -r imprime à la fois Origin/master et Origin/develop, mais pour une raison quelconque, elle n’imprime que le dernier.

J'ai lu quelque chose et essayé de trouver un moyen de faire cela: Par exemple, j'ai essayé d'installer le plug-in d'agent SSH pour Jenkins et modifié le fichier Jenkins en tant que:

node {
    stage('Checkout') {
        checkout scm
    }

    stage('Try different branch') {
        sshagent(['Bitbucket']) {
            sh "git branch -r"
            sh "git checkout master"
        }
    }
}

Mais il ne semble toujours pas trouver Origin/master. Pire encore, l'agent SSH semble être tué avant de tenter de passer à la caisse master:

[Pipeline] { (Try different branch)
[Pipeline] sshagent
[ssh-agent] Using credentials ThomasKasene (Used to communicate with Bitbucket)
[ssh-agent] Looking for ssh-agent implementation...
[ssh-agent]   Exec ssh-agent (binary ssh-agent on a remote machine)
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-M6pIguCUpAV4/agent.11899
SSH_AGENT_PID=11902
$ ssh-add /var/jenkins_home/workspace/e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA@tmp/private_key_2394129657382526146.key
Identity added: /var/jenkins_home/workspace/e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA@tmp/private_key_2394129657382526146.key (/var/jenkins_home/workspace/e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA@tmp/private_key_2394129657382526146.key)
[ssh-agent] Started.
[Pipeline] {
[Pipeline] sh
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running Shell script
+ git branch -r
  Origin/develop
[Pipeline] sh
$ ssh-agent -k
unset SSH_AUTH_SOCK;
unset SSH_AGENT_PID;
echo Agent pid 11902 killed;
[ssh-agent] Stopped.
[e_jenkinsfile-tests_develop-4R65E2H6B73J3LB52BLACQOZLBJGN2QG22IPONX3CV46B764LAXA] Running Shell script
+ git checkout master
error: pathspec 'master' did not match any file(s) known to git.
[Pipeline] }

Mon plan éventuel est d’engager quelque chose dans develop et de le fusionner ensuite en master, mais j’ai eu très peu de chance jusqu’à présent. Quelqu'un at-il une solution possible ou une solution de contournement?

PS: Cela semble seulement être un problème dans Jenkinsfile; J'ai un job de freestyle qui fait quelque chose de similaire à ce que je veux, et ça marche bien.

8
Thomas Kåsene

Après quelques heures d’essais et d’erreurs, j’ai trouvé une solution possible. Cela repose en partie sur la réponse de Matt, mais je devais la modifier pour que cela fonctionne.

Matt avait raison dans l'essentiel: checkout scm n'était tout simplement pas assez flexible pour me permettre de faire ce dont j'avais besoin, alors j'ai dû utiliser GitSCM pour le personnaliser. Les principaux points d'intérêt sont:

  • Ajout de l'extension LocalBranch pour m'assurer que je consulte une succursale réelle, et pas seulement une HEAD détachée.
  • Extension ajoutée WipeWorkspace pour tout supprimer dans l'espace de travail et forcer un clone complet. Je ne pense pas que cela faisait partie de la solution à ma question, mais c'était quand même pratique.
  • Spécifiez les informations d'identification SSH à l'aide de la propriété credentialsId car le référentiel est privé.

Pour une raison quelconque, lorsque l'étape checkout est exécutée, elle extrait uniquement la branche, mais ne la configure pas pour suivre la branche distante. Jusqu'à ce que je trouve une solution plus élégante, je devais le faire manuellement.

Après tout ce qui a été fait, je pouvais utiliser des sh "git checkout master" et même des sh "git Push" réguliers, à condition de les inclure dans une étape sshagent.

J'ai ajouté un exemple de travail du fichier Jenkins résultant ci-dessous, mais n'oubliez pas qu'il ne devrait pas être utilisé pour des applications proches de la production, car il en est encore à ses balbutiements; numéros de version codés en dur et pas de vérification de la branche dans laquelle vous vous trouvez, par exemple.

node {
    mvnHome = tool 'Maven'
    mvn = "${mvnHome}/bin/mvn"

    stage('Checkout') {
        checkout([
            $class: 'GitSCM',
            branches: scm.branches,
            extensions: scm.extensions + [[$class: 'LocalBranch'], [$class: 'WipeWorkspace']],
            userRemoteConfigs: [[credentialsId: 'Bitbucket', url: '[email protected]:NAVFREG/jenkinsfile-tests.git']],
            doGenerateSubmoduleConfigurations: false
        ])
    }

    stage('Release') {
        // Preparing Git
        sh "git branch -u Origin/develop develop"
        sh "git config user.email \"[email protected]\""
        sh "git config user.name \"Jenkins\""

        // Making and committing new verison
        sh "${mvn} versions:set -DnewVersion=2.0.0 -DgenerateBackupPoms=false"
        sh "git commit -am \"Released version 2.0.0\""

        // Merging new version into master
        sh "git checkout master"
        sh "git merge develop"
        sh "git checkout develop"

        // Making and committing new snapshot version
        sh "${mvn} versions:set -DnewVersion=3.0.0-SNAPSHOT -DgenerateBackupPoms=false"
        sh "git commit -am \"Made new snapshot version 3.0.0-SNAPSHOT\""

        // Pushing everything to remote repository
        sshagent(['Bitbucket']) {
            sh "git Push"
            sh "git checkout master"
            sh "git Push"
        }
    }
}
8
Thomas Kåsene

Vous pouvez utiliser la fonction intrinsèque du pipeline Jenkins créée pour le clonage et l'extraction de Git. Je suggérerais également de cloner les branches dans des répertoires séparés.

checkout([$class: 'GitSCM',
  branches: [[name: '*/branch_name']],
  doGenerateSubmoduleConfigurations: false,
  extensions: [[$class: 'RelativeTargetDirectory',
    relativeTargetDir: 'different_directory']],
  submoduleCfg: [],
  userRemoteConfigs: [[url: '[email protected]:org/repo.git']]])
4
Matt Schuchard

Je ne pouvais pas obtenir les deux réponses ci-dessus au travail. Je déclenchais un travail de pipeline Jenkins en spécifiant une branche et j'essayais de vérifier une autre branche (développer) dans le travail qui échouait avec:

error: pathspec 'develop' did not match any file(s) known to git.

Je pouvais le voir dans le travail en échec, qui indiquait que seule la branche de déclenchement était extraite:

git fetch --no-tags --progress https://<github URL> +refs/heads/branch-name:refs/remotes/Origin/branch-name

Je l'ai obtenu en changeant la configuration d'extraction à distance et en récupérant toutes les branches en procédant comme suit après avoir effectué uniquement l'étape checkout scm par défaut dans le fichier Jenkins du travail déclenché:

sh """
    git config remote.Origin.fetch '+refs/heads/*:refs/remotes/Origin/*'
    git fetch --all
"""

C'est grâce à cette réponse https://stackoverflow.com/a/39986737/1988883

Cela évite également de devoir configurer Jenkins pour les approbations de script GitSCM ce que je devais faire pour essayer les deux solutions ci-dessus.

2
swoop81

Le problème est que Jenkins définit la Origin avec uniquement la branche découverte.

La réponse de @ swoop81 fonctionne, mais si vous souhaitez simplement passer à la caisse d'une branche, vous pouvez ne récupérer que celle-ci.

git config --add remote.Origin.fetch +refs/heads/<branch-name>:refs/remotes/Origin/<branch-name>
git fetch --no-tags https://<github-url> +refs/heads/<branch-name>:refs/remotes/Origin/<branch-name>
0
D0m3