Skip to content

The goal of this project is to master the core of continuous integration. To achieve this goal, a small continuous integration CI server is to be implemented. This CI server will only contain the core features of continuous integration.

License

Notifications You must be signed in to change notification settings

joss2002/Continuous_Integration

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Host CI-server locally

Prerequisites

  • Java 8
  • Java JDK 17
  • Maven 3.9
  • Git
Run the server
  1. Clone the repository
git clone https://github.com/joss2002/Continuous_Integration.git
  1. Navigate to the repository and build the project with Maven
mvn clean compile
  1. Run the CI-server

Without commit status notifications:

mvn exec:java

With commit status notifications:

Bash

To set the status of commits, a github access token with commit status permission is required.

mvn exec:java -Dexec.mainClass=ci_server.Main -Dexec.args="<GITHUB ACCESS TOKEN>"
PowerShell

To set the status of commits, a github access token with commit status permission is required.

mvn --% exec:java -Dexec.mainClass=ci_server.Main -Dexec.args="<GITHUB ACCESS TOKEN>"
Test the server

Option 1: Use curl

curl http://localhost:8080/
Expected output
StatusCode        : 200
StatusDescription : OK
Content           : CI job done (placeholder)

Option 2: Open browser at http://localhost:8080/

Expected output
CI job done (placeholder)

Note: 8080 is the default port number.

Perform local push event successfully

  1. Run the server, see Run the server.
Bash
  1. Load local JSON payload test file
json=$(cat ./src/test/resources/githubPush.json)
  1. Post JSON payload to the CI-server
curl http://localhost:8080/webhook \
  -H "Content-Type: application/json" \
  -d "$json"
Expected output

Client side

HTTP/1.1 200 OK
Content-Length: 25
Date: Tue, 10 Feb 2026 12:27:04 GMT
Server: Jetty(9.4.50.v20221201)

Push received: e5f6g7h8

Server side

Received push on branch : main
After SHA               : e5f6g7h8
Repository URL          : https://github.com/user/repo.git
Pusher name             : name

Head commit message     : Update README
PowerShell
  1. Load local JSON payload test file
$json = Get-Content -Raw "./src/test/resources/githubPush.json"
  1. Post JSON payload to the CI-server
Invoke-WebRequest -Uri http://localhost:8080/webhook `
  -Method POST `
  -Body $json `
  -ContentType "application/json"
Expected output

Client side

StatusCode        : 200
StatusDescription : OK
Content           : {80, 117, 115, 104...}
RawContent        : HTTP/1.1 200 OK
                    Content-Length: 25
                    Date: Tue, 10 Feb 2026 12:27:04 GMT
                    Server: Jetty(9.4.50.v20221201)

                    Push received: e5f6g7h8

Server side

Received push on branch : main
After SHA               : e5f6g7h8
Repository URL          : https://github.com/user/repo.git
Pusher name             : name

Head commit message     : Update README

Test invalid payload

Bash

Post invalid JSON to the CI-server

curl -X POST http://localhost:8080/webhook \
  -H "Content-Type: application/json" \
  -d '{Invalid JSON}'
Expected output
Invalid payload: Invalid GitHub push payload
PowerShell

Post invalid JSON to the CI-server

Invoke-WebRequest `
  -Uri http://localhost:8080/webhook `
  -Method POST `
  -Body '{Invalid JSON}' `
  -ContentType "application/json"
Expected output
Invoke-WebRequest : Invalid payload: Invalid GitHub push payload
At line:1 char:1
+ Invoke-WebRequest -Uri http://localhost:8080/webhook -Method POST -Bo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

Connect the server to a webhook with ngrok

  1. Run the server, see Run the server.

  2. In a separate terminal, start ngrok to expose port 8080:

