Skip to content
Open
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
93 changes: 93 additions & 0 deletions .github/actions/install-build-deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,99 @@ runs:
sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-18 100
shell: bash

- name: Install Podman and docker-compose
Comment thread
mvillmow marked this conversation as resolved.
run: |
# shellcheck source=/dev/null
Comment thread
mvillmow marked this conversation as resolved.
source "${GITHUB_ACTION_PATH}/podman-version.env"
sudo apt-get install -y "podman=${PODMAN_APT_VERSION}" podman-compose
shell: bash

- name: Start Podman rootless socket
run: |
systemctl --user start podman.socket
Comment thread
mvillmow marked this conversation as resolved.
echo "DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock" >> "$GITHUB_ENV"
shell: bash

- name: Configure host for in-container sanitizers
run: |
# ASan/TSan/LSan abort with "Shadow memory range interleaves with an
# existing memory mapping" on the ubuntu-24.04 noble kernel unless the
# ASLR entropy is lowered. The sanitizer runs inside the dev container
# but shares the host kernel, so this must be set on the runner host.
sudo sysctl -w vm.mmap_rnd_bits=28
shell: bash

- name: Set container build environment
run: |
echo "GIT_COMMIT=${{ github.sha }}" >> "$GITHUB_ENV"
echo "BUILD_UID=$(id -u)" >> "$GITHUB_ENV"
echo "BUILD_GID=$(id -g)" >> "$GITHUB_ENV"
shell: bash

- name: Fix workspace permissions for Podman bind mounts
run: chmod -R a+rwX .
shell: bash

- name: Restore dev container image cache
id: image_cache
uses: actions/cache@v5
with:
path: /tmp/dev-image.tar
# Exact-match only: a partial restore-key (e.g. `podman-`) would load a
# stale tarball built from a different Containerfile/conanfile, so omit
# restore-keys and rebuild on any input change.
key: podman-${{ hashFiles('Containerfile', 'docker-compose.yml', 'conanfile.py') }}
Comment thread
mvillmow marked this conversation as resolved.

- name: Load or build dev container image
run: |
loaded=false
if [ "${{ steps.image_cache.outputs.cache-hit }}" = "true" ] && podman load -i /tmp/dev-image.tar 2>/dev/null; then
# Verify the tarball actually contained the tag compose resolves;
# a stale/mistagged tarball would otherwise pass here and fail at
# `podman-compose up`.
if podman image exists projectkeystone-dev:latest; then
echo "Loaded dev image from cache"
loaded=true
else
echo "Cached tarball missing projectkeystone-dev:latest tag; rebuilding" >&2
fi
fi
if [ "$loaded" != "true" ]; then
DOCKER_HOST="$DOCKER_HOST" podman-compose build dev
podman save -o /tmp/dev-image.tar projectkeystone-dev:latest
Comment thread
mvillmow marked this conversation as resolved.
fi
shell: bash

- name: Start dev container
run: |
DOCKER_HOST="$DOCKER_HOST" podman-compose up -d dev
shell: bash

- name: Wait for dev container readiness
run: |
for i in $(seq 1 10); do
Comment thread
mvillmow marked this conversation as resolved.
if DOCKER_HOST="$DOCKER_HOST" podman-compose exec -T dev true 2>/dev/null; then
echo "Container ready"
exit 0
fi
echo "Waiting for container... attempt $i/10"
sleep 2
done
echo "Container failed to become ready" >&2
DOCKER_HOST="$DOCKER_HOST" podman-compose logs dev >&2
exit 1
shell: bash

- name: Verify Podman works (rootless)
run: |
rootless="$(podman info --format '{{.Host.Security.Rootless}}')"
echo "Podman rootless: ${rootless}"
if [ "${rootless}" != "true" ]; then
echo "Expected rootless Podman but got '${rootless}'" >&2
exit 1
fi
shell: bash

- name: Verify installation
run: |
echo "Clang version:"
Expand Down
1 change: 1 addition & 0 deletions .github/actions/install-build-deps/podman-version.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PODMAN_APT_VERSION=5.0.2+ds1-4ubuntu1
73 changes: 44 additions & 29 deletions .github/workflows/_required.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,35 +240,50 @@ jobs:
fetchcontent-clang-tidy-${{ runner.os }}-

