Skip to content

Commit

Permalink
ci: run clang-tidy
Browse files Browse the repository at this point in the history
We run clang-tidy on every change. For that we introduce a separate CMake
preset that is selected in the CI and activates the clang-tidy support in
CMake. Additionally a Python script is provided to run clang-tidy locally
when the build already exists.

For now we enforce only the warning of one check as an error, but we aim to
increase that over time.
  • Loading branch information
romangg authored and LordTermor committed Sep 16, 2024
1 parent be5dc0f commit d0cf004
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 49 deletions.
12 changes: 11 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
Checks: "-*,modernize-*,cppcoreguidelines-*, -modernize-use-nodiscard, -modernize-use-trailing-return-type"
WarningsAsErrors: "readability-braces-around-statements"

Checks: "
-*,
modernize-*,
cppcoreguidelines-*,
readability-braces-around-statements,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type
"

CheckOptions:
- key: modernize-use-nullptr.NullMacros
value: "NULL"
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Static Analysis
on: workflow_call

jobs:
clang-tidy:
name: Check clang-tidy
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Download Docker image from artifacts
uses: actions/download-artifact@v4
with:
name: bxt-development-image
path: distfiles
- name: Load Docker image
run: docker load -i distfiles/bxt-development.tar
- uses: addnab/docker-run-action@v3
with:
image: anydistro/bxt-development:latest
options: -v ${{ github.workspace }}:/src
run: |
ls /src
cmake -S /src --preset clang-tidy
cmake --build /src/build/clang-tidy
65 changes: 19 additions & 46 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
name: Build and deploy to testing server
on: workflow_call
name: Build Docker Image
on:
workflow_call:
inputs:
tags:
description: List of tags of the resulting Docker image
required: true
type: string
target:
description: Sets the target stage to build
required: true
type: string

jobs:
build-docker:
Expand All @@ -16,54 +26,17 @@ jobs:
with:
context: .
push: false
target: production
tags: anydistro/bxt:latest
cache-from: type=gha
cache-to: type=gha,mode=max
outputs: type=docker,dest=./bxt-production.tar
target: ${{ inputs.target }}
tags: ${{ inputs.tags }}
cache-from: type=gha,scope=${{ inputs.target }}
cache-to: type=gha,mode=max,scope=${{ inputs.target }}
outputs: type=docker,dest=./bxt-${{ inputs.target }}.tar

- name: Upload Docker image to artifacts
uses: actions/upload-artifact@v4
with:
name: bxt-production-image
name: bxt-${{ inputs.target }}-image
path: |
bxt-production.tar
bxt-${{ inputs.target }}.tar
docker-compose.yml
docker-compose.caddy.yml
deploy-ssh:
name: Deploy to server using ssh
needs: build-docker
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' && github.repository == 'anydistro/bxt'

steps:
- name: Download Docker image from artifacts
uses: actions/download-artifact@v4
with:
name: bxt-production-image
path: distfiles

