Github Actions is configured through the YAML files.
💡 The trickiest part of writing the configuration files is typically getting the indentation right.
- Understand the basic structure of a workflow file
- Understand the basic structure of a job
- Understand the basic structure of a step
In this workshop we will use a small Java web service which is built and tested using Gradle.
The details of the implementation are not relevant for the purposes of these exercises. We will instead focus on how to build a CI pipeline using GitHub Actions, that builds, tests and packages the webservice.
The application is found in the app directory. Scripts to build, test and package the web service
are found in the ci directory.
We ultimately want a pipeline that has the following jobs:
- Build and test: Clones down and run the gradle build command found in ci/build-app.sh, and thereafter runs the gradle test command found in ci/unit-test-app.sh
- Build docker: runs both building of the docker image, and pushes it up to the hub
- Component test: runs a docker-compose file with a python test to test the application.
- Performance test: runs a docker-compose file with a k6 performance tester to test the application.
We are not going to do it all in one go, but rather step by step.
Examine the following example workflow definition:
name: Main workflow
on: push
jobs:
Build:
runs-on: ubuntu-latest
container: gradle:6-jdk11
steps:
- name: Clone down repository
uses: actions/checkout@v4
- name: Build application
run: ci/build-app.shA line-by-line explanation of the above:
- Line 1: Specifies the name of the workflow, in this case, "Main workflow".
- Line 2: Specifies that the workflow should be triggered on a
pushevent. - Line 3: Introduces the
jobssection where all job definitions reside. - Line 4-5: Defines a job named
Buildthat runs on an Ubuntu VM. - Line 6: Specifies that the job should run in a container with the image
gradle:6-jdk11. - Line 7: Defines the steps that should be executed in the job.
- Line 8: Defines a step named
Clone down repository... - Line 9: ... which uses the action
actions/checkout@v4, to clone down the repository's content to the runner, enabling subsequent steps to access it. - Line 10: Defines a step named
Build application... - Line 11: ... which runs the
build-app.shscript found in thecidirectory of the repository.
This workflow is a basic example that provides insights into the event type, branch reference, and repository structure when code is pushed to it.
If you want to see what build-app.sh is doing, look into the script.
- Replace the contents of
.github/workflows/main.ymlwith the above example. - Add and commit the file and push it to GitHub.
💡 Git commands to do it if you are using the terminal
git add .github/workflows/main.yml
git commit -m "Add basic workflow to build the web service"
git push
- Go to Github Actions tab of the repository and check the action status.
- When the build is green, click the
Buildjob entry to see the workflow log. - Expand the
Build applicationstep to see the output of the build.
See that the build status is green and the job log looks something like this:
Run ./ci/build-app.sh
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :clean UP-TO-DATE
> Task :compileJava
Note: Creating bean classes for 3 type elements
> Task :processResources
> Task :classes
> Task :shadowJar
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.9.4/userguide/command_line_interface.html#sec:command_line_warnings
BUILD SUCCESSFUL in 15s
4 actionable tasks: 3 executed, 1 up-to-dateCongratulations, you have now built the Java web service!
But we have some way to go yet, we want to build a Docker image, and run some tests on it as well.