/demo-ci

Hands-on exercise on CI Servers

Primary LanguageJavaMIT LicenseMIT

Demo-CI: Hands-on Exercise on Continuous Integration Servers

This repository contains a practical exercise to set up and use a Continuous Integration (CI) Server. The objective is to provide students with a first contact with this important tool when developing software nowadays.

For more details on CI, we recommend reading Chapter 10 of our Software Engineering textbook.

Even though there are many CI servers in the market, in this exercise, we will use the CI service provided by GitHub, which is called GitHub Actions. This service can be accessed in the top menu of any GitHub repo.

GitHub Actions

GitHub Actions allows us to execute external applications when GitHub detects some events in a repository. Our goal is to set up a CI server to compile and build a simple Java program and then run the tests. This pipeline will be executed every time a Pull Request (PR) is open.

CI Pull Request Diagram

Example

We'll use a simple Java program to llustrate the usage of a CI server. The code is also available in this repository in the "src" folder, and it is called SimpleCalculator.java.

public class SimpleCalculator {

  public int addition(int x, int y) {
    return x + y;
  }

  public int subtraction(int x, int y) {
    return x - y;
  }
}

When we submit a PR to this repository, the CI server will automatically compile and build this program and run the following unit test, called SimpleCalculatorTest.java.

public class SimpleCalculatorTest {
  private SimpleCalculator calc;

  @BeforeEach
  public void init(){
    calc = new SimpleCalculator();
  }

  @Test
  public void testAddition1() {
    int expected = 5;
    int result = calc.addition(2,3);
    assertEquals(expected, result);
  }
}

Task #1: Setting Up GitHub Actions

Step 1

Fork this repository, by clicking on the Fork button on the top right corner of this page. In this way, you will test the CI server into your own copy of the repository.

Step 2

Clone the forked repository into your local machine, using the following command (where <USER> should be replaced by your GitHub user).

git clone https://github.com/<USER>/demo-ci.git

Next, go to the folder .github/workflows/and create a configuration file called actions.yaml, with the following lines:

name: Github CI
on:
  # Set up a CI Server to execute the jobs pipeline below when 
  # a push or pull request is made at the main branch
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  pipeline:
    runs-on: ubuntu-latest # Commands must be executed on a Linux Ubuntu OS

    steps:
      - name: Git Checkout
        uses: actions/checkout@v2 # Checkout the received code 

      - name: Set up JDK 1.8
        uses: actions/setup-java@v1 # Set up Java 1.8
        with:
          java-version: 1.8

      - name: Build
        run: mvn package -Dmaven.test.skip=true # Build (compiles) the source code

      - name: Unit Test
        run: mvn test # Executes the testing framework 

Every time a push or pull_request event occurs on the main branch, this configuration file defines that GitHub Actions should:

  • checkout the source code;
  • build the source;
  • execute the tests.

Step 3

Commit and push the configuration file:

git add --all
git commit -m "Setting up GitHub Actions"
git push origin main

Step 4

When the previous push reaches the GitHub repository, GitHub Actions will automatically execute the jobs defined in actions.yaml.

You can checkout the status of these jobs by clicking on the Actions tab in your repository.

CI Jobs Inspection

Task #2: Creating a buggy Pull Request

Now let's see our CI server performing a more real live action. We will add a simple bug in our example and submit a PR. Then, the CI server will alert that a test has failed and will not integrate the change.

Step 1

Change the function addition in SimpleCalculator.java to work incorrectly (i.e., introduce a bug on it). For example, you can change line 6 to return x + y + 1, as detailed below.

--- a/src/main/java/br/ufmg/dcc/SimpleCalculator.java
+++ b/src/main/java/br/ufmg/dcc/SimpleCalculator.java
@@ -3,7 +3,7 @@ package br.ufmg.dcc;
 public class SimpleCalculator {

   public int addition(int x, int y) {
-    return x + y;
+    return x + y + 1;
   }

   public int subtraction(int x, int y) {

Step 2

Create a new branch, commit, and push:

git checkout -b buggy
git add --all
git commit -m "Deliberately introducing a bug in addition"
git push origin buggy

Step 3

Create a PR with your changes. Click on the Pull Request tab on your GitHub repository and follow the options to create a PR from your buggy branch to your main branch. If you prefer, you can just type the following URL in your browser (where <USER> should be replaced by your GitHub user).

https://github.com/<USER>/demo-ci/compare/main...buggy

You will be presented with the differences of both branches, and you should also write a description for your PR.

CI Creating a PR

After creating the PR, the job pipeline defined in GitHub Actions is triggered. Do not merge, wait at least 1 minute and you will see the results. GitHub itself will build the system and run the tests (just like it did in Task #1). However, this time the tests will fail, as shown in this figure.

CI Checks Failed

SUMMARIZING: The CI server automatically notified both the PR author and the integrator about a problem in the submitted code.

Credits

This exercise was created by Rodrigo Brito, an MSc student in DCC/UFMG, under the advisement of Prof. Marco Túlio Valente. It was translated and adapted to English by Prof. Henrique Rocha, at Loyola University Maryland.