Unauthorised error when publishing java contract to pact flow using jenkins - pom.xml

I have a contract that we can publish to the pact flow broker okay when running mvn pact:publish -Dpactbroker.auth.token=myToken. However, the same contract and maven command gives us an authentication error when running it from Jenkins. Not sure what could be wrong as the step that comes next and does the verification of the contract works successfully and using the same token.
This is the version we're using:
<pact.version>4.2.14</pact.version>
<pact.plugin.version>4.0.10</pact.plugin.version>
<maven.surefire.version>3.0.0-M5</maven.surefire.version>
And here our jenkins file
node {
def git_commit
def mvnHome = tool name: 'maven3.6.0'
stage(name: 'Checkout') {
git credentialsId: ‘someCredentials’, url: “my.git", branch: "$branch_name"
sh "git rev-parse HEAD > commit"
git_commit = readFile('commit').trim()
}
stage(name: 'Compile') {
sh "$mvnHome/bin/mvn clean package -DskipTests"
}
stage(name: 'Pact Generate Contracts') {
sh "$mvnHome/bin/mvn -Dtest=com.hmhco.viaductservice.pact.consumer.*Test test"
}
stage(name: 'Pact Publish Contracts Tests') {
sh "$mvnHome/bin/mvn pact:publish -Dpactbroker.auth.token=myToken”
}
stage(name: 'Pact Verify Tests') {
sh "$mvnHome/bin/mvn -Dpactbroker.auth.token=myToken -Dtest=com.hmhco.viaductservice.pact.provider.*Test test"
}
}

It's working now.
As the publishing step comes from the maven pact jvm plugin we needed to add a way for it to get the token by adding this line to the plugin.
<pactBrokerUrl>https://hmhco.pact.dius.com.au/</pactBrokerUrl>
So now we have
<plugin>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-provider-maven</artifactId>
<version>${pact.plugin.version}</version>
<configuration>
<pactDirectory>target/pacts</pactDirectory>
<pactBrokerUrl>https://hmhco.pact.dius.com.au/</pactBrokerUrl>
<!--suppress UnresolvedMavenProperty -->
<pactBrokerToken>${pactbroker.auth.token}</pactBrokerToken>
<projectVersion>${project.version}</projectVersion>
<trimSnapshot>true</trimSnapshot>
</configuration>
</plugin>

Related

Prevent Archiving In a Jenkins Pipeline

I have asked this question on the Jenkins mailing list.
I have an upstream component, libraryA, I build, archive, and deploy via a Maven job, jobA. This works great. I have a downstream Maven job, jobB, that has a dependency on libraryA. This also works great, except…
I have a completely separate pipeline job, pipelineA specified by Jenkinsfile. Within that Jenkinsfile, I build a specific branch of libraryA I don’t want archived or deployed. In my Jenkinsfile I have “withMaven(mavenLocalRepo: ‘libraryA/.repository’, publisherStrategy: ‘EXPLICIT’)”, and inside that, “sh “””[…]mvn clean package sonar:sonar[…]””” (Any typos here are probably the fault of my typing here as I did not copy-paste. There are no errors from Jenkins when executing these steps.) I have also tried “options: [artifactsPublisher(disabled: true)]” in place of “publisherStrategy: ‘EXPLICIT’” and had the same results. I have verified when pipelineA builds libraryA, it does NOT get deployed to my remote Maven repository, and I expect it not to get deployed there. Good.
So, what happens?
Well, if I build pipelineA followed by jobB, jobB gets its copy of libraryA from pipelineA, causing the build to fail. If I then run jobA, jobB succeeds as expected.
I could change the version of libraryA in the branch pipelineA builds, but I’d rather not do that as it’s not correct for my particular use case. What else could I do? What did I miss? (I do not admin this Jenkins instance, so my access is limited in that respect.)
For clarity here is an approximation of the pipeline's Jenkinsfile:
#!groovy
pipeline {
environment {
GIT_CREDENTIAL_ID = 'git_credential_name'
}
agent any
tools {
maven 'internal_maven'
jdk 'openjdk'
git 'internal_git'
}
stages {
stage('Build Parent') {
steps {
checkoutRepos([[checkoutDir: 'parent', branch: 'gold', url: 'ssh://git#fake-git-url/parent.git']], env.GIT_CREDENTIAL_ID)
withMaven(publisherStrategy: 'EXPLICIT') {
sh """
cd parent
mvn -U clean verify
"""
}
stash name: 'parent', includes: 'pom.xml'
}
}
stage('Build libraryParent') {
steps {
unstash 'parent'
checkoutRepos([[checkoutDir: 'libraryParent', branch: 'gold', url: 'ssh://git#fake-git-url/libraryParent.git']], env.GIT_CREDENTIAL_ID)
withMaven(mavenLocalRepo: 'libraryParent/.repository', publisherStrategy: 'EXPLICIT') {
sh """
mvn install:install-file -Dpackaging=pom -Dfile=pom.xml -DpomFile=pom.xml
cd libraryParent
mvn clean verify -P jacoco sonar:sonar -U -Dsonar.host.url=https://fake-sonar-url -Dsonar.scm.provider=git
"""
}
dir('libraryParent/libraryA/target/') {
stash name: 'libraryA', includes: 'libraryA-1000-SNAPSHOT.jar'
}
}
}
stage('Build appA') {
steps {
sonarAnApp 'appA'
}
}
stage('Build appB') {
steps {
sonarAnApp 'appB'
}
}
stage('Build appC') {
steps {
sonarAnApp 'appC'
}
}
}
}
def sonarAnApp(final String appName) {
unstash 'parent'
unstash 'libraryA'
checkoutRepos([[checkoutDir: appName, branch: 'gold', url: "ssh://git#fake-git-url/${appName}.git"]], env.GIT_CREDENTIAL_ID)
withMaven(mavenLocalRepo: "$appName/.repository", publisherStrategy: 'EXPLICIT') {
sh """
mvn install:install-file -Dpackaging=pom -Dfile=pom.xml -DpomFile=pom.xml
mvn install:install-file -Dfile=libraryA-1000-SNAPSHOT.jar
cd $appName
mvn clean verify -P jacoco sonar:sonar -U -Dsonar.host.url=https://fake-sonar-url -Dsonar.scm.provider=git
"""
}
}

