How to set SDK release when using Bitbucket repository integration - bitbucket

I have installed Bitbucket integration on sentry and used the Bitbucket pipeline to automatically notify and associate releases with commits as described here
I have also set up source maps to be uploaded as seen below:
sentry-cli releases files $BITBUCKET_COMMIT upload-sourcemaps build
The Bitbucket pipeline and the source map upload both use the $BITBUCKET_COMMIT as the identifier.
I am trying to figure out how to configure the SDK release to use this variable as my current set up is below:
if (process.env.NODE_ENV.toString().toLowerCase() === 'production') {
Sentry.init({
dsn: process.env.REACT_APP_SENTRY_DSN,
});
}

I found out how to do this. The BITBUCKET_COMMIT is an environment variable available in the bitbucket pipeline during build so I made this available to my docker container by passing it as an argument in the Docker build step.
docker build --build-arg release=$BITBUCKET_COMMIT
I could then make the passed variable available to my React build command through the DockerFile
//DockerFile
ENV BITBUCKET_COMMIT=$release
Then within my package.json I set the variable during build
"build": "REACT_APP_SENTRY_DSN=$BITBUCKET_COMMIT"

Related

Problems transferring build artifacts from Jenkins running in a docker container

I'm a little bit of a newb, with this CI/CD container stuff so please correct me anywhere I'm wrong.
I can't seem to find out how to send by npm build files created on my jenkins instance (workspace) to a remote server. I have a pipeline that successfully pulls in my github repo, does all my fun npm stuff (npm install, test, build). I see my build dir in my jenkins instance /workspace.
My environment is as follows. We have a server where docker (with Portainer) is installed. Jenkins is running in a container with a volume mounted (my react build dir goes here). No issues with the pipeline or building etc. I just can't figure out how to push my artifacts from my jenkins workspace directory to my 'remote' dev server.
I can successfully open a console in my jenkins container (portainer as the jenkins user) and scp files from the workspace directory using my remote server creds(but password is necessary).
I installed and used "Publish Over SSH" Jenkins plugin and get a successful "Test Configuration" from my setup.
I created my RSA keys on the REMOTE machine (that I'm trying to push my build files to).
I then pasted the private key (created without a password) into the plugin at the 'Use password authentication, or use a different key' section. Again, I get a successful test connection.
In my pipeline the last step is deploying and I use this command
sh 'scp -r build myusername#xx.xx.xx.xx:/var/files/react-tester'
I get a 'Permission denied (publickey,password).' error. I have no password associated with the rsa key. I tried both ways, creating the rsa key on the remote machine as my remote user, and the jenkins machine as the jenkins user. I've read examples of people creating the keys both ways, but not sure which user/machine combo to create the keys and paste to which section of the 'Publish Over SSH' plugin.
I'm out of ideas.
First, go to "Manage Jenkins" > "Credentials", add a new SSH credential of type "SSH Username with private key" and fill the "Username" and your private key (generate one if you haven't done it yet) fields (you can also upload one). Don't forget that you have to copy the generated public key to the ${SSH_USERNAME}/.ssh/authorized_keys file on the remote server.
I'm assuming you're using a scripted or DSL pipeline here. In your code, after you've builded your application, you can push it to your server adding this step to your pipeline:
pipeline {
stages {
stage("Pushing changes to remote server") {
steps {
script {
def remote_server = "1.2.3.4"
withCredentials([sshUserPrivateKey(credentialsId: 'my-key', keyFileVariable: 'SSH_KEY', passphraseVariable: '', usernameVariable: 'SSH_USERNAME')]) {
sh "scp -i \${SSH_KEY} build/ ${SSH_USERNAME}#${remote_server}:/var/files/react-tester/"
}
}
}
}
}
}
Best regards.

Pass variables to jenkins from workspace

I am trying to set up builds on Jenkins. When the build is successful, I push a tag of the build using the Post build Action Git Publisher.
Until Now, these have been done manually, with the tag being given the version number, A.B.C.D (which comes from a text file). Now we are using Jenkins, D comes from the $BUILD_NUMBER Jenkins variable, but A.B.C are stored in a text file within the workspace. Is there a way I can pass A.B.C to the git publisher? or will have to do all of the git commands in a script?
Using Jenkins v1.624. Updating not currently possible (before people suggest this)
Not entirely sure if this will work the Post build Action Git Publisher (as I don't use it), and I can only test this on:
Jenkins ver. 2.32.3
EnvInject+Plugin 1.93.1
Groovy+plugin 1.30
Based on suggestion by 'Joerg S' in this post:
Creating a Jenkins environment variable using Groovy
Add a 'Execute Groovy Script' build step to read in the workspace file (tmpFile) containing A.B.C and convert it to a java based properties file - name:value) :
def custom_tag = new File('tmpfile').text.trim()
File propFile = new File('properties.text')
propFile.write "CUSTOM_TAG:"+custom_tag
Then add a 'Inject Environment Variables' build step to read in the new file, so Properties File Path is properties.text
You should then be able to use the ${CUSTOM_TAG} in your post build git publish as the TAG, as now it's an environment variable.
If this doesn't work check out the groovy code in the link above, it might offer something else.

How do I chain Jenkins pipelines from a checked out git repo?

I want to checkout a git repo and then run its build so I tried:
sh "git clone --depth 1 -b master git#github.com:user/repo.git"
build './repo'
but that yields:
ERROR: No item named ./repo found
I've tried to use dir('repo') but apparently that errors when you run it from within docker (because kubernetes is stuck on an old version of docker that doesnt support this).
Any idea on how to run the build pipeline from the checked out repo?
The 'build' pipeline steps expect a job name, not a pipeline folder with a Jenkinsfile in its root folder.
The correct way to do this is to set the pipeline job with the Jenkinsfile, as described here ('In SCM' section), and call it by its Job name from your pipeline.
Pipelines are not built for chaining unless you use shared libraries where you put the Pipeline code in a Groovy class or as a step, but that it is a subject for a full article.

Jenkins Pipeline as Code with Docker Error

For one of my projects that I have on GitHub, I wanted to build it as a docker image and push it to my docker hub. The project is a sbt one with a Scala codebase.
Here is how my JenkinsFile is defined:
#!groovy
node {
// set this in Jenkins server under Manage Jenkins > Credentials > System > Global Credentials
docker.withRegistry('https://hub.docker.com/', 'joesan-docker-hub-credentials') {
git credentialsId: '630bd271-01e7-48c3-bc5f-5df059c1abb8', url: 'https://github.com/joesan/monix-samples.git'
sh "git rev-parse HEAD > .git/commit-id"
def commit_id = readFile('.git/commit-id').trim()
println comit_id
stage "build" {
def app = docker.build "Monix-Sample"
}
stage "publish" {
app.push 'master'
app.push "${commit_id}"
}
}
}
When I tried to run this from my Jenkins server, I get the following error:
java.io.FileNotFoundException
at jenkins.plugins.git.GitSCMFile$3.invoke(GitSCMFile.java:167)
at jenkins.plugins.git.GitSCMFile$3.invoke(GitSCMFile.java:159)
at jenkins.plugins.git.GitSCMFileSystem$3.invoke(GitSCMFileSystem.java:161)
at org.jenkinsci.plugins.gitclient.AbstractGitAPIImpl.withRepository(AbstractGitAPIImpl.java:29)
at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.withRepository(CliGitAPIImpl.java:65)
at jenkins.plugins.git.GitSCMFileSystem.invoke(GitSCMFileSystem.java:157)
at jenkins.plugins.git.GitSCMFile.content(GitSCMFile.java:159)
at jenkins.scm.api.SCMFile.contentAsString(SCMFile.java:338)
at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:101)
at org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition.create(CpsScmFlowDefinition.java:59)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:232)
at hudson.model.ResourceController.execute(ResourceController.java:98)
at hudson.model.Executor.run(Executor.java:404)
Finished: FAILURE
Since this is running inside a VM on Azure, I thought the VM was not able to reach outside, but that seems not to be the case as I was able to ssh into the VM and git pull from the Git repo. So what is the problem here? How could I make this work?
for me unchecking "lightweight checkout" fixed the issue
I experienced the exact same error. My setting:
Pipeline build inside a dockerized Jenkins (version 2.32.3)
In the configuration of the job, I specified a check out into a subdirectory: Open the configuration, e.g. https://myJenkins/job/my-job/configure. At the bottom, see section Pipeline -> Additional Behaviours -> Check out into a sub-directory with Local subdirectory for repo set to, e.g., my-sub-dir.
Expectation: Upon check out, the Jenkinsfile ends up in my-sub-dir/Jenkinsfile.
Via the option Script path, you configure the location of the Jenkinsfile so that Jenkins can start the build. I put my-sub-dir/Jenkinsfile as value.
I then received the exception you pasted in your question. I fixed it by setting Script Path to Jenkinsfile. If you don't specify a sub-directory for check out, then still try double checking values for Script Path.
Note: I have another Jenkins instance at work. There I have to specify Script Path including the custom check out sub-directory (as mentioned in Expectation above).
GO TO Job-->Config-->Pipline and uncheck checkbox lightweight checkout"
lightweight checkout : selected, try to obtain the Pipeline script contents >directly from
the SCM without performing a full checkout. The advantage of this mode
is its efficiency; however, you will not get any changelogs or polling
based on the SCM. (If you use checkout scm during the build, this will
populate the changelog and initialize polling.) Also build parameters
will not be substituted into SCM configuration in this mode. Only
selected SCM plugins support this mode.

