Connect Atomist to CI

Atomist can listen for CI events, correlate them with the commits that triggered the build, and show contextualized notifications in the Slack channel.

To enable this, we need to connect Atomist to your CI system. Atomist currently works with Travis CI and Jenkins. Use either the Travis CI or Jenkins section to help you configure Atomist to connect with your CI.

Travis CI Setup

Travis uses your GitHub user access token. Once you have set up Travis for your GitHub account, you are ready to go. No additional authorization required. If you have not yet setup Travis and want to as part of getting started with Atomist, please see the Travis getting started documentation.

Atomist works with Travis-CI.org and Travis-CI.com. Travis Enterprise is not currently supported.

You will need to enable your projects to be built using Travis if they aren’t already set up. See the Travis documentation to set up Travis builds.

Next, configure your Travis builds to send notifications to Atomist. In the .travis.yml configuration file in the project repo, add the following webhook configuration.

notifications:
  webhooks:
    urls:
    - https://webhook.atomist.com/travis
    on_success: always
    on_failure: always
    on_start: always
    on_cancel: always
    on_error: always

That’s all that you need to do. Now, Travis will send all notifications to Atomist. To test it out, see the CI Notifications section.

Jenkins Setup

Using the Notification Plugin

If you don’t already have the Notification plugin installed, go to the Plugin Manager in the Jenkins admin interface, select it and complete the installation.

Install Notification Plugin

To enable the plugin, be sure to restart Jenkins after installation.

Notification Plugin Installation Status

Now that the Notification plugin is installed and enabled, it’s time to configure project Notifications settings. Select a project that you would like Atomist to get events from. Next, select “Configure”.

Configure Project

We’re going to walk through setting up a webhook. In the Job Notifications section of the project configuration, click the “Add Endpoint” button.

Add Notification

In the Notification configuration section, configure the endpoint URL as https://webhook.atomist.com/jenkins and check that the other parameters match the information shown below.

Configure Webhook

Now, Jenkins is set up to send all notifications to Atomist. To test it out, see the next section, In Action: CI Notifications.

Using the Pipeline plugin

If you run a Pipeline job, your build is described in a Jenkinsfile. The integration with Atomist is done within the Jenkinsfile using the post section.

If you do not have the plugin installed, ask your Jenkins administrator to add the Pipeline project plugin.

Create Pipeline Plugin

The plugin will expect to have permissions to access your project on GitHub, you should therefore have the appropriate credentials declared in Jenkins for these operations.

The plugin supports various credential providers such as username/password or private keys. Below is the description of using a username/password approach where the password is a GitHub personal access token.

Go to your GitHub settings to generate a new token with only the repo scope:

GitHub personal access token for Jenkins

Then, ask your Jenkins administrator to create credentials for your GitHub username and token:

Jenkins credentials
Jenkins add new GitHub credentials

Now, you can create a pipeline build job as usual:

Create Pipeline Job

Next, declare the pipeline job settings by selecting a Pipeline script from SCM using the git SCM provider. Input the git URL of the project and the appropriate credentials. The plugin will warn you if something fails at this stage. You may select the branch you want to build and you may tune the other settings as needed.

Create Pipeline Job

A Jenkinsfile stub for notifying Atomist could look like this:

import groovy.json.JsonOutput

/*
 * Retrieve current SCM information from local checkout 
 */
def getSCMInformation() {
    def gitRemoteUrl = sh(returnStdout: true, script: 'git config --get remote.origin.url').trim()
    def gitCommitSha = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
    def gitBranchName = sh(returnStdout: true, script: 'git name-rev --always --name-only HEAD').trim().replace('remotes/origin/', '')

    return [
        url: gitRemoteUrl, 
        branch: gitBranchName,
        commit: gitCommitSha
    ]
}

/*
 * Notify the Atomist services about the status of a build based from a 
 * git repository.
 */
def notifyAtomist(buildStatus, buildPhase="FINALIZED", 
                  endpoint="https://webhook.atomist.com/atomist/jenkins") {

    def payload = JsonOutput.toJson([
        name: env.JOB_NAME,
        duration: currentBuild.duration,
        build      : [
            number: env.BUILD_NUMBER,
            phase: buildPhase,
            status: buildStatus,
            full_url: env.BUILD_URL,
            scm: getSCMInformation()
        ]
    ])

    sh "curl --silent -XPOST -H 'Content-Type: application/json' -d \'${payload}\' ${endpoint}"
}

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                // notifiy Atomist the buid starts now
                // could be at any state but should be done first
                notifyAtomist("UNSTABLE", "STARTED")

                // let's pretend something is being done
                sh "sleep 10"
            }
        }
    }
    post { 
        success { 
            notifyAtomist("SUCCESS")
        }
        unstable { 
            notifyAtomist("UNSTABLE")
        }
        failure { 
            notifyAtomist("FAILURE")
        }
    }
}

This pipeline should be considered a template for your own jobs. It provides however, the basics of notifying Atomist properly.

  • First, it defines two Groovy functions.
  • One extracts the repository metadata from the local copy of the build: its remote URL, the branch being built and the branch’s HEAD commit
  • The other one, notifyAtomist, performs the notification itself and associates another set of metadata related to the build itself: its id, duration, phase ("STARTED" or "FINALIZED") and status ("UNSTABLE", "SUCCESS" or "FAILURE").
  • In the pipeline declaration itself, it triggers those notifications with the relevant phase and status so Atomist can learn from the build lifecycle.

Important

Your pipeline will obviously looks a bit different, but it is necessary to send the appropriate payload structure, as JSON, to Atomist or the events will be rejected.

If events do not get rejected but you do not see them flowing into Slack, please contact-us with an example of the payload your are sending.

