Introduction

Continuous Integration (CI) is a widely accepted approach for ensuring software quality through regular, automated builds. But although the concept of CI is well understood, setting up the necessary infrastructure to implement it is generally considered a complex and time-consuming process.

It doesn't have to be that way. With Bitnami's ready-to-use application stacks, you can quickly deploy a reliable, automated CI pipeline for your project in less than an hour using popular open-source tools like GitLab and Jenkins. This guide will walk you through the process.

Assumptions and Pre-requisites

This guide makes the following assumptions:

  • You have launched or are otherwise running the Bitnami GitLab CE Stack and the Bitnami Jenkins Stack.
  • You have an IDE with Git support, such as Eclipse or Eclipse Che, or a standalone Git client.
  • You have the source code for your application.
  • You have the IP addresses and administrative login credentials for all these applications.
  • You have prepared two SSH key pairs, one for communication between your local Git environment and GitLab, and the other for communication between GitLab and Jenkins. These key pairs should be in OpenSSH format.
TIP: To generate a new SSH key pair, you can use PuTTYgen (Windows) or the ssh-keygen command (Linux and Mac OS X). Read instructions on how to use PuTTYgen and instructions on how to use ssh-keygen.

Step 1: Create a GitLab project

The first step is to create a Git repository for your project source code using GitLab. This is where you and your team will push code changes, and this will also be the source repository for Jenkins' automated builds. Follow these steps:

  • Create a new user account on GitLab and log in.

    GitLab configuration

  • From the "Your Projects" tab, click the "New Project" button.

    GitLab configuration

  • On the "New Project" page, enter a name for the project and set the visibility level. The project in this example is set to "Public", but you can also choose to make your project "Private" or "Internal". Click "Create Project" once done.

    GitLab configuration

    TIP: Read more about project visibility levels in the GiLab documentation.

GitLab will initialize an empty Git repository for the project, as shown below. Note the SSH URL to the repository, as you will need it in the next step.

GitLab configuration

Step 2: Configure SSH access to the GitLab project

Both Jenkins and your Git client will need access to the project repository, so this is a good time to configure that access. Follow these steps:

  • From the GitLab main menu (accessed via the hamburger icon in the top left corner), select the "Profile Settings" option.

    GitLab configuration

  • Select the "SSH Keys" tab and enter the public key content (as a single line) for use between GitLab and your Git client. Add a descriptive title and click the "Add key" button to add it to your profile.

    GitLab configuration

TIP: Public key files typically have a .pub suffix.

Repeat the steps above for the second key, to be used between GitLab and Jenkins. Once complete, you should see both public keys attached to your GitLab profile.

GitLab configuration

Step 3: Connect your project with the GitLab repository

Next, connect your project with the remote repository on GitLab and commit your initial code tree to it. You can do this from your IDE or via your Git tool.

If you're using the Git command-line interface (CLI), follow these steps:

  • Ensure that your user account is configured to use the private SSH key defined for use with GitLab in Step 2.
  • Change into your project's working directory and initialize a new local Git repository:

     $ cd project
     $ git init
    
  • Set the committer name and email address, replacing the NAME and EMAIL-ADDRESS placeholders below with actual values:

     $ git config user.name "NAME"
     $ git config user.email "EMAIL-ADDRESS"
    
  • Add the remote GitLab repository. Specify the repository name as origin and replace the SSH-URL-TO-GITLAB-REPOSITORY placeholder with the SSH URL to the repository (obtained in Step 1).

     $ git remote add origin SSH-URL-TO-GITLAB-REPOSITORY
    
  • Add your project files to the local repository and commit them:

     $ git add .
     $ git commit -a
    
  • Push the changes to the remote repository:

     $ git push origin master
    

Regardless of how you choose to commit your changes, if all goes well, you should see a success message and the committed files will appear in the Git repository on GitLab.

Commit result

Step 4: Configure Jenkins

The next step is to connect Jenkins with GitLab, such that a new push to the GitLab repository automatically triggers a Jenkins build. This requires you to add the GitLab plugin to Jenkins and create SSH credentials so that Jenkins can access the GitLab project.

  • Log in to Jenkins and click the "Manage Jenkins" link.
  • Select the "Manage Plugins" option.

    Jenkins configuration

  • From the "Available" tab, find and select the GitLab plugin. Click the "Download now and install after restart" button to download it.

    Jenkins configuration

  • Once the plugin has been downloaded, click the "Restart Jenkins" checkbox and wait for Jenkins to restart.

    Jenkins configuration