Terraform cannot pull modules as part of jenkins pipeline

I have a jenkinsfile that was working and able to deploy some infrastructure automatically with terraform. Unfortunately after adding a terraform module with a git source it stopped working with the following error:
+ terraform init -input=false -upgrade
Upgrading modules...
- module.logstash
Updating source "git::https://bitbucket.org/*****"
Error downloading modules: Error loading modules: error downloading 'https://bitbucket.org/*****': /usr/bin/git exited with 128: Cloning into '.terraform/modules/34024e811e7ce0e58ceae615c545a1f8'...
fatal: could not read Username for 'https://bitbucket.org': No such device or address
script returned exit code 1
The urls above were obfuscated after the fact. Below is the cut down module syntax:
module "logstash" {
source = "git::https://bitbucket.org/******"
...
}
Below is the Jenkinsfile:
pipeline {
agent {
label 'linux'
}
triggers {
pollSCM('*/5 * * * *')
}
stages {
stage ('init') {
steps {
sh 'terraform init -input=false -upgrade'
}
}
stage('validate') {
steps {
sh 'terraform validate -var-file="production.tfvars"'
}
}
stage('deploy') {
when {
branch 'master'
}
steps {
sh 'terraform apply -auto-approve -input=false -var-file=production.tfvars'
}
}
}
}
I believe this to be a problem with terraform internally using git to checkout the module but Jenkins has not configured the git client within the pipeline job itself. Preferably I would be able to somehow pass the credentials used by the multibranch pipeline job into the job itself and configure git but I am at a loss of how to do that. Any help would be appreciated.
So I found a non-ideal solution that requires you to specify the credentials inside your Jenkinsfile rather than automatically using the credentials used by the job for checkout.
withCredentials([usernamePassword(credentialsId: 'bitbucketcreds', passwordVariable: 'GIT_PASS', usernameVariable: 'GIT_USER')]) {
sh "git config --global credential.helper '!f() { sleep 1; echo \"username=${env.GIT_USER}\\npassword=${env.GIT_PASS}\"; }; f'"
sh 'terraform init -input=false -upgrade'
sh 'git config --global --remove-section credential'
}
The trick is to load the credentials into environment variables using the withCredentials block and then I used the answer from this question to set the credential helper for git to read in those creds. You can then run terraform init and it will pull down your modules. Finally it clears the modified git settings to hopefully avoid contaminating other builds. Note that the --global configuration here is probably not a good idea for most people but was required for me due to a quirk in our Jenkins agents.
If anyone has a smoother way of doing this I would be very interested in hearing it.

How to copy Jenkins config files in a jenkins pipeline to Web server

