Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 129 additions & 32 deletions .github/workflows/ci.yml
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,21 @@ jobs:

- name: Build and Start Docker Compose
run: |
docker-compose up -d --build
docker-compose up -d

- name: Run C Static Analysis
run: |
docker-compose exec -T app bash -c "dos2unix /workspace/ContinuousIntegration/run_c_static_code_analysis.sh && bash /workspace/ContinuousIntegration/run_c_static_code_analysis.sh"
docker-compose exec -T ionizationchamber bash -c "python3 -m venv /workspace/venv && source /workspace/venv/bin/activate && cd /workspace/build && cmake .. && make cstatic"

- name: Copy C Analysis Reports to Host
run: |
docker cp app:/workspace/build/C_Lint_ReportApplicationOnly.txt .
docker cp app:/workspace/build/C_Lint_ReportFull.txt .
docker cp ionizationchamber:/workspace/DevOps/BuildArtifacts/CStaticAnalysis .

- name: Archive C Analysis Reports
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: c-lint-reports
path: |
C_Lint_ReportApplicationOnly.txt
C_Lint_ReportFull.txt
path: CStaticAnalysis

- name: Clean Up Containers
run: |
Expand All @@ -60,28 +57,28 @@ jobs:

- name: Build and Start Docker Compose
run: |
docker-compose up -d --build
docker-compose up -d

- name: Run Python Static Analysis
run: |
docker-compose exec -T app bash -c "dos2unix /workspace/ContinuousIntegration/run_python_static_code_analysis.sh && bash /workspace/ContinuousIntegration/run_python_static_code_analysis.sh"
docker-compose exec -T ionizationchamber bash -c "python3 -m venv /workspace/venv && source /workspace/venv/bin/activate && pip install -e /workspace/Software/MeasurementAcquisition && cd /workspace/build/ && cmake .. && make pystatic"

- name: Copy Python Analysis Reports to Host
run: |
docker cp app:/workspace/build/python_lint_report ./python_lint_report
docker cp ionizationchamber:/workspace/DevOps/BuildArtifacts/PyStaticAnalysis .

- name: Archive Python Analysis Reports
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: python-lint-reports
path: python_lint_report
path: PyStaticAnalysis

- name: Clean Up Containers
run: |
docker-compose down

run-shell-static-analysis:
name: Run Shell Static Analysis
run-r-static-analysis:
name: Run R Static Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout Code
Expand All @@ -94,21 +91,21 @@ jobs:

- name: Build and Start Docker Compose
run: |
docker-compose up -d --build
docker-compose up -d

- name: Run Shell Static Analysis
- name: Run R Static Analysis
run: |
docker-compose exec -T app bash -c "dos2unix /workspace/ContinuousIntegration/run_shellscripts_static_code_analysis.sh && bash /workspace/ContinuousIntegration/run_shellscripts_static_code_analysis.sh"
docker-compose exec -T ionizationchamber bash -c "source /workspace/venv/bin/activate && cd /workspace/build && cmake .. && make rstatic"

- name: Copy Shell Analysis Report to Host
- name: Copy R Analysis Reports to Host
run: |
docker cp app:/workspace/build/Shell_Script_Lint_Report.txt Shell_Script_Lint_Report.txt
docker cp ionizationchamber:/workspace/DevOps/BuildArtifacts/RStaticAnalysis .

- name: Archive Shell Analysis Report
uses: actions/upload-artifact@v3
- name: Archive R Analysis Reports
uses: actions/upload-artifact@v4
with:
name: shell-lint-report
path: Shell_Script_Lint_Report.txt
name: r-lint-reports
path: RStaticAnalysis

- name: Clean Up Containers
run: |
Expand All @@ -128,29 +125,129 @@ jobs:

- name: Build and Start Docker Compose
run: |
docker-compose up -d --build
docker-compose up -d

- name: Build Firmware
run: |
docker-compose exec -T app bash -c "cd /workspace/build && cmake ../Software/Firmware/ && make -j$(nproc)"
docker-compose exec -T ionizationchamber bash -c "mkdir -p /workspace/build/firmware && cd /workspace/build/firmware && cmake -DCMAKE_TOOLCHAIN_FILE=/workspace/Software/Firmware/sdcc-stm8.cmake -B . -S /workspace/Software/Firmware/ && cmake --build . -j$(nproc)"

- name: Copy Firmware Files to Host
run: |
docker cp app:/workspace/build/IonizationChamber.cdb .
docker cp app:/workspace/build/IonizationChamber.lk .
docker cp app:/workspace/build/IonizationChamber.ihx .
docker cp app:/workspace/build/IonizationChamber.map .
docker cp ionizationchamber:/workspace/build/firmware/IonizationChamber.lk .
docker cp ionizationchamber:/workspace/build/firmware/IonizationChamber.ihx .
docker cp ionizationchamber:/workspace/build/firmware/IonizationChamber.map .

