This repository aims at centralizing the artifacts used for continuous integration across all other repositories in the Bao Project. Its main goal is to provide a consistent framework for running the code quality checks and tests both in a developer's local machine, as well in a remote CI pipeline, in a reproducible manner. It provides two main facilities:
- A ci.mk makefile, that defines how the tools used for the checks are invoked;
- A docker container definition which provides a reproducible enviroment for running the checks.
Besides these two main pillars, the repository contains a number of configuration and template files used by the tools and CI process in general.
Although we use GitHub Actions for the remote CI pipeline, all workflow steps are rab in the docker container by calling the rules defined in makefile.
The following checks are provided:
- gitlint: checks commit messages follow the conventional commit style
- license-check: for checking source files contain an SPDX license identifier
- pylint: python formatting and linting
- yamllint: yaml formatting and linting
- format: C formatting
- tidy and cppcheck: C static analysis
- misra: MISRA C checking
- asmfmt: assembly formatting
To make use of the facilities provided by this repository, first add it as a submodule name ci in each project's top-level directory.
cd bao-project-repo
git submodule add git@github.com:bao-project/bao-ci.git ci
Then you should include ci.mk in your projects Makefile, preferably at the
very end, but it must be after your first rule definition. Before including
ci.mk you must define the root_dir
variable with the of the project
top-level directory. Assuming the Makefile is located at the project's top-level
directory:
root_dir:=$(realpath .)
all:
include ci/ci.mk
The makefile rules might also assume a number of standard predefined make
variables containing C toolchain definition such as CPPFLAGS
or the target's
CROSS_COMPILE
prefix.
Then you can add the CI predefined checks using Make's call syntax. For example to run the static-analysis cppcheck tool on three C files:
$(call ci, cppcheck, file1.c file2.c file3.h)
Then you can invoke CI checks by running it as typical make target:
make cppcheck
If the checks are successful they will return 0, otherwise they'll return an error code, as is typical of CLI tools.
Note that each instantiated check might offer one or more rules. For example, when you instantiate the format rule:
$(call ci, format, file1.c file2.c file3.h)
You'll get a make target for checking if the formatting is correct and another to apply the formatting:
make format-check # checks if the files are correctly formatted
make format # formats the files
Check ci.mk for more details on the available CI rules, its arguments and how to invoke them.
By convention, repos using this CI infrastructure should also define a make
rule such that running make ci
locally runs all rules necessary for that
repo, except rules related to the commits themselves such as gitlint.
For example, for a repo composed of a mix of C an Python sources:
ci: license pylint format-check tidy cppcheck misra
We provide a docker container with all the needed tools and dependencies for building Bao, as well as running all the necessary CI rules, already installed. It is used in GitHub Actions workflows to run all CI rules remotely. To use it locally, please make sure you have installed docker.
We try to keep a docker hub image bao-project/bao:latest as updated as possible. Docker will automatically fetch it when you start the container for the first time.
We provide a Makefile to ease running any command inside the container. For example, if you want to run the format check in the container just:
make -C ci/docker format-check
You can also just invoke the container and work directly from its shell:
make -C ci/docker shell
Finally, if you prefer, you can build the container image locally by running:
make -C ci/docker build
In the case you want to use the locally built image, or just not want to fetch the latest available docker image, when invoking the Makefile you should tell it you want to use the local image and not fetch it automatically. This is also useful when you don't have a network connection or just want to skip that step to speed up the command. For example:
make -C ci/docker DOCKER_PULL=n format-check
NOTE
The provided Makefile always checks Docker Hub for an updated container
image. If you are not using it to start the container please make sure the
image is indeed up to date with the latest Dockefile either by pulling it
expliclity (i.e. docker pull baoproject/bao:latest
) or by bulding it yourself
locally.
When setting up GitHub Actions' workflows for you repo, each step should make use of the docker container to run the CI rules instantiated in that repo's Makefile as such:
name: Bao Project example workflow
on:
push:
branches: [ main ]
pull_request:
workflow_dispatch:
jobs:
example-ci-step:
runs-on: ubuntu-latest
container: baoproject/bao:latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- run: make <example-ci-check-target>
This repo also provides a template for the base CI Workflow that should be used by all C language projects by copying it to the .github/workflows directory, and adapting it to the repo's specific needs (e.g. target platform matrix). You should settup any GitHub setting for your repository's Github Actions CI pipeline according to the project's guidelines.