Static Code Analysis and GitLab CI
Few days ago I gave a talk on KDE Akademy about running static code analyzers
in the KDE instance of GitLab. There I explained what static code analyzers
are good for and why you want to use them. Then I showcased my progress
implementing a GitLab CI jobs to automatically run clazy and clang-tidy on
merge requests as well as individual git push
es to make it as easy for
KDE developers as possible to add static analyzers to their projects.
Based on some feedback from the KDE sysadmins as well as the talk audience I have revamped the pipeline and the helper scripts, so let’s see how the pipeline works now and how you can add it to your project.
How It Works
The pipeline on GitLab CI can have multiple stages. Jobs in the same stage
are executed in parallel and artifacts from the first stage are made available
to jobs in the next stage. The default stage is the build
stage where the
project is, well, built to see if the code actually compiles. The entire
“build” directory from this stage is than carried over to the static
analysis job in the test
stage. Thanks to that we no longer have to compile
the project twice, once in the build job and once in the static analysis job.
Why do we need to make sure the project is built before applying static analysis? Because the static analyzers need the code to compile, so we need to make sure that all the generated include files (MOC files, UI header files, DBus adaptors etc.) exist - and so far I’ve been unable to find a better way to have those files generated than actually building the project.
There are two types of static analysis job: one for merge requests and one for regular pushes into the master branch and for manually triggered pipelines. The merge-request= job detects which C++ files have been changed in the branch and will only run the static analyzers for those jobs. This saves a lot of CPU time and makes the static analysis jobs to finish much faster than if we had to analyze the entire project every time.
The second job is used when someone just pushes directly into the master
branch
(the branch trigger can be customized, I’ll get to that later). The job only executes
the static analyzers on files that have changed since the last push - again, no need
to recheck the entire project over and over again. The only case when the static
analyzers are ran for the entire project codebase is when the job is launched manually
from the GitLab UI.
The job will run clazy and clang-tidy on each file, collect the output of the tools and convert them to codequality report which is then displayed in the GitLab merge request UI.
How To Enable It:
Create .gitlab-ci.yml
file in the root of your git repository. Add the
following content to it:
include:
- https://invent.kde.org/sysadmin/ci-tooling/raw/master/invent/ci-before.yml
- https://invent.kde.org/sysadmin/ci-tooling/raw/master/invent/ci-<PRODUCT>-linux.yml
- https://invent.kde.org/sysadmin/ci-tooling/raw/master/invent/ci-static-analysis.yml
Replace <PRODUCT>
with applications
, frameworks
or extragear
based on what “product”
your project belongs to. If your project is not part of any of those group, you will need to
experiment a bit more, or refer to the documentation on the wiki here [TODO]
Those includes will give you access to all the necessary job templates. The templates themselves do not create any jobs, you still need to define the jobs:
static-analysis-linux-merge-request:
extends: .static-analysis-linux-merge-request
static-analysis-linux-commit:
extends: .static-analysis-linux-commit
This creates two new jobs that inherit from the job templates. This is all you need to do. Once you commit and push, you should already see a new pipeline appear in GitLab. I recommend that you go and manually trigger a new pipeline to make sure you get an initial run with full check - it will probably throw a lot of warnings that you will want to fix, otherwise your future merge requests might fail on issues that are unrelated to the change itself.
Documentation
The above is just a quick-start guideline. Go to the community wiki here to read in-depth documentation on how to configure and customize the static analysis jobs.
If you run into any issues with the integration, please let me know via email or try to catch me on IRC.
Happy analyzing! :)