I have some files.properties in Jenkins config File that I need to copy to a server during the jenkins pipeline.
pipeline code is more a less as showed, just to get an idea.
How can I add a step that copy this config file from jenkins on a destination server after las step after step DEPLOY WAR TO SERVER in pipeline like for example : "sh Scp file.properties jenkins#destinationserver:/destination/path/file.properties"
code {
stage ('Code Checkout') {
git branch: 'master',
credentialsId: 'b346fbxxxxxxxxxxxxxxxxxxx',
url: 'https://xxxxxxx#bitbucket.org/gr/code.git'
}
stage ('Check Branch') {
sh 'git branch'
}
stage('Compile and Build WAR') {
sh 'mvn clean compile war:war'
stage ('Deploy WAR to server') {
sh "scp .war jenkins#serverIp:/var/lib/tomcat/.war"
}
This is quite easy. You need to install the Config File Provider Plugin and then you can generate the appropriate line by visiting htts://localhost/jenkins/pipeline-syntax/. From there in the dropdown you can choose configFileProvider and fill the rest of the form.
The end result will be something like this:
configFileProvider(
[configFile(fileId: 'maven-settings-or-a-UUID-to-your-config-file', variable: 'MAVEN_SETTINGS')]) {
sh 'mvn -s $MAVEN_SETTINGS clean package'
}

How to change a Jenkins Declarative Pipeline environment variable?

I'm trying to create some Docker images. For that I want to use the version number specified in the Maven pom.xml file as tag. I am however rather new to the declarative Jenkins pipelines and I can't figure out how to change my environment variable so that VERSION contains the right version for all stages.
This is my code
#!groovy
pipeline {
tools {
maven 'maven 3.3.9'
jdk 'Java 1.8'
}
environment {
VERSION = '0.0.0'
}
agent any
stages {
stage('Checkout') {
steps {
git branch: 'master', credentialsId: '290dd8ee-2381-4c5b-8d33-5631d03ee7be', url: 'git#gitlab.crosslang.local:company/SOME-API.git'
sh "git clean -f && git reset --hard origin/master"
}
}
stage('Build and Test Java code') {
steps {
script {
def pom = readMavenPom file: 'pom.xml'
VERSION = pom.version
}
echo "${VERSION}"
sh "mvn clean install -DskipTests"
}
}
stage('Build Docker images') {
steps {
dir('whales-microservice/src/main/docker'){
sh 'cp ../../../target/whales-microservice-${VERSION}.jar whales-microservice.jar'
script {
docker.build "company/whales-microservice:${VERSION}"
}
}
}
}
}
}
The problem is the single quote of the statement
sh 'cp ../../../target/whales-microservice-${VERSION}.jar whales-microservice.jar'
single quotes don't expand variables in groovy: http://docs.groovy-lang.org/latest/html/documentation/#_string_interpolation
so you have to double quote your shell statement:
sh "cp ../../../target/whales-microservice-${VERSION}.jar whales-microservice.jar"
I just wanted to mention that if you have pipeline-utility-steps plugin installed you can use readMavenPom() in the environment part, too. It looks like this:
environment {
VERSION = readMavenPom().getVersion()
}

Get gradle variables in jenkins pipeline script

I'm trying to migrate my build pipelines to the "Pipeline plugin" using the groovy build scripts.
My pipelines are usually:
Test (gradle)
IntegrationTest (gradle)
Build (gradle)
Publish (artifactory)
I would like to use the gradle variables like version/group etc. in my jenkins build script to publish to the correct folders in artifactory. Something the artifactory plugin would take care of for me in the past. How can this be achieved?
For a single gradle project I use something like this:
node('master')
{
def version = 1.0
def gitUrl = 'some.git'
def projectRoot = ""
def group = "dashboard/frontend/"
def artifactName = "dashboard_ui"
def artifactRepo = "ext-release-local"
stage "git"
git branch: 'develop', poll: true, url: "${gitUrl}"
dir(projectRoot)
{
sh 'chmod +x gradlew'
stage "test"
sh './gradlew clean test'
stage "build"
sh './gradlew build createPom'
stage "artifact"
def server = Artifactory.server('artifactory_dev01')
def uploadSpec = """{
"files": [
{
"pattern": "build/**.jar",
"target": "${artifactRepo}/$group/${artifactName}/${version}/${artifactName}-${version}.jar"
},
{
"pattern": "pom.xml",
"target": "${artifactRepo}/$group/${artifactName}/${version}/${artifactName}.pom"
}
]
}"""
def buildInfo1 = server.upload spec: uploadSpec
server.publishBuildInfo buildInfo1
}
}
For future reference here an example with the more modern declarative pipeline:
pipeline {
agent any
stages {
stage('somestage') {
steps {
script {
def version = sh (
script: "./gradlew properties -q | grep \"version:\" | awk '{print \$2}'",
returnStdout: true
).trim()
sh "echo Building project in version: $version"
}
}
}
}
}
see also:
Gradle plugin project version number
How to do I get the output of a shell command executed using into a variable from Jenkinsfile (groovy)?
I think you actually have two different approaches to tackle this problem :
1. Get version/group from sh script
Find a way to get Gradle version from gradle build tool (e.g. gradle getVersion(), but I'm not familiar with Gradle) and then use shell script to get this version. If Gradle command to get the version is gradle getVersion(), you would do in your pipeline :
def projectVersion = sh script: "gradle getVersion()", returnStdout: true
def projectGroup= sh script: "gradle getGroup()", returnStdout: true
and then just inject your $projectVersion and $projectGroup variables in your current pipeline.
2. Configure your Gradle build script to publish to Artifactory
This is the reverse approach, which I personnaly prefer : instead of giving Artifactory all your Gradle project information, juste give Gradle your Artifactory settings and use Gradle goal to easily publish to Artifactory.
JFrog has a good documentation for this solution in their Working with Gradle section. Basically, you will follow the following steps :
Generate a compliant Gradle build script from Artifactory using Gradle Build Script Generator and include it to your project build script
Use Gradle goal gradle artifactoryPublish to simply publish your current artifact to Artifactory
For others who Google'd their way here, if you have the Pipeline Utility Steps plugin and store what you need in your gradle.properties file, you can do something like this in the environment block:
MY_PROPS = readProperties file:"${WORKSPACE}/gradle.properties"
MY_VERSION = MY_PROPS['version']

Resources