- name: Transfer Docker image to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.DEPLOYMENT_SERVER_HOST }}
username: ${{ secrets.DEPLOYMENT_SERVER_USER }}
key: ${{ secrets.DEPLOYMENT_SERVER_SSH_KEY }}
source: distfiles/*
target: "/tmp/bxt/"

- name: Deploy Docker image on server
uses: appleboy/[email protected]
env:
CADDY_HOST: ${{ secrets.DEPLOYMENT_SERVER_HOST }}
with:
host: ${{ secrets.DEPLOYMENT_SERVER_HOST }}
username: ${{ secrets.DEPLOYMENT_SERVER_USER }}
key: ${{ secrets.DEPLOYMENT_SERVER_SSH_KEY }}
envs: CADDY_HOST
script: |
cd /tmp/bxt/distfiles/
docker compose -f docker-compose.yml -f docker-compose.caddy.yml down production || true
docker load -i bxt-production.tar
docker compose -f docker-compose.yml -f docker-compose.caddy.yml -p bxt up -d production
22 changes: 21 additions & 1 deletion .github/workflows/change.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,33 @@ name: CI
on:
- push
- pull_request

jobs:
message-lint:
uses: ./.github/workflows/commit-lint.yml
with:
upstream-repo: https://github.com/anydistro/bxt.git
check-format:
uses: ./.github/workflows/check-format.yml
build:

prod-build:
uses: ./.github/workflows/build.yml
secrets: inherit
with:
tags: anydistro/bxt:latest
target: production
dev-build:
uses: ./.github/workflows/build.yml
secrets: inherit
with:
tags: anydistro/bxt-development:latest
target: development

analysis:
uses: ./.github/workflows/analysis.yml
needs: dev-build
secrets: inherit
deploy:
uses: ./.github/workflows/deploy.yml
needs: prod-build
secrets: inherit
39 changes: 39 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Deploy Docker Image to Server
on: workflow_call

jobs:
deploy-ssh:
name: SSH to testing server
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master' && github.repository == 'anydistro/bxt'

steps:
- name: Download Docker image from artifacts
uses: actions/download-artifact@v4
with:
name: bxt-production-image
path: distfiles

- name: Transfer Docker image to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.DEPLOYMENT_SERVER_HOST }}
username: ${{ secrets.DEPLOYMENT_SERVER_USER }}
key: ${{ secrets.DEPLOYMENT_SERVER_SSH_KEY }}
source: distfiles/*
target: "/tmp/bxt/"

- name: Deploy Docker image on server
uses: appleboy/[email protected]
env:
CADDY_HOST: ${{ secrets.DEPLOYMENT_SERVER_HOST }}
with:
host: ${{ secrets.DEPLOYMENT_SERVER_HOST }}
username: ${{ secrets.DEPLOYMENT_SERVER_USER }}
key: ${{ secrets.DEPLOYMENT_SERVER_SSH_KEY }}
envs: CADDY_HOST
script: |
cd /tmp/bxt/distfiles/
docker compose -f docker-compose.yml -f docker-compose.caddy.yml down production || true
docker load -i bxt-production.tar
docker compose -f docker-compose.yml -f docker-compose.caddy.yml -p bxt up -d production
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ include("${CMAKE_SOURCE_DIR}/cmake/bundled-deps.cmake")
################################################################################
include("${CMAKE_SOURCE_DIR}/cmake/deps.cmake")

################################################################################
# Static Analysis: Enable Clang-Tidy
################################################################################
option(ENABLE_CLANG_TIDY "Enable Clang-Tidy checks" OFF)
if(ENABLE_CLANG_TIDY)
find_program(CLANG_TIDY_EXE NAMES clang-tidy clang-tidy-18)

if(CLANG_TIDY_EXE)
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-header-filter=${CMAKE_SOURCE_DIR}/daemon/.*")
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
else()
message(SEND_ERROR "clang-tidy not found.")
endif()
endif()

################################################################################
# Project Structure: Add subdirectories for different components
Expand Down
10 changes: 9 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@
"name": "debug",
"inherits": "base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "clang-tidy",
"inherits": "debug",
"cacheVariables": {
"ENABLE_CLANG_TIDY": "ON"
}
},
{
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ apt-get install --yes \
build-essential \
clang-18 \
clang-format-18 \
clang-tidy-18 \
clangd-18 \
cmake \
curl \
Expand Down
7 changes: 7 additions & 0 deletions tooling/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Developer Tooling

The Clang-Tidy helper script can be run on an already existing development build in a dev container with:

```
/bin/python3 /workspaces/source/tooling/clang-tidy.py -p /workspaces/source/build/debug -clang-version 18 -header-filter=/workspaces/source/daemon/.*
```
99 changes: 99 additions & 0 deletions tooling/clang-tidy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python

# SPDX-FileCopyrightText: 2024 Roman Gilg <[email protected]>
# SPDX-License-Identifier: MIT

import argparse, os, subprocess, sys, tempfile
from shutil import which

script_dir = os.path.dirname(os.path.realpath(__file__))
source_dir = os.path.dirname(os.path.dirname(script_dir))


def parse_arguments():
parser = argparse.ArgumentParser(
description="Run clang-tidy script with additional options"
)
parser.add_argument(
"-p",
dest="build_path",
required=True,
help="path used to read a compile command database",
)
parser.add_argument(
"-j",
type=int,
default=0,
help="number of tidy instances to be run in parallel",
)
parser.add_argument(
"-clang-version",
dest="clang_version",
type=int,
default=-1,
help="clang-version to use (defaults to development version)",
)
parser.add_argument(
"-clang-tidy-binary",
dest="clang_tidy_path",
default="",
help="path to clant-tidy binary",
)
parser.add_argument(
"-header-filter",
dest="header_filter",
default=".*",
help="regular expression matching the names of the headers to output diagnostics from",
)
return parser.parse_args()


args = parse_arguments()
os.chdir(source_dir)


def get_binary_args():
add_args = ["-clang-tidy-binary"]

if args.clang_tidy_path:
return add_args + [args.clang_tidy_path]

if args.clang_version > 0:
versioned_path = which("clang-tidy-" + str(args.clang_version))
if versioned_path is not None:
return add_args + [versioned_path]
return []


# Additional arguments for run-clang-tidy.py
additional_args = [
"-use-color",
"-j",
str(args.j),
"-p=" + args.build_path,
"-header-filter=" + args.header_filter,
]
additional_args += get_binary_args()

if args.clang_version > 0:
run_script_url = (
"https://raw.githubusercontent.com/llvm/llvm-project/release/"
+ str(args.clang_version)
+ ".x/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py"
)
else:
run_script_url = "https://raw.githubusercontent.com/llvm/llvm-project/main/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py"

# Download the run-clang-tidy.py script and save it as a temporary file
with tempfile.NamedTemporaryFile(mode="w") as temp_file:
curl_process = subprocess.Popen(["curl", "-s", run_script_url], stdout=temp_file)
curl_process.wait()
run_clang_tidy_script_path = temp_file.name

# Execute the modified script using Python with additional arguments
python_process = subprocess.Popen(
[sys.executable, run_clang_tidy_script_path] + additional_args + [source_dir],
stdin=subprocess.PIPE,
)
python_process.communicate()
exit(python_process.returncode)

0 comments on commit d0cf004

Please sign in to comment.