- name: Archive Firmware Build Artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: firmware-build-artifacts
path: |
IonizationChamber.cdb
IonizationChamber.lk
IonizationChamber.ihx
IonizationChamber.map

- name: Clean Up Containers
run: |
docker-compose down

docs-coverage:
name: Documentation Coverage
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Docker Compose
run: |
sudo apt-get update
sudo apt-get install -y docker-compose

- name: Build and Start Docker Compose
run: |
docker-compose up -d

- name: Generate Documentation
run: |
docker-compose exec -T ionizationchamber bash -c "python3 -m venv /workspace/venv && source /workspace/venv/bin/activate && cd /workspace/build/ && cmake .. && make docs"

- name: Copy Documentation Coverage Report
run: |
docker cp ionizationchamber:/workspace/DevOps/BuildArtifacts/DocsCoverage .

- name: Archive Documentation Coverage
uses: actions/upload-artifact@v4
with:
name: docs-coverage-report
path: DocsCoverage

- name: Clean Up Containers
run: |
docker-compose down

c-code-coverage:
name: C Code Coverage
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Docker Compose
run: |
sudo apt-get update
sudo apt-get install -y docker-compose

- name: Build and Start Docker Compose
run: |
docker-compose up -d

- name: Generate C Code Coverage
run: |
docker-compose exec -T ionizationchamber bash -c "mkdir -p /workspace/build/ut && cd /workspace/build/ut && cmake -DCMAKE_BUILD_TYPE=Debug /workspace/Software/Firmware/UnitTest/ && make -j$(nproc) && make run_all_tests && make coverage"

- name: Copy C Code Coverage Report
run: |
docker cp ionizationchamber:/workspace/DevOps/BuildArtifacts/CCodeCoverage .

- name: Archive C Code Coverage
uses: actions/upload-artifact@v4
with:
name: c-code-coverage-report
path: CCodeCoverage

- name: Clean Up Containers
run: |
docker-compose down

run-python-code-coverage:
name: Run Python Code Coverage
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Docker Compose
run: |
sudo apt-get update
sudo apt-get install -y docker-compose

- name: Build and Start Docker Compose
run: |
docker-compose up -d

- name: Run Python Code Coverage
run: |
docker-compose exec -T ionizationchamber bash -c "source /workspace/venv/bin/activate && cd /workspace/build && cmake .. && make pycoverage"

- name: Copy Python Analysis Reports to Host
run: |
docker cp ionizationchamber:/workspace/DevOps/BuildArtifacts/PyCodeCoverage .

- name: Archive Python Analysis Reports
uses: actions/upload-artifact@v4
with:
name: python-code-coverage-reports
path: PyCodeCoverage

- name: Clean Up Containers
run: |
docker-compose down
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.31)
project(IoninizationChamberCodeQuality)

add_subdirectory(Software/Firmware/UnitTest/)

include(DevOps/Cmake/DocsCoverage.cmake)
include(DevOps/Cmake/PyStaticAnalysis.cmake)
include(DevOps/Cmake/PyCodeCoverage.cmake)
include(DevOps/Cmake/CStaticAnalysis.cmake)
include(DevOps/Cmake/RStaticAnalysis.cmake)
include(DevOps/Cmake/CodeBeautifier.cmake)
8 changes: 8 additions & 0 deletions DevOps/BuildArtifacts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
DocsCoverage/
PyStaticAnalysis/
PyCodeCoverage/
CStaticAnalysis/
CCodeCoverage/
RStaticAnalysis/
*.png
*.svg
Empty file added DevOps/BuildArtifacts/.gitkeep
Empty file.
88 changes: 88 additions & 0 deletions DevOps/Cmake/CStaticAnalysis.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
cmake_minimum_required(VERSION 3.31)

# Get the number of available processors
include(ProcessorCount)
ProcessorCount(NPROC)
if(NOT NPROC OR NPROC EQUAL 0)
set(NPROC 1) # Fallback to 1 if ProcessorCount fails
endif()

# Define the source directories to analyze
set(CODECHECKER_SOURCE_DIRS
"${CMAKE_SOURCE_DIR}/Software/Firmware/Application"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Device"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Driver"
"${CMAKE_SOURCE_DIR}/Software/Firmware/UnitTest")

# Define the output directories for CodeChecker analysis and reports
set(CODECHECKER_ANALYZE_DIR /tmp/StaticAnalysisIntermediary)
set(CODECHECKER_REPORT_DIR ${CMAKE_SOURCE_DIR}/DevOps/BuildArtifacts/CStaticAnalysis)
set(CODECHECKER_SKIP_FILE ${CMAKE_SOURCE_DIR}/DevOps/Scripts/CodeCheckerSkipList)

# Ensure the output directories exist
file(MAKE_DIRECTORY ${CODECHECKER_ANALYZE_DIR})
file(MAKE_DIRECTORY ${CODECHECKER_REPORT_DIR})

