From f7b357be4f1c4dfc9808cd9012e34142b27397e6 Mon Sep 17 00:00:00 2001 From: Ron <45816308+rjaegers@users.noreply.github.com> Date: Wed, 8 May 2024 15:51:10 +0200 Subject: [PATCH] feat: add rust container flavor (#351) * feat: add rust container flavor * ci: fix linter findings * ci: ignore some linter findings * ci: run for all flavours * ci: fix tests for rust container flavor * chore: add pkg-config * ci: fix linter findings * chore: modify build and push workflow for flavors * chore: reduce container size * chore: add Docker extension to devcontainer.json * chore: update rust from 1.76.0 to 1.77.2 * ci: publish result of all testsuites * ci: fix duplicate artifact * Update ci.yml * ci: different fix for multiple artifacts * ci: update all automation to cope with multiple containers * chore: move update-apt-packages to own action * chore: add flip-link package * chore: process review comments * chore: merge the -vscode image into the main image * Update build-push.yml * chore: minor fix after merge * chore: move Rust container to Ubuntu 24.04 * chore: update Rust to latest version * chore: update Docker cli from 25.0.3 to 26.1.1 * chore: add more test for Rust container * chore: reduce duplication in test code * chore: add test for coverage * chore: remove unused bats tags * chore: don't use run in bats tests when not needed See also: https://bats-core.readthedocs.io/en/stable/writing-tests.html#when-not-to-use-run * chore: add mutation testing support to Rust container * chore: correct test name to beter reflect its actual scope * docs: update documentation --- .devcontainer/{ => cpp}/Dockerfile | 8 +- .../{ => cpp}/apt-requirements-base.json | 0 .../{ => cpp}/apt-requirements-clang.json | 0 .../devcontainer-metadata-vscode.json | 0 .devcontainer/{ => cpp}/devcontainer.json | 9 +- .devcontainer/{ => cpp}/requirements.in | 0 .devcontainer/{ => cpp}/requirements.txt | 0 .../cpp/test}/CMakeLists.txt | 3 +- .../cpp/test}/CMakePresets.json | 0 .../cpp/test}/clang-cl/CMakeLists.txt | 0 .../cpp/test}/clang-cl/main.cpp | 0 .../cpp/test}/clang-cl/toolchain.cmake | 0 .../cpp/test}/clang-tools/CMakeLists.txt | 0 .../cpp/test}/clang-tools/main.cpp | 0 .../cpp/test}/clang-tools/unformatted.cpp | 0 .../cpp/test}/coverage/CMakeLists.txt | 0 .../cpp/test}/coverage/test.cpp | 0 .../cpp/test}/fuzzing/CMakeLists.txt | 0 .../cpp/test}/fuzzing/main.cpp | 0 .../test}/gcc-arm-none-eabi/CMakeLists.txt | 0 .../cpp/test}/gcc-arm-none-eabi/main.cpp | 0 .../test}/gcc-arm-none-eabi/toolchain.cmake | 0 .../cpp/test}/gcc/CMakeLists.txt | 0 .../cpp/test}/gcc/main-fail.cpp | 0 {test => .devcontainer/cpp/test}/gcc/main.cpp | 0 .../cpp/test}/sanitizers/CMakeLists.txt | 0 .../cpp/test}/sanitizers/asan.cpp | 0 .../cpp/test}/sanitizers/memsan.cpp | 0 .../cpp/test}/sanitizers/threadsan.cpp | 0 .../cpp/test}/sanitizers/ubsan.cpp | 0 .devcontainer/cpp/test/test/CMakeLists.txt | 31 +++ .../cpp/test/test}/test.cpp | 0 .../cpp/test}/testsuite.bats | 152 +++-------- .devcontainer/rust/Dockerfile | 60 ++++ .devcontainer/rust/apt-requirements-base.json | 9 + .../rust/devcontainer-metadata-vscode.json | 18 ++ .devcontainer/rust/devcontainer.json | 27 ++ .devcontainer/rust/test/cargo/Cargo.lock | 7 + .devcontainer/rust/test/cargo/Cargo.toml | 4 + .devcontainer/rust/test/cargo/src/main.rs | 3 + .devcontainer/rust/test/clippy/Cargo.lock | 7 + .devcontainer/rust/test/clippy/Cargo.toml | 4 + .devcontainer/rust/test/clippy/src/main.rs | 3 + .../rust/test/cortex-m/.cargo/config.toml | 2 + .devcontainer/rust/test/cortex-m/Cargo.lock | 257 ++++++++++++++++++ .devcontainer/rust/test/cortex-m/Cargo.toml | 9 + .devcontainer/rust/test/cortex-m/src/main.rs | 15 + .devcontainer/rust/test/rust/fail.rs | 1 + .devcontainer/rust/test/rust/hello.rs | 3 + .devcontainer/rust/test/rust/unformatted.rs | 4 + .devcontainer/rust/test/test/Cargo.lock | 7 + .devcontainer/rust/test/test/Cargo.toml | 4 + .devcontainer/rust/test/test/src/main.rs | 24 ++ .devcontainer/rust/test/testsuite.bats | 96 +++++++ .devcontainer/update-apt-dependencies.sh | 17 -- .github/ISSUE_TEMPLATE/bug_report.md | 5 +- .../actions/update-apt-packages/action.yml | 33 +++ .../update-apt-packages.sh | 24 ++ .github/workflows/build-push.yml | 65 ++--- .github/workflows/ci.yml | 32 ++- .github/workflows/pr-image-cleanup.yml | 14 +- .github/workflows/prime-cache.yml | 7 +- .github/workflows/update-dependencies.yml | 26 +- .github/workflows/vulnerability-scan.yml | 5 +- .gitignore | 4 + .vscode/tasks.json | 2 +- README.md | 49 ++-- test/mutation/CMakeLists.txt | 19 -- 68 files changed, 819 insertions(+), 250 deletions(-) rename .devcontainer/{ => cpp}/Dockerfile (95%) rename .devcontainer/{ => cpp}/apt-requirements-base.json (100%) rename .devcontainer/{ => cpp}/apt-requirements-clang.json (100%) rename .devcontainer/{ => cpp}/devcontainer-metadata-vscode.json (100%) rename .devcontainer/{ => cpp}/devcontainer.json (71%) rename .devcontainer/{ => cpp}/requirements.in (100%) rename .devcontainer/{ => cpp}/requirements.txt (100%) rename {test => .devcontainer/cpp/test}/CMakeLists.txt (84%) rename {test => .devcontainer/cpp/test}/CMakePresets.json (100%) rename {test => .devcontainer/cpp/test}/clang-cl/CMakeLists.txt (100%) rename {test => .devcontainer/cpp/test}/clang-cl/main.cpp (100%) rename {test => .devcontainer/cpp/test}/clang-cl/toolchain.cmake (100%) rename {test => .devcontainer/cpp/test}/clang-tools/CMakeLists.txt (100%) rename {test => .devcontainer/cpp/test}/clang-tools/main.cpp (100%) rename {test => .devcontainer/cpp/test}/clang-tools/unformatted.cpp (100%) rename {test => .devcontainer/cpp/test}/coverage/CMakeLists.txt (100%) rename {test => .devcontainer/cpp/test}/coverage/test.cpp (100%) rename {test => .devcontainer/cpp/test}/fuzzing/CMakeLists.txt (100%) rename {test => .devcontainer/cpp/test}/fuzzing/main.cpp (100%) rename {test => .devcontainer/cpp/test}/gcc-arm-none-eabi/CMakeLists.txt (100%) rename {test => .devcontainer/cpp/test}/gcc-arm-none-eabi/main.cpp (100%) rename {test => .devcontainer/cpp/test}/gcc-arm-none-eabi/toolchain.cmake (100%) rename {test => .devcontainer/cpp/test}/gcc/CMakeLists.txt (100%) rename {test => .devcontainer/cpp/test}/gcc/main-fail.cpp (100%) rename {test => .devcontainer/cpp/test}/gcc/main.cpp (100%) rename {test => .devcontainer/cpp/test}/sanitizers/CMakeLists.txt (100%) rename {test => .devcontainer/cpp/test}/sanitizers/asan.cpp (100%) rename {test => .devcontainer/cpp/test}/sanitizers/memsan.cpp (100%) rename {test => .devcontainer/cpp/test}/sanitizers/threadsan.cpp (100%) rename {test => .devcontainer/cpp/test}/sanitizers/ubsan.cpp (100%) create mode 100644 .devcontainer/cpp/test/test/CMakeLists.txt rename {test/mutation => .devcontainer/cpp/test/test}/test.cpp (100%) rename {test => .devcontainer/cpp/test}/testsuite.bats (63%) create mode 100644 .devcontainer/rust/Dockerfile create mode 100644 .devcontainer/rust/apt-requirements-base.json create mode 100644 .devcontainer/rust/devcontainer-metadata-vscode.json create mode 100644 .devcontainer/rust/devcontainer.json create mode 100644 .devcontainer/rust/test/cargo/Cargo.lock create mode 100644 .devcontainer/rust/test/cargo/Cargo.toml create mode 100644 .devcontainer/rust/test/cargo/src/main.rs create mode 100644 .devcontainer/rust/test/clippy/Cargo.lock create mode 100644 .devcontainer/rust/test/clippy/Cargo.toml create mode 100644 .devcontainer/rust/test/clippy/src/main.rs create mode 100644 .devcontainer/rust/test/cortex-m/.cargo/config.toml create mode 100644 .devcontainer/rust/test/cortex-m/Cargo.lock create mode 100644 .devcontainer/rust/test/cortex-m/Cargo.toml create mode 100644 .devcontainer/rust/test/cortex-m/src/main.rs create mode 100644 .devcontainer/rust/test/rust/fail.rs create mode 100644 .devcontainer/rust/test/rust/hello.rs create mode 100644 .devcontainer/rust/test/rust/unformatted.rs create mode 100644 .devcontainer/rust/test/test/Cargo.lock create mode 100644 .devcontainer/rust/test/test/Cargo.toml create mode 100644 .devcontainer/rust/test/test/src/main.rs create mode 100644 .devcontainer/rust/test/testsuite.bats delete mode 100755 .devcontainer/update-apt-dependencies.sh create mode 100644 .github/actions/update-apt-packages/action.yml create mode 100644 .github/actions/update-apt-packages/update-apt-packages.sh delete mode 100644 test/mutation/CMakeLists.txt diff --git a/.devcontainer/Dockerfile b/.devcontainer/cpp/Dockerfile similarity index 95% rename from .devcontainer/Dockerfile rename to .devcontainer/cpp/Dockerfile index a52eaaf7..abdf8105 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/cpp/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:24.04@sha256:3f85b7caad41a95462cf5b787d8a04604c8262cdcdf9a472b8c52ef ARG BATS_VERSION=1.10.0 ARG CCACHE_VERSION=4.9.1 ARG CLANG_VERSION=17 -ARG DOCKER_VERSION=25.0.3 +ARG DOCKER_VERSION=26.1.1 ARG MULL_VERSION=main ARG INCLUDE_WHAT_YOU_USE_VERSION=0.21 ARG XWIN_VERSION=0.5.0 @@ -15,7 +15,7 @@ HEALTHCHECK NONE SHELL ["/bin/bash", "-o", "pipefail", "-c"] # Install the base system with all tool dependencies -COPY .devcontainer/apt-requirements-base.json /tmp/apt-requirements-base.json +COPY .devcontainer/cpp/apt-requirements-base.json /tmp/apt-requirements-base.json # hadolint ignore=DL3008 RUN apt-get update && apt-get install -y --no-install-recommends jq \ && jq -r 'to_entries | .[] | .key + "=" + .value' /tmp/apt-requirements-base.json | xargs apt-get install -y --no-install-recommends \ @@ -27,7 +27,7 @@ RUN wget -qO /usr/local/share/ca-certificates/Cisco_Umbrella_Root_CA.crt https:/ && update-ca-certificates # Install some tools via pip to get more recent versions -COPY .devcontainer/requirements.txt /tmp/requirements.txt +COPY .devcontainer/cpp/requirements.txt /tmp/requirements.txt RUN python3 -m pip install --break-system-packages --require-hashes --no-cache-dir -r /tmp/requirements.txt \ && rm -rf /tmp/requirements.txt @@ -36,7 +36,7 @@ ENV CMAKE_GENERATOR="Ninja" ENV CMAKE_EXPORT_COMPILE_COMMANDS="On" # Install clang toolchain -COPY .devcontainer/apt-requirements-clang.json /tmp/apt-requirements-clang.json +COPY .devcontainer/cpp/apt-requirements-clang.json /tmp/apt-requirements-clang.json # hadolint ignore=SC1091 RUN wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /usr/share/keyrings/llvm-snapshot-keyring.gpg \ && UBUNTU_CODENAME=$(. /etc/os-release; echo "${UBUNTU_CODENAME/*, /}") \ diff --git a/.devcontainer/apt-requirements-base.json b/.devcontainer/cpp/apt-requirements-base.json similarity index 100% rename from .devcontainer/apt-requirements-base.json rename to .devcontainer/cpp/apt-requirements-base.json diff --git a/.devcontainer/apt-requirements-clang.json b/.devcontainer/cpp/apt-requirements-clang.json similarity index 100% rename from .devcontainer/apt-requirements-clang.json rename to .devcontainer/cpp/apt-requirements-clang.json diff --git a/.devcontainer/devcontainer-metadata-vscode.json b/.devcontainer/cpp/devcontainer-metadata-vscode.json similarity index 100% rename from .devcontainer/devcontainer-metadata-vscode.json rename to .devcontainer/cpp/devcontainer-metadata-vscode.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/cpp/devcontainer.json similarity index 71% rename from .devcontainer/devcontainer.json rename to .devcontainer/cpp/devcontainer.json index 1dd231d1..7322e7b2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/cpp/devcontainer.json @@ -1,7 +1,10 @@ { "build": { "dockerfile": "Dockerfile", - "context": ".." + "context": "../.." + }, + "remoteEnv": { + "CONTAINER_FLAVOR": "cpp" }, "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" @@ -14,9 +17,11 @@ "jetmartin.bats@0.1.10", "matepek.vscode-catch2-test-adapter@4.6.3", "mhutchie.git-graph@1.30.0", + "ms-azuretools.vscode-docker@1.29.0", "ms-vscode.cmake-tools@1.16.32", "ms-vscode.cpptools@1.18.5", - "SonarSource.sonarlint-vscode@4.1.0" + "SonarSource.sonarlint-vscode@4.1.0", + "usernamehw.errorlens@3.16.0" ] } } diff --git a/.devcontainer/requirements.in b/.devcontainer/cpp/requirements.in similarity index 100% rename from .devcontainer/requirements.in rename to .devcontainer/cpp/requirements.in diff --git a/.devcontainer/requirements.txt b/.devcontainer/cpp/requirements.txt similarity index 100% rename from .devcontainer/requirements.txt rename to .devcontainer/cpp/requirements.txt diff --git a/test/CMakeLists.txt b/.devcontainer/cpp/test/CMakeLists.txt similarity index 84% rename from test/CMakeLists.txt rename to .devcontainer/cpp/test/CMakeLists.txt index 54863d40..b565a590 100644 --- a/test/CMakeLists.txt +++ b/.devcontainer/cpp/test/CMakeLists.txt @@ -6,9 +6,8 @@ include(GoogleTest) add_subdirectory(clang-cl) add_subdirectory(clang-tools) -add_subdirectory(coverage) add_subdirectory(fuzzing) add_subdirectory(gcc) add_subdirectory(gcc-arm-none-eabi) -add_subdirectory(mutation) add_subdirectory(sanitizers) +add_subdirectory(test) diff --git a/test/CMakePresets.json b/.devcontainer/cpp/test/CMakePresets.json similarity index 100% rename from test/CMakePresets.json rename to .devcontainer/cpp/test/CMakePresets.json diff --git a/test/clang-cl/CMakeLists.txt b/.devcontainer/cpp/test/clang-cl/CMakeLists.txt similarity index 100% rename from test/clang-cl/CMakeLists.txt rename to .devcontainer/cpp/test/clang-cl/CMakeLists.txt diff --git a/test/clang-cl/main.cpp b/.devcontainer/cpp/test/clang-cl/main.cpp similarity index 100% rename from test/clang-cl/main.cpp rename to .devcontainer/cpp/test/clang-cl/main.cpp diff --git a/test/clang-cl/toolchain.cmake b/.devcontainer/cpp/test/clang-cl/toolchain.cmake similarity index 100% rename from test/clang-cl/toolchain.cmake rename to .devcontainer/cpp/test/clang-cl/toolchain.cmake diff --git a/test/clang-tools/CMakeLists.txt b/.devcontainer/cpp/test/clang-tools/CMakeLists.txt similarity index 100% rename from test/clang-tools/CMakeLists.txt rename to .devcontainer/cpp/test/clang-tools/CMakeLists.txt diff --git a/test/clang-tools/main.cpp b/.devcontainer/cpp/test/clang-tools/main.cpp similarity index 100% rename from test/clang-tools/main.cpp rename to .devcontainer/cpp/test/clang-tools/main.cpp diff --git a/test/clang-tools/unformatted.cpp b/.devcontainer/cpp/test/clang-tools/unformatted.cpp similarity index 100% rename from test/clang-tools/unformatted.cpp rename to .devcontainer/cpp/test/clang-tools/unformatted.cpp diff --git a/test/coverage/CMakeLists.txt b/.devcontainer/cpp/test/coverage/CMakeLists.txt similarity index 100% rename from test/coverage/CMakeLists.txt rename to .devcontainer/cpp/test/coverage/CMakeLists.txt diff --git a/test/coverage/test.cpp b/.devcontainer/cpp/test/coverage/test.cpp similarity index 100% rename from test/coverage/test.cpp rename to .devcontainer/cpp/test/coverage/test.cpp diff --git a/test/fuzzing/CMakeLists.txt b/.devcontainer/cpp/test/fuzzing/CMakeLists.txt similarity index 100% rename from test/fuzzing/CMakeLists.txt rename to .devcontainer/cpp/test/fuzzing/CMakeLists.txt diff --git a/test/fuzzing/main.cpp b/.devcontainer/cpp/test/fuzzing/main.cpp similarity index 100% rename from test/fuzzing/main.cpp rename to .devcontainer/cpp/test/fuzzing/main.cpp diff --git a/test/gcc-arm-none-eabi/CMakeLists.txt b/.devcontainer/cpp/test/gcc-arm-none-eabi/CMakeLists.txt similarity index 100% rename from test/gcc-arm-none-eabi/CMakeLists.txt rename to .devcontainer/cpp/test/gcc-arm-none-eabi/CMakeLists.txt diff --git a/test/gcc-arm-none-eabi/main.cpp b/.devcontainer/cpp/test/gcc-arm-none-eabi/main.cpp similarity index 100% rename from test/gcc-arm-none-eabi/main.cpp rename to .devcontainer/cpp/test/gcc-arm-none-eabi/main.cpp diff --git a/test/gcc-arm-none-eabi/toolchain.cmake b/.devcontainer/cpp/test/gcc-arm-none-eabi/toolchain.cmake similarity index 100% rename from test/gcc-arm-none-eabi/toolchain.cmake rename to .devcontainer/cpp/test/gcc-arm-none-eabi/toolchain.cmake diff --git a/test/gcc/CMakeLists.txt b/.devcontainer/cpp/test/gcc/CMakeLists.txt similarity index 100% rename from test/gcc/CMakeLists.txt rename to .devcontainer/cpp/test/gcc/CMakeLists.txt diff --git a/test/gcc/main-fail.cpp b/.devcontainer/cpp/test/gcc/main-fail.cpp similarity index 100% rename from test/gcc/main-fail.cpp rename to .devcontainer/cpp/test/gcc/main-fail.cpp diff --git a/test/gcc/main.cpp b/.devcontainer/cpp/test/gcc/main.cpp similarity index 100% rename from test/gcc/main.cpp rename to .devcontainer/cpp/test/gcc/main.cpp diff --git a/test/sanitizers/CMakeLists.txt b/.devcontainer/cpp/test/sanitizers/CMakeLists.txt similarity index 100% rename from test/sanitizers/CMakeLists.txt rename to .devcontainer/cpp/test/sanitizers/CMakeLists.txt diff --git a/test/sanitizers/asan.cpp b/.devcontainer/cpp/test/sanitizers/asan.cpp similarity index 100% rename from test/sanitizers/asan.cpp rename to .devcontainer/cpp/test/sanitizers/asan.cpp diff --git a/test/sanitizers/memsan.cpp b/.devcontainer/cpp/test/sanitizers/memsan.cpp similarity index 100% rename from test/sanitizers/memsan.cpp rename to .devcontainer/cpp/test/sanitizers/memsan.cpp diff --git a/test/sanitizers/threadsan.cpp b/.devcontainer/cpp/test/sanitizers/threadsan.cpp similarity index 100% rename from test/sanitizers/threadsan.cpp rename to .devcontainer/cpp/test/sanitizers/threadsan.cpp diff --git a/test/sanitizers/ubsan.cpp b/.devcontainer/cpp/test/sanitizers/ubsan.cpp similarity index 100% rename from test/sanitizers/ubsan.cpp rename to .devcontainer/cpp/test/sanitizers/ubsan.cpp diff --git a/.devcontainer/cpp/test/test/CMakeLists.txt b/.devcontainer/cpp/test/test/CMakeLists.txt new file mode 100644 index 00000000..60d4a9cf --- /dev/null +++ b/.devcontainer/cpp/test/test/CMakeLists.txt @@ -0,0 +1,31 @@ +option(ENABLE_COVERAGE_TEST Off) +option(ENABLE_MUTATION_TESTING_TEST Off) + +include(FetchContent) + +FetchContent_Declare(googletest + GIT_REPOSITORY https://github.com/google/googletest + GIT_TAG v1.14.0 +) + +if (ENABLE_COVERAGE_TEST) + FetchContent_MakeAvailable(googletest) + + add_executable(test-coverage EXCLUDE_FROM_ALL test.cpp) + target_compile_options(test-coverage PRIVATE + -g -O0 --coverage -fprofile-arcs -ftest-coverage -fno-inline + ) + target_link_libraries(test-coverage PRIVATE gmock_main gcov) + add_test(NAME test-coverage COMMAND test-coverage) +endif() + +if (ENABLE_MUTATION_TESTING_TEST) + FetchContent_MakeAvailable(googletest) + + add_executable(test-mutation EXCLUDE_FROM_ALL test.cpp) + target_compile_options(test-mutation PRIVATE + -g -O0 -grecord-command-line -fprofile-instr-generate -fcoverage-mapping -fpass-plugin=/usr/lib/mull-ir-frontend + ) + target_link_libraries(test-mutation PRIVATE gmock_main) + add_test(NAME test-mutation COMMAND mull-runner $) +endif() diff --git a/test/mutation/test.cpp b/.devcontainer/cpp/test/test/test.cpp similarity index 100% rename from test/mutation/test.cpp rename to .devcontainer/cpp/test/test/test.cpp diff --git a/test/testsuite.bats b/.devcontainer/cpp/test/testsuite.bats similarity index 63% rename from test/testsuite.bats rename to .devcontainer/cpp/test/testsuite.bats index 8cead042..e27540c7 100644 --- a/test/testsuite.bats +++ b/.devcontainer/cpp/test/testsuite.bats @@ -32,149 +32,105 @@ teardown() { rm -rf build crash-* } -# bats test_tags=tc:1 @test "valid code input should result in working executable using host compiler" { - run cmake --preset gcc - assert_success - - run cmake --build --preset gcc - assert_success + cmake --preset gcc + cmake --build --preset gcc run build/gcc/gcc/test-gcc assert_success assert_output "Hello World!" } -# bats test_tags=tc:2 @test "valid code input should result in elf executable using arm-none-eabi compiler" { - run cmake --preset gcc-arm-none-eabi - assert_success - - run cmake --build --preset gcc-arm-none-eabi - assert_success + cmake --preset gcc-arm-none-eabi + cmake --build --preset gcc-arm-none-eabi run readelf -h build/gcc-arm-none-eabi/gcc-arm-none-eabi/test-gcc-arm-none-eabi assert_output --partial "Type: EXEC" assert_output --partial "Machine: ARM" } -# bats test_tags=tc:3 -@test "valid code input should result in working Windows executable using clang-cl compiler" { - run cmake --preset clang-cl - assert_success - - run cmake --build --preset clang-cl - assert_success +@test "valid code input should result in Windows executable using clang-cl compiler" { + cmake --preset clang-cl + cmake --build --preset clang-cl } -# bats test_tags=tc:20 @test "compilation database should be generated on CMake configure" { - run cmake --preset gcc - [ -e build/gcc/compile_commands.json ] + cmake --preset gcc + assert [ -e build/gcc/compile_commands.json ] - run cmake --preset gcc-arm-none-eabi - [ -e build/gcc-arm-none-eabi/compile_commands.json ] + cmake --preset gcc-arm-none-eabi + assert [ -e build/gcc-arm-none-eabi/compile_commands.json ] } -# bats test_tags=tc:4 @test "invalid code input should result in failing build" { - run cmake --preset gcc - assert_success - - run cmake --build --preset gcc-fail - assert_failure + cmake --preset gcc + run ! cmake --build --preset gcc-fail } -# bats test_tags=tc:5 @test "using ccache as a compiler launcher should result in cached build using gcc compiler" { - run ccache --clear --zero-stats - - run cmake --preset gcc -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - assert_success - - run cmake --build --preset gcc - assert_success + ccache --clear --zero-stats + cmake --preset gcc -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build --preset gcc run ccache -s assert_output --partial "Hits: 0" assert_output --partial "Misses: 1" - run rm -rf build - run ccache --zero-stats - - run cmake --preset gcc -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - assert_success - - run cmake --build --preset gcc - assert_success + rm -rf build + ccache --zero-stats + cmake --preset gcc -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build --preset gcc run ccache -s assert_output --partial "Hits: 1" assert_output --partial "Misses: 0" } -# bats test_tags=tc:17 @test "using ccache as a compiler launcher should result in cached build using clang-cl compiler" { - run ccache --clear --zero-stats - - run cmake --preset clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - assert_success - - run cmake --build --preset clang-cl - assert_success + ccache --clear --zero-stats + cmake --preset clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build --preset clang-cl run ccache -s assert_output --partial "Hits: 0" assert_output --partial "Misses: 1" - run rm -rf build - run ccache --zero-stats - - run cmake --preset clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache - assert_success - - run cmake --build --preset clang-cl - assert_success + rm -rf build + ccache --zero-stats + cmake --preset clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build --preset clang-cl run ccache -s assert_output --partial "Hits: 1" assert_output --partial "Misses: 0" } -# bats test_tags=tc:6 @test "running clang-tidy as part of the build should result in warning diagnostics" { - run cmake --preset clang - assert_success + cmake --preset clang run cmake --build --preset clang-tidy assert_success assert_output --partial "warning: use a trailing return type for this function" } -# bats test_tags=tc:7 @test "running include-what-you-use as part of the build should result in warning diagnostics" { - run cmake --preset clang - assert_success + cmake --preset clang run cmake --build --preset clang-iwyu assert_success assert_output --partial "Warning: include-what-you-use reported diagnostics:" } -# bats test_tags=tc:8 @test "running clang-format should result in re-formatted code" { run clang-format clang-tools/unformatted.cpp assert_success assert_output "int main() {}" } -# bats test_tags=tc:9 @test "coverage information should be generated when running a testsuite" { - run cmake --preset coverage - assert_success - - run cmake --build --preset coverage - assert_success + cmake --preset coverage + cmake --build --preset coverage run ctest --preset coverage assert_success @@ -185,57 +141,40 @@ teardown() { assert_output --partial "GCC Code Coverage Report" } -# bats test_tags=tc:10 @test "crashes should be detected when fuzzing an executable" { - run cmake --preset clang - assert_success - - run cmake --build --preset fuzzing - assert_success + cmake --preset clang + cmake --build --preset fuzzing run build/clang/fuzzing/test-fuzzing assert_failure assert_output --partial "SUMMARY: libFuzzer: deadly signal" } -# bats test_tags=tc:11 @test "a mutation score should be calculated when mutation testing a testsuite" { - run cmake --preset mutation - assert_success - - run cmake --build --preset mutation - assert_success + cmake --preset mutation + cmake --build --preset mutation run ctest --preset mutation assert_output --partial "[info] Mutation score:" } -# bats test_tags=tc:12 @test "host gdb should be able to start" { - run gdb --version - assert_success + gdb --version } -# bats test_tags=tc:13 @test "gdb-multiarch should be able to start" { - run gdb-multiarch --version - assert_success + gdb-multiarch --version } -# bats test_tags=tc:14 @test "clangd should be able to analyze source files" { run clangd --check=gcc/main.cpp assert_success assert_output --partial "All checks completed, 0 errors" } -# bats test_tags=tc:15 @test "using lld as an alternative linker should result in working host executable" { - run cmake --preset gcc - assert_success - - run cmake --build --preset gcc-lld - assert_success + cmake --preset gcc + cmake --build --preset gcc-lld run readelf --string-dump .comment build/gcc/gcc/test-gcc-lld assert_output --partial "Linker: Ubuntu LLD" @@ -245,18 +184,15 @@ teardown() { assert_output "Hello World!" } -# bats test_tags=tc:18 @test "when the docker socket is mounted, using the docker cli should give access to the host docker daemon" { run docker info assert_success assert_output --partial "Server Version:" } -# bats test_tags=tc:21 @test "sanitizers should detect undefined or suspicious behavior in code compiled with gcc" { - run cmake --preset gcc - run cmake --build --preset gcc-sanitizers - assert_success + cmake --preset gcc + cmake --build --preset gcc-sanitizers run build/gcc/sanitizers/test-asan assert_failure @@ -267,11 +203,9 @@ teardown() { assert_output --partial "runtime error: load of null pointer" } -# bats test_tags=tc:22 @test "sanitizers should detect undefined or suspicious behavior in code compiled with clang" { - run cmake --preset clang - run cmake --build --preset clang-sanitizers - assert_success + cmake --preset clang + cmake --build --preset clang-sanitizers run build/clang/sanitizers/test-asan assert_failure diff --git a/.devcontainer/rust/Dockerfile b/.devcontainer/rust/Dockerfile new file mode 100644 index 00000000..bcb2e3b6 --- /dev/null +++ b/.devcontainer/rust/Dockerfile @@ -0,0 +1,60 @@ +FROM ubuntu:24.04@sha256:3f85b7caad41a95462cf5b787d8a04604c8262cdcdf9a472b8c52ef83375fe15 + +ARG BATS_VERSION=1.10.0 +ARG RUST_VERSION=1.78.0 +ARG RUSTUP_INIT_VERSION=1.26.0 + +ARG DEBIAN_FRONTEND=noninteractive + +HEALTHCHECK NONE + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Install the base system with all tool dependencies +COPY .devcontainer/rust/apt-requirements-base.json /tmp/apt-requirements-base.json +# hadolint ignore=DL3008 +RUN apt-get update && apt-get install -y --no-install-recommends jq \ + && jq -r 'to_entries | .[] | .key + "=" + .value' /tmp/apt-requirements-base.json | xargs apt-get install -y --no-install-recommends \ + && rm /tmp/apt-requirements-base.json \ + && rm -rf /var/lib/apt/lists/* + +# Include the Cisco Umbrella PKI Root +RUN wget -qO /usr/local/share/ca-certificates/Cisco_Umbrella_Root_CA.crt https://www.cisco.com/security/pki/certs/ciscoumbrellaroot.pem \ + && update-ca-certificates + +# Install rust +ENV RUSTUP_HOME=/usr/local/rustup \ + CARGO_HOME=/usr/local/cargo \ + PATH=/usr/local/cargo/bin:"$PATH" +RUN declare -A RUSTUP_SHA \ + RUSTUP_SHA["x86_64"]="0b2f6c8f85a3d02fde2efc0ced4657869d73fccfce59defb4e8d29233116e6db" \ + RUSTUP_SHA["aarch64"]="673e336c81c65e6b16dcdede33f4cc9ed0f08bde1dbe7a935f113605292dc800" \ + && wget -qO /tmp/rustup-init "https://static.rust-lang.org/rustup/archive/${RUSTUP_INIT_VERSION}/$(uname -m)-unknown-linux-gnu/rustup-init" \ + && echo "${RUSTUP_SHA[$(uname -m)]} /tmp/rustup-init" | sha256sum -c - \ + && chmod +x /tmp/rustup-init \ + && /tmp/rustup-init -y --no-modify-path --default-toolchain=${RUST_VERSION} --component llvm-tools --target thumbv7em-none-eabi \ + && rm -rf /tmp/rustup-init + +# Install bats +RUN batstmp="$(mktemp -d /tmp/bats-core-${BATS_VERSION}.XXXX)" \ + && wget -qO - "https://github.com/bats-core/bats-core/archive/refs/tags/v${BATS_VERSION}.tar.gz" | tar xz -C "${batstmp}" \ + && bash "${batstmp}/bats-core-${BATS_VERSION}/install.sh" /usr/local \ + && rm -rf "${batstmp}" \ + && git -C /usr/local clone -b v0.3.0 https://github.com/bats-core/bats-support.git \ + && git -C /usr/local clone -b v2.1.0 https://github.com/bats-core/bats-assert.git + +# Update all tool alternatives to the correct version +RUN update-alternatives --install /usr/bin/cc cc /usr/bin/gcc-13 20 + +# hadolint ignore=DL3008 +RUN apt-get update \ + && apt-get install -y --no-install-recommends libudev-dev \ + && cargo install cargo-binutils \ + && cargo install cargo-mutants \ + && cargo install flip-link \ + && cargo install probe-rs --features cli \ + && rm -rf "$CARGO_HOME/registry" \ + && apt-get purge -y libudev-dev \ + && apt-get autoremove -y \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* diff --git a/.devcontainer/rust/apt-requirements-base.json b/.devcontainer/rust/apt-requirements-base.json new file mode 100644 index 00000000..bff2366e --- /dev/null +++ b/.devcontainer/rust/apt-requirements-base.json @@ -0,0 +1,9 @@ +{ + "ca-certificates": "20240203", + "g++-13": "13.2.0-23ubuntu4", + "git": "1:2.43.0-1ubuntu7", + "gnupg2": "2.4.4-2ubuntu17", + "libc6-dev": "2.39-0ubuntu8.1", + "pkg-config": "1.8.1-2build1", + "wget": "1.21.4-1ubuntu4" +} diff --git a/.devcontainer/rust/devcontainer-metadata-vscode.json b/.devcontainer/rust/devcontainer-metadata-vscode.json new file mode 100644 index 00000000..c582081a --- /dev/null +++ b/.devcontainer/rust/devcontainer-metadata-vscode.json @@ -0,0 +1,18 @@ +[ + { + "remoteEnv": { + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" + }, + "customizations": { + "vscode": { + "extensions": [ + "mhutchie.git-graph@1.30.0", + "ms-vsliveshare.vsliveshare@1.0.5905", + "rust-lang.rust-analyzer@0.3.1868", + "tamasfe.even-better-toml@0.19.2", + "usernamehw.errorlens@3.16.0" + ] + } + } + } +] diff --git a/.devcontainer/rust/devcontainer.json b/.devcontainer/rust/devcontainer.json new file mode 100644 index 00000000..1278b9bb --- /dev/null +++ b/.devcontainer/rust/devcontainer.json @@ -0,0 +1,27 @@ +{ + "build": { + "dockerfile": "Dockerfile", + "context": "../.." + }, + "privileged": true, + "remoteEnv": { + "CONTAINER_FLAVOR": "rust" + }, + "mounts": [ + "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" + ], + "customizations": { + "vscode": { + "extensions": [ + "tamasfe.even-better-toml@0.19.2", + "GitHub.vscode-github-actions@0.26.2", + "GitHub.vscode-pull-request-github@0.76.1", + "jetmartin.bats@0.1.10", + "mhutchie.git-graph@1.30.0", + "ms-azuretools.vscode-docker@1.29.0", + "rust-lang.rust-analyzer@0.3.1868", + "usernamehw.errorlens@3.16.0" + ] + } + } +} diff --git a/.devcontainer/rust/test/cargo/Cargo.lock b/.devcontainer/rust/test/cargo/Cargo.lock new file mode 100644 index 00000000..ed5cc731 --- /dev/null +++ b/.devcontainer/rust/test/cargo/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "hello-cargo" +version = "0.1.0" diff --git a/.devcontainer/rust/test/cargo/Cargo.toml b/.devcontainer/rust/test/cargo/Cargo.toml new file mode 100644 index 00000000..0e0e5bd0 --- /dev/null +++ b/.devcontainer/rust/test/cargo/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "hello-cargo" +version = "0.1.0" +edition = "2021" diff --git a/.devcontainer/rust/test/cargo/src/main.rs b/.devcontainer/rust/test/cargo/src/main.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/.devcontainer/rust/test/cargo/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/.devcontainer/rust/test/clippy/Cargo.lock b/.devcontainer/rust/test/clippy/Cargo.lock new file mode 100644 index 00000000..bd0e358b --- /dev/null +++ b/.devcontainer/rust/test/clippy/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "hello-clippy" +version = "0.1.0" diff --git a/.devcontainer/rust/test/clippy/Cargo.toml b/.devcontainer/rust/test/clippy/Cargo.toml new file mode 100644 index 00000000..6b2bbb4b --- /dev/null +++ b/.devcontainer/rust/test/clippy/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "hello-clippy" +version = "0.1.0" +edition = "2021" diff --git a/.devcontainer/rust/test/clippy/src/main.rs b/.devcontainer/rust/test/clippy/src/main.rs new file mode 100644 index 00000000..fea5802f --- /dev/null +++ b/.devcontainer/rust/test/clippy/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + let _x = 3.14; +} diff --git a/.devcontainer/rust/test/cortex-m/.cargo/config.toml b/.devcontainer/rust/test/cortex-m/.cargo/config.toml new file mode 100644 index 00000000..cc80e051 --- /dev/null +++ b/.devcontainer/rust/test/cortex-m/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "thumbv7em-none-eabi" diff --git a/.devcontainer/rust/test/cortex-m/Cargo.lock b/.devcontainer/rust/test/cortex-m/Cargo.lock new file mode 100644 index 00000000..68116912 --- /dev/null +++ b/.devcontainer/rust/test/cortex-m/Cargo.lock @@ -0,0 +1,257 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aligned" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a785a543aea40f5e4e2e93bb2655d31bc21bb391fff65697150973e383f16bb" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.7", + "stable_deref_trait", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "cortex-m" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9075300b07c6a56263b9b582c214d0ff037b00d45ec9fde1cc711490c56f1bb9" +dependencies = [ + "aligned", + "bare-metal", + "bitfield", + "cortex-m 0.7.7", + "volatile-register", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "454f278bf469e2de0a4d22ea019d169d8944f86957c8207a39e3f66c32be2fc6" +dependencies = [ + "cortex-m-rt-macros", + "r0", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3aa52243e26f5922fa522b0814019e0c98fc567e2756d715dce7ad7a81f49" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "hello-cortex" +version = "0.1.0" +dependencies = [ + "cortex-m 0.6.7", + "cortex-m-rt", + "panic-halt", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r0" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] diff --git a/.devcontainer/rust/test/cortex-m/Cargo.toml b/.devcontainer/rust/test/cortex-m/Cargo.toml new file mode 100644 index 00000000..66cb5e18 --- /dev/null +++ b/.devcontainer/rust/test/cortex-m/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "hello-cortex" +version = "0.1.0" +edition = "2021" + +[dependencies] +cortex-m = "0.6.0" +cortex-m-rt = "0.6.10" +panic-halt = "0.2.0" diff --git a/.devcontainer/rust/test/cortex-m/src/main.rs b/.devcontainer/rust/test/cortex-m/src/main.rs new file mode 100644 index 00000000..f48a83a5 --- /dev/null +++ b/.devcontainer/rust/test/cortex-m/src/main.rs @@ -0,0 +1,15 @@ +#![no_std] +#![no_main] + +use panic_halt as _; + +use cortex_m::asm; +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + asm::nop(); + + loop { + } +} diff --git a/.devcontainer/rust/test/rust/fail.rs b/.devcontainer/rust/test/rust/fail.rs new file mode 100644 index 00000000..d955fb2d --- /dev/null +++ b/.devcontainer/rust/test/rust/fail.rs @@ -0,0 +1 @@ +fn main() diff --git a/.devcontainer/rust/test/rust/hello.rs b/.devcontainer/rust/test/rust/hello.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/.devcontainer/rust/test/rust/hello.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/.devcontainer/rust/test/rust/unformatted.rs b/.devcontainer/rust/test/rust/unformatted.rs new file mode 100644 index 00000000..61bf0494 --- /dev/null +++ b/.devcontainer/rust/test/rust/unformatted.rs @@ -0,0 +1,4 @@ +fn main() +{ + println!("Hello, world!"); +} diff --git a/.devcontainer/rust/test/test/Cargo.lock b/.devcontainer/rust/test/test/Cargo.lock new file mode 100644 index 00000000..39141897 --- /dev/null +++ b/.devcontainer/rust/test/test/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "test" +version = "0.1.0" diff --git a/.devcontainer/rust/test/test/Cargo.toml b/.devcontainer/rust/test/test/Cargo.toml new file mode 100644 index 00000000..709c737b --- /dev/null +++ b/.devcontainer/rust/test/test/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "test" +version = "0.1.0" +edition = "2021" diff --git a/.devcontainer/rust/test/test/src/main.rs b/.devcontainer/rust/test/test/src/main.rs new file mode 100644 index 00000000..82d12e25 --- /dev/null +++ b/.devcontainer/rust/test/test/src/main.rs @@ -0,0 +1,24 @@ +fn factorial(number: i128) -> i128 { + let mut factorial: i128 = 1; + + for i in 1..(number + 1) { + factorial *= i; + } + + return factorial; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_negative() { + assert_eq!(factorial(-1), 1); + } + + #[test] + fn test_zero() { + assert_eq!(factorial(0), 1); + } +} diff --git a/.devcontainer/rust/test/testsuite.bats b/.devcontainer/rust/test/testsuite.bats new file mode 100644 index 00000000..76c3070e --- /dev/null +++ b/.devcontainer/rust/test/testsuite.bats @@ -0,0 +1,96 @@ +#!/usr/bin/env bats + +setup() { + load '/usr/local/bats-support/load' + load '/usr/local/bats-assert/load' +} + +teardown() { + rm -rf build ./**/target ./**/default*.prof* ./**/mutants.out +} + +@test "valid code input should result in working executable targeting the host architecture" { + rustc --out-dir build rust/hello.rs + + run build/hello + assert_success + assert_output "Hello, world!" +} + +@test "valid code input should result in working elf executable targeting the cortex-m architecture" { + pushd cortex-m + + cargo build + + run cargo readobj --bin hello-cortex -- --file-headers + assert_output --partial "Class: ELF32" + assert_output --partial "Type: EXEC" + assert_output --partial "Machine: ARM" + + popd +} + +@test "using cargo run should result in working executable" { + pushd cargo + + run cargo run + assert_success + assert_output --partial "Hello, world!" + + popd +} + +@test "invalid code input should result in failing build" { + run rustc rust/fail.rs + assert_failure + assert_output --partial "error: " +} + +@test "running clippy should result in warning diagnostics" { + pushd clippy + + run cargo clippy + assert_failure + assert_output --partial "approximate value of" + + popd +} + +@test "running rustfmt should result in re-formatted code" { + run rustfmt --color=never --check rust/unformatted.rs + assert_failure + assert_output --partial - < $FILE -done diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8655e992..6f3ccd37 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -24,9 +24,10 @@ A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. **Environment (please complete the following information):** +- Container: [e.g. ghcr.io/philips-software/amp-devcontainer-cpp:1.0.0] - OS: [e.g. Windows, Linux, OSX] -- Architecture [e.g. x86_64, Apple M2] -- Docker Version [e.g. Docker Desktop 4.25.2] +- Architecture: [e.g. x86_64, Apple M2] +- Docker Version: [e.g. Docker Desktop 4.25.2] **Additional context** Add any other context about the problem here. diff --git a/.github/actions/update-apt-packages/action.yml b/.github/actions/update-apt-packages/action.yml new file mode 100644 index 00000000..bbbcf1c0 --- /dev/null +++ b/.github/actions/update-apt-packages/action.yml @@ -0,0 +1,33 @@ +--- +name: "Update apt packages" +description: "Updates version-pinned apt packages in JSON files" + +inputs: + input-file: + description: "Input file(s) in JSON format containing a list of version pinned apt packages" + required: true + +outputs: + updated-dependencies: + description: "JSON array with the names of the updated dependencies" + value: ${{ steps.update-extensions.outputs.updated-dependencies }} + +runs: + using: "composite" + steps: + - run: echo "$GITHUB_ACTION_PATH" >> "$GITHUB_PATH" + shell: bash + env: + GITHUB_ACTION_PATH: ${{ github.action_path }} + - run: | + sudo apt-get update + sudo apt-get install --no-install-recommends -y jq + shell: bash + - run: | + update-apt-packages.sh ${INPUT_FILE} + echo "updated-dependencies=$(cat updated-packages.json)" >> "${GITHUB_OUTPUT}" + rm updated-packages.json + id: update-extensions + shell: bash + env: + INPUT_FILE: ${{ inputs.input-file }} diff --git a/.github/actions/update-apt-packages/update-apt-packages.sh b/.github/actions/update-apt-packages/update-apt-packages.sh new file mode 100644 index 00000000..314292e5 --- /dev/null +++ b/.github/actions/update-apt-packages/update-apt-packages.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +set -Eeuo pipefail + +UPDATED_PACKAGES_JSON="[]" + +for FILE in "$@"; do + JSON=$(cat $FILE) + + for PACKAGE in $(echo $JSON | jq -r 'keys | .[]'); do + CURRENT_VERSION=$(apt-cache policy "$PACKAGE" | grep -oP '(?<=Installed:\s)(.+)') + CANDIDATE_VERSION=$(apt-cache policy "$PACKAGE" | grep -oP '(?<=Candidate:\s)(.+)') + if [[ $CURRENT_VERSION != $CANDIDATE_VERSION ]]; + then + UPDATED_PACKAGES_JSON=$(echo $UPDATED_PACKAGES_JSON | jq -c '. += ["'$PACKAGE'"]') + fi + + JSON=$(echo $JSON | jq '.[$package] = $version' --arg package $PACKAGE --arg version $CANDIDATE_VERSION) + done + + echo $JSON | jq . > $FILE +done + +echo "$UPDATED_PACKAGES_JSON" > updated-packages.json diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml index 91322163..e05577cc 100644 --- a/.github/workflows/build-push.yml +++ b/.github/workflows/build-push.yml @@ -28,6 +28,9 @@ jobs: # This is used to complete the identity challenge # with sigstore/fulcio when running outside of PRs. id-token: write + strategy: + matrix: + flavor: ["cpp", "rust"] steps: - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: @@ -36,8 +39,6 @@ jobs: if: github.event_name != 'merge_group' - uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 - with: - version: v0.12.1 - uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 if: github.event_name != 'merge_group' with: @@ -45,38 +46,11 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 - id: metadata-base - env: - DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index - with: - images: ${{ env.REGISTRY }}/${{ github.repository }} - # Generate Docker tags based on the following events/attributes - tags: | - type=raw,value=latest,enable={{is_default_branch}} - type=ref,event=pr - type=semver,pattern={{raw}} - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - - uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 - id: build-and-push-base - with: - file: .devcontainer/Dockerfile - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'merge_group' }} - tags: ${{ steps.metadata-base.outputs.tags }} - labels: ${{ steps.metadata-base.outputs.labels }} - annotations: ${{ steps.metadata-base.outputs.annotations }} - sbom: true - provenance: true - cache-from: type=gha - cache-to: type=gha,mode=max - - uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 - id: metadata-vscode + id: metadata env: DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index with: - images: ${{ env.REGISTRY }}/${{ github.repository }}-vscode + images: ${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }} # Generate Docker tags based on the following events/attributes tags: | type=raw,value=latest,enable={{is_default_branch}} @@ -87,36 +61,37 @@ jobs: type=semver,pattern={{major}} # Generate image LABEL for devcontainer.metadata # the sed expression is a workaround for quotes being eaten in arrays (e.g. ["x", "y", "z"] -> ["x",y,"z"]) - - run: echo "metadata=$(jq -cj '.' .devcontainer/devcontainer-metadata-vscode.json | sed 's/,"/, "/g')" >> "$GITHUB_OUTPUT" + - run: echo "metadata=$(jq -cj '.' .devcontainer/${{ matrix.flavor }}/devcontainer-metadata-vscode.json | sed 's/,"/, "/g')" >> "$GITHUB_OUTPUT" id: devcontainer-metadata - uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 - id: build-and-push-vscode + id: build-and-push with: - file: .devcontainer/Dockerfile + file: .devcontainer/${{ matrix.flavor }}/Dockerfile platforms: linux/amd64,linux/arm64 push: ${{ github.event_name != 'merge_group' }} - tags: ${{ steps.metadata-vscode.outputs.tags }} + tags: ${{ steps.metadata.outputs.tags }} labels: | - ${{ steps.metadata-vscode.outputs.labels }} + ${{ steps.metadata.outputs.labels }} devcontainer.metadata=${{ steps.devcontainer-metadata.outputs.metadata }} - annotations: ${{ steps.metadata-vscode.outputs.annotations }} + annotations: ${{ steps.metadata.outputs.annotations }} sbom: true provenance: true cache-from: type=gha + cache-to: type=gha,mode=max - uses: ./.github/actions/container-size-diff id: container-size-diff with: - from-container: ${{ env.REGISTRY }}/${{ github.repository }}:latest - to-container: ${{ env.REGISTRY }}/${{ github.repository }}@${{ steps.build-and-push-base.outputs.digest }} + from-container: ${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }}:latest + to-container: ${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }}@${{ steps.build-and-push.outputs.digest }} - uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2.9.0 with: - header: container-size-diff + header: container-size-diff-${{ matrix.flavor }} message: | ${{ steps.container-size-diff.outputs.size-diff-markdown }} - uses: anchore/sbom-action@7ccf588e3cf3cc2611714c2eeae48550fbc17552 # v0.15.11 - if: steps.build-and-push-base.outputs.digest != '' && github.event_name != 'merge_group' + if: steps.build-and-push.outputs.digest != '' && github.event_name != 'merge_group' with: - image: ${{ env.REGISTRY }}/${{ github.repository }}@${{ steps.build-and-push-base.outputs.digest }} + image: ${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }}@${{ steps.build-and-push.outputs.digest }} dependency-snapshot: true - uses: actions/dependency-review-action@0c155c5e8556a497adf53f2c18edabf945ed8e70 # v4.3.2 if: github.event_name == 'pull_request' @@ -128,8 +103,6 @@ jobs: # This step uses the GitHub OIDC identity token to provision an ephemeral certificate # against the sigstore community Fulcio instance. env: - DIGEST_BASE: ${{ steps.build-and-push-base.outputs.digest }} - DIGEST_VSCODE: ${{ steps.build-and-push-vscode.outputs.digest }} + DIGEST: ${{ steps.build-and-push.outputs.digest }} run: | - cosign sign --yes --recursive "${{ env.REGISTRY }}/${{ github.repository }}@${DIGEST_BASE}" - cosign sign --yes --recursive "${{ env.REGISTRY }}/${{ github.repository }}-vscode@${DIGEST_VSCODE}" + cosign sign --yes --recursive "${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }}@${DIGEST}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f88fb7c5..61dd2de4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,9 +16,9 @@ permissions: jobs: build-test: runs-on: ubuntu-latest - permissions: - checks: write - pull-requests: write + strategy: + matrix: + flavor: ["cpp", "rust"] steps: # While the docker/build-push-action works from the Git context, we still need # the checkout step for running our tests. @@ -28,20 +28,36 @@ jobs: - uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 - uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: - file: .devcontainer/Dockerfile + file: .devcontainer/${{ matrix.flavor }}/Dockerfile load: true - tags: ${{ github.repository }}:test + tags: ${{ github.repository }}-${{ matrix.flavor }}:test cache-from: type=gha cache-to: type=gha,mode=max - uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + if: matrix.flavor == 'cpp' with: path: test/.xwin-cache key: xwin-cache - name: Run Tests run: | set -Eeuo pipefail - docker run --rm --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock --mount type=bind,src="$(pwd)/test",dst=/ws -w /ws ${{ github.repository }}:test bats --formatter junit testsuite.bats | tee test-report.xml - - uses: EnricoMi/publish-unit-test-result-action@30eadd5010312f995f0d3b3cff7fe2984f69409e # v2.16.1 + docker run --rm --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock --mount type=bind,src="${{ github.workspace }}/.devcontainer/${{ matrix.flavor }}/test",dst=/ws -w /ws ${{ github.repository }}-${{ matrix.flavor }}:test bats --formatter junit testsuite.bats | tee test-report-${{ matrix.flavor }}.xml + - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 if: always() with: - files: test-report.xml + name: test-results-${{ matrix.flavor }} + path: test-report-*.xml + publish-test: + runs-on: ubuntu-latest + permissions: + checks: write + pull-requests: write + needs: build-test + if: always() + steps: + - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + with: + merge-multiple: true + - uses: EnricoMi/publish-unit-test-result-action@30eadd5010312f995f0d3b3cff7fe2984f69409e # v2.16.1 + with: + files: test-report-*.xml diff --git a/.github/workflows/pr-image-cleanup.yml b/.github/workflows/pr-image-cleanup.yml index 7c302ba0..7b4d43b4 100644 --- a/.github/workflows/pr-image-cleanup.yml +++ b/.github/workflows/pr-image-cleanup.yml @@ -14,6 +14,9 @@ env: jobs: delete-images: runs-on: ubuntu-latest + strategy: + matrix: + flavor: ["cpp", "rust"] permissions: packages: write steps: @@ -23,17 +26,10 @@ jobs: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - run: cosign clean -f --type=signature "${{ env.REGISTRY }}/${{ github.repository }}:pr-${{ github.event.pull_request.number }}" - - run: cosign clean -f --type=signature "${{ env.REGISTRY }}/${{ github.repository }}-vscode:pr-${{ github.event.pull_request.number }}" + - run: cosign clean -f --type=signature "${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }}:pr-${{ github.event.pull_request.number }}" - uses: bots-house/ghcr-delete-image-action@3827559c68cb4dcdf54d813ea9853be6d468d3a4 # v1.1.0 with: owner: ${{ github.repository_owner }} - name: ${{ github.event.repository.name }} - token: ${{ secrets.GITHUB_TOKEN }} - tag: pr-${{ github.event.pull_request.number }} - - uses: bots-house/ghcr-delete-image-action@3827559c68cb4dcdf54d813ea9853be6d468d3a4 # v1.1.0 - with: - owner: ${{ github.repository_owner }} - name: ${{ github.event.repository.name }}-vscode + name: ${{ github.event.repository.name }}-${{ matrix.flavor }} token: ${{ secrets.GITHUB_TOKEN }} tag: pr-${{ github.event.pull_request.number }} diff --git a/.github/workflows/prime-cache.yml b/.github/workflows/prime-cache.yml index 06a91ba7..047e3116 100644 --- a/.github/workflows/prime-cache.yml +++ b/.github/workflows/prime-cache.yml @@ -15,12 +15,15 @@ concurrency: jobs: prime-docker-cache: runs-on: ubuntu-latest + strategy: + matrix: + flavor: ["cpp", "rust"] steps: - uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 - uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 with: - file: .devcontainer/Dockerfile + file: .devcontainer/${{ matrix.flavor }}/Dockerfile platforms: linux/amd64,linux/arm64 cache-from: type=gha cache-to: type=gha,mode=max @@ -30,7 +33,7 @@ jobs: - run: | set -Eeuo pipefail mkdir test - docker run --rm --mount type=bind,src="$(pwd)/test",dst=/ws -w /ws ghcr.io/${{ github.repository }}:latest xwin --accept-license splat --preserve-ms-arch-notation + docker run --rm --mount type=bind,src="$(pwd)/test",dst=/ws -w /ws ghcr.io/${{ github.repository }}-cpp:latest xwin --accept-license splat --preserve-ms-arch-notation - uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: test/.xwin-cache diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index fe267516..566b8cb6 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -12,9 +12,12 @@ permissions: jobs: update-apt-dependencies: runs-on: ubuntu-latest + strategy: + matrix: + flavor: ["cpp", "rust"] # Using our own container is required since we need all package sources # set-up correctly. - container: ghcr.io/philips-software/amp-devcontainer:latest + container: ghcr.io/philips-software/amp-devcontainer-${{ matrix.flavor }}:latest permissions: contents: write pull-requests: write @@ -22,8 +25,10 @@ jobs: - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: persist-credentials: false - - run: ./update-apt-dependencies.sh apt-requirements-base.json apt-requirements-clang.json - working-directory: .devcontainer + - uses: ./.github/actions/update-apt-packages + id: update-packages + with: + input-file: .devcontainer/${{ matrix.flavor }}/apt-requirements-*.json - uses: philips-software/app-token-action@9f5d57062c9f2beaffafaa9a34f66f824ead63a9 # v2.0.0 id: token with: @@ -32,13 +37,16 @@ jobs: auth_type: installation - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 with: - commit-message: "chore(deps): update dependencies" - branch: feature/update-apt-dependencies - title: "chore(deps): update dependencies" + commit-message: "Update ${{ join(fromJson(steps.update-packages.outputs.updated-dependencies), ', ') }}" + branch: feature/amp-devcontainer-${{ matrix.flavor }}/update-apt-packages + title: "chore(deps,${{ matrix.flavor }}): update ${{ join(fromJson(steps.update-packages.outputs.updated-dependencies), ', ') }}" labels: dependencies,apt token: ${{ steps.token.outputs.token }} update-vscode-extensions: runs-on: ubuntu-latest + strategy: + matrix: + flavor: ["cpp", "rust"] permissions: contents: write pull-requests: write @@ -49,7 +57,7 @@ jobs: - uses: ./.github/actions/update-vscode-extensions id: update-extensions with: - input-file: .devcontainer/devcontainer-metadata-vscode.json + input-file: .devcontainer/${{ matrix.flavor }}/devcontainer-metadata-vscode.json - uses: philips-software/app-token-action@9f5d57062c9f2beaffafaa9a34f66f824ead63a9 # v2.0.0 id: token with: @@ -58,13 +66,13 @@ jobs: auth_type: installation - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 with: - commit-message: "chore(deps): update ${{ join(fromJson(steps.update-extensions.outputs.updated-dependencies), ', ') }}" + commit-message: "Update ${{ join(fromJson(steps.update-extensions.outputs.updated-dependencies), ', ') }}" branch: feature/update-vscode-extensions body: | ${{ steps.update-extensions.outputs.markdown-summary }} > [!NOTE] > Before merging this PR, please conduct a manual test checking basic functionality of the updated plug-ins. There are no automated tests for the VS Code Extension updates. - title: "chore(deps): update ${{ join(fromJson(steps.update-extensions.outputs.updated-dependencies), ', ') }}" + title: "chore(deps,${{ matrix.flavor }}): update ${{ join(fromJson(steps.update-extensions.outputs.updated-dependencies), ', ') }}" labels: dependencies,vscode-extensions token: ${{ steps.token.outputs.token }} diff --git a/.github/workflows/vulnerability-scan.yml b/.github/workflows/vulnerability-scan.yml index 037b8727..102eb6dc 100644 --- a/.github/workflows/vulnerability-scan.yml +++ b/.github/workflows/vulnerability-scan.yml @@ -11,13 +11,16 @@ permissions: {} jobs: vulnerability-scan: runs-on: ubuntu-latest + strategy: + matrix: + flavor: ["cpp", "rust"] permissions: security-events: write steps: - uses: crazy-max/ghaction-container-scan@3e9c23f89cd6b0bda949ffe14f28a3ce282323b7 # v3.0.0 id: scan with: - image: ghcr.io/${{ github.repository }}:latest + image: ghcr.io/${{ github.repository }}-${{ matrix.flavor }}:latest dockerfile: .devcontainer/Dockerfile - uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 if: steps.scan.outputs.sarif != '' diff --git a/.gitignore b/.gitignore index 4b42b9ff..25de2ddf 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ .xwin-hash/ build/ megalinter-reports/ +mutants.out/ +target/ +*.profdata +*.profraw diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6d8b0f65..955891ec 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -11,7 +11,7 @@ "command": "bats", "args": ["testsuite.bats"], "options": { - "cwd": "${workspaceFolder}/test" + "cwd": "${workspaceFolder}/.devcontainer/${env:CONTAINER_FLAVOR}/test" }, "presentation": { "reveal": "always", diff --git a/README.md b/README.md index 061dd149..aed080da 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ## Overview -This repository contains a [devcontainer](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/introduction-to-dev-containers) tailored towards modern (embedded) C++ development. +This repository contains [devcontainers](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/introduction-to-dev-containers) tailored towards modern, embedded, C++ and Rust development. ## State @@ -18,21 +18,32 @@ This repository is under active development; see [pulse](https://github.com/phil Two devcontainers are published towards the [GitHub Container Registry](https://ghcr.io/): -- [amp-devcontainer](https://github.com/orgs/philips-software/packages/container/package/amp-devcontainer); the base container including all tools mentioned below -- [amp-devcontainer-vscode](https://github.com/orgs/philips-software/packages/container/package/amp-devcontainer-vscode); as above, but including a full [Visual Studio Code](https://code.visualstudio.com/) configuration that is compatible with [GitHub Codespaces](https://github.com/features/codespaces) +- [amp-devcontainer-cpp](https://github.com/orgs/philips-software/packages/container/package/amp-devcontainer-cpp); the C++ container +- [amp-devcontainer-rust](https://github.com/orgs/philips-software/packages/container/package/amp-devcontainer-rust); the Rust container -### amp-devcontainer +Both containers include a full [Visual Studio Code](https://code.visualstudio.com/) configuration that is compatible with [GitHub Codespaces](https://github.com/features/codespaces). + +A summary of the included tools can be found below. For the full list of all included tools and tool versions see the [Dependency Graph](https://github.com/philips-software/amp-devcontainer/network/dependencies), the SBOM published with a [release](https://github.com/philips-software/amp-devcontainer/releases), or the SBOM attached to the image. + +#### amp-devcontainer-cpp + +The amp-devcontainer-cpp built from this repository contains compilers and tools to facilitate modern, embedded, C++ development. +The amp-devcontainer-cpp includes support for host- and cross-compilation using gcc, arm-gcc and clang compilers. +Next to the compilers there is support for code-coverage measurement, mutation testing (using [mull](https://github.com/mull-project/mull)), fuzzing (using [libfuzzer](https://www.llvm.org/docs/LibFuzzer.html)) and static analysis and formatting (clang-format, clang-tidy, clangd, include-what-you-use). -The amp-devcontainer built from this repository contains compilers and tools to facilitate modern (embedded) C++ development. -The amp-devcontainer includes support for host- and cross-compilation using gcc, arm-gcc and clang compilers. -Next to the compilers there is support for code-coverage measurement, mutation testing (using [mull](https://github.com/mull-project/mull)), fuzzing (using [libfuzzer](https://www.llvm.org/docs/LibFuzzer.html)) and static analysis (clang-format, clang-tidy, clangd, include-what-you-use). The default build system is set up to use CMake, Ninja and CCache. -For the full list of all included tools and tool versions see the [Dependency Graph](https://github.com/philips-software/amp-devcontainer/network/dependencies), the SBOM published with a [release](https://github.com/philips-software/amp-devcontainer/releases), or the SBOM attached to the image. +#### amp-devcontainer-rust + +The amp-devcontainer-rust built from this repository contains the Rust ecosystem and additional tools to facilitate, embedded, Rust development. +The amp-devcontainer-rust includes support for host- and cross-compilation. +Next to the Rust ecosystem there is support for code-coverage measurement, mutation testing (using [cargo-mutants](https://mutants.rs/)), fuzzing (using [rust-fuzz](https://rust-fuzz.github.io/book/introduction.html)) and static analysis and formatting (clippy, rustfmt). + +For embedded development and flashing and debugging [probe-rs](https://probe.rs/) and [flip-link](https://github.com/knurling-rs/flip-link) are included. -### amp-devcontainer-vscode +### Visual Studio Code -The amp-devcontainer-vscode is a, slightly more, opinionated variant that can be used in Visual Studio Code or GitHub Codespaces without any additional configuration. All included tools are set-up and necessary plug-ins will be installed at container start. This behavior is implemented by appending devcontainer metadata to an image label according to the [specifications](https://containers.dev/implementors/reference/#labels). It is possible to override, amend or change the options following this [merge logic](https://containers.dev/implementors/spec/#merge-logic). +Both containers can be used in Visual Studio Code or GitHub Codespaces without any additional configuration. All included tools are set-up and necessary plug-ins will be installed at container start. This behavior is implemented by appending devcontainer metadata to an image label according to the [specifications](https://containers.dev/implementors/reference/#labels). It is possible to override, amend or change the options following this [merge logic](https://containers.dev/implementors/spec/#merge-logic). ## Usage @@ -42,16 +53,16 @@ The container images are signed with [SigStore](https://www.sigstore.dev/) [Cosi The signature can be verified with the following command (using Docker), verifying that the image is actually signed by the GitHub CI system: -> amp-devcontainer +> amp-devcontainer-cpp ```sh -docker run --rm gcr.io/projectsigstore/cosign verify ghcr.io/philips-software/amp-devcontainer --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp https://github.com/philips-software/amp-devcontainer +docker run --rm gcr.io/projectsigstore/cosign verify ghcr.io/philips-software/amp-devcontainer-cpp --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp https://github.com/philips-software/amp-devcontainer ``` -> amp-devcontainer-vscode +> amp-devcontainer-rust ```sh -docker run --rm gcr.io/projectsigstore/cosign verify ghcr.io/philips-software/amp-devcontainer-vscode --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp https://github.com/philips-software/amp-devcontainer +docker run --rm gcr.io/projectsigstore/cosign verify ghcr.io/philips-software/amp-devcontainer-rust --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp https://github.com/philips-software/amp-devcontainer ``` The resulting containers can be used in a `.devcontainer.json` file or in a `.devcontainer` folder. @@ -59,23 +70,23 @@ The resulting containers can be used in a `.devcontainer.json` file or in a `.de > [!NOTE] > While the following examples use the `latest` tag, it is recommended to pin to a specific version. Or better yet, a specific SHA. -### amp-devcontainer +### amp-devcontainer-cpp > .devcontainer/devcontainer.json or .devcontainer.json ```json { - "image": "ghcr.io/philips-software/amp-devcontainer:latest" + "image": "ghcr.io/philips-software/amp-devcontainer-cpp:latest" } ``` -### amp-devcontainer-vscode +### amp-devcontainer-rust > .devcontainer/devcontainer.json or .devcontainer.json ```json { - "image": "ghcr.io/philips-software/amp-devcontainer-vscode:latest" + "image": "ghcr.io/philips-software/amp-devcontainer-rust:latest" } ``` @@ -94,7 +105,7 @@ This project uses [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.htm ### Build & Test -The container can be built and tested locally by importing this repository in VS Code with the [Remote Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) plug-in installed. As a prerequisite Docker needs to be installed on the host system. Alternatively a GitHub Codespace can be started. +The containers can be built and tested locally by importing this repository in VS Code with the [Remote Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) plug-in installed. As a prerequisite Docker needs to be installed on the host system. Alternatively a GitHub Codespace can be started. A test task is available to run the included `bats` tests. Choose `Tasks: Run Test Task` from the command pallette (Ctrl + Shift + P). diff --git a/test/mutation/CMakeLists.txt b/test/mutation/CMakeLists.txt deleted file mode 100644 index 9bbbf58c..00000000 --- a/test/mutation/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -option(ENABLE_MUTATION_TESTING_TEST Off) - -if (ENABLE_MUTATION_TESTING_TEST) - include(FetchContent) - - FetchContent_Declare(googletest - GIT_REPOSITORY https://github.com/google/googletest - GIT_TAG release-1.12.1 - ) - - FetchContent_MakeAvailable(googletest) - - add_executable(test-mutation EXCLUDE_FROM_ALL test.cpp) - target_compile_options(test-mutation PRIVATE - -g -O0 -grecord-command-line -fprofile-instr-generate -fcoverage-mapping -fpass-plugin=/usr/lib/mull-ir-frontend - ) - target_link_libraries(test-mutation PRIVATE gmock_main) - add_test(NAME test-mutation COMMAND mull-runner $) -endif()