Finally, you need to configure your Jenkins job so that it knows when to start new builds. Two approaches exist out of the box, either your Jenkins server can be accessed from GitHub and you can configure a GitHub webhook to push to your job on every git operation, or you can configure your Jenkins job so that it monitors your GitHib repository for changes on a regular basis.

For instance, to poll GitHub every minute for changes:

Poll SCM every minute

Be careful not to poll too often as each call counts towards your hourly GitHub rate limit.

Now, Jenkins is set up to send all notifications to Atomist. To test it out, see the next section, In Action: CI Notifications.

Using the Multibranch Pipeline plugin

If you run a Multibranch Pipeline job, your build is described in a Jenkinsfile. The integration with Atomist is done within the Jenkinsfile using the post section. A multibranch pipeline build job is interesting because it allows you to concurrently build all the branches of your project.

If you do not have the plugin installed, ask your Jenkins administrator to add the Multibranch Pipeline project plugin.

Create Multibranch Pipeline Plugin

By default, the Multibranch pipeline plugin relies on anonymous calls to the GitHub API to scan existing repositories and their branches. However, the number of anonymous calls that can be made from a given IP is rather limited, it is therefore best if you set the credentials for an account that will perform those queries.

The plugin supports various credential providers such as username/password or private keys. Below is the description of using a username/password approach where the password is a GitHub personal access token.

Go to your GitHub settings to generate a new token with only the repo scope:

GitHub personal access token for Jenkins

Then, ask your Jenkins administrator to create credentials for your GitHub username and token:

Jenkins credentials
Jenkins add new GitHub credentials

Now, you can create a multibranch pipeline build job as usual:

Create Multibranch Pipeline Job

A multibranch pipeline project expects at least one source to monitor and build from. This source is essentially your project on GitHub and it must have a file named Jenkinsfile in the top-level directory. That file contains the description of your build pipeline.

Configure Multibranch source

Set the Owner to the GitHub organization holding your project. The plugin will automatically scan for repositories in that organization.

Select the new pair of credentials in the Multibranch build job so that it uses that account to scan for repositories and branches in the project you will be building.

Once a repository has been selected, attach the appropriate credentials used for the checkout. You may leave the other settings at their default values or tune as you see fit.

At this stage you don’t need to configure the build job further as it will automatically run the Jenkinsfile it finds in the top-level directory of your project when it pulls it.

A Jenkinsfile stub for notifying Atomist could look like this:

import groovy.json.JsonOutput

/*
 * Retrieve current SCM information from local checkout 
 */
def getSCMInformation() {
    def gitRemoteUrl = sh(returnStdout: true, script: 'git config --get remote.origin.url').trim()
    def gitCommitSha = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
    def gitBranchName = env.BRANCH_NAME

    return [
        url: gitRemoteUrl, 
        branch: gitBranchName,
        commit: gitCommitSha
    ]
}

/*
 * Notify the Atomist services about the status of a build based from a 
 * git repository.
 */
def notifyAtomist(buildStatus, buildPhase="FINALIZED", 
                  endpoint="https://webhook.atomist.com/atomist/jenkins") {

    def payload = JsonOutput.toJson([
        name: env.JOB_NAME,
        duration: currentBuild.duration,
        build      : [
            number: env.BUILD_NUMBER,
            phase: buildPhase,
            status: buildStatus,
            full_url: env.BUILD_URL,
            scm: getSCMInformation()
        ]
    ])

    sh "curl --silent -XPOST -H 'Content-Type: application/json' -d \'${payload}\' ${endpoint}"
}

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                // notifiy Atomist the buid starts now
                // could be at any state but should be done first
                notifyAtomist("UNSTABLE", "STARTED")

                // let's pretend something is being done
                sh "sleep 10"
            }
        }
    }
    post { 
        success { 
            notifyAtomist("SUCCESS")
        }
        unstable { 
            notifyAtomist("UNSTABLE")
        }
        failure { 
            notifyAtomist("FAILURE")
        }
    }
}

This pipeline should be considered a template for your own jobs. It provides however, the basics of notifying Atomist properly.

  • First, it defines two Groovy functions.
  • One extracts the repository metadata from the local copy of the build: its remote URL, the branch being built and the branch’s HEAD commit
  • The other one, notifyAtomist, performs the notification itself and associates another set of metadata related to the build itself: its id, duration, phase ("STARTED" or "FINALIZED") and status ("UNSTABLE", "SUCCESS" or "FAILURE").
  • In the pipeline declaration itself, it triggers those notifications with the relevant phase and status so Atomist can learn from the build lifecycle.

Important

Your pipeline will obviously look a bit different, but it is necessary to send the appropriate payload structure, as JSON, to Atomist or the events will be rejected.

If events do not get rejected but you do not see them flowing into Slack, please contact-us with an example of the payload your are sending.

Finally, you need to configure your Jenkins job so that it knows when to start new builds. Two approaches exist out of the box, either your Jenkins server can be accessed from GitHub and you can configure a GitHub webhook to push to your job on every git operations, or you can configure your Jenkins job so that it monitors your GitHib repository for changes on a regular basis.

For instance, to poll GitHub every minute for changes:

Poll SCM every minute

Be careful not to poll too often as each call counts towards your hourly GitHub rate limit.

Now, Jenkins is set up to send all notifications to Atomist. To test it out, see the next section, In Action: CI Notifications.

CI Notifications

Now that CI is also configured, let’s take a look at how Atomist handles CI events.

Let’s make a little change the README.md of our sprockets repo, then commit it.

Edit README
Commit README

This project is configured so that the commit triggers a Travis build. Atomist is now receiving CI notifications, and is notified of the build started.

Commit Notification