How can I test a change made to Jenkinsfile locally?

When writing jenkins pipelines it seems to be very inconvenient to commit each new change in order to see if it works.
Is there a way to execute these locally without committing the code?
You cannot execute a Pipeline script locally, since its whole purpose is to script Jenkins. (Which is one reason why it is best to keep your Jenkinsfile short and limited to code which actually deals with Jenkins features; your actual build logic should be handled with external processes or build tools which you invoke via a one-line sh or bat step.)
If you want to test a change to Jenkinsfile live but without committing it, use the Replay feature added in 1.14.
JENKINS-33925 tracks the feature request for an automated test framework.
I have a solution that works well for me. It consists of a local jenkins running in docker and a git web hook to trigger the pipeline in the local jenkins on every commit. You no longer need to push to your github or bitbucket repository to test the pipeline.
This has only been tested in a linux environment.
It is fairly simple to make this work although this instruction is a tad long. Most steps are there.
This is what you need
Docker installed and working. This is not part of this instruction.
A Jenkins running in docker locally. Explained how below.
The proper rights (ssh access key) for your local Jenkins docker user to pull from your local git repo. Explained how below.
A Jenkins pipeline project that pulls from your local git repository. Explained below.
A git user in your local Jenkins with minimal rights. Explained below.
A git project with a post-commit web hook that triggers the pipeline project. Explained below.
This is how you do it
Jenkins Docker
Create a file called Dockerfile in place of your choosing. I'm placing it in /opt/docker/jenkins/Dockerfile fill it with this:
FROM jenkins/jenkins:lts
USER root
RUN apt-get -y update && apt-get -y upgrade
# Your needed installations goes here
USER jenkins
Build the local_jenkins image
This you will need to do only once or after you have added something to the Dockerfile.
$ docker build -t local_jenkins /opt/docker/jenkins/
Start and restart local_jenkins
From time to time you want to start and restart jenkins easily. E.g. after a reboot of your machine. For this I made an alias that I put in .bash_aliases in my home folder.
$ echo "alias localjenkinsrestart='docker stop jenkins;docker rm jenkins;docker run --name jenkins -i -d -p 8787:8080 -p 50000:50000 -v /opt/docker/jenkins/jenkins_home:/var/jenkins_home:rw local_jenkins'" >> ~/.bash_aliases
$ source .bash_aliases # To make it work
Make sure the /opt/docker/jenkins/jenkins_home folder exists and that you have user read and write rights to it.
To start or restart your jenkins just type:
$ localjenkinsrestart
Everything you do in your local jenkins will be stored in the folder /opt/docker/jenkins/jenkins_home and preserved between restarts.
Create a ssh access key in your docker jenkins
This is a very important part for this to work. First we start the docker container and create a bash shell to it:
$ localjenkinsrestart
$ docker exec -it jenkins /bin/bash
You have now entered into the docker container, this you can see by something like jenkins#e7b23bad10aa:/$ in your terminal. The hash after the # will for sure differ.
Create the key
jenkins#e7b23bad10aa:/$ ssh-keygen
Press enter on all questions until you get the prompt back
Copy the key to your computer. From within the docker container your computer is 172.17.0.1 should you wonder.
jenkins#e7b23bad10aa:/$ ssh-copy-id user#172.17.0.1
user = your username and 172.17.0.1 is the ip address to your computer from within the docker container.
You will have to type your password at this point.
Now lets try to complete the loop by ssh-ing to your computer from within the docker container.
jenkins#e7b23bad10aa:/$ ssh user#172.17.0.1
This time you should not need to enter you password. If you do, something went wrong and you have to try again.
You will now be in your computers home folder. Try ls and have a look.
Do not stop here since we have a chain of ssh shells that we need to get out of.
$ exit
jenkins#e7b23bad10aa:/$ exit
Right! Now we are back and ready to continue.
Install your Jenkins
You will find your local Jenkins in your browser at http://localhost:8787.
First time you point your browser to your local Jenkins your will be greated with a Installation Wizard.
Defaults are fine, do make sure you install the pipeline plugin during the setup though.
Setup your jenkins
It is very important that you activate matrix based security on http://localhost:8787/configureSecurity and give yourself all rights by adding yourself to the matrix and tick all the boxes. (There is a tick-all-boxes icon on the far right)
Select Jenkins’ own user database as the Security Realm
Select Matrix-based security in the Authorization section
Write your username in the field User/group to add: and click on the [ Add ] button
In the table above your username should pop up with a people icon next to it. If it is crossed over you typed your username incorrectly.
Go to the far right of the table and click on the tick-all-button or manually tick all the boxes in your row.
Please verify that the checkbox Prevent Cross Site Request Forgery exploits is unchecked. (Since this Jenkins is only reachable from your computer this isn't such a big deal)
Click on [ Save ] and log out of Jenkins and in again just to make sure it works.
If it doesn't you have to start over from the beginning and emptying the /opt/docker/jenkins/jenkins_home folder before restarting
Add the git user
We need to allow our git hook to login to our local Jenkins with minimal rights. Just to see and build jobs is sufficient. Therefore we create a user called git with password login.
Direct your browser to http://localhost:8787/securityRealm/addUser and add git as username and login as password.
Click on [ Create User ].
Add the rights to the git user
Go to the http://localhost:8787/configureSecurity page in your browser. Add the git user to the matrix:
Write git in the field User/group to add: and click on [ Add ]
Now it is time to check the boxes for minimal rights to the git user. Only these are needed:
overall:read
job:build
job:discover
job:read
Make sure that the Prevent Cross Site Request Forgery exploits checkbox is unchecked and click on [ Save ]
Create the pipeline project
We assume we have the username user and our git enabled project with the Jenkinsfile in it is called project and is located at /home/user/projects/project
In your http://localhost:8787 Jenkins add a new pipeline project. I named it hookpipeline for reference.
Click on New Item in the Jenkins menu
Name the project hookpipeline
Click on Pipeline
Click [ OK ]
Tick the checkbox Poll SCM in the Build Triggers section. Leave the Schedule empty.
In the Pipeline section:
select Pipeline script from SCM
in the Repository URL field enter user#172.17.0.1:projects/project/.git
in the Script Path field enter Jenkinsfile
Save the hookpipeline project
Build the hookpipeline manually once, this is needed for the Poll SCM to start working.
Create the git hook
Go to the /home/user/projects/project/.git/hooks folder and create a file called post-commit that contains this:
#!/bin/sh
BRANCHNAME=$(git rev-parse --abbrev-ref HEAD)
MASTERBRANCH='master'
curl -XPOST -u git:login http://localhost:8787/job/hookpipeline/build
echo "Build triggered successfully on branch: $BRANCHNAME"
Make this file executable:
$ chmod +x /home/user/projects/project/.git/hooks/post-commit
Test the post-commit hook:
$ /home/user/projects/project/.git/hooks/post-commit
Check in Jenkins if your hookpipeline project was triggered.
Finally make some arbitrary change to your project, add the changes and do a commit. This will now trigger the pipeline in your local Jenkins.
Happy Days!
TL;DR
Jenkins Pipeline Unit testing framework
Jenkinsfile Runner
Long Version
Jenkins Pipeline testing becomes more and more of a pain. Unlike the classic declarative job configuration approach where the user was limited to what the UI exposed the new Jenkins Pipeline is a full fledged programming language for the build process where you mix the declarative part with your own code. As good developers we want to have some unit tests for this kind of code as well.
There are three steps you should follow when developing Jenkins Pipelines. The step 1. should cover 80% of the uses cases.
Do as much as possible in build scripts (eg. Maven, Gradle, Gulp etc.). Then in your pipeline scripts just calls the build tasks in the right order. The build pipeline just orchestrates and executes the build tasks but does not have any major logic that needs a special testing.
If the previous rule can't be fully applied then move over to Pipeline Shared libraries where you can develop and test custom logic on its own and integrate them into the pipeline.
If all of the above fails you, you can try one of those libraries that came up recently (March-2017). Jenkins Pipeline Unit testing framework or pipelineUnit (examples). Since 2018 there is also Jenkinsfile Runner, a package to execution Jenkins pipelines from a command line tool.
Examples
The pipelineUnit GitHub repo contains some Spock examples on how to use Jenkins Pipeline Unit testing framework
Jenkins has a 'Replay' feature, which enables you to quickly replay a job without updating sources:
At the moment of writing (end of July 2017) with the Blue Ocean plugin you can check the syntax of a declarative pipeline directly in the visual pipeline editor. The editor, works from the Blue Ocean UI when you click "configure" only for github projects (this is a known issue and they are working to make it work also on git etc).
But, as explained in this question you can open the editor browsing to:
[Jenkins URL]/blue/organizations/jenkins/pipeline-editor/
Then click in the middle of the page, and press Ctrl+S, this will open a textarea where you can paste a pipeline declarative script. When you click on Update, if there is a syntax error, the editor will let you know where the syntax error is. Like in this screenshot:
If there is no syntax error, the textarea will close and the page will visualize your pipeline. Don't worry it won't save anything (if it's a github project it would commit the Jenkinsfile change).
I'm new to Jenkins and this is quite helpful, without this I had to commit a Jenkinsfile many times, till it works (very annoying!). Hope this helps. Cheers.
A bit late to the party, but that's why I wrote jenny, a small reimplementation of some core Jenkinsfile steps. (https://github.com/bmustiata/jenny)
In my development setup – missing a proper Groovy editor – a great deal of Jenkinsfile issues originates from simple syntax errors. To tackle this issue, you can validate the Jenkinsfile against your Jenkins instance (running at $JENKINS_HTTP_URL):
curl -X POST -H $(curl '$JENKINS_HTTP_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)') -F "jenkinsfile=<Jenkinsfile" $JENKINS_HTTP_URL/pipeline-model-converter/validate
The above command is a slightly modified version from
https://github.com/jenkinsci/pipeline-model-definition-plugin/wiki/Validating-(or-linting)-a-Declarative-Jenkinsfile-from-the-command-line
As far as i know this Pipeline Plugin is the "Engine" of the new Jenkinsfile mechanics, so im quite positive you could use this to locally test your scripts.
Im not sure if there is any additional steps needed when you copy it into a Jenkinsfile, however the syntax etc should be exactly the same.
Edit: Found the reference on the "engine", check this feature description, last paragraph, first entry.
For simplicity, you can create a Jenkinsfile at the root of the git repository, similar to the below example 'Jenkinsfile' based on the groovy syntax of the declarative pipeline.
pipeline {
agent any
stages {
stage('Build the Project') {
steps {
git 'https://github.com/jaikrgupta/CarthageAPI-1.0.git'
echo pwd()
sh 'ls -alrt'
sh 'pip install -r requirements.txt'
sh 'python app.py &'
echo "Build stage gets finished here"
}
}
stage('Test') {
steps {
sh 'chmod 777 ./scripts/test-script.sh'
sh './scripts/test-script.sh'
sh 'cat ./test-reports/test_script.log'
echo "Test stage gets finished here"
}
}
}
https://github.com/jaikrgupta/CarthageAPI-1.0.git
You can now set up a new item in Jenkins as a Pipeline job.
Select the Definition as Pipeline script from SCM and Git for the SCM option.
Paste the project's git repo link in the Repository URL and Jenkinsfile in the script name box.
Then click on the lightweight checkout option and save the project.
So whenever you pushed a commit to the git repo, you can always test the changes running the Build Now every time in Jenkins.
Please follow the instructions in the below visuals for easy setup a Jenkins Pipeline's job.
Aside from the Replay feature that others already mentioned (ditto on its usefulness!), I found the following to be useful as well:
Create a test Pipeline job where you can type in Pipeline code or point to your repo/branch of a Jenkinsfile to quickly test out something. For more accurate testing, use a Multibranch Pipeline that points to your own fork where you can quickly make changes and commit without affecting prod. Stuff like BRANCH_NAME env is only available in Multibranch.
Since Jenkinsfile is Groovy code, simply invoke it with "groovy Jenkinsfile" to validate basic syntax.
Put your SSH key into your Jenkins profile, then use the declarative linter as follows:
ssh jenkins.hostname.here declarative-linter < Jenkinsfile
This will do a static analysis on your Jenkinsfile. In the editor of your choice, define a keyboard shortcut that runs that command automatically. In Visual Studio Code, which is what I use, go to Tasks > Configure Tasks, then use the following JSON to create a Validate Jenkinsfile command:
{
"version": "2.0.0",
"tasks": [
{
"label": "Validate Jenkinsfile",
"type": "shell",
"command": "ssh jenkins.hostname declarative-linter < ${file}"
}
]
}
You can just validate your pipeline to find out syntax issues. Jenkins has nice API for Jenkisfile validation - https://jenkins_url/pipeline-model-converter/validate
Using curl and passing your .Jenkinsfile, you will get syntax check instantly
curl --user username:password -X POST -F "jenkinsfile=<jenkinsfile" https://jenkins_url/pipeline-model-converter/validate
You can add this workflow to editors:
VS Code
Sublime Text
Using the VS Code Jenkins Jack extension, you can have a way to test your Jenkinsfiles without use the git push way, from your local files to a local or remote running Jenkins. And you will have the running log of the job inside VS Code, the ability to create jobs in Jenkins and more staff. I hope this help to more people looking for a way to develop Jenkinsfiles.
i am using replay future , to do some update and run quickly .
With some limitations and for scripted pipelines I use this solution:
Pipeline job with an inlined groovy script:
node('master') {
stage('Run!') {
def script = load('...you job file...')
}
}
Jenkinsfile for testing have same structure as for lesfurets:
def execute() {
... main job code here ...
}
execute()
This is a short solution that lets me test Pipeline code very quickly:
pipeline {
agent any
options {
skipDefaultCheckout true
timestamps()
}
parameters {
text(name: 'SCRIPT', defaultValue: params.SCRIPT,
description: 'Groovy script')
}
stages {
stage("main") {
steps {
script {
writeFile file: 'script.groovy',
text: params.SCRIPT
def groovyScript = load 'script.groovy'
echo "Return value: " + groovyScript
}
} // steps
} // stage
} // stages
} // pipeline
skipDefaultCheckout true because we do not need the files in this tool git repository.
defaultValue: params.SCRIPT sets the default to the latest execution. If used by just one user, it allows for a very quick cycle of short tests.
The given script is written to a file, and loaded and with load.
With this setup I can test everything I can do inside my other Jenkinsfiles, including using shared libraries.

Resources