How to migrate from Jenkins to Bitbucket Pipelines

Bitbucket Cloud gives you the flexibility to connect to several on-premises CI/CD tools. However, if you’re using Bitbucket Cloud to manage your code, migrating your CI/CD pipelines to Bitbucket Pipelines will improve your overall CI/CD experience.

Since Bitbucket Pipelines built-in to Bitbucket Cloud, there is no integration to manage or plugins to install. You’ll be able to use Atlassian’s cloud runners to scale on demand (or connect to your own runners), easily extend your workflows using Pipes, and manage your pipelines at scale to meet your compliance needs. Learn more about the benefits of migrating to Bitbucket Pipelines.

Here is a guide on how the syntax varies and guidelines on how to plan your migration from Jenkins.

Syntax examples

Below are several examples and syntax comparisons for migrating from Jenkins to Bitbucket Pipelines.

Running a Hello World build

Jenkins (groovy)

Pipelines (yaml)

1 2 3 4 5 6 7 8 9 10 pipeline { agent any stages { stage('Example') { steps { echo 'Hello World' } } } }
1 2 3 4 5 6 7 image: atlassian/default-image:4 pipelines: default: - step: name: Example script: - echo 'Hello World'

Running parallel jobs

Jenkins (groovy)

Pipelines (yaml)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 pipeline { agent any stages { stage('Parallel Steps') { parallel { stage('Build and Test') { steps { echo "Your build and test goes here..." } } stage('Lint') { steps { echo "Your linting goes here..." } } stage('Security scan') { steps { echo "Your security scan goes here..." } } } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 image: atlassian/default-image:4 pipelines: default: - parallel: - step: name: 'Build and Test' script: - echo "Your build and test goes here..." - step: name: 'Lint' script: - echo "Your linting goes here..." - step: name: 'Security scan' script: - echo "Your security scan goes here..."

Referencing environment variables

Jenkins (groovy)

Pipelines (yaml)

1 2 3 4 5 6 7 8 9 10 pipeline { agent any stages { stage('Example') { steps { echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}" } } } }
1 2 3 4 5 6 7 image: atlassian/default-image:4 pipelines: default: - step: name: Example script: - echo "Running $BITBUCKET_BUILD_NUMBER on $BITBUCKET_GIT_HTTP_ORIGIN"

Handling credentials

The following Pipeline code shows an example of how to create a Pipeline using environment variables for secret text credentials.

Jenkins (groovy)

Pipelines (yaml)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 pipeline { agent any environment { AWS_ACCESS_KEY_ID = credentials('jenkins-aws-secret-key-id') AWS_SECRET_ACCESS_KEY = credentials('jenkins-aws-secret-access-key') } stages { stage('Example stage 1') { steps { // logic required credentials } } } }
1 2 3 4 5 6 7 8 9 10 image: atlassian/default-image:4 pipelines: default: - step: name: Example script: - pipe: atlassian/bitbucket-upload-file:0.7.1 variables: BITBUCKET_ACCESS_TOKEN: $BITBUCKET_ACCESS_TOKEN FILENAME: 'package.json'

Increase timeout

Jenkins (groovy)

Pipelines (yaml)

1 2 3 4 5 6 7 8 9 10 11 12 13 pipeline { agent any stages { stage('Example') { options { timeout(time: 1, unit: 'HOURS') } steps { echo 'Hello World' } } } }
1 2 3 4 5 6 7 8 image: atlassian/default-image:4 pipelines: default: - step: name: Example script: - echo 'Hello World' max-time: 60 # Timeout in minutes

Cron expressions

Jenkins (groovy)

Pipelines

1 2 3 4 5 6 7 8 9 10 11 12 13 pipeline { agent any triggers { cron('H 0 * * *') // This cron expression triggers the pipeline once every day at midnight } stages { stage('Example') { steps { echo 'Hello World' } } } }

Bitbucket Pipelines scheduled builds are configured in the user interface. You can easily set up and manage your build schedules, specify the frequency, and timing of builds.

Build, test and deploy

Jenkins (groovy)

Pipelines (yaml)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 pipeline { agent any tools {nodejs "nodejs"} environment { HEROKU_API_KEY = credentials('jenkins-heroku-api-key') HEROKU_APP_NAME = credentials('jenkins-heroku-app-name') } stages { stage('Build') { steps { sh 'npm install' sh 'npm run build' sh 'zip -r build.zip build/ } } stage('Test') { steps { sh 'npm test' } } stage('Deploy to Heroku') { steps { script { def deploymentUrl = "https://api.heroku.com/sources" def response = sh(script: """ curl -X POST \ -H "Content-Type: application/json" \ -H "Accept: application/vnd.heroku+json; version=3" \ -H "Authorization: Bearer ${HEROKU_API_KEY}" \ "${deploymentUrl}" """, returnStdout: true).trim() def jsonSlurper = new groovy.json.JsonSlurper() def parsedResponse = jsonSlurper.parseText(response) def putUrl = parsedResponse.source_blob.put_url def getUrl = parsedResponse.source_blob.get_url sh """ curl "${putUrl}" \ -X PUT \ -H "Content-Type:" \ --data-binary @build.zip """ sh """ curl -X POST \ -H "Content-Type: application/json" \ -H "Accept: application/vnd.heroku+json; version=3" \ -H "Authorization: Bearer ${HEROKU_API_KEY}" \ -d '{"source_blob":{"url":"${getUrl}","version":"${BUILD_NUMBER}"}}' \ "https://api.heroku.com/apps/${HEROKU_APP_NAME}/builds" """ } } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 image: atlassian/default-image:4 pipelines: default: - step: name: Build script: - npm install - npm run build - zip -r build.zip build/ artifacts: - build.zip - step: name: Test caches: - node script: - npm install - npm test - step: name: Deploy to Heroku services: - docker script: - pipe: atlassian/heroku-deploy:2.4.0 variables: HEROKU_API_KEY: $HEROKU_API_KEY HEROKU_APP_NAME: $HEROKU_APP_NAME ZIP_FILE: 'build.zip' WAIT: 'true'

Migration best practices

For mission critical workflows, we recommend a progressive rollout for your migration from Jenkins to Bitbucket Pipelines. This strategy allows you to gradually transition your existing repositories to Bitbucket Pipelines while still leveraging Jenkins where necessary, helping to ensure a smooth and efficient transition to Bitbucket Pipelines.

You can start by migrating less critical repositories or parts of your build processes to Bitbucket Pipelines, which allows you to test and refine your configurations along the way. During this transitional period, you can configure Bitbucket Pipelines to trigger Jenkins jobs using the jenkins-job-trigger pipe. This hybrid approach enables you to gradually familiarize your team with Bitbucket Pipelines and address any migration challenges without disrupting your ongoing development processes.

Below are some examples on how to trigger a basic Jenkins job from Pipelines:

1 2 3 4 5 6 7 script: - pipe: atlassian/jenkins-job-trigger:0.8.0 variables: JENKINS_URL: 'http://my-jenkinsio-host:8080/job' JENKINS_USER: $JENKINS_USER JENKINS_TOKEN: $JENKINS_TOKEN JOB_NAME: 'awesome-project-job'

The following example triggers a Jenkins job build and waits for build to complete:

Make sure to set a sufficient WAIT_MAX_TIME time for your workflows.

1 2 3 4 5 6 7 8 9 script: - pipe: atlassian/jenkins-job-trigger:0.8.0 variables: JENKINS_URL: 'http://my-jenkinsio-host/job' JENKINS_USER: $JENKINS_USER JENKINS_TOKEN: $JENKINS_TOKEN JOB_NAME: 'staging-awesome-project-job' WAIT: 'true' WAIT_MAX_TIME: 120

Additionally, it’s recommend to enhance your CI/CD workflows and minimize boilerplate code with our powerful CI/CD integrations, known as Pipes. Choose from our curated list of 100+ Pipes, or create and share your own custom solutions within your organization.

Still need help?

The Atlassian Community is here for you.