From d95d861a9d14cfa6b9d5a2a281345a37af01424c Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Mon, 10 Aug 2026 15:30:34 +0200 Subject: [PATCH 01/15] Publish the OPC UA module stagings The stage workflow pulls the core staging matching each job, builds the modules against it and publishes them to ghcr. CPack packs the module runtime into a TGZ named by opendaq-cmake-utils, the same way core names its packages. --- .github/workflows/stage.yml | 125 ++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 7 ++ CMakePresets.json | 11 ++++ cmake/CMakeLists.txt | 2 +- cmake/Packing.cmake | 53 +++++++++++++++ 5 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/stage.yml create mode 100644 cmake/Packing.cmake diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml new file mode 100644 index 00000000..d14f59e1 --- /dev/null +++ b/.github/workflows/stage.yml @@ -0,0 +1,125 @@ +name: Build OPC UA module stagings + +on: + push: + branches: [main] + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + # the core stagings the modules build against + CORE_STAGING: ghcr.io/${{ github.repository_owner }}/test/staging/opendaq + +jobs: + resolve: + name: Resolve staging jobs + runs-on: ubuntu-latest + outputs: + include-jobs: ${{ steps.jobs.outputs.include-jobs }} + staging-pull: ${{ steps.jobs.outputs.staging-pull }} + packages: ${{ steps.jobs.outputs.packages }} + staging-push: ${{ steps.jobs.outputs.staging-push }} + steps: + - name: Resolve staging jobs + id: jobs + shell: python3 {0} + env: + OWNER: ${{ github.repository_owner }} + REF: ${{ github.ref }} + CORE: ${{ env.CORE_STAGING }} + run: | + import json, os + + # every job pulls the core staging built the same way, selected by the annotations + # that name it + JOBS = { + "windows-2022-x86_64-msvs-v143-release": {"platform": "windows", "arch": "x86_64"}, + "windows-2022-x86-msvs-v143-release": {"platform": "windows", "arch": "x86"}, + "manylinux_2_28-x86_64-ninja-gcc-release": {"platform": "manylinux_2_28", "arch": "x86_64"}, + "ubuntu-22.04-x86_64-ninja-gcc-release": {"platform": "linux", "arch": "x86_64"}, + "ubuntu-22.04-armv8-ninja-gcc-release": {"platform": "linux", "arch": "armv8"}, + "macos-26-x86_64-ninja-appleclang-release":{"platform": "macos", "arch": "x86_64"}, + "macos-26-armv8-ninja-appleclang-release": {"platform": "macos", "arch": "armv8"}, + } + + owner = os.environ["OWNER"] + ref = os.environ["REF"] + core = os.environ["CORE"] + + if ref.startswith("refs/heads/release/"): + channel = "stable" + elif ref == "refs/heads/main": + channel = "dev" + else: + channel = "test" + + resolved = { + "include-jobs": list(JOBS), + "staging-pull": [{ + "artifact": f"core-{job}", + "packages": [{ + "path": core, + "tag": "latest", + "annotations": { + "com.opendaq.custom.platform": settings["platform"], + "com.opendaq.settings.arch": settings["arch"], + }, + }], + } for job, settings in JOBS.items()], + "packages": [{ + "match-jobs": [job], + "artifacts": [{"name": f"core-{job}", "dir": "staging-deps"}], + } for job in JOBS], + "staging-push": [{ + "path": f"ghcr.io/{owner}/{channel}/staging/opcua-modules", + "artifacts": ["staging-*/opcua"], + "tags": ["latest"], + }], + } + + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + for key, value in resolved.items(): + f.write(f"{key}={json.dumps(value)}\n") + + print(json.dumps(resolved, indent=2)) + + stage: + needs: resolve + name: OpcUaModules + permissions: + contents: read + packages: write + uses: openDAQ/openDAQ-CI/.github/workflows/stage.yml@jira/TBBAS-3439-multi-staging + with: + timeout: '[{"timeout-minutes": 180}]' + staging-pull: ${{ needs.resolve.outputs.staging-pull }} + include-jobs: ${{ needs.resolve.outputs.include-jobs }} + packages: ${{ needs.resolve.outputs.packages }} + cmake-presets: > + [ + { + "match-jobs": ["*"], + "configure-preset": "stage", + "cache-variables": + { + "CMAKE_PREFIX_PATH": "${sourceDir}/staging-deps;${sourceDir}/staging-deps/opt/opendaq" + } + }, + { + "match-jobs": ["macos-*"], + "cache-variables": {"CMAKE_OSX_DEPLOYMENT_TARGET": "10.15"} + } + ] + cpack-presets: > + [ + { + "match-jobs": ["*"], + "stagings": [{"name": "opcua"}] + } + ] + staging-push: ${{ needs.resolve.outputs.staging-push }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 5df94b39..63075436 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ set(REPO_OPTION_PREFIX DAQMODULES_OPCUA) list(APPEND CMAKE_MESSAGE_CONTEXT ${REPO_NAME}) add_subdirectory(cmake) +# Names the install components of the modules: openDAQ__Runtime / _Development +set(SDK_NAME "${OPENDAQ_SDK_NAME}") + opendaq_read_file_contents("${CMAKE_CURRENT_LIST_DIR}/module_version" module_version) opendaq_get_version_major_minor_patch("${module_version}" ${REPO_OPTION_PREFIX}_VERSION) @@ -85,3 +88,7 @@ add_subdirectory(external/boost) add_subdirectory(external) add_subdirectory(shared) add_subdirectory(modules) + +if (PROJECT_IS_TOP_LEVEL) + include(cmake/Packing.cmake) +endif() diff --git a/CMakePresets.json b/CMakePresets.json index 7cb57754..288849a9 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -224,6 +224,17 @@ "cacheVariables": { "DAQMODULES_OPCUA_ENABLE_TESTS": "ON" } + }, + { + "name": "stage", + "hidden": true, + "cacheVariables": { + "DAQMODULES_OPCUA_ENABLE_CLIENT": "ON", + "DAQMODULES_OPCUA_ENABLE_SERVER": "ON", + "DAQMODULES_OPCUA_ENABLE_GENERIC_CLIENT": "OFF", + "DAQMODULES_OPCUA_ENABLE_EXAMPLE_APP": "OFF", + "DAQMODULES_OPCUA_ENABLE_TESTS": "OFF" + } } ], "testPresets": [ diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 9a35aa9b..6c7fd46f 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -8,7 +8,7 @@ include(FetchContent) FetchContent_Declare( opendaq-cmake-utils GIT_REPOSITORY https://github.com/openDAQ/opendaq-cmake-utils.git - GIT_TAG v1.0.1 + GIT_TAG ci/staging GIT_PROGRESS ON ) FetchContent_MakeAvailable(opendaq-cmake-utils) diff --git a/cmake/Packing.cmake b/cmake/Packing.cmake new file mode 100644 index 00000000..77dd5a5a --- /dev/null +++ b/cmake/Packing.cmake @@ -0,0 +1,53 @@ +## +## CPack configuration for the OPC UA modules +## + +set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) +set(CPACK_PACKAGE_VENDOR "openDAQ d.o.o.") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "openDAQ OPC UA client and server modules") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://opendaq.io/") +set(CPACK_PACKAGE_CONTACT "info@opendaq.io") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + +set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) + +set(CPACK_VERBATIM_VARIABLES ON) +set(CPACK_THREADS 0) + +set(CPACK_GENERATOR TGZ) +set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) +set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) + +if(NOT CPACK_PACKAGE_DIRECTORY) + set(CPACK_PACKAGE_DIRECTORY "${CMAKE_SOURCE_DIR}/build/_packages") +endif() + +## +## Package filename and staging metadata +## +## Format: opcua-modules-[-]----- +## Composed by opendaq-cmake-utils, the same way core names its packages. +## + +set(CPACK_OPENDAQ_META_PACKAGE_NAME "opcua-modules") + +execute_process(COMMAND git -C "${CMAKE_CURRENT_SOURCE_DIR}" rev-parse --short=7 HEAD + OUTPUT_VARIABLE _PACKING_SHORT_SHA + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET +) +if(_PACKING_SHORT_SHA) + set(CPACK_OPENDAQ_META_PACKAGE_VERSION_SUFFIX "-${_PACKING_SHORT_SHA}") +endif() + +opendaq_detect_settings() +opendaq_detect_package() +opendaq_compose_package_triplet() +opendaq_compose_package_file_name() + +# Let each cpack run name the package it produces (-D CPACK_OPENDAQ_META_PACKAGE_NAME=...). +set(CPACK_PROJECT_CONFIG_FILE "${CPACK_OPENDAQ_PROJECT_CONFIG}") + +include(CPack) From 22d861e01f39fc8f4d3286ba47d862867fd34df5 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Fri, 14 Aug 2026 17:22:31 +0200 Subject: [PATCH 02/15] Pack only the module runtime Without the component scope the package also carries the MSVC runtime that InstallRequiredSystemLibraries installs, which core already ships. --- CMakePresets.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakePresets.json b/CMakePresets.json index 288849a9..a875a993 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -233,7 +233,8 @@ "DAQMODULES_OPCUA_ENABLE_SERVER": "ON", "DAQMODULES_OPCUA_ENABLE_GENERIC_CLIENT": "OFF", "DAQMODULES_OPCUA_ENABLE_EXAMPLE_APP": "OFF", - "DAQMODULES_OPCUA_ENABLE_TESTS": "OFF" + "DAQMODULES_OPCUA_ENABLE_TESTS": "OFF", + "CPACK_COMPONENTS_ALL": "openDAQ_opcua_client_module_Runtime;openDAQ_opcua_server_module_Runtime" } } ], From c3020dbc8c9cd572a8f430f4301c797e27a35527 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:50:09 +0200 Subject: [PATCH 03/15] Pull the core staging opendaq_ref names The staging index of a core commit is tagged with its sha, so opendaq_ref -- already the ref this repository builds against -- is resolved to one and the pull asks for that, instead of whatever latest points at. The job list, what each job pulls and where the stagings are published are literal, so the workflow shows them. The job computes the two values that cannot be written down: the commit and the channel the branch publishes to. --- .github/workflows/stage.yml | 133 ++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 73 deletions(-) diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index d14f59e1..da78d9f5 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -11,82 +11,35 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -env: - # the core stagings the modules build against - CORE_STAGING: ghcr.io/${{ github.repository_owner }}/test/staging/opendaq - jobs: resolve: - name: Resolve staging jobs + name: Resolve the core commit runs-on: ubuntu-latest outputs: - include-jobs: ${{ steps.jobs.outputs.include-jobs }} - staging-pull: ${{ steps.jobs.outputs.staging-pull }} - packages: ${{ steps.jobs.outputs.packages }} - staging-push: ${{ steps.jobs.outputs.staging-push }} + core-sha: ${{ steps.core.outputs.core-sha }} + channel: ${{ steps.core.outputs.channel }} steps: - - name: Resolve staging jobs - id: jobs - shell: python3 {0} + - uses: actions/checkout@v4 + + - name: Resolve the core commit and the publish channel + id: core + shell: bash env: - OWNER: ${{ github.repository_owner }} - REF: ${{ github.ref }} - CORE: ${{ env.CORE_STAGING }} + GH_TOKEN: ${{ github.token }} run: | - import json, os + core_ref=$(cat opendaq_ref) + core_sha=$(gh api "/repos/openDAQ/openDAQ/commits/$core_ref" --jq .sha) \ + || { echo "::error::opendaq_ref names no commit of openDAQ/openDAQ: $core_ref"; exit 1; } - # every job pulls the core staging built the same way, selected by the annotations - # that name it - JOBS = { - "windows-2022-x86_64-msvs-v143-release": {"platform": "windows", "arch": "x86_64"}, - "windows-2022-x86-msvs-v143-release": {"platform": "windows", "arch": "x86"}, - "manylinux_2_28-x86_64-ninja-gcc-release": {"platform": "manylinux_2_28", "arch": "x86_64"}, - "ubuntu-22.04-x86_64-ninja-gcc-release": {"platform": "linux", "arch": "x86_64"}, - "ubuntu-22.04-armv8-ninja-gcc-release": {"platform": "linux", "arch": "armv8"}, - "macos-26-x86_64-ninja-appleclang-release":{"platform": "macos", "arch": "x86_64"}, - "macos-26-armv8-ninja-appleclang-release": {"platform": "macos", "arch": "armv8"}, - } + case "$GITHUB_REF" in + refs/heads/release/*) channel=stable ;; + refs/heads/main) channel=dev ;; + *) channel=test ;; + esac - owner = os.environ["OWNER"] - ref = os.environ["REF"] - core = os.environ["CORE"] - - if ref.startswith("refs/heads/release/"): - channel = "stable" - elif ref == "refs/heads/main": - channel = "dev" - else: - channel = "test" - - resolved = { - "include-jobs": list(JOBS), - "staging-pull": [{ - "artifact": f"core-{job}", - "packages": [{ - "path": core, - "tag": "latest", - "annotations": { - "com.opendaq.custom.platform": settings["platform"], - "com.opendaq.settings.arch": settings["arch"], - }, - }], - } for job, settings in JOBS.items()], - "packages": [{ - "match-jobs": [job], - "artifacts": [{"name": f"core-{job}", "dir": "staging-deps"}], - } for job in JOBS], - "staging-push": [{ - "path": f"ghcr.io/{owner}/{channel}/staging/opcua-modules", - "artifacts": ["staging-*/opcua"], - "tags": ["latest"], - }], - } - - with open(os.environ["GITHUB_OUTPUT"], "a") as f: - for key, value in resolved.items(): - f.write(f"{key}={json.dumps(value)}\n") - - print(json.dumps(resolved, indent=2)) + echo "core-sha=$core_sha" >> "$GITHUB_OUTPUT" + echo "channel=$channel" >> "$GITHUB_OUTPUT" + echo "opendaq_ref $core_ref -> $core_sha, channel $channel" stage: needs: resolve @@ -97,10 +50,37 @@ jobs: uses: openDAQ/openDAQ-CI/.github/workflows/stage.yml@jira/TBBAS-3439-multi-staging with: timeout: '[{"timeout-minutes": 180}]' - staging-pull: ${{ needs.resolve.outputs.staging-pull }} - include-jobs: ${{ needs.resolve.outputs.include-jobs }} - packages: ${{ needs.resolve.outputs.packages }} - cmake-presets: > + staging-pull: >- + [ + { "artifact": "core-windows-2022-x86_64-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-windows-2022-x86-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86" } }] }, + { "artifact": "core-manylinux_2_28-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "manylinux_2_28", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-ubuntu-22.04-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-ubuntu-22.04-armv8-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "armv8" } }] }, + { "artifact": "core-macos-26-x86_64-ninja-appleclang-release","packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-macos-26-armv8-ninja-appleclang-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "armv8" } }] } + ] + include-jobs: >- + [ + "windows-2022-x86_64-msvs-v143-release", + "windows-2022-x86-msvs-v143-release", + "manylinux_2_28-x86_64-ninja-gcc-release", + "ubuntu-22.04-x86_64-ninja-gcc-release", + "ubuntu-22.04-armv8-ninja-gcc-release", + "macos-26-x86_64-ninja-appleclang-release", + "macos-26-armv8-ninja-appleclang-release" + ] + packages: >- + [ + { "match-jobs": ["windows-2022-x86_64-msvs-v143-release"], "artifacts": [{ "name": "core-windows-2022-x86_64-msvs-v143-release", "dir": "staging-deps" }] }, + { "match-jobs": ["windows-2022-x86-msvs-v143-release"], "artifacts": [{ "name": "core-windows-2022-x86-msvs-v143-release", "dir": "staging-deps" }] }, + { "match-jobs": ["manylinux_2_28-x86_64-ninja-gcc-release"], "artifacts": [{ "name": "core-manylinux_2_28-x86_64-ninja-gcc-release", "dir": "staging-deps" }] }, + { "match-jobs": ["ubuntu-22.04-x86_64-ninja-gcc-release"], "artifacts": [{ "name": "core-ubuntu-22.04-x86_64-ninja-gcc-release", "dir": "staging-deps" }] }, + { "match-jobs": ["ubuntu-22.04-armv8-ninja-gcc-release"], "artifacts": [{ "name": "core-ubuntu-22.04-armv8-ninja-gcc-release", "dir": "staging-deps" }] }, + { "match-jobs": ["macos-26-x86_64-ninja-appleclang-release"],"artifacts": [{ "name": "core-macos-26-x86_64-ninja-appleclang-release", "dir": "staging-deps" }] }, + { "match-jobs": ["macos-26-armv8-ninja-appleclang-release"], "artifacts": [{ "name": "core-macos-26-armv8-ninja-appleclang-release", "dir": "staging-deps" }] } + ] + cmake-presets: >- [ { "match-jobs": ["*"], @@ -115,11 +95,18 @@ jobs: "cache-variables": {"CMAKE_OSX_DEPLOYMENT_TARGET": "10.15"} } ] - cpack-presets: > + cpack-presets: >- [ { "match-jobs": ["*"], "stagings": [{"name": "opcua"}] } ] - staging-push: ${{ needs.resolve.outputs.staging-push }} + staging-push: >- + [ + { + "path": "ghcr.io/${{ github.repository_owner }}/${{ needs.resolve.outputs.channel }}/staging/opcua-modules", + "artifacts": ["staging-*/opcua"], + "tags": ["latest"] + } + ] From 254373a99f38422ac0f4079fabf5987ab5091220 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:50:09 +0200 Subject: [PATCH 04/15] Pin core to a staged commit Stagings exist only from openDAQ/openDAQ#1265 on, so this is the one core commit the pull can resolve today. --- opendaq_ref | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendaq_ref b/opendaq_ref index 881016eb..d07ff756 100644 --- a/opendaq_ref +++ b/opendaq_ref @@ -1 +1 @@ -e6f13d80fa7c64697e5549fc1d897b03ad813415 +60f8ae4d08a02a9a262c457d3e1da759e6f92bc6 From dc45497bd9d6a19d008b9011ba49484d86722f86 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:50:09 +0200 Subject: [PATCH 05/15] Publish the stagings weekly, not on every merge A staging matrix is seven runners, and most of the merges between two runs produce nothing a consumer asks for. workflow_dispatch covers what cannot wait for the schedule. --- .github/workflows/stage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index da78d9f5..6a896690 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -1,8 +1,8 @@ name: Build OPC UA module stagings on: - push: - branches: [main] + schedule: + - cron: '0 2 * * 1' pull_request: types: [opened, reopened, synchronize, ready_for_review] workflow_dispatch: From af94c36f4ff0bf87e6b840f10937cc585349715a Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:50:09 +0200 Subject: [PATCH 06/15] Trigger on push again Temporary: until the workflow reaches main, workflow_dispatch is not offered, so pushing is the only way to run it outside a pull request. --- .github/workflows/stage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index 6a896690..210cd945 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -1,6 +1,7 @@ name: Build OPC UA module stagings on: + push: schedule: - cron: '0 2 * * 1' pull_request: From a68fd27945d0c5eb893337b5869c3a345dcd1ab0 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:39:07 +0200 Subject: [PATCH 07/15] Stop staging on pull requests A pull request is checked out as its merge commit, so what it publishes is tagged with a sha that lives in no branch and cannot be pinned or cloned. --- .github/workflows/stage.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index 210cd945..94dcb2af 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -4,8 +4,6 @@ on: push: schedule: - cron: '0 2 * * 1' - pull_request: - types: [opened, reopened, synchronize, ready_for_review] workflow_dispatch: concurrency: From 8783fbe92846f8e35cdf1dd233beee37c552eb06 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 19 Aug 2026 18:01:46 +0200 Subject: [PATCH 08/15] Pin core to a commit that is on a branch The staging pulled so far was published from a pull request, so its sha was a merge commit -- in the registry, but in no branch, so the source build could not check it out. --- opendaq_ref | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendaq_ref b/opendaq_ref index d07ff756..9c3b4d7e 100644 --- a/opendaq_ref +++ b/opendaq_ref @@ -1 +1 @@ -60f8ae4d08a02a9a262c457d3e1da759e6f92bc6 +7e569c0afed4c5ca43ceca8ba396aa635cb8b4fc From 88e054ad98eecc53d9daa0a5d83e72a8c18fce44 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Thu, 20 Aug 2026 07:43:16 +0200 Subject: [PATCH 09/15] Bump core to the current staging The pinned core carried a packaging bug that only shows when the SDK is built as a subproject, which is what the source path of this repository does. --- opendaq_ref | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendaq_ref b/opendaq_ref index 9c3b4d7e..d50f2792 100644 --- a/opendaq_ref +++ b/opendaq_ref @@ -1 +1 @@ -7e569c0afed4c5ca43ceca8ba396aa635cb8b4fc +4a6ee1d1912ca9fc68a435e3312a3b95ee1f3960 From d0bebbb1bcaceeef30d0fab95c1dc62b1d44c16b Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Mon, 24 Aug 2026 13:44:31 +0200 Subject: [PATCH 10/15] Resolve the channel with the shared action The rule is the same in every repository, and the staging build had its own copy of it. Reading the pinned ref is all that is left here, and it is a line. --- .github/workflows/stage.yml | 40 +++++++++++++------------------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index 94dcb2af..ea0a74fc 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -15,30 +15,18 @@ jobs: name: Resolve the core commit runs-on: ubuntu-latest outputs: - core-sha: ${{ steps.core.outputs.core-sha }} - channel: ${{ steps.core.outputs.channel }} + core-ref: ${{ steps.core.outputs.ref }} + channel: ${{ steps.channel.outputs.channel }} steps: - uses: actions/checkout@v4 - - name: Resolve the core commit and the publish channel + - uses: openDAQ/openDAQ-CI/.github/actions/resolve-channel@jira/TBBAS-3477-staging-check + id: channel + + - name: Read the pinned core ref id: core shell: bash - env: - GH_TOKEN: ${{ github.token }} - run: | - core_ref=$(cat opendaq_ref) - core_sha=$(gh api "/repos/openDAQ/openDAQ/commits/$core_ref" --jq .sha) \ - || { echo "::error::opendaq_ref names no commit of openDAQ/openDAQ: $core_ref"; exit 1; } - - case "$GITHUB_REF" in - refs/heads/release/*) channel=stable ;; - refs/heads/main) channel=dev ;; - *) channel=test ;; - esac - - echo "core-sha=$core_sha" >> "$GITHUB_OUTPUT" - echo "channel=$channel" >> "$GITHUB_OUTPUT" - echo "opendaq_ref $core_ref -> $core_sha, channel $channel" + run: echo "ref=$(cat opendaq_ref)" >> "$GITHUB_OUTPUT" stage: needs: resolve @@ -51,13 +39,13 @@ jobs: timeout: '[{"timeout-minutes": 180}]' staging-pull: >- [ - { "artifact": "core-windows-2022-x86_64-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86_64" } }] }, - { "artifact": "core-windows-2022-x86-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86" } }] }, - { "artifact": "core-manylinux_2_28-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "manylinux_2_28", "com.opendaq.settings.arch": "x86_64" } }] }, - { "artifact": "core-ubuntu-22.04-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "x86_64" } }] }, - { "artifact": "core-ubuntu-22.04-armv8-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "armv8" } }] }, - { "artifact": "core-macos-26-x86_64-ninja-appleclang-release","packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "x86_64" } }] }, - { "artifact": "core-macos-26-armv8-ninja-appleclang-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-sha }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "armv8" } }] } + { "artifact": "core-windows-2022-x86_64-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-windows-2022-x86-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86" } }] }, + { "artifact": "core-manylinux_2_28-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "manylinux_2_28", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-ubuntu-22.04-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-ubuntu-22.04-armv8-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "armv8" } }] }, + { "artifact": "core-macos-26-x86_64-ninja-appleclang-release","packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-macos-26-armv8-ninja-appleclang-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "armv8" } }] } ] include-jobs: >- [ From a84a14700510958c5765399d9898e431bca00ff3 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:45:08 +0200 Subject: [PATCH 11/15] Bump core to the current staging --- opendaq_ref | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendaq_ref b/opendaq_ref index d50f2792..0d7a81b2 100644 --- a/opendaq_ref +++ b/opendaq_ref @@ -1 +1 @@ -4a6ee1d1912ca9fc68a435e3312a3b95ee1f3960 +64ab85c594f0ad5fef169c84ae24bda251540f38 From 3b83a1391d3cbb02e8242972c7867bd1b304d673 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Mon, 24 Aug 2026 15:27:57 +0200 Subject: [PATCH 12/15] Prune the stagings this repository publishes A repository owns the packages it publishes, so it is the one that can delete them. Only the nightly channel is listed: a channel that is never cleaned is how a release is kept. --- .github/workflows/cleanup.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/cleanup.yml diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml new file mode 100644 index 00000000..11dd7839 --- /dev/null +++ b/.github/workflows/cleanup.yml @@ -0,0 +1,24 @@ +name: Clean up stagings + +on: + schedule: + - cron: '0 6 * * 1' + workflow_dispatch: + inputs: + dry-run: + description: "List what would be pruned without deleting." + type: boolean + default: false + +jobs: + cleanup: + name: Stagings + permissions: + packages: write + uses: openDAQ/openDAQ-CI/.github/workflows/staging-cleanup.yml@jira/TBBAS-3293-staging-cleanup + with: + dry-run: ${{ inputs.dry-run || false }} + staging-retentions: >- + [ + { "path": "ghcr.io/openDAQ/dev/staging/opcua-modules", "retention": { "days": 30 } } + ] From 43c7db1d65fe1471ec8de2da4b72b36ff3809e17 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Mon, 24 Aug 2026 17:15:31 +0200 Subject: [PATCH 13/15] Never skip a publishing run Grouping the runs cancels a pending one when a third arrives, which leaves a commit unpublished and nothing republishes it. Publishing weekly and on demand, runs do not overlap enough for the group to buy anything. --- .github/workflows/stage.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index ea0a74fc..56846c2f 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -6,9 +6,6 @@ on: - cron: '0 2 * * 1' workflow_dispatch: -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true jobs: resolve: From 0e2443d3de991cb346a72b0d0da6db1343a5bc01 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Mon, 24 Aug 2026 17:21:30 +0200 Subject: [PATCH 14/15] Publish on the schedule and on demand only The push trigger was there to run the workflow before it reached main, where workflow_dispatch becomes available. --- .github/workflows/stage.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index 56846c2f..48b97986 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -1,7 +1,6 @@ name: Build OPC UA module stagings on: - push: schedule: - cron: '0 2 * * 1' workflow_dispatch: From ed9a2bf6238481a26ae170609162cec3d293f1d4 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:54:10 +0200 Subject: [PATCH 15/15] Build against the pinned compiler configs The referenced openDAQ-CI branches and the cmake utils ci/staging branch were deleted once their PRs merged, so neither the workflow calls nor FetchContent resolved any more. The workflows now point at the branch carrying the pinned job configs, and the job names follow: manylinux builds with gcc-toolset-14, macOS with the Xcode-pinned Apple clang 17 or 21. The utils are pinned to v1.0.3, the release cut from that merge. --- .github/workflows/cleanup.yml | 2 +- .github/workflows/stage.yml | 22 +++++++++++----------- cmake/CMakeLists.txt | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml index 11dd7839..10bd4568 100644 --- a/.github/workflows/cleanup.yml +++ b/.github/workflows/cleanup.yml @@ -15,7 +15,7 @@ jobs: name: Stagings permissions: packages: write - uses: openDAQ/openDAQ-CI/.github/workflows/staging-cleanup.yml@jira/TBBAS-3293-staging-cleanup + uses: openDAQ/openDAQ-CI/.github/workflows/staging-cleanup.yml@jira/TBBAS-3440-pinned-configs with: dry-run: ${{ inputs.dry-run || false }} staging-retentions: >- diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index 48b97986..8c7cae56 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: openDAQ/openDAQ-CI/.github/actions/resolve-channel@jira/TBBAS-3477-staging-check + - uses: openDAQ/openDAQ-CI/.github/actions/resolve-channel@jira/TBBAS-3440-pinned-configs id: channel - name: Read the pinned core ref @@ -30,38 +30,38 @@ jobs: permissions: contents: read packages: write - uses: openDAQ/openDAQ-CI/.github/workflows/stage.yml@jira/TBBAS-3439-multi-staging + uses: openDAQ/openDAQ-CI/.github/workflows/stage.yml@jira/TBBAS-3440-pinned-configs with: timeout: '[{"timeout-minutes": 180}]' staging-pull: >- [ { "artifact": "core-windows-2022-x86_64-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86_64" } }] }, { "artifact": "core-windows-2022-x86-msvs-v143-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "windows", "com.opendaq.settings.arch": "x86" } }] }, - { "artifact": "core-manylinux_2_28-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "manylinux_2_28", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-manylinux_2_28-x86_64-ninja-gcc-14-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "manylinux_2_28", "com.opendaq.settings.arch": "x86_64" } }] }, { "artifact": "core-ubuntu-22.04-x86_64-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "x86_64" } }] }, { "artifact": "core-ubuntu-22.04-armv8-ninja-gcc-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "linux", "com.opendaq.settings.arch": "armv8" } }] }, - { "artifact": "core-macos-26-x86_64-ninja-appleclang-release","packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "x86_64" } }] }, - { "artifact": "core-macos-26-armv8-ninja-appleclang-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "armv8" } }] } + { "artifact": "core-macos-26-x86_64-ninja-appleclang-21-release","packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "x86_64" } }] }, + { "artifact": "core-macos-26-armv8-ninja-appleclang-21-release", "packages": [{ "path": "ghcr.io/openDAQ/test/staging/opendaq", "tag": "${{ needs.resolve.outputs.core-ref }}", "annotations": { "com.opendaq.custom.platform": "macos", "com.opendaq.settings.arch": "armv8" } }] } ] include-jobs: >- [ "windows-2022-x86_64-msvs-v143-release", "windows-2022-x86-msvs-v143-release", - "manylinux_2_28-x86_64-ninja-gcc-release", + "manylinux_2_28-x86_64-ninja-gcc-14-release", "ubuntu-22.04-x86_64-ninja-gcc-release", "ubuntu-22.04-armv8-ninja-gcc-release", - "macos-26-x86_64-ninja-appleclang-release", - "macos-26-armv8-ninja-appleclang-release" + "macos-26-x86_64-ninja-appleclang-21-release", + "macos-26-armv8-ninja-appleclang-21-release" ] packages: >- [ { "match-jobs": ["windows-2022-x86_64-msvs-v143-release"], "artifacts": [{ "name": "core-windows-2022-x86_64-msvs-v143-release", "dir": "staging-deps" }] }, { "match-jobs": ["windows-2022-x86-msvs-v143-release"], "artifacts": [{ "name": "core-windows-2022-x86-msvs-v143-release", "dir": "staging-deps" }] }, - { "match-jobs": ["manylinux_2_28-x86_64-ninja-gcc-release"], "artifacts": [{ "name": "core-manylinux_2_28-x86_64-ninja-gcc-release", "dir": "staging-deps" }] }, + { "match-jobs": ["manylinux_2_28-x86_64-ninja-gcc-14-release"], "artifacts": [{ "name": "core-manylinux_2_28-x86_64-ninja-gcc-14-release", "dir": "staging-deps" }] }, { "match-jobs": ["ubuntu-22.04-x86_64-ninja-gcc-release"], "artifacts": [{ "name": "core-ubuntu-22.04-x86_64-ninja-gcc-release", "dir": "staging-deps" }] }, { "match-jobs": ["ubuntu-22.04-armv8-ninja-gcc-release"], "artifacts": [{ "name": "core-ubuntu-22.04-armv8-ninja-gcc-release", "dir": "staging-deps" }] }, - { "match-jobs": ["macos-26-x86_64-ninja-appleclang-release"],"artifacts": [{ "name": "core-macos-26-x86_64-ninja-appleclang-release", "dir": "staging-deps" }] }, - { "match-jobs": ["macos-26-armv8-ninja-appleclang-release"], "artifacts": [{ "name": "core-macos-26-armv8-ninja-appleclang-release", "dir": "staging-deps" }] } + { "match-jobs": ["macos-26-x86_64-ninja-appleclang-21-release"],"artifacts": [{ "name": "core-macos-26-x86_64-ninja-appleclang-21-release", "dir": "staging-deps" }] }, + { "match-jobs": ["macos-26-armv8-ninja-appleclang-21-release"], "artifacts": [{ "name": "core-macos-26-armv8-ninja-appleclang-21-release", "dir": "staging-deps" }] } ] cmake-presets: >- [ diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 6c7fd46f..22f2e696 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -8,7 +8,7 @@ include(FetchContent) FetchContent_Declare( opendaq-cmake-utils GIT_REPOSITORY https://github.com/openDAQ/opendaq-cmake-utils.git - GIT_TAG ci/staging + GIT_TAG v1.0.3 GIT_PROGRESS ON ) FetchContent_MakeAvailable(opendaq-cmake-utils)