# Add a custom target for CodeChecker analysis
add_custom_target(cstatic

COMMAND CodeChecker analyze compile_commands.json
--output ${CODECHECKER_ANALYZE_DIR}
--file ${CODECHECKER_SOURCE_DIRS}
--skip ${CODECHECKER_SKIP_FILE}
--jobs ${NPROC}
--enable-all
#--disable checker:clang-diagnostic-c++98-compat
#--disable modernize-use-trailing-return-type
#--disable readability-identifier-length
#--disable readability-uppercase-literal-suffix
#--disable modernize-avoid-c-arrays
#--disable modernize-use-auto
--disable altera-unroll-loops
#--disable cppcheck-missingIncludeSystem
#--disable cppcheck-toomanyconfigs
#--disable checker:clang-diagnostic-padded
--disable altera-struct-pack-align
#--disable clang-diagnostic-weak-vtables
#--disable altera-id-dependent-backward-branch
--disable bugprone-easily-swappable-parameters
#--disable clang-diagnostic-covered-switch-default
# project specific
--disable modernize-macro-to-enum
--disable clang-diagnostic-declaration-after-statement
--disable optin.core.EnumCastOutOfRange # https://github.com/llvm/llvm-project/issues/76208
--disable checker:clang-diagnostic-unsafe-buffer-usage # https://stackoverflow.com/questions/77017567/how-to-fix-code-to-avoid-warning-wunsafe-buffer-usage
--disable security.insecureAPI.DeprecatedOrUnsafeBufferHandling # we dont use string-related functions due to STM8 binary size limitation
COMMENT "Running CodeChecker analysis..."

COMMAND CodeChecker parse ${CODECHECKER_ANALYZE_DIR}
--skip ${CODECHECKER_SKIP_FILE}
--export html
--output ${CODECHECKER_REPORT_DIR}
COMMENT "Generating CodeChecker HTML report..."

VERBATIM
)

# Add a custom command to generate the HTML report
add_custom_command(TARGET cstatic POST_BUILD
COMMAND CodeChecker parse ${CODECHECKER_ANALYZE_DIR}
--skip ${CODECHECKER_SKIP_FILE}
--export html
--output ${CODECHECKER_REPORT_DIR}
COMMENT "Generating CodeChecker HTML report..."
VERBATIM
)

# Add a custom command to check for errors and fail the build if any are found
add_custom_command(TARGET cstatic POST_BUILD
COMMAND bash -c "if [ -n \"\$(CodeChecker parse ${CODECHECKER_ANALYZE_DIR} | grep -i 'error')\" ]; then echo 'CodeChecker found errors!'; exit 1; fi"
COMMENT "Failing the build if CodeChecker finds errors..."
VERBATIM
)

# Message if CodeChecker is not found (optional)
find_program(CODECHECKER_EXECUTABLE CodeChecker)
if(NOT CODECHECKER_EXECUTABLE)
message(WARNING "CodeChecker not found. Skipping static analysis.")
endif()
42 changes: 42 additions & 0 deletions DevOps/Cmake/CodeBeautifier.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 3.31)

find_program(UNCRUSTIFY uncrustify)
find_program(RSCRIPT Rscript)
find_program(BLACK black)
# Get all files
file(GLOB MODIFY_FILES
"${CMAKE_SOURCE_DIR}/Software/Firmware/*.c"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Application/*.h"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Application/*.c"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Device/*.h"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Device/*.c"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Driver/*.h"
"${CMAKE_SOURCE_DIR}/Software/Firmware/Driver/*.c"
"${CMAKE_SOURCE_DIR}/Software/Firmware/UnitTest/*.h"
"${CMAKE_SOURCE_DIR}/Software/Firmware/UnitTest/*.c"
)

# Files to exclude
set(EXCLUDE_FILES
# "${CMAKE_SOURCE_DIR}/Software/Firmware/Driver/interrupt_handler.h"
# "${CMAKE_SOURCE_DIR}/Software/Firmware/Driver/interrupt_handler.c"
)

# Remove excluded files
list(REMOVE_ITEM MODIFY_FILES ${EXCLUDE_FILES})

add_custom_target(style
COMMAND ${UNCRUSTIFY} -c "${CMAKE_SOURCE_DIR}/DevOps/Scripts/uncrustify.cfg" --replace --no-backup ${MODIFY_FILES}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
COMMENT "Running uncrustify on source directories"

COMMAND ${BLACK} "${CMAKE_SOURCE_DIR}/Software/MeasurementAcquisition"
COMMAND ${BLACK} "${CMAKE_SOURCE_DIR}/Simulation"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
COMMENT "Running black on source directories"

COMMAND ${RSCRIPT} "${CMAKE_SOURCE_DIR}/Software/MeasurementAnalysis"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
COMMENT "Running styler (R language formatter) on source directories"
VERBATIM
)
Loading