ngrok http 8080
  1. Copy the forwarding URL (e.g. https://xxxx.ngrok-free.app) from the ngrok output.

  2. In your GitHub repository, go to Settings > Webhooks > Add webhook and set:

    • Payload URL: https://xxxx.ngrok-free.app/webhook
    • Content type: application/json
    • Events: Select "Just the push event"
  3. Push a commit to the repository and observe the compilation output in the server console.


API Documentation (Javadoc)

Browsable API documentation is generated using the Maven Javadoc plugin. To generate or update it:

mvn javadoc:javadoc

The HTML documentation is output to docs/index.html. Open it in a browser:

open docs/index.html

Perform unit tests

  1. Build the project with Maven
mvn clean compile
  1. Run the junit unit tests
mvn test

Compilation and Automated Test Execution

Implementation

When the CI server receives a GitHub push webhook on /webhook, it triggers compilation of the pushed branch. After compilation the Compiler class runs the tests. The Compiler class in se.ciserver.build performs the following steps:

  1. Creates a temporary directory
  2. Clones the specific branch using git clone --branch <branch> --single-branch <url>
  3. Checks out the exact commit SHA with git checkout <sha>
  4. Runs mvn clean compile in the cloned project
  5. Captures and prints the build output to the server console
  6. Runs mvn test in the cloned project
  7. Captures and prints the test output to the server console
  8. Cleans up the temporary directory

The compilation result (success/failure) and test result (success/failure) is returned in the HTTP response and shown on the ngrok site.

Unit testing

Compilation is unit-tested in src/test/java/MainTest.java with the following tests:

  • compilationResultStoresSuccess() — verifies that a successful CompilationResult stores success=true and the build output.
  • compilationResultStoresFailure() — verifies that a failed CompilationResult stores success=false and the build output.
  • compilerHandlesCloneFailure() — subclasses Compiler to override createProcessBuilder() with a failing command, verifying that a clone failure returns success=false without throwing an exception.
  • compilerReturnsSuccessWhenAllStepsPass() — subclasses Compiler to override createProcessBuilder() with a succeeding command, verifying the full pipeline returns success=true.
  • compilerReturnesFailedCompilationForBadInputs - verifies failed compilation results are returned for bad parameters.

To run the tests, see Perform unit tests.


Notification Implementation and Testing

Notifications are implemented by setting the status of commits using github's REST api. A post request containing the status is sent to the url of the push's last commit.

The notification implementation is tested by running a test server and sending the status post request to it instead, which checks that its contents are correct.


Build List

The build list url is http://localhost:8080/builds.


The states of the team

By analyzing the team, based on SEMAT standard [p.51-52], following this instance of the project, it could be concluded that currently positioned between "Formed" and "Collaborating". This because some of the checklist items are not met in relation to "Formed" but at the same time some checklist items has been fulfilled related to "Collaborating". The checklist looks as follows;

State Checklist
Formed
  • Individual responsibilities are understood.
  • Enough team members have been recruited to enable the work to progress.
  • Every team member understands how the team is organized and what their individual role is.
  • All team members understand how to perform their work.
  • The team members have met (perhaps virtually) and are beginning to get to know each other.
  • The team members understand their responsibilities and how they align with their competencies.
  • Team members are accepting work.
  • Any external collaborators (organizations, teams and individuals) are identified.
  • Team communication mechanisms have been defined.
  • Each team member commits to working on the team as defined.
Collaborating
  • The team is working as one cohesive unit.
  • Communication within the team is open and honest.
  • The team is focused on achieving the team mission.
  • The team members know and trust each other.

Notations

In relation to the checklist it is of importance to understand why certain checkboxes has not been checked. Regarding the "Formed" state "All team members understand how to perform there work" has been kept unchecked due to all team members not following requested formatting and standards at all times. This could be a result of both miscommunication or that some sort of permanent source of information should have been created. In addition, "Each team member commits to working on the team as defined" was kept unchecked partly in relation to the previous point in terms of applying the standards in practice, but could also be rooted in the amount of initiative from the team regarding expectations.

Moving on, the "Collaborating" state had some unchecked requirements too. Firstly, "The team is working as one cohesive unit" was not checked mainly due to certain lack in providing information as well as actively participating in discussions at times, meaning that some team members will not be up to date on what is going on in the repository. Secondly, "The team members know and trust each other" was mainly left unchecked because lack of communication regarding progress and when certain parts of the work are expected to be done. Here some deadlines might have been useful to lower stress within the team, as well as being clearer on how to communicate details of contributed work and more clearly present what aspects has been tested successfully and how that was accomplished.


Statements of contributions

Name Contribution
Josefine "joss2002" Nyholm
  • Added initial Maven file-tree structure, including a basic pom.xml with JDK 17 support.
  • Added skeleton for CI-server in src/main/java/se/ciserver/ContinuousIntegrationServer.java.
    • Added related dependencies, plugins; jetty-server, exec-maven-plugin
    • Added additional documentation.
  • Added GitHub push event JSON payload component.
    • Added required Webhook payload object parameters and classes for push within src/main/java/se/ciserver/github including files; PushParser.java, Push.java, Pusher.java, Commit.java, Author.java and Repository.java.
    • Added additional Exception extension in InvalidPayloadException.java specified for invalid payloads.
    • Integrated the push parsing JSON payload functionality in the ContinuousIntegrationServer.java handler() to allow the CI-server to receive JSON payloads and present the relevant variables; ref, after, repository.clone_url, pusher.name, head_commit.message.
    • Added unit tests in src/test/java/MainTest.java for PushParser.java push parsing JSON payload functionality and local testing of the ContinuousIntegrationServer.java CI-server handling of push parsing JSON payloads. This, as well as an additional file src/main/java/se/ciserver/TestUtils.java including test utilities such as reading filed. Supporting the unit tests a test JSON file src/main/test/resources/githubPush.java was added to represent a typical push event payload.
    • Added additional dependencies in pom.xml for jackson-databind and junit
    • Added additional documentation in README.md.
    • Tested that the push event implementation was successfull using ngrok and GitHub webhooks.
  • Added "The states of the team" following the SEMAT standard [p.51-52]
  • Avid "HotFazz" Fayaz
    • Added webhook-triggered compilation (P1) in src/main/java/se/ciserver/build/Compiler.java.
      • Clones the pushed branch, checks out the exact commit, and runs mvn clean compile.
      • Added CompilationResult.java to hold build outcome and output.
      • Integrated compilation into ContinuousIntegrationServer.java webhook handler.
      • Added unit tests in MainTest.java for CompilationResult and Compiler failure handling.
      • Added documentation in README.md for compilation implementation and unit testing.
    • Generated browsable Javadoc API documentation (P5).
      • Configured Maven Javadoc plugin in pom.xml to output to docs/.
      • Fixed incomplete Javadoc on public classes and methods in Build.java and BuildStore.java.
      • Generated docs/index.html browsable in a browser via mvn javadoc:javadoc.
      • Added documentation in README.md for generating Javadoc.
    Albin "zzimbaa" Blomqvist
    • Implemented automated test execution triggered by GitHub push webhooks.
    • Added TestRunner.java in src/main/java/se/ciserver/ to handle CI test execution.
      • Dynamically checks out the pushed branch using git checkout and updates it with git pull.
      • Executes Maven test suite using mvn test.
      • Captures test output via ProcessBuilder and write logs to both terminal and HTTP response indicating test success or failure.
      • Determines build success/failure based on process exit code.
      • Added unit test for runTests method to verify correct correct branch checkout and pull commands using command hook.
    • Integrated the test execution logic into ContinuousIntegrationServer.java so that tests are triggered automatically upon receiving a GitHub push webhook event.
    • Verified webhook-based test execution using ngrok for local tunneling and GitHub webhook deliveries.
    • Added documentation in README.md describing how to trigger automated tests via GitHub push events.
    Erik Olsson "erik-ol"
    • Added GitHub commit status setter component.
      • Added ContinuousIntegrationServer() startHttpClient() and setCommitStatus() to ContinuousIntegrationServer.java
      • Extended ContinuousIntegrationServer.java handler() to set commit status of recieved pushes.
      • Added unit tests in src/test/java/MainTest.java for setCommitStatus() sending post request functionality and failing due to invalid url.
      • Implemented github access token handling
      • Added additional dependencies in pom.xml for jetty-client
      • Added documentation for commit status implementation and testing in README.md.
    • Refactored test code from TestRunner.java into Compiler.java enabling running tests of the watched repository.
    Pun Chun "MrNoodlez-1227" Chow
    • Implemented persistent build history with unique URLs.
      • Added the Build model in src/main/java/se/ciserver/buildlist/Build.java to represent individual CI builds (commit id, branch, timestamp, status, and logs).
      • Implemented BuildStore in src/main/java/se/ciserver/buildlist/BuildStore.java to persist build history as JSON on disk, including loading on startup, adding new builds, and looking up builds by id.
      • Extended ContinuousIntegrationServer to wire in BuildStore, and to expose the /builds endpoint for listing all builds and the /builds/<id> endpoint for viewing a single build’s information and log output.
      • Added JUnit tests under src/test/java/MainTest.java to verify correct construction of Build objects and that BuildStore correctly saves and reloads history from file across server restarts.
      • Updated this README with documentation for the build list URL and unique build URLs so graders can browse the history directly.

    About

    The goal of this project is to master the core of continuous integration. To achieve this goal, a small continuous integration CI server is to be implemented. This CI server will only contain the core features of continuous integration.

    Topics

    Resources

    License

    Stars

    Watchers

    Forks

    Releases

    No releases published

    Packages

    No packages published

    Contributors 5

    Languages