Latest commit

History

18 Commits

Folders and files

NameName
Last commit message
Last commit date

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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

Server side

Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

StateChecklist
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

NameContribution
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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
     blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
    }
    } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
    })();
    (function(){
    try {
    var __m = "github.com";
    var __re = new RegExp('^' + "github\\.com" + '
    
    Skip to content

    Latest commit

    History

    18 Commits

    Folders and files

    NameName
    Last commit message
    Last commit date

    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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

    Server side

    Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

    StateChecklist
    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

    NameContribution
    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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
    Skip to content

    Latest commit

    History

    18 Commits

    Folders and files

    NameName
    Last commit message
    Last commit date

    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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

    Server side

    Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

    StateChecklist
    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

    NameContribution
    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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
    Skip to content

    Latest commit

    History

    18 Commits

    Folders and files

    NameName
    Last commit message
    Last commit date

    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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

    Server side

    Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

    StateChecklist
    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

    NameContribution
    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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
    Skip to content

    Latest commit

    History

    18 Commits

    Folders and files

    NameName
    Last commit message
    Last commit date

    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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

    Server side

    Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

    StateChecklist
    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

    NameContribution
    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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
    Skip to content

    Latest commit

    History

    18 Commits

    Folders and files

    NameName
    Last commit message
    Last commit date

    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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

    Server side

    Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

    StateChecklist
    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

    NameContribution
    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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
    Skip to content

    Latest commit

    History

    18 Commits

    Folders and files

    NameName
    Last commit message
    Last commit date

    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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

    Server side

    Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

    StateChecklist
    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

    NameContribution
    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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages

    , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
    Skip to content

    Latest commit

    History

    18 Commits

    Folders and files

    NameName
    Last commit message
    Last commit date

    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 : 200StatusDescription : OKContent : 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 OKContent-Length: 25Date: Tue, 10 Feb 2026 12:27:04 GMTServer: Jetty(9.4.50.v20221201)Push received: e5f6g7h8

    Server side

    Received push on branch : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 : 200StatusDescription : OKContent : {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 : mainAfter SHA : e5f6g7h8Repository URL : https://github.com/user/repo.gitPusher name : nameHead 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 payloadAt 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;

    StateChecklist
    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

    NameContribution
    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.javahandler() 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.javahandler() 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

    Stars

    2 stars

    Watchers

    0 watching

    Forks

    Releases

    Packages

    Used by

    Contributors

    Languages