- name: Install Conan dependencies
run: make deps.native
run: make deps
Comment thread
mvillmow marked this conversation as resolved.

- name: Configure CMake with clang-tidy
# `make deps` runs Conan inside the dev container, so the generated
# conan_toolchain.cmake references container-internal compiler/library
# paths. Configure must therefore run inside the same container or the
# toolchain will not resolve — this preserves the environment-parity
# goal. We reuse the Makefile's container invocation pattern
# (DOCKER_HOST + podman-compose exec -T dev).
run: |
CONAN_TOOLCHAIN=""
if [ -f build/conan-deps/conan_toolchain.cmake ]; then
CONAN_TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=build/conan-deps/conan_toolchain.cmake"
fi
cmake -S . -B build/x86.debug.clang-tidy \
-G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DENABLE_CLANG_TIDY=ON \
$CONAN_TOOLCHAIN
DOCKER_HOST="${DOCKER_HOST:-}" podman-compose exec -T dev bash -c '
CONAN_TOOLCHAIN=""
if [ -f build/conan-deps/conan_toolchain.cmake ]; then
CONAN_TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=build/conan-deps/conan_toolchain.cmake"
fi
cmake -S . -B build/x86.debug.clang-tidy \
-G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DENABLE_CLANG_TIDY=ON \
$CONAN_TOOLCHAIN
'

- name: Build with clang-tidy
# Must run inside the dev container for the same reason as the configure
# step: the build consumes the container-generated Conan toolchain and
# uses the container's clang/clang-tidy. clang-tidy-output.txt and
# clang-tidy-build.rc are written under /workspace, which is bind-mounted
# back to the host so the gating step below can read them.
run: |
# clang-tidy build often returns non-zero when diagnostics are found.
# The next step parses clang-tidy-output.txt and decides whether those
# diagnostics reference real source files (vs. third-party headers).
# We must capture the build output without aborting the job — but we
# also must record the build rc for the next step to inspect, rather
# than silently masking it with continue-on-error.
set +e
set -o pipefail
cmake --build build/x86.debug.clang-tidy -j"$(nproc)" 2>&1 | tee clang-tidy-output.txt
rc=${PIPESTATUS[0]}
set -e
echo "$rc" > clang-tidy-build.rc
echo "clang-tidy build exited rc=$rc (gating happens in next step)"
DOCKER_HOST="${DOCKER_HOST:-}" podman-compose exec -T dev bash -c '
set +e
set -o pipefail
cmake --build build/x86.debug.clang-tidy -j"$(nproc)" 2>&1 | tee clang-tidy-output.txt
rc=${PIPESTATUS[0]}
set -e
echo "$rc" > clang-tidy-build.rc
echo "clang-tidy build exited rc=$rc (gating happens in next step)"
'

- name: Fail on clang-tidy errors
run: |
Expand Down Expand Up @@ -436,10 +451,10 @@ jobs:
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV

- name: Install Conan dependencies
run: make deps.native
run: make deps

- name: Build debug (C++)
run: make compile.debug.native
run: make compile.debug

- name: Run C++ unit tests
run: |
Expand Down Expand Up @@ -504,21 +519,21 @@ jobs:
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV

- name: Install Conan dependencies
run: make deps.native
run: make deps

- name: Build + test (ASan)
run: make compile.debug.asan.native && make test.debug.asan.native
run: make compile.debug.asan && make test.debug.asan

- name: Build + test (UBSan)
run: make compile.debug.ubsan.native && make test.debug.ubsan.native
run: make compile.debug.ubsan && make test.debug.ubsan

- name: Build + test (TSan)
run: make compile.debug.tsan.native && make test.debug.tsan.native
run: make compile.debug.tsan && make test.debug.tsan
env:
TSAN_OPTIONS: "suppressions=${{ github.workspace }}/tsan.supp:second_deadlock_stack=1"

- name: Build + test (LSan)
run: make compile.debug.lsan.native && make test.debug.lsan.native
run: make compile.debug.lsan && make test.debug.lsan

- name: Show sccache stats
if: always()
Expand Down Expand Up @@ -574,10 +589,10 @@ jobs:
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV

