From 8240091219f56f06f60d8d00a73a41baf1a6d6e6 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:45:57 +0100 Subject: [PATCH 01/11] Create unified reusable workflow to build and test external modules --- .github/workflows/reusable-module-ci.yml | 164 +++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 .github/workflows/reusable-module-ci.yml diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml new file mode 100644 index 0000000..5f20d41 --- /dev/null +++ b/.github/workflows/reusable-module-ci.yml @@ -0,0 +1,164 @@ +name: Build and Test + +on: + workflow_call: + inputs: + opendaq-ref: + description: "openDAQ commit, branch or tag. If empty, uses the opendaq_ref file from the repo." + type: string + default: '' + exclude-presets: + description: "JSON array of wildcard patterns to exclude presets, e.g. '[\"ci-*-macos-latest-*\", \"ci-test-*\"]'" + type: string + default: '[]' + packages: + description: 'JSON array of package requests, e.g. [{"packages": {"apt": ["libpcap-dev"]}}]' + type: string + default: '[]' + +jobs: + generate: + name: Generate matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.filter-jobs.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + + - name: List available presets + id: presets + shell: bash + run: | + cmake_presets=$(cmake --build --list-presets 2>/dev/null | grep '^ ' | sed 's/^ *"//;s/".*$//' | tr '\n' ' ') + ctest_presets=$(ctest --list-presets 2>/dev/null | grep '^ ' | sed 's/^ *"//;s/".*$//' | tr '\n' ' ') + echo "cmake=$cmake_presets" >> $GITHUB_OUTPUT + echo "ctest=$ctest_presets" >> $GITHUB_OUTPUT + + - name: Filter jobs to run + id: filter-jobs + shell: python3 {0} + run: | + import json, os + from fnmatch import fnmatch + + available_cmake_presets = set("""${{ steps.presets.outputs.cmake }}""".split()) + available_ctest_presets = set("""${{ steps.presets.outputs.ctest }}""".split()) + + exclude_presets = json.loads("""${{ inputs.exclude-presets }}""") + + user_packages = json.loads("""${{ inputs.packages }}""") + + default_packages = [ + { + "preset-pattern": "ci-build-ubuntu-latest-*", + "packages": { + "apt": [ + "mono-runtime", + "libmono-system-json-microsoft4.0-cil", + "libmono-system-data4.0-cil", + ], + }, + }, + ] + + pm_cmds = { + "apt": "sudo apt-get update && sudo apt-get install -y --no-install-recommends", + "brew": "brew install", + "choco": "choco install -y", + } + + jobs_matrix = [ + {"runner": "ubuntu-latest", "cmake-preset": "ci-build-ubuntu-latest-release", "ctest-preset": "ci-test-ubuntu-latest-release"}, + {"runner": "ubuntu-latest", "cmake-preset": "ci-build-ubuntu-latest-debug", "ctest-preset": "ci-test-ubuntu-latest-debug"}, + {"runner": "macos-latest", "cmake-preset": "ci-build-macos-latest-release", "ctest-preset": "ci-test-macos-latest-release"}, + {"runner": "macos-latest", "cmake-preset": "ci-build-macos-latest-debug", "ctest-preset": "ci-test-macos-latest-debug"}, + {"runner": "windows-latest", "cmake-preset": "ci-build-windows-latest-release", "ctest-preset": "ci-test-windows-latest-release"}, + {"runner": "windows-latest", "cmake-preset": "ci-build-windows-latest-debug", "ctest-preset": "ci-test-windows-latest-debug"}, + ] + + def matches_any(name: str, patterns: list[str]) -> bool: + return any(fnmatch(name, p) for p in patterns) + + def build_install_cmd(pm: str, packages: dict[str, list[str]]) -> str: + pkgs = packages.get(pm, []) + if not pkgs or pm not in pm_cmds: + return "" + return f"{pm_cmds[pm]} {' '.join(pkgs)}" + + matrix = [] + for job_cfg in jobs_matrix: + cmake_preset = job_cfg["cmake-preset"] + ctest_preset = job_cfg.get("ctest-preset", "") + + # skip if build preset not available or excluded + if cmake_preset not in available_cmake_presets: + continue + if matches_any(cmake_preset, exclude_presets): + continue + + # merge packages: defaults + user + packages: dict[str, list[str]] = {} + for req in default_packages + user_packages: + if not matches_any(cmake_preset, [req.get("preset-pattern", "*")]): + continue + for pm, pkgs in req.get("packages", {}).items(): + packages.setdefault(pm, []).extend(pkgs) + + # skip test if ctest preset not available or excluded + if ctest_preset and (ctest_preset not in available_ctest_presets or matches_any(ctest_preset, exclude_presets)): + ctest_preset = "" + + matrix_job = { + "name": f"{job_cfg['runner']} / {cmake_preset}", + "runner": job_cfg["runner"], + "cmake-preset": cmake_preset, + "ctest-preset": ctest_preset, + "cmd-install-apt": build_install_cmd("apt", packages), + "cmd-install-brew": build_install_cmd("brew", packages), + "cmd-install-choco": build_install_cmd("choco", packages), + } + + matrix.append(matrix_job) + + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"matrix={json.dumps({'include': matrix})}\n") + + build: + needs: generate + if: ${{ needs.generate.outputs.matrix != '' }} + name: ${{ matrix.name }} + runs-on: ${{ matrix.runner }} + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.generate.outputs.matrix) }} + + steps: + - uses: actions/checkout@v4 + + - name: Override opendaq_ref + if: ${{ inputs.opendaq-ref != '' }} + shell: bash + run: echo "${{ inputs.opendaq-ref }}" > opendaq_ref + + - name: Install dependencies (apt) + if: matrix.cmd-install-apt != '' + run: ${{ matrix.cmd-install-apt }} + + - name: Install dependencies (brew) + if: matrix.cmd-install-brew != '' + run: ${{ matrix.cmd-install-brew }} + + - name: Install dependencies (choco) + if: matrix.cmd-install-choco != '' + run: ${{ matrix.cmd-install-choco }} + + - name: Configure + run: cmake --preset ${{ matrix.cmake-preset }} + + - name: Build + run: cmake --build --preset ${{ matrix.cmake-preset }} + + - name: Test + if: matrix.ctest-preset != '' + run: ctest --preset ${{ matrix.ctest-preset }} From a990cbb48f4a88519a3ded3a340683c158abce1f Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Mon, 30 Mar 2026 23:12:00 +0200 Subject: [PATCH 02/11] Add dynamic preset generation with centralized compiler control --- .github/workflows/reusable-module-ci.yml | 223 +++++++++++++++-------- 1 file changed, 150 insertions(+), 73 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index 5f20d41..2ef472c 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -7,12 +7,12 @@ on: description: "openDAQ commit, branch or tag. If empty, uses the opendaq_ref file from the repo." type: string default: '' - exclude-presets: - description: "JSON array of wildcard patterns to exclude presets, e.g. '[\"ci-*-macos-latest-*\", \"ci-test-*\"]'" + exclude-configs: + description: "JSON array of wildcard patterns to exclude configurations, e.g. '[\"*-debug\", \"macos-*\"]'" type: string default: '[]' packages: - description: 'JSON array of package requests, e.g. [{"packages": {"apt": ["libpcap-dev"]}}]' + description: 'JSON array of package requests, e.g. [{"runners": ["ubuntu-*"], "packages": {"apt": ["libpcap-dev"]}}]' type: string default: '[]' @@ -21,60 +21,59 @@ jobs: name: Generate matrix runs-on: ubuntu-latest outputs: - matrix: ${{ steps.filter-jobs.outputs.matrix }} + matrix: ${{ steps.matrix.outputs.matrix }} steps: - - uses: actions/checkout@v4 - - - name: List available presets - id: presets - shell: bash - run: | - cmake_presets=$(cmake --build --list-presets 2>/dev/null | grep '^ ' | sed 's/^ *"//;s/".*$//' | tr '\n' ' ') - ctest_presets=$(ctest --list-presets 2>/dev/null | grep '^ ' | sed 's/^ *"//;s/".*$//' | tr '\n' ' ') - echo "cmake=$cmake_presets" >> $GITHUB_OUTPUT - echo "ctest=$ctest_presets" >> $GITHUB_OUTPUT - - - name: Filter jobs to run - id: filter-jobs + - name: Generate matrix + id: matrix shell: python3 {0} run: | import json, os from fnmatch import fnmatch - available_cmake_presets = set("""${{ steps.presets.outputs.cmake }}""".split()) - available_ctest_presets = set("""${{ steps.presets.outputs.ctest }}""".split()) - - exclude_presets = json.loads("""${{ inputs.exclude-presets }}""") - + exclude_configs = json.loads("""${{ inputs.exclude-configs }}""") user_packages = json.loads("""${{ inputs.packages }}""") default_packages = [ { - "preset-pattern": "ci-build-ubuntu-latest-*", + "runners": ["ubuntu-*"], "packages": { "apt": [ - "mono-runtime", - "libmono-system-json-microsoft4.0-cil", - "libmono-system-data4.0-cil", - ], - }, - }, + "mono-runtime", + "libmono-system-json-microsoft4.0-cil", + "libmono-system-data4.0-cil" + ] + } + } ] pm_cmds = { - "apt": "sudo apt-get update && sudo apt-get install -y --no-install-recommends", + "apt": "sudo apt-get install -y --no-install-recommends", "brew": "brew install", "choco": "choco install -y", + "pip": "pip install", } - jobs_matrix = [ - {"runner": "ubuntu-latest", "cmake-preset": "ci-build-ubuntu-latest-release", "ctest-preset": "ci-test-ubuntu-latest-release"}, - {"runner": "ubuntu-latest", "cmake-preset": "ci-build-ubuntu-latest-debug", "ctest-preset": "ci-test-ubuntu-latest-debug"}, - {"runner": "macos-latest", "cmake-preset": "ci-build-macos-latest-release", "ctest-preset": "ci-test-macos-latest-release"}, - {"runner": "macos-latest", "cmake-preset": "ci-build-macos-latest-debug", "ctest-preset": "ci-test-macos-latest-debug"}, - {"runner": "windows-latest", "cmake-preset": "ci-build-windows-latest-release", "ctest-preset": "ci-test-windows-latest-release"}, - {"runner": "windows-latest", "cmake-preset": "ci-build-windows-latest-debug", "ctest-preset": "ci-test-windows-latest-debug"}, - ] + runner_cfg = { + "ubuntu-latest": { + "runner": "ubuntu-latest", + "bootstrap": "sudo apt-get update", + "generator": "Ninja", + "c-compiler": "gcc", + "cxx-compiler": "g++", + }, + "windows-latest": { + "runner": "windows-latest", + "generator": "Visual Studio 17 2022", + }, + "macos-latest": { + "runner": "macos-latest", + "generator": "Ninja", + "c-compiler": "/usr/bin/clang", + "cxx-compiler": "/usr/bin/clang++", + }, + } + + build_types = ["Release", "Debug"] def matches_any(name: str, patterns: list[str]) -> bool: return any(fnmatch(name, p) for p in patterns) @@ -86,39 +85,39 @@ jobs: return f"{pm_cmds[pm]} {' '.join(pkgs)}" matrix = [] - for job_cfg in jobs_matrix: - cmake_preset = job_cfg["cmake-preset"] - ctest_preset = job_cfg.get("ctest-preset", "") - - # skip if build preset not available or excluded - if cmake_preset not in available_cmake_presets: - continue - if matches_any(cmake_preset, exclude_presets): - continue - - # merge packages: defaults + user - packages: dict[str, list[str]] = {} - for req in default_packages + user_packages: - if not matches_any(cmake_preset, [req.get("preset-pattern", "*")]): + for cfg_key, cfg in runner_cfg.items(): + for bt in build_types: + key = f"{cfg_key}-{bt.lower()}" + + if matches_any(key, exclude_configs): continue - for pm, pkgs in req.get("packages", {}).items(): - packages.setdefault(pm, []).extend(pkgs) - - # skip test if ctest preset not available or excluded - if ctest_preset and (ctest_preset not in available_ctest_presets or matches_any(ctest_preset, exclude_presets)): - ctest_preset = "" - - matrix_job = { - "name": f"{job_cfg['runner']} / {cmake_preset}", - "runner": job_cfg["runner"], - "cmake-preset": cmake_preset, - "ctest-preset": ctest_preset, - "cmd-install-apt": build_install_cmd("apt", packages), - "cmd-install-brew": build_install_cmd("brew", packages), - "cmd-install-choco": build_install_cmd("choco", packages), - } - matrix.append(matrix_job) + # merge packages: defaults + user + runner = cfg["runner"] + image = cfg.get("image", "") + packages: dict[str, list[str]] = {} + for req in default_packages + user_packages: + runners = req.get("runners", ["*"]) + if not any(fnmatch(runner, r) or (image and fnmatch(image, r)) for r in runners): + continue + for pm, pkgs in req.get("packages", {}).items(): + packages.setdefault(pm, []).extend(pkgs) + + matrix.append({ + "name": key, + "runner": cfg["runner"], + "image": cfg.get("image", ""), + "bootstrap": cfg.get("bootstrap", ""), + "generator": cfg["generator"], + "c-compiler": cfg.get("c-compiler", ""), + "cxx-compiler": cfg.get("cxx-compiler", ""), + "build-type": bt, + "build-dir": "build", + "cmd-install-apt": build_install_cmd("apt", packages), + "cmd-install-brew": build_install_cmd("brew", packages), + "cmd-install-choco": build_install_cmd("choco", packages), + "cmd-install-pip": build_install_cmd("pip", packages), + }) with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write(f"matrix={json.dumps({'include': matrix})}\n") @@ -128,12 +127,18 @@ jobs: if: ${{ needs.generate.outputs.matrix != '' }} name: ${{ matrix.name }} runs-on: ${{ matrix.runner }} + container: + image: ${{ matrix.image }} timeout-minutes: 120 strategy: fail-fast: false matrix: ${{ fromJSON(needs.generate.outputs.matrix) }} steps: + - name: Bootstrap + if: matrix.bootstrap != '' + run: ${{ matrix.bootstrap }} + - uses: actions/checkout@v4 - name: Override opendaq_ref @@ -153,12 +158,84 @@ jobs: if: matrix.cmd-install-choco != '' run: ${{ matrix.cmd-install-choco }} + - name: Install dependencies (pip) + if: matrix.cmd-install-pip != '' + run: ${{ matrix.cmd-install-pip }} + + - name: Detect base presets + id: presets + shell: bash + run: | + base_cfg=$(cmake --list-presets 2>/dev/null | grep -o '"module"' | tr -d '"' || true) + base_test=$(ctest --list-presets 2>/dev/null | grep -o '"module-test"' | tr -d '"' || true) + echo "cmake=$base_cfg" >> $GITHUB_OUTPUT + echo "ctest=$base_test" >> $GITHUB_OUTPUT + + - name: Generate CI presets + id: generate + shell: python3 {0} + run: | + import json, os + + name = "${{ matrix.name }}" + base_cfg = "${{ steps.presets.outputs.cmake }}" + base_test = "${{ steps.presets.outputs.ctest }}" + + cfg_preset = f"ci-cfg-{name}" + build_preset = f"ci-build-{name}" + test_preset = f"ci-test-{name}" if base_test else "" + + presets = { + "version": 4, + "configurePresets": [{ + "name": cfg_preset, + **({"inherits": [base_cfg]} if base_cfg else {}), + "generator": "${{ matrix.generator }}", + "binaryDir": "$" + "{sourceDir}" + "/${{ matrix.build-dir }}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "${{ matrix.build-type }}", + **({ + "CMAKE_C_COMPILER": "${{ matrix.c-compiler }}", + "CMAKE_CXX_COMPILER": "${{ matrix.cxx-compiler }}", + } if "${{ matrix.c-compiler }}" else {}), + }, + }], + "buildPresets": [{ + "name": build_preset, + "configurePreset": cfg_preset, + "configuration": "${{ matrix.build-type }}", + }], + } + + if base_test: + presets["testPresets"] = [{ + "name": test_preset, + "inherits": [base_test], + "configurePreset": cfg_preset, + "configuration": "${{ matrix.build-type }}", + }] + + with open("CMakeUserPresets.json", "w") as f: + json.dump(presets, f, indent=2) + + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"cmake-user-cfg={cfg_preset}\n") + f.write(f"cmake-user-build={build_preset}\n") + f.write(f"ctest-user={test_preset}\n") + + - name: Upload CI presets + uses: actions/upload-artifact@v4 + with: + name: ci-presets-${{ matrix.name }} + path: CMakeUserPresets.json + retention-days: 7 + - name: Configure - run: cmake --preset ${{ matrix.cmake-preset }} + run: cmake --preset ${{ steps.generate.outputs.cmake-user-cfg }} - name: Build - run: cmake --build --preset ${{ matrix.cmake-preset }} + run: cmake --build --preset ${{ steps.generate.outputs.cmake-user-build }} - name: Test - if: matrix.ctest-preset != '' - run: ctest --preset ${{ matrix.ctest-preset }} + if: steps.generate.outputs.ctest-user != '' + run: ctest --preset ${{ steps.generate.outputs.ctest-user }} From afcecb74deb3f1b70818f6cc108e175bc5138a89 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Tue, 31 Mar 2026 11:25:25 +0200 Subject: [PATCH 03/11] Add macos default packages --- .github/workflows/reusable-module-ci.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index 2ef472c..9ba518e 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -38,12 +38,18 @@ jobs: "runners": ["ubuntu-*"], "packages": { "apt": [ - "mono-runtime", - "libmono-system-json-microsoft4.0-cil", + "mono-runtime", + "libmono-system-json-microsoft4.0-cil", "libmono-system-data4.0-cil" ] } - } + }, + { + "runners": ["macos-*"], + "packages": { + "brew": ["mono"] + } + }, ] pm_cmds = { From 16d84a204549a232b8156f04fd86c28edb852a47 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Tue, 31 Mar 2026 16:40:08 +0200 Subject: [PATCH 04/11] Add macOS 25 x86_64 runner and GTest output directory --- .github/workflows/reusable-module-ci.yml | 70 ++++++++++++++---------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index 9ba518e..7f11853 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -77,6 +77,12 @@ jobs: "c-compiler": "/usr/bin/clang", "cxx-compiler": "/usr/bin/clang++", }, + "macos-26-intel": { + "runner": "macos-26-intel", + "generator": "Ninja", + "c-compiler": "/usr/bin/clang", + "cxx-compiler": "/usr/bin/clang++", + }, } build_types = ["Release", "Debug"] @@ -118,7 +124,7 @@ jobs: "c-compiler": cfg.get("c-compiler", ""), "cxx-compiler": cfg.get("cxx-compiler", ""), "build-type": bt, - "build-dir": "build", + "build-dir": "build/output", "cmd-install-apt": build_install_cmd("apt", packages), "cmd-install-brew": build_install_cmd("brew", packages), "cmd-install-choco": build_install_cmd("choco", packages), @@ -172,10 +178,10 @@ jobs: id: presets shell: bash run: | - base_cfg=$(cmake --list-presets 2>/dev/null | grep -o '"module"' | tr -d '"' || true) - base_test=$(ctest --list-presets 2>/dev/null | grep -o '"module-test"' | tr -d '"' || true) - echo "cmake=$base_cfg" >> $GITHUB_OUTPUT - echo "ctest=$base_test" >> $GITHUB_OUTPUT + preset_base_cmake=$(cmake --list-presets 2>/dev/null | grep -o '"module"' | tr -d '"' || true) + preset_base_ctest=$(ctest --list-presets 2>/dev/null | grep -o '"module-test"' | tr -d '"' || true) + echo "base-cmake=$preset_base_cmake" >> $GITHUB_OUTPUT + echo "base-ctest=$preset_base_ctest" >> $GITHUB_OUTPUT - name: Generate CI presets id: generate @@ -183,19 +189,15 @@ jobs: run: | import json, os - name = "${{ matrix.name }}" - base_cfg = "${{ steps.presets.outputs.cmake }}" - base_test = "${{ steps.presets.outputs.ctest }}" - - cfg_preset = f"ci-cfg-{name}" - build_preset = f"ci-build-{name}" - test_preset = f"ci-test-{name}" if base_test else "" + preset = "ci-generated" + preset_base_cmake = "${{ steps.presets.outputs.base-cmake }}" + preset_base_ctest = "${{ steps.presets.outputs.base-ctest }}" presets = { "version": 4, "configurePresets": [{ - "name": cfg_preset, - **({"inherits": [base_cfg]} if base_cfg else {}), + "name": preset, + **({"inherits": [preset_base_cmake]} if preset_base_cmake else {}), "generator": "${{ matrix.generator }}", "binaryDir": "$" + "{sourceDir}" + "/${{ matrix.build-dir }}", "cacheVariables": { @@ -207,41 +209,53 @@ jobs: }, }], "buildPresets": [{ - "name": build_preset, - "configurePreset": cfg_preset, + "name": preset, + "configurePreset": preset, "configuration": "${{ matrix.build-type }}", }], } - if base_test: + if preset_base_ctest: presets["testPresets"] = [{ - "name": test_preset, - "inherits": [base_test], - "configurePreset": cfg_preset, + "name": preset, + "inherits": [preset_base_ctest], + "configurePreset": preset, "configuration": "${{ matrix.build-type }}", }] with open("CMakeUserPresets.json", "w") as f: json.dump(presets, f, indent=2) + gtest_output = os.path.join("${{ github.workspace }}", "build", "test-results", "gtest") + os.sep + with open(os.environ["GITHUB_OUTPUT"], "a") as f: - f.write(f"cmake-user-cfg={cfg_preset}\n") - f.write(f"cmake-user-build={build_preset}\n") - f.write(f"ctest-user={test_preset}\n") + f.write(f"cmake={preset}\n") + f.write(f"ctest={preset if preset_base_ctest else ''}\n") + f.write(f"gtest-output=xml:{gtest_output}\n") - name: Upload CI presets uses: actions/upload-artifact@v4 with: - name: ci-presets-${{ matrix.name }} + name: ci-preset-${{ matrix.name }} path: CMakeUserPresets.json retention-days: 7 - name: Configure - run: cmake --preset ${{ steps.generate.outputs.cmake-user-cfg }} + run: cmake --preset ${{ steps.generate.outputs.cmake }} - name: Build - run: cmake --build --preset ${{ steps.generate.outputs.cmake-user-build }} + run: cmake --build --preset ${{ steps.generate.outputs.cmake }} - name: Test - if: steps.generate.outputs.ctest-user != '' - run: ctest --preset ${{ steps.generate.outputs.ctest-user }} + if: steps.generate.outputs.ctest != '' + env: + GTEST_OUTPUT: ${{ steps.generate.outputs.gtest-output }} + run: ctest --preset ${{ steps.generate.outputs.ctest }} + + - name: Upload test results + if: ${{ !cancelled() && steps.generate.outputs.ctest != '' }} + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ matrix.name }} + path: build/test-results/ + retention-days: 7 From c5b2ca18cb3e45ea1af7cd8b71fa6496ebade0b7 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Tue, 31 Mar 2026 18:07:41 +0200 Subject: [PATCH 05/11] Add Ubuntu GCC 7 and Clang 8 configs --- .github/workflows/reusable-module-ci.yml | 47 +++++++++++++++++++----- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index 7f11853..f0a55d6 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -53,7 +53,7 @@ jobs: ] pm_cmds = { - "apt": "sudo apt-get install -y --no-install-recommends", + "apt": "sudo -E apt-get install -y --no-install-recommends", "brew": "brew install", "choco": "choco install -y", "pip": "pip install", @@ -67,6 +67,30 @@ jobs: "c-compiler": "gcc", "cxx-compiler": "g++", }, + "ubuntu-20.04-gcc-7": { + "runner": "ubuntu-latest", + "image": "ubuntu:20.04", + "bootstrap": "apt-get update && apt-get install -y git sudo", + "generator": "Ninja", + "c-compiler": "gcc-7", + "cxx-compiler": "g++-7", + "packages": { + "apt": ["gcc-7", "g++-7", "python3-pip"], + "pip": ["cmake", "ninja"], + }, + }, + "ubuntu-20.04-clang-8": { + "runner": "ubuntu-latest", + "image": "ubuntu:20.04", + "bootstrap": "apt-get update && apt-get install -y git sudo", + "generator": "Ninja", + "c-compiler": "clang-8", + "cxx-compiler": "clang++-8", + "packages": { + "apt": ["clang-8", "python3-pip"], + "pip": ["cmake", "ninja"], + }, + }, "windows-latest": { "runner": "windows-latest", "generator": "Visual Studio 17 2022", @@ -104,10 +128,12 @@ jobs: if matches_any(key, exclude_configs): continue - # merge packages: defaults + user + # merge packages: runner_cfg + defaults + user runner = cfg["runner"] image = cfg.get("image", "") packages: dict[str, list[str]] = {} + for pm, pkgs in cfg.get("packages", {}).items(): + packages.setdefault(pm, []).extend(pkgs) for req in default_packages + user_packages: runners = req.get("runners", ["*"]) if not any(fnmatch(runner, r) or (image and fnmatch(image, r)) for r in runners): @@ -141,6 +167,9 @@ jobs: runs-on: ${{ matrix.runner }} container: image: ${{ matrix.image }} + env: + DEBIAN_FRONTEND: noninteractive + TZ: Europe/Berlin timeout-minutes: 120 strategy: fail-fast: false @@ -151,7 +180,7 @@ jobs: if: matrix.bootstrap != '' run: ${{ matrix.bootstrap }} - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Override opendaq_ref if: ${{ inputs.opendaq-ref != '' }} @@ -226,15 +255,15 @@ jobs: with open("CMakeUserPresets.json", "w") as f: json.dump(presets, f, indent=2) - gtest_output = os.path.join("${{ github.workspace }}", "build", "test-results", "gtest") + os.sep + test_results_dir = os.path.join(os.environ["GITHUB_WORKSPACE"], "build", "test-results") + os.sep with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write(f"cmake={preset}\n") f.write(f"ctest={preset if preset_base_ctest else ''}\n") - f.write(f"gtest-output=xml:{gtest_output}\n") + f.write(f"test-results-dir={test_results_dir}\n") - name: Upload CI presets - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: ci-preset-${{ matrix.name }} path: CMakeUserPresets.json @@ -249,13 +278,13 @@ jobs: - name: Test if: steps.generate.outputs.ctest != '' env: - GTEST_OUTPUT: ${{ steps.generate.outputs.gtest-output }} + GTEST_OUTPUT: xml:${{ steps.generate.outputs.test-results-dir }} run: ctest --preset ${{ steps.generate.outputs.ctest }} - name: Upload test results if: ${{ !cancelled() && steps.generate.outputs.ctest != '' }} - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: test-results-${{ matrix.name }} - path: build/test-results/ + path: ${{ steps.generate.outputs.test-results-dir }} retention-days: 7 From d4670b5193c4cd66113701a326a549fa32fa3c7d Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Wed, 1 Apr 2026 20:53:43 +0200 Subject: [PATCH 06/11] Replace Clang 8 with 9 as openDAQ for compatibility reason --- .github/workflows/reusable-module-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index f0a55d6..e672e6b 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -79,15 +79,15 @@ jobs: "pip": ["cmake", "ninja"], }, }, - "ubuntu-20.04-clang-8": { + "ubuntu-20.04-clang-9": { "runner": "ubuntu-latest", "image": "ubuntu:20.04", "bootstrap": "apt-get update && apt-get install -y git sudo", "generator": "Ninja", - "c-compiler": "clang-8", - "cxx-compiler": "clang++-8", + "c-compiler": "clang-9", + "cxx-compiler": "clang++-9", "packages": { - "apt": ["clang-8", "python3-pip"], + "apt": ["clang-9", "python3-pip"], "pip": ["cmake", "ninja"], }, }, From 16b10634d9c48d714f737c6d8e720aead2216e7b Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Fri, 3 Apr 2026 19:35:29 +0200 Subject: [PATCH 07/11] Add different compilers + macOS 15 runners --- .github/workflows/reusable-module-ci.yml | 368 +++++++++++++++-------- 1 file changed, 239 insertions(+), 129 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index e672e6b..876d5de 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -7,12 +7,12 @@ on: description: "openDAQ commit, branch or tag. If empty, uses the opendaq_ref file from the repo." type: string default: '' - exclude-configs: - description: "JSON array of wildcard patterns to exclude configurations, e.g. '[\"*-debug\", \"macos-*\"]'" + exclude-jobs: + description: "JSON array of wildcard patterns to exclude matrix jobs, e.g. '[\"*-debug\", \"macos-*\"]'" type: string default: '[]' packages: - description: 'JSON array of package requests, e.g. [{"runners": ["ubuntu-*"], "packages": {"apt": ["libpcap-dev"]}}]' + description: 'JSON array of package requests, e.g. [{"jobs": ["ubuntu-*"], "apt-install": ["libpcap-dev"]}]' type: string default: '[]' @@ -30,136 +30,214 @@ jobs: import json, os from fnmatch import fnmatch - exclude_configs = json.loads("""${{ inputs.exclude-configs }}""") + exclude_jobs = json.loads("""${{ inputs.exclude-jobs }}""") user_packages = json.loads("""${{ inputs.packages }}""") - default_packages = [ - { - "runners": ["ubuntu-*"], - "packages": { - "apt": [ - "mono-runtime", - "libmono-system-json-microsoft4.0-cil", - "libmono-system-data4.0-cil" - ] - } - }, - { - "runners": ["macos-*"], - "packages": { - "brew": ["mono"] - } - }, - ] - - pm_cmds = { - "apt": "sudo -E apt-get install -y --no-install-recommends", - "brew": "brew install", - "choco": "choco install -y", - "pip": "pip install", + print(f"::notice::Input: exclude-jobs = {json.dumps(exclude_jobs) if exclude_jobs else 'None'}") + print(f"::notice::Input: packages = {json.dumps(user_packages) if user_packages else 'None'}") + + # --- General config --- + + _base = { + "runner": None, + "image": None, + "bootstrap": None, + "package-managers": [], + "generator": None, + "toolset": None, + "cc": None, + "cxx": None, + "cmd-sudo": None, + "cmd-apt-envs": ["DEBIAN_FRONTEND=noninteractive", "TZ=Etc/UTC"], + "cmd-apt-install": "apt-get install -y --no-install-recommends", + "cmd-pip-install": "pip install", + "cmd-brew-install": "brew install", + "cmd-choco-install": "choco install -y", + "apt-install-default": ["mono-runtime", "libmono-system-json-microsoft4.0-cil", "libmono-system-data4.0-cil"], + "pip-install-default": ["cmake", "ninja"], + "brew-install-default": ["mono"], + "apt-install": [], + "brew-install": [], + "choco-install": [], + "pip-install": [], } - runner_cfg = { - "ubuntu-latest": { - "runner": "ubuntu-latest", - "bootstrap": "sudo apt-get update", - "generator": "Ninja", - "c-compiler": "gcc", - "cxx-compiler": "g++", - }, - "ubuntu-20.04-gcc-7": { - "runner": "ubuntu-latest", - "image": "ubuntu:20.04", - "bootstrap": "apt-get update && apt-get install -y git sudo", - "generator": "Ninja", - "c-compiler": "gcc-7", - "cxx-compiler": "g++-7", - "packages": { - "apt": ["gcc-7", "g++-7", "python3-pip"], - "pip": ["cmake", "ninja"], - }, - }, - "ubuntu-20.04-clang-9": { - "runner": "ubuntu-latest", - "image": "ubuntu:20.04", - "bootstrap": "apt-get update && apt-get install -y git sudo", - "generator": "Ninja", - "c-compiler": "clang-9", - "cxx-compiler": "clang++-9", - "packages": { - "apt": ["clang-9", "python3-pip"], - "pip": ["cmake", "ninja"], - }, - }, - "windows-latest": { - "runner": "windows-latest", - "generator": "Visual Studio 17 2022", - }, - "macos-latest": { - "runner": "macos-latest", - "generator": "Ninja", - "c-compiler": "/usr/bin/clang", - "cxx-compiler": "/usr/bin/clang++", - }, - "macos-26-intel": { - "runner": "macos-26-intel", - "generator": "Ninja", - "c-compiler": "/usr/bin/clang", - "cxx-compiler": "/usr/bin/clang++", - }, + # --- Ubuntu configs --- + + _ubuntu_host_x86_64 = { + **_base, + "runner": "ubuntu-latest", + "bootstrap": "sudo apt-get update", + "package-managers": ["apt", "pip"], + "cmd-sudo": "sudo", + "generator": "Ninja", + "cc": "gcc", + "cxx": "g++", } - build_types = ["Release", "Debug"] + _ubuntu_guest_x86_64 = { + **_ubuntu_host_x86_64, + "bootstrap": "apt-get update && apt-get install -y git", + "apt-install-default": [*_base["apt-install-default"], "python3-pip"], + "cmd-sudo": "", + } - def matches_any(name: str, patterns: list[str]) -> bool: - return any(fnmatch(name, p) for p in patterns) + _ubuntu_20_04_x86_64 = { **_ubuntu_guest_x86_64, "image": "ubuntu:20.04" } + _ubuntu_24_04_x86_64 = { **_ubuntu_guest_x86_64, "image": "ubuntu:24.04", "cmd-pip-install": "pip install --break-system-packages" } + + # --- macOS configs --- + + _macos = { + **_base, + "package-managers": ["brew", "pip"], + "generator": "Ninja", + } + + _macos_15_armv8 = {**_macos, "runner": "macos-15"} + _macos_15_x86_64 = {**_macos, "runner": "macos-15-intel"} + _macos_26_armv8 = {**_macos, "runner": "macos-26"} + _macos_26_x86_64 = {**_macos, "runner": "macos-26-intel"} + + # --- Windows configs --- + + _windows_2025_x86_64 = { + **_base, + "runner": "windows-2025", + "generator": "Visual Studio 17 2022", + "package-managers": ["choco", "pip"], + "pip-install-default": ["cmake"], + } + + # --- Jobs configs --- + + jobs_cfg = { + "windows-2025-x86_64-msvc-v143": {**_windows_2025_x86_64, "toolset": "v143"}, + + "ubuntu-20.04-x86_64-gcc-7": {**_ubuntu_20_04_x86_64, "cc": "gcc-7", "cxx": "g++-7", "apt-install": ["gcc-7", "g++-7"]}, + "ubuntu-20.04-x86_64-clang-9": {**_ubuntu_20_04_x86_64, "cc": "clang-9", "cxx": "clang++-9", "apt-install": ["clang-9"]}, + "ubuntu-24.04-x86_64-gcc-13": {**_ubuntu_24_04_x86_64, "cc": "gcc-13", "cxx": "g++-13"}, + "ubuntu-24.04-x86_64-clang-18": {**_ubuntu_24_04_x86_64, "cc": "clang-18", "cxx": "clang++-18", "apt-install": ["clang-18"]}, + + "macos-15-armv8-appleclang": {**_macos_15_armv8, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + "macos-15-x86_64-appleclang": {**_macos_15_x86_64, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + "macos-26-armv8-appleclang": {**_macos_26_armv8, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + "macos-26-x86_64-appleclang": {**_macos_26_x86_64, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + } + + # --- Generate jobs matrix --- - def build_install_cmd(pm: str, packages: dict[str, list[str]]) -> str: - pkgs = packages.get(pm, []) - if not pkgs or pm not in pm_cmds: - return "" - return f"{pm_cmds[pm]} {' '.join(pkgs)}" + def matches_any(name, patterns): + return any(fnmatch(name, p) for p in patterns) matrix = [] - for cfg_key, cfg in runner_cfg.items(): - for bt in build_types: - key = f"{cfg_key}-{bt.lower()}" + for cfg_key, cfg in jobs_cfg.items(): + for build_type in ["Release", "Debug"]: + job_id = f"{cfg_key}-{build_type.lower()}" - if matches_any(key, exclude_configs): + if matches_any(job_id, exclude_jobs): + print(f"::notice::Matrix job '{job_id}': skipped by 'exclude-jobs' input") continue - # merge packages: runner_cfg + defaults + user - runner = cfg["runner"] - image = cfg.get("image", "") - packages: dict[str, list[str]] = {} - for pm, pkgs in cfg.get("packages", {}).items(): - packages.setdefault(pm, []).extend(pkgs) - for req in default_packages + user_packages: - runners = req.get("runners", ["*"]) - if not any(fnmatch(runner, r) or (image and fnmatch(image, r)) for r in runners): + supported_pms = set(cfg.get("package-managers", [])) + + # collect user packages for this job + user_pkgs = {} + for req in user_packages: + if not matches_any(job_id, req.get("jobs", ["*"])): continue - for pm, pkgs in req.get("packages", {}).items(): - packages.setdefault(pm, []).extend(pkgs) + + user_install = {k: v for k, v in req.items() if k.endswith("-install") and v} + for k, v in user_install.items(): + pm = k.removesuffix("-install") + if pm not in supported_pms: + print(f"::warning::Matrix job '{job_id}': '{pm}' is not supported by this runner, skipping installation of {v}") + continue + user_pkgs.setdefault(k, []).extend(v) + + # merge and build install commands per package manager + install_cmds = {} + for pm in supported_pms: + sudo = cfg.get("cmd-sudo") or "" + envs = " ".join(cfg.get(f"cmd-{pm}-envs", [])) + + install = cfg.get(f"{pm}-install-default", []) + cfg.get(f"{pm}-install", []) + user_pkgs.get(f"{pm}-install", []) + if install: + cmd = cfg.get(f"cmd-{pm}-install", "") + if not cmd: + print(f"::error::Matrix job '{job_id}': 'cmd-{pm}-install' is not defined but packages {install} are requested") + else: + parts = [envs, cmd, *install] + if pm == "apt" and sudo: + parts = [sudo, *parts] + install_cmds[f"cmd-install-{pm}"] = " ".join(p for p in parts if p) matrix.append({ - "name": key, + "name": job_id, "runner": cfg["runner"], - "image": cfg.get("image", ""), - "bootstrap": cfg.get("bootstrap", ""), + "image": cfg.get("image") or "", + "bootstrap": cfg.get("bootstrap") or "", "generator": cfg["generator"], - "c-compiler": cfg.get("c-compiler", ""), - "cxx-compiler": cfg.get("cxx-compiler", ""), - "build-type": bt, - "build-dir": "build/output", - "cmd-install-apt": build_install_cmd("apt", packages), - "cmd-install-brew": build_install_cmd("brew", packages), - "cmd-install-choco": build_install_cmd("choco", packages), - "cmd-install-pip": build_install_cmd("pip", packages), + "toolset": cfg.get("toolset") or "", + "cc": cfg.get("cc") or "", + "cxx": cfg.get("cxx") or "", + "build-type": build_type, + **install_cmds, }) with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write(f"matrix={json.dumps({'include': matrix})}\n") + matrix_json = json.dumps({"include": matrix}, indent=2) + + with open("matrix.json", "w") as f: + f.write(matrix_json) + + print(matrix_json) + + - name: Upload matrix + uses: actions/upload-artifact@v6 + with: + name: matrix + path: matrix.json + retention-days: 7 + + - name: Job summary + if: always() + shell: bash + run: | + { + echo "## Generate Matrix" + echo "| Step | Status |" + echo "|------|--------|" + echo "| ๐Ÿ”ง Generate | ${{ steps.matrix.outcome == 'success' && 'โœ…' || 'โŒ' }} |" + echo "" + echo "**opendaq-ref:** \`${{ inputs.opendaq-ref || 'default' }}\`" + echo "" + echo "
๐Ÿ“ฅ exclude-jobs" + echo "" + echo '```json' + echo '${{ inputs.exclude-jobs }}' | jq . 2>/dev/null || echo '[]' + echo '```' + echo "" + echo "
" + echo "" + echo "
๐Ÿ“ฆ packages" + echo "" + echo '```json' + echo '${{ inputs.packages }}' | jq . 2>/dev/null || echo '[]' + echo '```' + echo "" + echo "
" + echo "" + echo "
๐Ÿ“‹ matrix.json" + echo "" + echo '```json' + cat matrix.json 2>/dev/null || echo "Not generated" + echo '```' + echo "" + echo "
" + } >> "$GITHUB_STEP_SUMMARY" + build: needs: generate if: ${{ needs.generate.outputs.matrix != '' }} @@ -207,10 +285,10 @@ jobs: id: presets shell: bash run: | - preset_base_cmake=$(cmake --list-presets 2>/dev/null | grep -o '"module"' | tr -d '"' || true) - preset_base_ctest=$(ctest --list-presets 2>/dev/null | grep -o '"module-test"' | tr -d '"' || true) - echo "base-cmake=$preset_base_cmake" >> $GITHUB_OUTPUT - echo "base-ctest=$preset_base_ctest" >> $GITHUB_OUTPUT + base_cmake=$(cmake --list-presets 2>/dev/null | grep -o '"module"' | tr -d '"' || true) + base_ctest=$(ctest --list-presets 2>/dev/null | grep -o '"module-test"' | tr -d '"' || true) + echo "base-cmake=$base_cmake" >> $GITHUB_OUTPUT + echo "base-ctest=$base_ctest" >> $GITHUB_OUTPUT - name: Generate CI presets id: generate @@ -219,37 +297,43 @@ jobs: import json, os preset = "ci-generated" - preset_base_cmake = "${{ steps.presets.outputs.base-cmake }}" - preset_base_ctest = "${{ steps.presets.outputs.base-ctest }}" + build_dir = "build/output" + base_cmake = "${{ steps.presets.outputs.base-cmake }}" + base_ctest = "${{ steps.presets.outputs.base-ctest }}" + + build_type = "${{ matrix.build-type }}" + cc = "${{ matrix.cc }}" + cxx = "${{ matrix.cxx }}" + generator = "${{ matrix.generator }}" + toolset = "${{ matrix.toolset }}" presets = { "version": 4, "configurePresets": [{ "name": preset, - **({"inherits": [preset_base_cmake]} if preset_base_cmake else {}), - "generator": "${{ matrix.generator }}", - "binaryDir": "$" + "{sourceDir}" + "/${{ matrix.build-dir }}", + **({"inherits": [base_cmake]} if base_cmake else {}), + **({"generator": generator} if generator else {}), + **({"toolset": toolset} if toolset else {}), + "binaryDir": "$" + "{sourceDir}" + f"/{build_dir}", "cacheVariables": { - "CMAKE_BUILD_TYPE": "${{ matrix.build-type }}", - **({ - "CMAKE_C_COMPILER": "${{ matrix.c-compiler }}", - "CMAKE_CXX_COMPILER": "${{ matrix.cxx-compiler }}", - } if "${{ matrix.c-compiler }}" else {}), + **({"CMAKE_BUILD_TYPE": build_type} if build_type else {}), + **({"CMAKE_C_COMPILER": cc} if cc else {}), + **({"CMAKE_CXX_COMPILER": cxx} if cxx else {}), }, }], "buildPresets": [{ "name": preset, "configurePreset": preset, - "configuration": "${{ matrix.build-type }}", + **({"configuration": build_type} if build_type else {}), }], } - if preset_base_ctest: + if base_ctest: presets["testPresets"] = [{ "name": preset, - "inherits": [preset_base_ctest], "configurePreset": preset, - "configuration": "${{ matrix.build-type }}", + "inherits": [base_ctest], + **({"configuration": build_type} if build_type else {}), }] with open("CMakeUserPresets.json", "w") as f: @@ -259,7 +343,7 @@ jobs: with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write(f"cmake={preset}\n") - f.write(f"ctest={preset if preset_base_ctest else ''}\n") + f.write(f"ctest={preset if base_ctest else ''}\n") f.write(f"test-results-dir={test_results_dir}\n") - name: Upload CI presets @@ -270,12 +354,15 @@ jobs: retention-days: 7 - name: Configure + id: configure run: cmake --preset ${{ steps.generate.outputs.cmake }} - name: Build + id: build run: cmake --build --preset ${{ steps.generate.outputs.cmake }} - name: Test + id: test if: steps.generate.outputs.ctest != '' env: GTEST_OUTPUT: xml:${{ steps.generate.outputs.test-results-dir }} @@ -288,3 +375,26 @@ jobs: name: test-results-${{ matrix.name }} path: ${{ steps.generate.outputs.test-results-dir }} retention-days: 7 + + - name: Job summary + if: always() + shell: bash + run: | + status() { [ "$1" = "success" ] && echo "โœ…" || ([ "$1" = "skipped" ] && echo "โž–" || echo "โŒ"); } + { + echo "## ${{ matrix.name }}" + echo "| Step | Status |" + echo "|------|--------|" + echo "| ๐Ÿ”ง Generate preset | $(status ${{ steps.generate.outcome }}) |" + echo "| โš™๏ธ Configure | $(status ${{ steps.configure.outcome }}) |" + echo "| ๐Ÿ”จ Build | $(status ${{ steps.build.outcome }}) |" + echo "| ๐Ÿงช Test | $(status ${{ steps.test.outcome }}) |" + echo "" + echo "
CMakeUserPresets.json" + echo "" + echo '```json' + cat CMakeUserPresets.json 2>/dev/null || echo "Not generated" + echo '```' + echo "" + echo "
" + } >> "$GITHUB_STEP_SUMMARY" From e7d00a76a1524437c81bc9b77e12d2a937e823c9 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Fri, 3 Apr 2026 20:01:51 +0200 Subject: [PATCH 08/11] Set GCC 14 compiler on Ubuntu 24.04 runners --- .github/workflows/reusable-module-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index 876d5de..46efbec 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -115,7 +115,7 @@ jobs: "ubuntu-20.04-x86_64-gcc-7": {**_ubuntu_20_04_x86_64, "cc": "gcc-7", "cxx": "g++-7", "apt-install": ["gcc-7", "g++-7"]}, "ubuntu-20.04-x86_64-clang-9": {**_ubuntu_20_04_x86_64, "cc": "clang-9", "cxx": "clang++-9", "apt-install": ["clang-9"]}, - "ubuntu-24.04-x86_64-gcc-13": {**_ubuntu_24_04_x86_64, "cc": "gcc-13", "cxx": "g++-13"}, + "ubuntu-24.04-x86_64-gcc-14": {**_ubuntu_24_04_x86_64, "cc": "gcc-14", "cxx": "g++-14", "apt-install": ["gcc-14", "g++-14"]}, "ubuntu-24.04-x86_64-clang-18": {**_ubuntu_24_04_x86_64, "cc": "clang-18", "cxx": "clang++-18", "apt-install": ["clang-18"]}, "macos-15-armv8-appleclang": {**_macos_15_armv8, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, @@ -233,6 +233,7 @@ jobs: echo "" echo '```json' cat matrix.json 2>/dev/null || echo "Not generated" + echo "" echo '```' echo "" echo "" From 1ab7ee64f2775943d27a5b1c15f1a871e88ff418 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Sun, 5 Apr 2026 17:00:34 +0200 Subject: [PATCH 09/11] Generate single CMakeUserPreset.json for all jobs --- .github/workflows/reusable-module-ci.yml | 267 +++++++++++++---------- 1 file changed, 148 insertions(+), 119 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index 46efbec..a9963ef 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -12,13 +12,17 @@ on: type: string default: '[]' packages: - description: 'JSON array of package requests, e.g. [{"jobs": ["ubuntu-*"], "apt-install": ["libpcap-dev"]}]' + description: 'JSON array of package requests, e.g. [{"match-jobs": ["ubuntu-*"], "apt-install": ["libpcap-dev"]}]' + type: string + default: '[]' + cmake-presets: + description: 'JSON array of preset configs, e.g. [{"match-jobs": ["*"], "configure-preset": "module", "test-preset": "module-test"}]' type: string default: '[]' jobs: generate: - name: Generate matrix + name: Generate runs-on: ubuntu-latest outputs: matrix: ${{ steps.matrix.outputs.matrix }} @@ -33,8 +37,11 @@ jobs: exclude_jobs = json.loads("""${{ inputs.exclude-jobs }}""") user_packages = json.loads("""${{ inputs.packages }}""") - print(f"::notice::Input: exclude-jobs = {json.dumps(exclude_jobs) if exclude_jobs else 'None'}") - print(f"::notice::Input: packages = {json.dumps(user_packages) if user_packages else 'None'}") + cmake_presets = json.loads("""${{ inputs.cmake-presets }}""") + + print(f"Input: exclude-jobs = {json.dumps(exclude_jobs) if exclude_jobs else 'None'}") + print(f"Input: packages = {json.dumps(user_packages) if user_packages else 'None'}") + print(f"Input: cmake-presets = {json.dumps(cmake_presets) if cmake_presets else 'None'}") # --- General config --- @@ -132,10 +139,10 @@ jobs: matrix = [] for cfg_key, cfg in jobs_cfg.items(): for build_type in ["Release", "Debug"]: - job_id = f"{cfg_key}-{build_type.lower()}" + job_name = f"{cfg_key}-{build_type.lower()}" - if matches_any(job_id, exclude_jobs): - print(f"::notice::Matrix job '{job_id}': skipped by 'exclude-jobs' input") + if matches_any(job_name, exclude_jobs): + print(f"XMatrix job '{job_name}': skipped by 'exclude-jobs' input") continue supported_pms = set(cfg.get("package-managers", [])) @@ -143,14 +150,14 @@ jobs: # collect user packages for this job user_pkgs = {} for req in user_packages: - if not matches_any(job_id, req.get("jobs", ["*"])): + if not matches_any(job_name, req.get("match-jobs", ["*"])): continue user_install = {k: v for k, v in req.items() if k.endswith("-install") and v} for k, v in user_install.items(): pm = k.removesuffix("-install") if pm not in supported_pms: - print(f"::warning::Matrix job '{job_id}': '{pm}' is not supported by this runner, skipping installation of {v}") + print(f"::warning::Matrix job '{job_name}': '{pm}' is not supported by this runner, skipping installation of {v}") continue user_pkgs.setdefault(k, []).extend(v) @@ -164,7 +171,7 @@ jobs: if install: cmd = cfg.get(f"cmd-{pm}-install", "") if not cmd: - print(f"::error::Matrix job '{job_id}': 'cmd-{pm}-install' is not defined but packages {install} are requested") + print(f"::error::Matrix job '{job_name}': 'cmd-{pm}-install' is not defined but packages {install} are requested") else: parts = [envs, cmd, *install] if pm == "apt" and sudo: @@ -172,7 +179,7 @@ jobs: install_cmds[f"cmd-install-{pm}"] = " ".join(p for p in parts if p) matrix.append({ - "name": job_id, + "name": job_name, "runner": cfg["runner"], "image": cfg.get("image") or "", "bootstrap": cfg.get("bootstrap") or "", @@ -187,52 +194,109 @@ jobs: with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write(f"matrix={json.dumps({'include': matrix})}\n") - matrix_json = json.dumps({"include": matrix}, indent=2) + print(f"Output: matrix = {json.dumps({'include': matrix}, indent=2)}") + + - name: Generate user presets + id: presets + shell: python3 {0} + run: | + import json + from fnmatch import fnmatch + + cmake_presets = json.loads("""${{ inputs.cmake-presets }}""") + matrix = json.loads("""${{ steps.matrix.outputs.matrix }}""")["include"] + + build_dir = "build/output" + user_presets = {"version": 4, "configurePresets": [], "buildPresets": [], "testPresets": []} + + for entry in matrix: + name = entry["name"] + build_type = entry.get("build-type") or "" + generator = entry.get("generator") or "" + toolset = entry.get("toolset") or "" + cc = entry.get("cc") or "" + cxx = entry.get("cxx") or "" + + # find matching cmake-presets config + configure_preset = "" + test_preset = "" + for req in cmake_presets: + if any(fnmatch(name, p) for p in req.get("match-jobs", ["*"])): + configure_preset = req.get("configure-preset", configure_preset) + test_preset = req.get("test-preset", test_preset) + + user_presets["configurePresets"].append({ + "name": name, + **({"inherits": [configure_preset]} if configure_preset else {}), + **({"generator": generator} if generator else {}), + **({"toolset": toolset} if toolset else {}), + "binaryDir": "$" + "{sourceDir}" + f"/{build_dir}", + "cacheVariables": { + **({"CMAKE_BUILD_TYPE": build_type} if build_type else {}), + **({"CMAKE_C_COMPILER": cc} if cc else {}), + **({"CMAKE_CXX_COMPILER": cxx} if cxx else {}), + }, + }) - with open("matrix.json", "w") as f: - f.write(matrix_json) + user_presets["buildPresets"].append({ + "name": name, + "configurePreset": name, + **({"configuration": build_type} if build_type else {}), + }) + + if test_preset: + user_presets["testPresets"].append({ + "name": name, + "configurePreset": name, + "inherits": [test_preset], + **({"configuration": build_type} if build_type else {}), + }) - print(matrix_json) + with open("CMakeUserPresets.json", "w") as f: + json.dump(user_presets, f, indent=2) - - name: Upload matrix + - name: Upload presets uses: actions/upload-artifact@v6 with: - name: matrix - path: matrix.json + name: CMakeUserPresets + path: CMakeUserPresets.json retention-days: 7 - name: Job summary if: always() shell: bash run: | + s() { [ "$1" = "success" ] && echo "โœ…" || ([ "$1" = "skipped" ] && echo "โž–" || echo "โŒ"); } + overall="โœ…" + [[ "${{ steps.matrix.outcome }}" == "failure" || "${{ steps.presets.outcome }}" == "failure" ]] && overall="โŒ" { - echo "## Generate Matrix" - echo "| Step | Status |" - echo "|------|--------|" - echo "| ๐Ÿ”ง Generate | ${{ steps.matrix.outcome == 'success' && 'โœ…' || 'โŒ' }} |" - echo "" - echo "**opendaq-ref:** \`${{ inputs.opendaq-ref || 'default' }}\`" + echo "
${overall} Generate job inputs" echo "" - echo "
๐Ÿ“ฅ exclude-jobs" - echo "" - echo '```json' - echo '${{ inputs.exclude-jobs }}' | jq . 2>/dev/null || echo '[]' + echo '```yaml' + echo "on:" + echo " workflow_call:" + echo " inputs:" + echo " opendaq-ref: ${{ inputs.opendaq-ref || '\"\"' }}" + echo " exclude-jobs: '${{ inputs.exclude-jobs || '[]' }}'" + echo " packages: '${{ inputs.packages || '[]' }}'" + echo " cmake-presets: '${{ inputs.cmake-presets || '[]' }}'" echo '```' echo "" echo "
" echo "" - echo "
๐Ÿ“ฆ packages" + echo "
$(s ${{ steps.matrix.outcome }}) Generate matrix (matrix.json)" echo "" echo '```json' - echo '${{ inputs.packages }}' | jq . 2>/dev/null || echo '[]' + echo '${{ steps.matrix.outputs.matrix }}' | jq . 2>/dev/null || echo "Not generated" + echo "" echo '```' echo "" echo "
" echo "" - echo "
๐Ÿ“‹ matrix.json" + echo "
$(s ${{ steps.presets.outcome }}) Generate presets (CMakeUserPresets.json)" echo "" echo '```json' - cat matrix.json 2>/dev/null || echo "Not generated" + cat CMakeUserPresets.json 2>/dev/null || echo "Not generated" echo "" echo '```' echo "" @@ -282,119 +346,84 @@ jobs: if: matrix.cmd-install-pip != '' run: ${{ matrix.cmd-install-pip }} - - name: Detect base presets - id: presets + - name: Download CI presets + uses: actions/download-artifact@v6 + with: + name: CMakeUserPresets + + - name: Detect tests + id: detect-tests shell: bash run: | - base_cmake=$(cmake --list-presets 2>/dev/null | grep -o '"module"' | tr -d '"' || true) - base_ctest=$(ctest --list-presets 2>/dev/null | grep -o '"module-test"' | tr -d '"' || true) - echo "base-cmake=$base_cmake" >> $GITHUB_OUTPUT - echo "base-ctest=$base_ctest" >> $GITHUB_OUTPUT - - - name: Generate CI presets - id: generate - shell: python3 {0} - run: | - import json, os - - preset = "ci-generated" - build_dir = "build/output" - base_cmake = "${{ steps.presets.outputs.base-cmake }}" - base_ctest = "${{ steps.presets.outputs.base-ctest }}" - - build_type = "${{ matrix.build-type }}" - cc = "${{ matrix.cc }}" - cxx = "${{ matrix.cxx }}" - generator = "${{ matrix.generator }}" - toolset = "${{ matrix.toolset }}" - - presets = { - "version": 4, - "configurePresets": [{ - "name": preset, - **({"inherits": [base_cmake]} if base_cmake else {}), - **({"generator": generator} if generator else {}), - **({"toolset": toolset} if toolset else {}), - "binaryDir": "$" + "{sourceDir}" + f"/{build_dir}", - "cacheVariables": { - **({"CMAKE_BUILD_TYPE": build_type} if build_type else {}), - **({"CMAKE_C_COMPILER": cc} if cc else {}), - **({"CMAKE_CXX_COMPILER": cxx} if cxx else {}), - }, - }], - "buildPresets": [{ - "name": preset, - "configurePreset": preset, - **({"configuration": build_type} if build_type else {}), - }], - } - - if base_ctest: - presets["testPresets"] = [{ - "name": preset, - "configurePreset": preset, - "inherits": [base_ctest], - **({"configuration": build_type} if build_type else {}), - }] - - with open("CMakeUserPresets.json", "w") as f: - json.dump(presets, f, indent=2) - - test_results_dir = os.path.join(os.environ["GITHUB_WORKSPACE"], "build", "test-results") + os.sep - - with open(os.environ["GITHUB_OUTPUT"], "a") as f: - f.write(f"cmake={preset}\n") - f.write(f"ctest={preset if base_ctest else ''}\n") - f.write(f"test-results-dir={test_results_dir}\n") - - - name: Upload CI presets - uses: actions/upload-artifact@v6 - with: - name: ci-preset-${{ matrix.name }} - path: CMakeUserPresets.json - retention-days: 7 + if ctest --list-presets 2>/dev/null | grep -q '"${{ matrix.name }}"'; then + echo "preset=${{ matrix.name }}" >> $GITHUB_OUTPUT + fi - name: Configure id: configure - run: cmake --preset ${{ steps.generate.outputs.cmake }} + run: cmake --preset ${{ matrix.name }} - name: Build id: build - run: cmake --build --preset ${{ steps.generate.outputs.cmake }} + run: cmake --build --preset ${{ matrix.name }} + + - name: Setup GTest + id: setup-gtest + if: steps.detect-tests.outputs.preset != '' + shell: python3 {0} + run: | + import os + test_results_dir = os.path.join(os.environ["GITHUB_WORKSPACE"], "build", "test-results") + os.makedirs(test_results_dir, exist_ok=True) + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"test-results-dir={test_results_dir}{os.sep}\n") - name: Test id: test - if: steps.generate.outputs.ctest != '' + if: steps.detect-tests.outputs.preset != '' env: - GTEST_OUTPUT: xml:${{ steps.generate.outputs.test-results-dir }} - run: ctest --preset ${{ steps.generate.outputs.ctest }} + GTEST_OUTPUT: xml:${{ steps.setup-gtest.outputs.test-results-dir }} + run: ctest --preset ${{ steps.detect-tests.outputs.preset }} - name: Upload test results - if: ${{ !cancelled() && steps.generate.outputs.ctest != '' }} + if: ${{ !cancelled() && steps.detect-tests.outputs.preset != '' }} uses: actions/upload-artifact@v6 with: name: test-results-${{ matrix.name }} - path: ${{ steps.generate.outputs.test-results-dir }} + path: ${{ steps.setup-gtest.outputs.test-results-dir }} retention-days: 7 - name: Job summary if: always() shell: bash run: | - status() { [ "$1" = "success" ] && echo "โœ…" || ([ "$1" = "skipped" ] && echo "โž–" || echo "โŒ"); } + s() { [ "$1" = "success" ] && echo "โœ…" || ([ "$1" = "skipped" ] && echo "โž–" || echo "โŒ"); } + overall="โœ…" + [[ "${{ steps.configure.outcome }}" == "failure" || "${{ steps.build.outcome }}" == "failure" || "${{ steps.test.outcome }}" == "failure" ]] && overall="โŒ" { - echo "## ${{ matrix.name }}" - echo "| Step | Status |" - echo "|------|--------|" - echo "| ๐Ÿ”ง Generate preset | $(status ${{ steps.generate.outcome }}) |" - echo "| โš™๏ธ Configure | $(status ${{ steps.configure.outcome }}) |" - echo "| ๐Ÿ”จ Build | $(status ${{ steps.build.outcome }}) |" - echo "| ๐Ÿงช Test | $(status ${{ steps.test.outcome }}) |" + echo "
${overall} ${{ matrix.name }}" echo "" - echo "
CMakeUserPresets.json" + echo '```bash' + echo "# Download preset (see Generate job summary CMakeUserPresets.json section, if expired):" + echo "gh run download ${{ github.run_id }} -n CMakeUserPresets -D ." + if [ -n "${{ inputs.opendaq-ref }}" ]; then + echo "" + echo "# Override openDAQ ref:" + echo 'echo "${{ inputs.opendaq-ref }}" > opendaq_ref' + fi echo "" - echo '```json' - cat CMakeUserPresets.json 2>/dev/null || echo "Not generated" + echo "# $(s ${{ steps.configure.outcome }}) Configure:" + echo "cmake --preset ${{ matrix.name }}" + echo "" + echo "# $(s ${{ steps.build.outcome }}) Build:" + echo "cmake --build --preset ${{ matrix.name }}" + echo "" + if [ "${{ steps.test.outcome }}" = "skipped" ]; then + echo "# $(s ${{ steps.test.outcome }}) Test skipped" + else + echo "# $(s ${{ steps.test.outcome }}) Test:" + echo "ctest --preset ${{ matrix.name }}" + fi echo '```' echo "" echo "
" From e94408361d77f7b6f416288539121ae465fbd635 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Sun, 5 Apr 2026 19:10:43 +0200 Subject: [PATCH 10/11] Add generator to job names --- .github/workflows/reusable-module-ci.yml | 73 +++++++++++------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index a9963ef..487a20c 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -37,11 +37,8 @@ jobs: exclude_jobs = json.loads("""${{ inputs.exclude-jobs }}""") user_packages = json.loads("""${{ inputs.packages }}""") - cmake_presets = json.loads("""${{ inputs.cmake-presets }}""") - print(f"Input: exclude-jobs = {json.dumps(exclude_jobs) if exclude_jobs else 'None'}") print(f"Input: packages = {json.dumps(user_packages) if user_packages else 'None'}") - print(f"Input: cmake-presets = {json.dumps(cmake_presets) if cmake_presets else 'None'}") # --- General config --- @@ -60,9 +57,9 @@ jobs: "cmd-pip-install": "pip install", "cmd-brew-install": "brew install", "cmd-choco-install": "choco install -y", - "apt-install-default": ["mono-runtime", "libmono-system-json-microsoft4.0-cil", "libmono-system-data4.0-cil"], - "pip-install-default": ["cmake", "ninja"], - "brew-install-default": ["mono"], + "apt-install-default": [], + "pip-install-default": [], + "brew-install-default": [], "apt-install": [], "brew-install": [], "choco-install": [], @@ -71,43 +68,40 @@ jobs: # --- Ubuntu configs --- - _ubuntu_host_x86_64 = { + _ubuntu_guest_x86_64_ninja = { **_base, "runner": "ubuntu-latest", - "bootstrap": "sudo apt-get update", + "bootstrap": "apt-get update && apt-get install -y git", "package-managers": ["apt", "pip"], - "cmd-sudo": "sudo", + "cmd-sudo": "", "generator": "Ninja", "cc": "gcc", "cxx": "g++", + "apt-install-default": ["mono-runtime", "libmono-system-json-microsoft4.0-cil", "libmono-system-data4.0-cil", "python3-pip"], + "pip-install-default": ["cmake", "ninja"], } - _ubuntu_guest_x86_64 = { - **_ubuntu_host_x86_64, - "bootstrap": "apt-get update && apt-get install -y git", - "apt-install-default": [*_base["apt-install-default"], "python3-pip"], - "cmd-sudo": "", - } - - _ubuntu_20_04_x86_64 = { **_ubuntu_guest_x86_64, "image": "ubuntu:20.04" } - _ubuntu_24_04_x86_64 = { **_ubuntu_guest_x86_64, "image": "ubuntu:24.04", "cmd-pip-install": "pip install --break-system-packages" } + _ubuntu_20_04_x86_64_ninja = { **_ubuntu_guest_x86_64_ninja, "image": "ubuntu:20.04" } + _ubuntu_24_04_x86_64_ninja = { **_ubuntu_guest_x86_64_ninja, "image": "ubuntu:24.04", "cmd-pip-install": "pip install --break-system-packages" } # --- macOS configs --- - _macos = { + _macos_ninja = { **_base, "package-managers": ["brew", "pip"], - "generator": "Ninja", + "brew-install-default": ["mono"], + "generator": "Ninja", + "pip-install-default": ["cmake", "ninja"] } - _macos_15_armv8 = {**_macos, "runner": "macos-15"} - _macos_15_x86_64 = {**_macos, "runner": "macos-15-intel"} - _macos_26_armv8 = {**_macos, "runner": "macos-26"} - _macos_26_x86_64 = {**_macos, "runner": "macos-26-intel"} + _macos_15_armv8_ninja = {**_macos_ninja, "runner": "macos-15"} + _macos_15_x86_64_ninja = {**_macos_ninja, "runner": "macos-15-intel"} + _macos_26_armv8_ninja = {**_macos_ninja, "runner": "macos-26"} + _macos_26_x86_64_ninja = {**_macos_ninja, "runner": "macos-26-intel"} # --- Windows configs --- - _windows_2025_x86_64 = { + _windows_2025_x86_64_msvs = { **_base, "runner": "windows-2025", "generator": "Visual Studio 17 2022", @@ -118,17 +112,17 @@ jobs: # --- Jobs configs --- jobs_cfg = { - "windows-2025-x86_64-msvc-v143": {**_windows_2025_x86_64, "toolset": "v143"}, - - "ubuntu-20.04-x86_64-gcc-7": {**_ubuntu_20_04_x86_64, "cc": "gcc-7", "cxx": "g++-7", "apt-install": ["gcc-7", "g++-7"]}, - "ubuntu-20.04-x86_64-clang-9": {**_ubuntu_20_04_x86_64, "cc": "clang-9", "cxx": "clang++-9", "apt-install": ["clang-9"]}, - "ubuntu-24.04-x86_64-gcc-14": {**_ubuntu_24_04_x86_64, "cc": "gcc-14", "cxx": "g++-14", "apt-install": ["gcc-14", "g++-14"]}, - "ubuntu-24.04-x86_64-clang-18": {**_ubuntu_24_04_x86_64, "cc": "clang-18", "cxx": "clang++-18", "apt-install": ["clang-18"]}, - - "macos-15-armv8-appleclang": {**_macos_15_armv8, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, - "macos-15-x86_64-appleclang": {**_macos_15_x86_64, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, - "macos-26-armv8-appleclang": {**_macos_26_armv8, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, - "macos-26-x86_64-appleclang": {**_macos_26_x86_64, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + "windows-2025-x86_64-msvs-v143": {**_windows_2025_x86_64_msvs, "toolset": "v143"}, + + "ubuntu-20.04-x86_64-ninja-gcc-7": {**_ubuntu_20_04_x86_64_ninja, "cc": "gcc-7", "cxx": "g++-7", "apt-install": ["gcc-7", "g++-7"]}, + "ubuntu-20.04-x86_64-ninja-clang-9": {**_ubuntu_20_04_x86_64_ninja, "cc": "clang-9", "cxx": "clang++-9", "apt-install": ["clang-9"]}, + "ubuntu-24.04-x86_64-ninja-gcc-14": {**_ubuntu_24_04_x86_64_ninja, "cc": "gcc-14", "cxx": "g++-14", "apt-install": ["gcc-14", "g++-14"]}, + "ubuntu-24.04-x86_64-ninja-clang-18": {**_ubuntu_24_04_x86_64_ninja, "cc": "clang-18", "cxx": "clang++-18", "apt-install": ["clang-18"]}, + + "macos-15-armv8-ninja-appleclang": {**_macos_15_armv8_ninja, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + "macos-15-x86_64-ninja-appleclang": {**_macos_15_x86_64_ninja, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + "macos-26-armv8-ninja-appleclang": {**_macos_26_armv8_ninja, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, + "macos-26-x86_64-ninja-appleclang": {**_macos_26_x86_64_ninja, "cc": "/usr/bin/clang", "cxx": "/usr/bin/clang++"}, } # --- Generate jobs matrix --- @@ -142,7 +136,7 @@ jobs: job_name = f"{cfg_key}-{build_type.lower()}" if matches_any(job_name, exclude_jobs): - print(f"XMatrix job '{job_name}': skipped by 'exclude-jobs' input") + print(f"Matrix job '{job_name}': skipped by 'exclude-jobs' input") continue supported_pms = set(cfg.get("package-managers", [])) @@ -206,6 +200,8 @@ jobs: cmake_presets = json.loads("""${{ inputs.cmake-presets }}""") matrix = json.loads("""${{ steps.matrix.outputs.matrix }}""")["include"] + print(f"Input: cmake-presets = {json.dumps(cmake_presets) if cmake_presets else 'None'}") + build_dir = "build/output" user_presets = {"version": 4, "configurePresets": [], "buildPresets": [], "testPresets": []} @@ -310,9 +306,6 @@ jobs: runs-on: ${{ matrix.runner }} container: image: ${{ matrix.image }} - env: - DEBIAN_FRONTEND: noninteractive - TZ: Europe/Berlin timeout-minutes: 120 strategy: fail-fast: false From 54c7adf539ec70d85dd9a90792852647aed350e3 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika Date: Tue, 7 Apr 2026 11:03:55 +0200 Subject: [PATCH 11/11] Update checkout@v6, upload-artifact@v7, and download-artifact@v8 --- .github/workflows/reusable-module-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable-module-ci.yml b/.github/workflows/reusable-module-ci.yml index 487a20c..2ad2739 100644 --- a/.github/workflows/reusable-module-ci.yml +++ b/.github/workflows/reusable-module-ci.yml @@ -252,7 +252,7 @@ jobs: json.dump(user_presets, f, indent=2) - name: Upload presets - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: CMakeUserPresets path: CMakeUserPresets.json @@ -340,7 +340,7 @@ jobs: run: ${{ matrix.cmd-install-pip }} - name: Download CI presets - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v8 with: name: CMakeUserPresets @@ -380,7 +380,7 @@ jobs: - name: Upload test results if: ${{ !cancelled() && steps.detect-tests.outputs.preset != '' }} - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: test-results-${{ matrix.name }} path: ${{ steps.setup-gtest.outputs.test-results-dir }}