- Java 8
- Java JDK 17
- Maven 3.9
- Git
Run the server
- Clone the repository
git clone https://github.com/joss2002/Continuous_Integration.git- Navigate to the repository and build the project with Maven
mvn clean compile- Run the CI-server
Without commit status notifications:
mvn exec:javaWith commit status notifications:
To set the status of commits, a github access token with commit status permission is required.
mvn exec:java -Dexec.mainClass=ci_server.Main -Dexec.args="<GITHUB ACCESS TOKEN>"Test the server
Option 1: Use curl
curl http://localhost:8080/Expected output
StatusCode : 200
StatusDescription : OK
Content : CI job done (placeholder)Option 2: Open browser at http://localhost:8080/
Expected output
CI job done (placeholder)
Note: 8080 is the default port number.
- Run the server, see Run the server.
Bash
- Load local
JSONpayload test file
json=$(cat ./src/test/resources/githubPush.json)- Post JSON payload to the CI-server
curl http://localhost:8080/webhook \
-H "Content-Type: application/json" \
-d "$json"Expected output
Client side
HTTP/1.1 200 OK
Content-Length: 25
Date: Tue, 10 Feb 2026 12:27:04 GMT
Server: Jetty(9.4.50.v20221201)
Push received: e5f6g7h8Server side
Received push on branch : main
After SHA : e5f6g7h8
Repository URL : https://github.com/user/repo.git
Pusher name : name
Head commit message : Update READMEPowerShell
- Load local
JSONpayload test file
$json = Get-Content -Raw "./src/test/resources/githubPush.json"- Post JSON payload to the CI-server
Invoke-WebRequest -Uri http://localhost:8080/webhook `
-Method POST `
-Body $json `
-ContentType "application/json"Expected output
Client side
StatusCode : 200
StatusDescription : OK
Content : {80, 117, 115, 104...}
RawContent : HTTP/1.1 200 OK
Content-Length: 25
Date: Tue, 10 Feb 2026 12:27:04 GMT
Server: Jetty(9.4.50.v20221201)
Push received: e5f6g7h8Server side
Received push on branch : main
After SHA : e5f6g7h8
Repository URL : https://github.com/user/repo.git
Pusher name : name
Head commit message : Update READMEBash
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 payloadPowerShell
Post invalid JSON to the CI-server
Invoke-WebRequest `
-Uri http://localhost:8080/webhook `
-Method POST `
-Body '{Invalid JSON}' `
-ContentType "application/json"Expected output
Invoke-WebRequest : Invalid payload: Invalid GitHub push payload
At line:1 char:1
+ Invoke-WebRequest -Uri http://localhost:8080/webhook -Method POST -Bo ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommandWhen the CI server receives a GitHub push webhook on /webhook, it triggers compilation of the pushed branch. The Compiler class in se.ciserver.build performs the following steps:
- Creates a temporary directory
- Clones the specific branch using
git clone --branch <branch> --single-branch <url> - Checks out the exact commit SHA with
git checkout <sha> - Runs
mvn clean compilein the cloned project - Captures and prints the build output to the server console
- Cleans up the temporary directory
The compilation result (success/failure) is returned in the HTTP response and printed to the server console.
Compilation is unit-tested in src/test/java/MainTest.java with the following tests:
compilationResultStoresSuccess()— verifies that a successfulCompilationResultstoressuccess=trueand the build output.compilationResultStoresFailure()— verifies that a failedCompilationResultstoressuccess=falseand the build output.compilerHandlesCloneFailure()— subclassesCompilerto overridecreateProcessBuilder()with a failing command, verifying that a clone failure returnssuccess=falsewithout throwing an exception.compilerReturnsSuccessWhenAllStepsPass()— subclassesCompilerto overridecreateProcessBuilder()with a succeeding command, verifying the full pipeline returnssuccess=true.ciServerHandleCompilationOnPush()— starts a local Jetty server, sends a valid push payload to/webhook, and verifies the response is200and contains the compilation result with the commit SHA.
To run the tests, see Perform unit tests.
- Build the project with Maven
mvn clean compile- Run the
junitunit tests
mvn test- Verify all tests pass in the output
Tests run: 9, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS-
Run the server, see Run the server.
-
In a separate terminal, start ngrok to expose port
8080:
ngrok http 8080-
Copy the forwarding URL (e.g.
https://xxxx.ngrok-free.app) from the ngrok output. -
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"
- Payload URL:
-
Push a commit to the repository and observe the compilation output in the server console.
When a push is made to the git repository, Github sends a HTTP POST request (Webhook) to the running server. From the request and its payload, the branch to which the push was made can be extracted. Upon parsing the payload, the server checks out to the target branch, pulls the latest changes and runs the project's test suite.
The automated test logic is handled by the TestRunner class which is responsible for executing the following:
Functionality
-
Checkout the pushed branch using Git.
-
Running the test suite using
mvn test -
Capturing the output and exit status
-
Returning the test logs, displayed both in server terminal and in the HTTP response.
Test the functionality
-
Run the server, see Run the server.
-
Configure Webhook from server to repository.
-
Expose server to Github using
ngrok. -
Observe response upon a Github push event in terminal or HTTP response.
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.
To avoid using real Git and Maven commands during unit testing, the TestRunner class uses a command hook mechanism that intercepts command execution. When this hook mechanism is set, command are captured rather than executed and the expected behaviour could be asserted within the unit test.
| Name | Contribution |
|---|---|
| Josefine "joss2002" Nyholm |
|
| Avid "HotFazz" Fayaz |
|
| Albin "zzimbaa" Blomqvist |
|
| Erik Olsson "erik-ol" |
|
| Albin "zzimbaa" Blomqvist |
|