If you want Jenkins to merge successful builds back to the GitLab repository, you also need to configure a Git user name and email address in Jenkins. To do this:

  • Click the "Manage Jenkins" link.
  • Select the "Configure System" option.

    Jenkins configuration

  • In the "Git plugin" section, enter a user name and email address.

    Jenkins configuration

  • Click "Save" to save the configuration.

Step 5: Create a Jenkins project

You're now ready to create a Jenkins project and connect it to GitLab.

  • Log in to Jenkins and click the "New Item" link to create a new job.
  • Enter a name for the job and set it to be a "Freestyle project".

    Jenkins configuration

  • On the job configuration page, find the "Source Code Management" section and select "Git". Configure the GitLab connection as follows:

    • Enter the SSH URL to the GitLab repository.

      Jenkins configuration

    • Click the "Add" button next to the "Credentials" field and select the "Jenkins" option.
    • In the resulting dialog, select "SSH Username with private key" as the credential type, set the "Username" to git, and enter the content of the private key selected for use between GitLab and Jenkins (remember that you already attached the corresponding public key to your GitLab profile in Step 2).

      Jenkins configuration

  • On the configuration page, select the newly-added credential and attach it to the SSH URL.

    Jenkins configuration

  • On the same configuration page, find the "Build Triggers" section and check the option to "Build when a change is pushed to GitLab".

    Jenkins configuration

    Note the Jenkins service URL for the project next to the checkbox, as you will need this in the next step.

  • It is common to have Jenkins merge the new changes into the production branch before building. On the same configuration page, find the "Additional Behaviours" section and check the option to "Merge before build". Specify the name of the repository as origin and the branch to merge to as production.

    Jenkins configuration

    NOTE: The production branch does not exist yet. You will create it in the next step.
  • As part of the continuous integration process, you will also usually want Jenkins to automatically merge successful builds back into the production branch. To do this:

    • Click the "Add post-build action" button.
    • Select the "Git Publisher" option
    • Check the "Push only if build succeeds" and "Merge Results" options.
    • Specify the remote name and branch to push as origin and production respectively. You can also add custom tags if you wish.

    Jenkins configuration

    NOTE: The production branch does not exist yet. You will create it in the next step.
  • Click "Save" to save the configuration.

Step 6: Create a GitLab branch for Jenkins

The Jenkins configuration in the previous step will merge successful builds to a production branch in the GitLab repository. This branch doesn't exist yet so go ahead and create it, as follows:

  • Log in to GitLab and browse to the GitLab page for the project.
  • Select the "New branch" (accessed via the plus symbol) option.

    GitLab configuration

  • Create a new branch named production derived from the existing master branch.

    GitLab configuration

  • Click "Create branch" to create the new branch.

Step 7: Connect GitLab and Jenkins

The final step is to connect Jenkins and GitLab, such that Jenkins is automatically notified when there's a new commit to the GitLab repository and can commit successful builds back to it. To do this:

  • Log in to GitLab and browse to the GitLab page for the project.
  • Open the project setting page (accessed via the cogwheel icon in the top right corner) and select the "Webhooks" option.

    GitLab configuration

  • Configure a new Jenkins webhook as follows:

    • In the "URL" field, enter the Jenkins service URL from Step 5.
    • In the list of triggers, ensure that the "Push events" trigger is checked. Optionally, select other events that should trigger a new Jenkins build, such as new tags or new comments.
    • If you haven't configured SSL, disable SSL by unchecking the "Enable SSL verification" flag.

      GitLab configuration

  • Click "Add Webhook" to save the new settings.

You're all set! To verify that it all works, head back to your project, make a change to your project source code and commit the changes. Then, push the changes to the GitLab repository as described in Step 3.

CI pipeline usage

The push should automatically trigger a new build in Jenkins, with the build results visible on the Jenkins overview page for the project.

CI pipeline usage

If the build is successful, Jenkins will also merge the build back to the production branch in the GitLab repository.

CI pipeline usage

Your Continuous Integration (CI) pipeline is now ready for use!

centurylink

Bitnami Documentation