From dee703a7ee0a951e5f5583828fa0f6b1eeda4949 Mon Sep 17 00:00:00 2001 From: drslebedev Date: Thu, 29 Jan 2026 11:20:46 +0100 Subject: [PATCH 1/4] Use system OpenSSL for QUIC deps * Drop the custom OpenSSL ExternalProject build and link QUIC components against system OpenSSL::SSL / OpenSSL::Crypto. Signed-off-by: drslebedev --- CMakeLists.txt | 8 +-- cmake/DependenciesNative.cmake | 119 +++++++++++++-------------------- 2 files changed, 52 insertions(+), 75 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b6cf18b..7f72f3de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ elseif(EMSCRIPTEN) OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0.0) message(FATAL_ERROR "Clang>=14.0.0 required for emscripten, but clang ${CMAKE_CXX_COMPILER_VERSION} detected.") endif() - message("You are building with Emscripten Clang. Be advised that support is limited to working in conjunction with" + message(STATUS "You are building with Emscripten Clang. Be advised that support is limited to working in conjunction with" " libc++ and certain modules. libc++ has been enabled.") set(CMAKE_EXECUTABLE_SUFFIX ".js") add_compile_options( @@ -134,7 +134,7 @@ endif() if(OPENCMW_ENABLE_TESTING) enable_testing() - message("Building Tests.") + message(STATUS "Building Tests.") if(OPENCMW_ENABLE_COVERAGE) if(UNIX AND NOT APPLE @@ -143,7 +143,7 @@ if(OPENCMW_ENABLE_TESTING) MATCHES ".*Clang" AND NOT EMSCRIPTEN) # Linux - message("Coverage reporting enabled") + message(STATUS "Coverage reporting enabled") include(cmake/CodeCoverage.cmake) # https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake # # (License: BSL-1.0) target_compile_options( @@ -190,6 +190,6 @@ endif() add_subdirectory(src) if(OPENCMW_ENABLE_CONCEPTS) - message("Building Concepts") + message(STATUS "Building Concepts") add_subdirectory(concepts) endif() diff --git a/cmake/DependenciesNative.cmake b/cmake/DependenciesNative.cmake index 21a99a88..fc4b1bb7 100644 --- a/cmake/DependenciesNative.cmake +++ b/cmake/DependenciesNative.cmake @@ -1,38 +1,54 @@ include(ExternalProject) include(GNUInstallDirs) -set(OPENSSL_C_FLAGS "-O3 -march=x86-64-v3 -fPIC" CACHE STRING "OpenSSL custom CFLAGS" FORCE) -set(OPENSSL_CXX_FLAGS "-O3 -march=x86-64-v3 -fPIC" CACHE STRING "OpenSSL custom CXXFLAGS" FORCE) -set(OPENSSL_INSTALL_DIR "${CMAKE_BINARY_DIR}/_deps/openssl-install") +find_package(OpenSSL 3.5.1 REQUIRED) # QUIC support OpenSSL +message(STATUS "Using system OpenSSL: ${OPENSSL_VERSION}") -# Build custom OpenSSL with QUIC support -ExternalProject_Add(OpenSslProject - GIT_REPOSITORY https://github.com/openssl/openssl.git - GIT_TAG openssl-3.6.0 # 3.6.0 required for server-side QUIC support +option(ENABLE_NGHTTP_DEBUG "Enable verbose nghttp2 debug output" OFF) + +ExternalProject_Add(NgTcp2Project + GIT_REPOSITORY https://github.com/ngtcp2/ngtcp2.git + GIT_TAG v1.18.0 GIT_SHALLOW ON - BUILD_BYPRODUCTS ${OPENSSL_INSTALL_DIR}/lib64/libcrypto.a ${OPENSSL_INSTALL_DIR}/lib64/libssl.a - CONFIGURE_COMMAND COMMAND ./Configure CFLAGS=${OPENSSL_C_FLAGS} CXXFLAGS=${OPENSSL_CXX_FLAGS} no-shared no-tests --prefix=${OPENSSL_INSTALL_DIR} --openssldir=${OPENSSL_INSTALL_DIR} linux-x86_64 + PREFIX ${CMAKE_BINARY_DIR}/_deps/ngtcp2-install + BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2.a ${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2_crypto_ossl.a UPDATE_COMMAND "" - BUILD_COMMAND make -j - INSTALL_COMMAND make install_sw # only installs software components (no docs, etc) - BUILD_IN_SOURCE ON + CMAKE_ARGS + -DENABLE_OPENSSL:BOOL=ON + -DOPENSSL_USE_STATIC_LIBS:BOOL=OFF + -DOPENSSL_ROOT_DIR:PATH=${OPENSSL_ROOT_DIR} + -DOPENSSL_INCLUDE_DIR:PATH=${OPENSSL_INCLUDE_DIR} + -DOPENSSL_SSL_LIBRARY:FILEPATH=${OPENSSL_SSL_LIBRARY} + -DOPENSSL_CRYPTO_LIBRARY:FILEPATH=${OPENSSL_CRYPTO_LIBRARY} + -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/_deps/ngtcp2-install + -DCMAKE_INSTALL_LIBDIR:PATH=${CMAKE_INSTALL_LIBDIR} + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DENABLE_LIB_ONLY:BOOL=ON + -DENABLE_DEBUG:BOOL=${ENABLE_NGHTTP_DEBUG} + -DBUILD_STATIC_LIBS:BOOL=ON + -DBUILD_SHARED_LIBS:BOOL=OFF + -DENABLE_STATIC_LIB:BOOL=ON + -DENABLE_SHARED_LIB:BOOL=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON + -DCMAKE_C_FLAGS:STRING=-fPIC + -DCMAKE_CXX_FLAGS:STRING=-fPIC ) -add_library(openssl-crypto-static STATIC IMPORTED GLOBAL) -add_dependencies(openssl-crypto-static OpenSslProject) -set_target_properties(openssl-crypto-static PROPERTIES - IMPORTED_LOCATION "${OPENSSL_INSTALL_DIR}/lib64/libcrypto.a" - INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INSTALL_DIR}/include" +add_library(ngtcp2-static STATIC IMPORTED GLOBAL) +target_link_libraries(ngtcp2-static INTERFACE OpenSSL::SSL OpenSSL::Crypto) +set_target_properties(ngtcp2-static PROPERTIES + IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2.a" + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/include" ) +add_dependencies(ngtcp2-static NgTcp2Project) -add_library(openssl-ssl-static STATIC IMPORTED GLOBAL) -add_dependencies(openssl-ssl-static OpenSslProject) -set_target_properties(openssl-ssl-static PROPERTIES - IMPORTED_LOCATION "${OPENSSL_INSTALL_DIR}/lib64/libssl.a" - INTERFACE_INCLUDE_DIRECTORIES "${OPENSSL_INSTALL_DIR}/include" +add_library(ngtcp2-crypto-ossl-static STATIC IMPORTED GLOBAL) +target_link_libraries(ngtcp2-crypto-ossl-static INTERFACE OpenSSL::SSL OpenSSL::Crypto) +set_target_properties(ngtcp2-crypto-ossl-static PROPERTIES + IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2_crypto_ossl.a" + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/include" ) - -option(ENABLE_NGHTTP_DEBUG "Enable verbose nghttp2 debug output" OFF) +add_dependencies(ngtcp2-crypto-ossl-static NgTcp2Project) ExternalProject_Add(Nghttp2Project GIT_REPOSITORY https://github.com/nghttp2/nghttp2 @@ -42,6 +58,7 @@ ExternalProject_Add(Nghttp2Project UPDATE_COMMAND "" CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/_deps/nghttp2-install + -DCMAKE_INSTALL_LIBDIR:PATH=${CMAKE_INSTALL_LIBDIR} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DENABLE_LIB_ONLY:BOOL=ON -DENABLE_HTTP3:BOOL=OFF @@ -51,13 +68,12 @@ ExternalProject_Add(Nghttp2Project -DENABLE_STATIC_LIB:BOOL=ON -DENABLE_SHARED_LIB:BOOL=OFF -DENABLE_DOC:BOOL=OFF - -DCMAKE_POSITION_INDEPENDENT_CODE=ON - -DCMAKE_C_FLAGS=-fPIC - -DCMAKE_CXX_FLAGS=-fPIC + -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON + -DCMAKE_C_FLAGS:STRING=-fPIC + -DCMAKE_CXX_FLAGS:STRING=-fPIC ) add_library(nghttp2-static STATIC IMPORTED GLOBAL) -target_link_libraries(nghttp2-static INTERFACE ngtcp2-static ngtcp2-crypto-ossl-static) set_target_properties(nghttp2-static PROPERTIES IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/_deps/nghttp2-install/${CMAKE_INSTALL_LIBDIR}/libnghttp2.a" INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/_deps/nghttp2-install/include" @@ -72,6 +88,7 @@ ExternalProject_Add(Nghttp3Project UPDATE_COMMAND "" CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/_deps/nghttp3-install + -DCMAKE_INSTALL_LIBDIR:PATH=${CMAKE_INSTALL_LIBDIR} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DENABLE_LIB_ONLY:BOOL=ON -DENABLE_DEBUG:BOOL=${ENABLE_NGHTTP_DEBUG} @@ -80,9 +97,9 @@ ExternalProject_Add(Nghttp3Project -DENABLE_STATIC_LIB:BOOL=ON -DENABLE_SHARED_LIB:BOOL=OFF -DENABLE_DOC:BOOL=OFF - -DCMAKE_POSITION_INDEPENDENT_CODE=ON - -DCMAKE_C_FLAGS=-fPIC - -DCMAKE_CXX_FLAGS=-fPIC + -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON + -DCMAKE_C_FLAGS:STRING=-fPIC + -DCMAKE_CXX_FLAGS:STRING=-fPIC ) add_library(nghttp3-static STATIC IMPORTED GLOBAL) target_link_libraries(nghttp3-static INTERFACE ngtcp2-static ngtcp2-crypto-ossl-static) @@ -92,46 +109,6 @@ set_target_properties(nghttp3-static PROPERTIES ) add_dependencies(nghttp3-static Nghttp3Project) -ExternalProject_Add(NgTcp2Project - GIT_REPOSITORY https://github.com/ngtcp2/ngtcp2.git - GIT_TAG v1.18.0 - GIT_SHALLOW ON - PREFIX ${CMAKE_BINARY_DIR}/_deps/ngtcp2-install - BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2.a ${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2_crypto_ossl.a - UPDATE_COMMAND "" - CMAKE_ARGS - -DOPENSSL_ROOT_DIR:PATH=${OPENSSL_INSTALL_DIR} - -DENABLE_OPENSSL:BOOL=ON - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/_deps/ngtcp2-install - -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DENABLE_LIB_ONLY:BOOL=ON - -DENABLE_DEBUG:BOOL=${ENABLE_NGHTTP_DEBUG} - -DBUILD_STATIC_LIBS:BOOL=ON - -DBUILD_SHARED_LIBS:BOOL=OFF - -DENABLE_STATIC_LIB:BOOL=ON - -DENABLE_SHARED_LIB:BOOL=OFF - -DCMAKE_POSITION_INDEPENDENT_CODE=ON - -DCMAKE_C_FLAGS=-fPIC - -DCMAKE_CXX_FLAGS=-fPIC - DEPENDS openssl-crypto-static openssl-ssl-static -) - -add_library(ngtcp2-static STATIC IMPORTED GLOBAL) -target_link_libraries(ngtcp2-static INTERFACE openssl-ssl-static openssl-crypto-static) -set_target_properties(ngtcp2-static PROPERTIES - IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2.a" - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/include" -) -add_dependencies(ngtcp2-static NgTcp2Project) - -add_library(ngtcp2-crypto-ossl-static STATIC IMPORTED GLOBAL) -target_link_libraries(ngtcp2-crypto-ossl-static INTERFACE openssl-ssl-static openssl-crypto-static) -set_target_properties(ngtcp2-crypto-ossl-static PROPERTIES - IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/${CMAKE_INSTALL_LIBDIR}/libngtcp2_crypto_ossl.a" - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/_deps/ngtcp2-install/include" -) -add_dependencies(ngtcp2-crypto-ossl-static NgTcp2Project) - add_library(mustache INTERFACE) target_include_directories(mustache INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/kainjow) add_library(mustache::mustache ALIAS mustache) From 0916e9c0e7ed621e31a58773ccdc1a35af0b882b Mon Sep 17 00:00:00 2001 From: drslebedev Date: Thu, 29 Jan 2026 12:36:59 +0100 Subject: [PATCH 2/4] Update CI configuration to use Docker * switch to clang-20 Signed-off-by: drslebedev --- .github/workflows/build_cmake.yml | 96 ++++++++++----------- .github/workflows/build_keycloak_docker.yml | 64 ++++++++++++++ docker/keycloak/Dockerfile | 2 + sonar-project.properties | 2 +- src/client/test/setup-keycloak.sh | 8 +- src/services/test/OAuthClient_tests.cpp | 19 +++- 6 files changed, 137 insertions(+), 54 deletions(-) create mode 100644 .github/workflows/build_keycloak_docker.yml create mode 100644 docker/keycloak/Dockerfile diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index ffafd58c..8859dc9f 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -8,30 +8,44 @@ on: types: [ created ] env: - REFERENCE_CONFIG: 'Ubuntu gcc14' # configuration used for coverage etc + REFERENCE_CONFIG: 'gcc14' # configuration used for coverage etc jobs: + buildKeycloakDockerImage: + uses: ./.github/workflows/build_keycloak_docker.yml + permissions: + contents: read + packages: write + build: + needs: buildKeycloakDockerImage name: "${{ matrix.configurations.name }} | ${{ matrix.cmake-build-type }}" environment: configure coverage - runs-on: ${{ matrix.configurations.os }} + runs-on: "ubuntu-latest" + container: "ghcr.io/fair-acc/gr4-build-container:latest" strategy: fail-fast: false matrix: configurations: - - name: Ubuntu gcc14 - os: ubuntu-24.04 + - name: gcc14 compiler: gcc14 - - name: Ubuntu clang18 - os: ubuntu-24.04 - compiler: clang18 - - name: ubuntu-22.04 emscripten - os: ubuntu-24.04 + cc: gcc-14 + cxx: g++-14 + - name: clang20 + compiler: clang20 + cc: clang-20 + cxx: clang++-20 + - name: emscripten compiler: emscripten - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) cmake-build-type: [ Release, Debug ] env: BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory + services: + keycloak: + image: ${{ needs.buildKeycloakDockerImage.outputs.image }} + env: + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: admin steps: - uses: actions/checkout@v6 @@ -46,56 +60,26 @@ jobs: path: ${{runner.workspace}}/build/_deps key: ${{ runner.os }}-${{ matrix.configurations.compiler }}-${{ matrix.cmake-build-type }}-${{ hashFiles('CMakeLists.txt') }}-${{ hashFiles('cmake/Dependencies.cmake') }} - - name: Install gcovr - shell: bash - if: matrix.configurations.name == env.REFERENCE_CONFIG && matrix.cmake-build-type == 'Debug' - run: sudo apt-get install -y gcovr - - - name: Install gcc-14 - if: matrix.configurations.compiler == 'gcc14' - run: | - sudo apt-get install -y gcc-14 g++-14 - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 110 --slave /usr/bin/g++ g++ /usr/bin/g++-14 --slave /usr/bin/gcov gcov /usr/bin/gcov-14 - - - name: Install clang-18 - if: matrix.configurations.compiler == 'clang18' - run: | - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - - sudo apt update - sudo apt upgrade -y - sudo apt install -y clang-18 libc++-18-dev libc++abi-18-dev - sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-18 110 - sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-18 110 - - - name: Install emscripten - if: matrix.configurations.compiler == 'emscripten' - run: | - cd - git clone https://github.com/emscripten-core/emsdk.git - cd emsdk - # Download and install emscripten. - ./emsdk install 3.1.59 - # Make "active" for the current user. (writes .emscripten file) - ./emsdk activate 3.1.59 - - name: Install sonar-scanner and build-wrapper if: matrix.configurations.name == env.REFERENCE_CONFIG && matrix.cmake-build-type == 'Debug' uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v7 - name: Configure CMake if: matrix.configurations.compiler != 'emscripten' - # Use a bash shell, so we can use the same syntax for environment variable access regardless of the host operating system shell: bash + env: + CC: "${{ matrix.configurations.cc }}" + CXX: "${{ matrix.configurations.cxx }}" + CMAKE_EXPORT_COMPILE_COMMANDS: "ON" run: cmake -S . -B ../build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=${{ matrix.cmake-build-type }} -DOPENCMW_ENABLE_COVERAGE=${{ matrix.configurations.name == env.REFERENCE_CONFIG && matrix.cmake-build-type == 'Debug' }} - name: Configure CMake Emscripten if: matrix.configurations.compiler == 'emscripten' - # Use a bash shell, so we can use the same syntax for environment variable access regardless of the host operating system shell: bash run: | export SYSTEM_NODE=`which node` # use system node instead of old version distributed with emsdk for threading support - source ~/emsdk/emsdk_env.sh - emcmake cmake -S . -B ../build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=${{ matrix.cmake-build-type }} -DENABLE_TESTING=ON -DCMAKE_CROSSCOMPILING_EMULATOR=${SYSTEM_NODE} + source $EMSDK_HOME/emsdk_env.sh + emcmake cmake -S . -B ../build -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DCMAKE_BUILD_TYPE=${{ matrix.cmake-build-type }} -DCMAKE_CROSSCOMPILING_EMULATOR=${SYSTEM_NODE} - name: Build if: matrix.configurations.name != env.REFERENCE_CONFIG || matrix.cmake-build-type != 'Debug' @@ -107,14 +91,27 @@ jobs: shell: bash run: build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build ../build --config ${{ matrix.cmake-build-type }} - - name: Run Keycloak Docker + - name: Setup Keycloak + if: matrix.configurations.compiler != 'emscripten' shell: bash - run: docker run -p 8090:8080 -d -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.0.5 start-dev && src/client/test/setup-keycloak.sh + env: + KEYCLOAK_URL: http://keycloak:8080 + KEYCLOAK_REDIRECT_URI: http://localhost:8091 + KEYCLOAK_ADMIN_PASSWORD: admin + run: | + if ! command -v jq >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y --no-install-recommends jq + fi + src/client/test/setup-keycloak.sh - name: Run tests if: matrix.configurations.name != env.REFERENCE_CONFIG || matrix.cmake-build-type != 'Debug' working-directory: ${{runner.workspace}}/build shell: bash + env: + KEYCLOAK_URL: http://keycloak:8080 + KEYCLOAK_REDIRECT_URI: http://localhost:8091 # Execute tests defined by the CMake configuration. The coverage target runs the autodiscovered catch2 tests using # ctest and records the coverage using gcov # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail @@ -124,6 +121,9 @@ jobs: if: matrix.configurations.name == env.REFERENCE_CONFIG && matrix.cmake-build-type == 'Debug' working-directory: ${{runner.workspace}}/build shell: bash + env: + KEYCLOAK_URL: http://keycloak:8080 + KEYCLOAK_REDIRECT_URI: http://localhost:8091 # Execute tests defined by the CMake configuration. The coverage target runs the autodiscovered catch2 tests using # ctest and records the coverage using gcov # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail diff --git a/.github/workflows/build_keycloak_docker.yml b/.github/workflows/build_keycloak_docker.yml new file mode 100644 index 00000000..0303a78e --- /dev/null +++ b/.github/workflows/build_keycloak_docker.yml @@ -0,0 +1,64 @@ +# This workflow builds and publishes a tiny Keycloak “wrapper” image that defaults to `kc.sh start-dev`. +# GitHub Actions service containers cannot pass command arguments (like `start-dev`) to the upstream Keycloak image. +# The image is rebuilt/pushed only when `docker/keycloak/Dockerfile` changes, otherwise CI reuses the existing tag. + +name: Build Keycloak Docker Image + +on: + workflow_call: + outputs: + image: + description: "Keycloak wrapper image tag" + value: ${{ jobs.build.outputs.image }} + +permissions: + contents: read + packages: write + +jobs: + build: + runs-on: ubuntu-latest + outputs: + image: ${{ steps.docker-label.outputs.label }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check if Keycloak Dockerfile was modified + id: changes + uses: dorny/paths-filter@v3 + with: + filters: | + docker: + - 'docker/keycloak/Dockerfile' + + - name: Set up Docker Label + id: docker-label + shell: bash + run: | + if [ ${{ steps.changes.outputs.docker == 'true' && github.event_name != 'push' }} = "true" ]; then + echo "label=ghcr.io/fair-acc/keycloak-start-dev:${GITHUB_HEAD_REF/\//-}" >> "$GITHUB_OUTPUT" + else + echo "label=ghcr.io/fair-acc/keycloak-start-dev:latest" >> "$GITHUB_OUTPUT" + fi + + - name: Set up Docker Buildx + if: steps.changes.outputs.docker == 'true' + uses: docker/setup-buildx-action@v3 + + - name: Login to GHCR + if: steps.changes.outputs.docker == 'true' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build & push Keycloak wrapper image + if: steps.changes.outputs.docker == 'true' + uses: docker/build-push-action@v5 + with: + context: "{{defaultContext}}:docker/keycloak" + push: true + tags: ${{ steps.docker-label.outputs.label }} diff --git a/docker/keycloak/Dockerfile b/docker/keycloak/Dockerfile new file mode 100644 index 00000000..b4907e1d --- /dev/null +++ b/docker/keycloak/Dockerfile @@ -0,0 +1,2 @@ +FROM quay.io/keycloak/keycloak:26.0.5 +CMD ["start-dev"] diff --git a/sonar-project.properties b/sonar-project.properties index 5fe7d891..8cf7b3fe 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -13,4 +13,4 @@ sonar.organization=fair-acc # exclude benchmark which crashes the Analysis # sonar.exclusions=bench/bm_case1.cpp -sonar.coverageReportPaths=/home/runner/work/opencmw-cpp/build/coverage_sonarcube.xml +sonar.cfamily.gcovr.reportPaths=/home/runner/work/opencmw-cpp/build/coverage_sonarcube.xml diff --git a/src/client/test/setup-keycloak.sh b/src/client/test/setup-keycloak.sh index 5b9c5a07..11b65a39 100755 --- a/src/client/test/setup-keycloak.sh +++ b/src/client/test/setup-keycloak.sh @@ -6,11 +6,11 @@ # # For more information see: https://www.keycloak.org/getting-started/getting-started-docker -URL="http://localhost:8090" -REDIRECT_URI="http://localhost:8091" -ADMIN_PASSWORD="admin" +URL="${KEYCLOAK_URL:-http://localhost:8090}" +REDIRECT_URI="${KEYCLOAK_REDIRECT_URI:-http://localhost:8091}" +ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD:-admin}" -while ! curl -s "$URL"; do +while ! curl -s "$URL" >/dev/null; do echo "Waiting for $URL to be reachable..." sleep 1 done diff --git a/src/services/test/OAuthClient_tests.cpp b/src/services/test/OAuthClient_tests.cpp index c6d65686..8fbca2c8 100644 --- a/src/services/test/OAuthClient_tests.cpp +++ b/src/services/test/OAuthClient_tests.cpp @@ -90,7 +90,24 @@ bool loginAtUri(const opencmw::URI &uri) { TEST_CASE("Worker test", "[OAuth]") { opencmw::majordomo::Broker<> broker{ "/Broker", {} }; - opencmw::OAuthWorker oauthWorker{ opencmw::URI("http://localhost:8091"), opencmw::URI("http://localhost:8090/realms/testrealm/protocol/openid-connect/auth"), opencmw::URI("http://localhost:8090/realms/testrealm/protocol/openid-connect/token"), broker }; + + auto envOr = [](std::string_view name, std::string_view fallback) -> std::string { + std::string key{name}; // ensures null-terminated + if (const char* v = std::getenv(key.c_str()); v && *v) { + return std::string(v); + } + return std::string(fallback); + }; + + const std::string kcBase = envOr("KEYCLOAK_URL", "http://localhost:8090"); + const std::string redirectBase = envOr("KEYCLOAK_REDIRECT_URI", "http://localhost:8091"); + + opencmw::OAuthWorker oauthWorker{ + opencmw::URI(redirectBase), + opencmw::URI(kcBase + "/realms/testrealm/protocol/openid-connect/auth"), + opencmw::URI(kcBase + "/realms/testrealm/protocol/openid-connect/token"), + broker + }; REQUIRE(broker.bind(opencmw::URI<>("mds://127.0.0.1:12345"))); REQUIRE(broker.bind(opencmw::URI<>("mdp://127.0.0.1:12346"))); From 52d249257135b64a55afd6710896793f3118c6c6 Mon Sep 17 00:00:00 2001 From: drslebedev Date: Fri, 30 Jan 2026 13:25:57 +0100 Subject: [PATCH 3/4] Use system nghttp2; keep ngtcp2/nghttp3 as ExternalProjects Signed-off-by: drslebedev --- cmake/DependenciesNative.cmake | 34 ++++------------------------------ src/rest/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 31 deletions(-) diff --git a/cmake/DependenciesNative.cmake b/cmake/DependenciesNative.cmake index fc4b1bb7..50ab56ea 100644 --- a/cmake/DependenciesNative.cmake +++ b/cmake/DependenciesNative.cmake @@ -6,6 +6,10 @@ message(STATUS "Using system OpenSSL: ${OPENSSL_VERSION}") option(ENABLE_NGHTTP_DEBUG "Enable verbose nghttp2 debug output" OFF) +find_package(PkgConfig REQUIRED) +pkg_check_modules(NGHTTP2 REQUIRED IMPORTED_TARGET libnghttp2) + +# We can’t use the system ngtcp2/nghttp3 packages because Ubuntu doesn’t ship the ngtcp2_crypto_ossl backend library and headers. ExternalProject_Add(NgTcp2Project GIT_REPOSITORY https://github.com/ngtcp2/ngtcp2.git GIT_TAG v1.18.0 @@ -50,36 +54,6 @@ set_target_properties(ngtcp2-crypto-ossl-static PROPERTIES ) add_dependencies(ngtcp2-crypto-ossl-static NgTcp2Project) -ExternalProject_Add(Nghttp2Project - GIT_REPOSITORY https://github.com/nghttp2/nghttp2 - GIT_TAG v1.65.0 - GIT_SHALLOW ON - BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/_deps/nghttp2-install/${CMAKE_INSTALL_LIBDIR}/libnghttp2.a - UPDATE_COMMAND "" - CMAKE_ARGS - -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/_deps/nghttp2-install - -DCMAKE_INSTALL_LIBDIR:PATH=${CMAKE_INSTALL_LIBDIR} - -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} - -DENABLE_LIB_ONLY:BOOL=ON - -DENABLE_HTTP3:BOOL=OFF - -DENABLE_DEBUG:BOOL=${ENABLE_NGHTTP_DEBUG} - -DBUILD_STATIC_LIBS:BOOL=ON - -DBUILD_SHARED_LIBS:BOOL=OFF - -DENABLE_STATIC_LIB:BOOL=ON - -DENABLE_SHARED_LIB:BOOL=OFF - -DENABLE_DOC:BOOL=OFF - -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON - -DCMAKE_C_FLAGS:STRING=-fPIC - -DCMAKE_CXX_FLAGS:STRING=-fPIC -) - -add_library(nghttp2-static STATIC IMPORTED GLOBAL) -set_target_properties(nghttp2-static PROPERTIES - IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/_deps/nghttp2-install/${CMAKE_INSTALL_LIBDIR}/libnghttp2.a" - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/_deps/nghttp2-install/include" -) -add_dependencies(nghttp2-static Nghttp2Project) - ExternalProject_Add(Nghttp3Project GIT_REPOSITORY https://github.com/ngtcp2/nghttp3.git GIT_TAG v1.10.1 diff --git a/src/rest/CMakeLists.txt b/src/rest/CMakeLists.txt index 8923f82b..0e3b5663 100644 --- a/src/rest/CMakeLists.txt +++ b/src/rest/CMakeLists.txt @@ -5,7 +5,7 @@ add_library(rest INTERFACE target_include_directories(rest INTERFACE $ $) target_link_libraries(rest INTERFACE - nghttp2-static + PkgConfig::NGHTTP2 nghttp3-static ) From 482afeee2c53075f72151101c948a7643433bbe1 Mon Sep 17 00:00:00 2001 From: drslebedev Date: Fri, 30 Jan 2026 13:51:37 +0100 Subject: [PATCH 4/4] Fix REST test flakiness with system nghttp2 library Serialize HTTP/2 requests in the simple REST test to avoid relying on response ordering across concurrent streams. Signed-off-by: drslebedev --- src/majordomo/test/majordomoworker_rest_tests.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/majordomo/test/majordomoworker_rest_tests.cpp b/src/majordomo/test/majordomoworker_rest_tests.cpp index 6b845aff..7cddfa21 100644 --- a/src/majordomo/test/majordomoworker_rest_tests.cpp +++ b/src/majordomo/test/majordomoworker_rest_tests.cpp @@ -273,6 +273,7 @@ TEST_CASE("Simple REST example", "[majordomo][majordomoworker][simple_example][h responseCount++; }; client.request(std::move(getJson)); + waitFor(responseCount, 1); // Get worker data as HTML opencmw::client::Command getHtml; @@ -287,6 +288,7 @@ TEST_CASE("Simple REST example", "[majordomo][majordomoworker][simple_example][h responseCount++; }; client.request(std::move(getHtml)); + waitFor(responseCount, 2); // Set worker data opencmw::client::Command postJson; @@ -301,6 +303,7 @@ TEST_CASE("Simple REST example", "[majordomo][majordomoworker][simple_example][h responseCount++; }; client.request(std::move(postJson)); + waitFor(responseCount, 3); // Test that the Set call is correctly applied opencmw::client::Command getJsonAfterSet;