- name: Install Conan dependencies
run: make deps.native
run: make deps

- name: Build release
run: make compile.release.native
run: make compile.release

- name: Show sccache stats
if: always()
Expand Down Expand Up @@ -1019,17 +1034,17 @@ jobs:
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV

- name: Install Conan dependencies
run: make deps.native
run: make deps

- name: Build with coverage
run: make compile.debug.coverage.native
run: make compile.debug.coverage

- name: Show sccache stats
if: always()
run: sccache --show-stats

- name: Run tests for coverage
run: make test.debug.coverage.native
run: make test.debug.coverage

- name: Generate coverage report
run: |
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/extras.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ jobs:
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV

- name: Install Conan dependencies
run: make deps.native
run: make deps

- name: Build release
run: make compile.release.native
run: make compile.release

- name: Show sccache stats
if: always()
run: sccache --show-stats

- name: Run benchmarks
run: make benchmark.native
run: make benchmark

- name: Upload benchmark results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand Down Expand Up @@ -121,10 +121,10 @@ jobs:
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV

- name: Install Conan dependencies
run: make deps.native
run: make deps

- name: Build release
run: make compile.release.native
run: make compile.release

- name: Show sccache stats
if: always()
Expand Down Expand Up @@ -189,17 +189,17 @@ jobs:
echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV

- name: Install Conan dependencies
run: make deps.native
run: make deps

- name: Build with coverage
run: make compile.debug.coverage.native
run: make compile.debug.coverage

- name: Show sccache stats
if: always()
run: sccache --show-stats

- name: Run tests for coverage
run: make test.debug.coverage.native
run: make test.debug.coverage

- name: Generate coverage report
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ jobs:
uses: ./.github/actions/install-build-deps

- name: Build release
run: make compile.release.native
run: make compile.release

- name: Run tests on release build
run: make test.release.native
run: make test.release

- name: Build CPack packages
run: |
Expand Down
24 changes: 10 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,8 @@ add_executable(

# The gRPC test fixture (grpc_test_fixture.cpp) and TLS test (test_grpc_tls.cpp)
# were removed with the HMAS orchestration layer (ADR-015/016).
target_link_libraries(
unit_tests keystone_core keystone_concurrency
keystone_transport GTest::gtest_main)
target_link_libraries(unit_tests keystone_core keystone_concurrency
keystone_transport GTest::gtest_main)

gtest_discover_tests(unit_tests)

Expand Down Expand Up @@ -383,9 +382,10 @@ gtest_discover_tests(simulation_unit_tests)
# Transport library — NATS connection with TLS support (issue #122),
# NATSListener pull-based fetch loop (issues #178, #205, #307), and
# TransparentBridge automatic off-host forwarding (issue #512).
add_library(keystone_transport src/transport/nats_connection.cpp
src/network/nats_listener.cpp
src/transport/transparent_bridge.cpp)
add_library(
keystone_transport
src/transport/nats_connection.cpp src/network/nats_listener.cpp
src/transport/transparent_bridge.cpp)

target_include_directories(
keystone_transport PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
Expand All @@ -399,8 +399,8 @@ target_include_directories(
keystone_transport PUBLIC ${spdlog_INCLUDE_DIRS_RELEASE}
${fmt_INCLUDE_DIRS_RELEASE})

# Daemon — production service binary (issue #513)
# Must come after keystone_core and keystone_transport are defined.
# Daemon — production service binary (issue #513) Must come after keystone_core
# and keystone_transport are defined.
add_subdirectory(src/daemon)

# Unit Tests — NATS transport (issue #122)
Expand Down Expand Up @@ -618,12 +618,8 @@ install(

# Install test executables (keystone-test package)
install(
TARGETS distributed_hierarchy_tests
unit_tests
concurrency_unit_tests
simulation_unit_tests
transport_unit_tests
bridge_unit_tests
TARGETS distributed_hierarchy_tests unit_tests concurrency_unit_tests
simulation_unit_tests transport_unit_tests bridge_unit_tests
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/tests COMPONENT keystone-test)

# Install benchmarks (keystone-misc package)
Expand Down
Loading
Loading