Static code check for a Gerrit refspec

I wanted to introduce static code check for our repo in Gerrit. Gerrit allows you to fetch the given refspec, then you may use git diff-tree to see what files are in the given change. The trouble is that you already need the repo cloned to do so, which is not that efficient for a larger repo. Fear not, the Gerrit ssh API is to the rescue. Let’s how to make it work.

Let’s say you set up a Jenkins job to be triggered from Gerrit whenever a patchset is created. Gerrit sends a bunch of parameter about the given commit to Jenkins, eg.

Now let’s get the files from the patchset using the Gerrit SSH API (you need the jq utility to process the json output):
ssh -p $GERRIT_PORT $GERRIT_HOST gerrit query –files –format JSON change:$GERRIT_CHANGE_NUMBER –current-patch-set | jq -r “select(.project==\”$GERRIT_PROJECT\”)|.currentPatchSet.files[].file”
The above command produces the following output:


Now we have to filter /COMMIT_MSG, since it’s not an actual file in the commit, rather the commit message which we are not interested in this time. So we have two files in the patchset: ‘’ and ‘bbb.groovy’.

Once we have the affected files we use git archive to get only these specific files even from a large repo:

git archive –format=tar –remote=ssh://${GERRIT_HOST}:${GERRIT_PORT}/${GERRIT_PROJECT} “$GERRIT_REFSPEC” “${FILES[@]}” | tar xf –

The FILES array is supposed to contain “” and “bbb.groovy” strings. Note that I omitted the –prefix parameter, so it dumps the files to the current directory, ie. to $WORKSPACE

Finally we run a docker container to do some checks on these files:

docker run –rm -u $(id -u):$(id -g) –name “${JOB_NAME}-${BUILD_NUMBER}” -v “${WORKSPACE}:${WORKSPACE}” -w “$WORKSPACE” -e PATTERN=”.*(sh|inc|groovy)” “static_check:latest”

Notice the PATTERN variables in which we may define what file extensions we want to include in the static code check. I recommend to make this a job variable.

The actual entrypoint in the container executes the following code:


set -o nounset
set -o errexit
set -o pipefail


error() {
echo “$*”
exit 1

check_for_trailing_whitespace() {
local f=”$1″

if grep ‘[[:blank:]]$’ “$f”; then
error “Trailing whitespace in the above lines”

while read -r f; do
echo “Checking ${f}”

check_for_trailing_whitespace “$f”

if [[ “$f” =~ .sh$ || “$f” =~ .inc$ ]]; then
shellcheck “$f”
done < <(find . -type f -regextype posix-extended -regex “$PATTERN”)

The above code check every file for trailing white characters, and runs shellcheck for each file with .sh or .inc extensions.