From 15ddc7b03791dc55f305e4d879866699141f34cb Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:21:22 +0200 Subject: [PATCH 1/2] Create reusable workflow and composite action for module build and test - Add ci-framework.yml: reusable workflow for testing with openDAQ framework artifacts - Add module-build-test composite action: automated CMake configure, build, and test - Update ci.yml: use new composite action, add fail-fast: false for matrix jobs --- .github/actions/framework-download/action.yml | 50 -------- .github/actions/framework-install/action.yml | 42 ------- .../framework-latest-release/action.yml | 111 ------------------ .github/actions/module-build-test/action.yml | 29 +++++ .github/workflows/ci-framework.yml | 82 +++++++++++++ .github/workflows/ci.yml | 85 ++++++-------- .gitignore | 7 +- 7 files changed, 152 insertions(+), 254 deletions(-) delete mode 100644 .github/actions/framework-download/action.yml delete mode 100644 .github/actions/framework-install/action.yml delete mode 100644 .github/actions/framework-latest-release/action.yml create mode 100644 .github/actions/module-build-test/action.yml create mode 100644 .github/workflows/ci-framework.yml diff --git a/.github/actions/framework-download/action.yml b/.github/actions/framework-download/action.yml deleted file mode 100644 index 6d34b86..0000000 --- a/.github/actions/framework-download/action.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Download openDAQ framework package -description: "Download a package from S3 for Linux or Windows" - -inputs: - src-opendaq-framework-dev: - required: true - description: "S3 path to the package" - dst-opendaq-framework-dev: - required: false - default: ${{ runner.temp }} - description: "Destination path for downloaded package" - - aws_access_key_id: - required: true - description: "AWS Access Key ID" - aws_secret_access_key: - required: true - description: "AWS Secret Access Key" - aws_region: - required: true - description: "AWS Region" - -runs: - using: composite - steps: - - name: Configure AWS - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ inputs.aws_access_key_id }} - aws-secret-access-key: ${{ inputs.aws_secret_access_key }} - aws-region: ${{ inputs.aws_region }} - - - name: Download package from S3 (Linux/macOS) - if: runner.os != 'Windows' - shell: bash - run: | - set -e - DST="${{ inputs.dst-opendaq-framework-dev }}" - SRC="${{ inputs.src-opendaq-framework-dev }}" - echo "Downloading $SRC to $DST" - aws s3 cp "$SRC" "$DST" - - - name: Download package from S3 (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - $dst = "${{ inputs.dst-opendaq-framework-dev }}" - $src = "${{ inputs.src-opendaq-framework-dev }}" - Write-Host "Downloading $src to $dst" - aws s3 cp "$src" "$dst" diff --git a/.github/actions/framework-install/action.yml b/.github/actions/framework-install/action.yml deleted file mode 100644 index 6e3e6de..0000000 --- a/.github/actions/framework-install/action.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Install openDAQ framework package - -inputs: - opendaq-framework-package-filename: - required: true - - opendaq-framework-package-path: - required: false - default: ${{ runner.temp }} - -runs: - using: composite - - steps: - - name: Install openDAQ framework package (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - $packagePath = Join-Path "${{ inputs.opendaq-framework-package-path }}" "${{ inputs.opendaq-framework-package-filename }}" - $process = Start-Process -FilePath $packagePath -ArgumentList "/S" -Wait -NoNewWindow -PassThru - if ($process.ExitCode -eq 0) { - Write-Host "OpenDAQ installed successfully, updating PATH..." - $openDAQBin = "C:\Program Files\openDAQ\bin" - Add-Content -Path $env:GITHUB_ENV -Value "PATH=$openDAQBin`;$env:PATH" - Write-Host $env:PATH - } - else { - Write-Host "OpenDAQ installation failed with exit code $($process.ExitCode)" - exit $process.ExitCode - } - - - name: Install openDAQ framework package (Linux) - if: runner.os == 'Linux' - shell: bash - run: sudo dpkg -i "${{ inputs.opendaq-framework-package-path }}/${{ inputs.opendaq-framework-package-filename }}" - - - name: Unsupported runner OS - if: runner.os != 'Windows' && runner.os != 'Linux' - shell: bash - run: | - echo "Install openDAQ is not supported for ${{ runner.os }}" - exit 1 diff --git a/.github/actions/framework-latest-release/action.yml b/.github/actions/framework-latest-release/action.yml deleted file mode 100644 index c2750b5..0000000 --- a/.github/actions/framework-latest-release/action.yml +++ /dev/null @@ -1,111 +0,0 @@ -name: Determine latest openDAQ framework artefact - -inputs: - - opendaq-framework-release-version: - required: false - default: latest - - win32-force: - required: false - default: false - -outputs: - - version: - description: "Latest openDAQ release version" - value: ${{ steps.determine-latest-package.outputs.version }} - - platform: - description: "Detected platform" - value: ${{ steps.determine-latest-package.outputs.platform }} - - packaging: - description: "Package type (deb/exe)" - value: ${{ steps.determine-latest-package.outputs.packaging }} - - artefact: - description: "Artefact filename" - value: ${{ steps.determine-latest-package.outputs.artefact }} - - uri: - description: "Full URI to artefact" - value: ${{ steps.determine-latest-package.outputs.uri }} - - scheme: - description: "Scheme (s3)" - value: ${{ steps.determine-latest-package.outputs.scheme }} - - authority: - description: "Authority (bucket)" - value: ${{ steps.determine-latest-package.outputs.authority }} - - path: - description: "Path inside bucket" - value: ${{ steps.determine-latest-package.outputs.path }} - -runs: - using: composite - steps: - - name: Determine latest openDAQ package - id: determine-latest-package - shell: bash - run: | - set -e - - input_version="${{ inputs.opendaq-framework-release-version }}" - - if [[ -z "$input_version" || "$input_version" == "latest" ]]; then - version=$(gh api repos/openDAQ/openDAQ/releases/latest --jq '.tag_name') - if [[ -z "$version" || "$version" == "null" ]]; then - echo "::error::Failed to determine latest openDAQ release version" - exit 1 - fi - - version=${version#v} - else - version="$input_version" - fi - - platform="" - packaging="" - - if [[ "$RUNNER_OS" == "Linux" ]]; then - arch=$(uname -m) - if [[ "$arch" == "x86_64" ]]; then - platform="ubuntu22.04-x86_64" - elif [[ "$arch" == "aarch64" ]]; then - platform="ubuntu22.04-arm64" - else - echo "::error::Unsupported Linux arch: $arch" - exit 1 - fi - packaging="deb" - - elif [[ "$RUNNER_OS" == "Windows" ]]; then - WIN32_FORCE="${{ inputs.win32-force }}" - if [[ "$WIN32_FORCE" == "true" ]]; then - platform="win32" - else - platform="win64" - fi - packaging="exe" - - else - echo "::error::Unsupported runner OS $RUNNER_OS" - exit 1 - fi - - artefact="opendaq-${version}-${platform}.${packaging}" - scheme="s3" - authority="bb-blueberry-sdk-releases" - sdk="releases/v${version}/SDK" - - echo "version=$version" >> $GITHUB_OUTPUT - echo "platform=$platform" >> $GITHUB_OUTPUT - echo "packaging=$packaging" >> $GITHUB_OUTPUT - echo "artefact=$artefact" >> $GITHUB_OUTPUT - echo "scheme=$scheme" >> $GITHUB_OUTPUT - echo "authority=$authority" >> $GITHUB_OUTPUT - echo "path=$sdk" >> $GITHUB_OUTPUT - echo "uri=${scheme}://${authority}/${sdk}/${artefact}" >> $GITHUB_OUTPUT diff --git a/.github/actions/module-build-test/action.yml b/.github/actions/module-build-test/action.yml new file mode 100644 index 0000000..f5e0fb4 --- /dev/null +++ b/.github/actions/module-build-test/action.yml @@ -0,0 +1,29 @@ +name: Build and test simple device module +description: Configure, build and test simple device module with CMake + +runs: + using: composite + steps: + - name: Set CMake generator + shell: bash + run: | + if [[ "${{ runner.os }}" == "Windows" ]]; then + echo "CMAKE_GENERATOR=Visual Studio 17 2022" >> $GITHUB_ENV + else + echo "CMAKE_GENERATOR=Ninja" >> $GITHUB_ENV + fi + + - name: Configure simple device module with CMake + shell: bash + run: | + cmake -B build/output -S . -G "$CMAKE_GENERATOR" -DEXAMPLE_MODULE_ENABLE_TESTS=ON -DCMAKE_BUILD_TYPE=Release + + - name: Build simple device module with CMake + shell: bash + run: | + cmake --build build/output --config Release + + - name: Run simple device module tests with CMake + shell: bash + run: | + ctest --test-dir build/output --output-on-failure -C Release -V diff --git a/.github/workflows/ci-framework.yml b/.github/workflows/ci-framework.yml new file mode 100644 index 0000000..e63c830 --- /dev/null +++ b/.github/workflows/ci-framework.yml @@ -0,0 +1,82 @@ +name: Build simple device module with openDAQ framework and run tests + +on: + workflow_dispatch: + inputs: + runner: + description: "Runner label" + required: true + type: string + + branch: + description: "Branch to checkout" + required: false + type: string + default: "" + + artifact-run-id: + required: true + type: string + + artifact-name: + required: true + type: string + + file-name: + required: true + type: string + + workflow_call: + inputs: + runner: + description: "Runner label" + required: true + type: string + + branch: + description: "Branch to checkout" + required: false + type: string + default: "" + + artifact-run-id: + required: true + type: string + + artifact-name: + required: true + type: string + + file-name: + required: true + type: string + +env: + GH_TOKEN: ${{ github.token }} + +jobs: + test-artifact: + runs-on: ${{ inputs.runner }} + + steps: + - name: Checkout openDAQ module repository + uses: actions/checkout@v4 + with: + repository: openDAQ/SimpleDeviceModule + ref: ${{ inputs.branch }} + + - name: Download openDAQ framework artifact + id: download + uses: openDAQ/actions/framework-download-artifact@jira/TBBAS-2680-opendaq-gh-actions-github-api-wrapper-unit-tests + with: + run-id: ${{ inputs.artifact-run-id }} + artifact-name: ${{ inputs.artifact-name }} + artifact-filename: ${{ inputs.file-name }} + + - name: Install openDAQ framework artifact + uses: openDAQ/actions/framework-install@jira/TBBAS-2680-opendaq-gh-actions-github-api-wrapper-unit-tests + with: + framework-filename: ${{ steps.download.outputs.artifact }} + + - name: Build and test simple device module + uses: ./.github/actions/module-build-test diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0dce16..72bb675 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,74 +2,59 @@ name: Build and Test simple device module with latest openDAQ release on: push: - branches: - - main - + branches: [main] pull_request: - branches: - - main - - jira/* - - workflow_dispatch: - inputs: - - branch: - required: false - default: "main" - - opendaq-framework-version: - required: false - type: string - default: latest env: GH_TOKEN: ${{ github.token }} jobs: - build-and-test: + test-asset: + permissions: + contents: read + actions: read + + env: + GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }} strategy: + fail-fast: false matrix: include: - os: ubuntu-latest - generator: Ninja - + platform-alias: "ubuntu20.04-x86_64" - os: windows-latest - generator: "Visual Studio 17 2022" + platform-alias: "win64" runs-on: ${{ matrix.os }} - + steps: - name: Checkout simple device module repo uses: actions/checkout@v4 - with: - ref: ${{ github.event.inputs.branch || github.event.client_payload.branch || github.ref }} - - name: Determine openDAQ framework package - id: opendaq-framework - uses: ./.github/actions/framework-latest-release + - name: Download openDAQ framework asset + id: download-framework-filename + uses: openDAQ/actions/framework-download-release@jira/TBBAS-2680-opendaq-gh-actions-github-api-wrapper-unit-tests with: - opendaq-framework-release-version: ${{ github.event.inputs.opendaq-framework-version || 'latest' }} - - - name: Download openDAQ framework - uses: ./.github/actions/framework-download + platform: ${{ matrix.platform-alias }} + github-token: ${{ secrets.PAT_TOKEN }} + + - name: Normalize downloaded asset path + id: normalize-framework-filename + shell: bash + run: | + asset=${{ steps.download-framework-filename.outputs.asset }} + # Normalize output-dir path for cross-platform compatibility + if command -v cygpath >/dev/null 2>&1; then + asset="$(cygpath -w "$asset")" + echo "Normalized path (Windows): $asset" + fi + echo "asset=$asset" >> $GITHUB_OUTPUT + + - name: Install openDAQ framework asset + uses: openDAQ/actions/framework-install@jira/TBBAS-2680-opendaq-gh-actions-github-api-wrapper-unit-tests with: - src-opendaq-framework-dev: ${{ steps.opendaq-framework.outputs.uri }} - dst-opendaq-framework-dev: ${{ runner.temp }}/${{ steps.opendaq-framework.outputs.artefact }} - aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws_region: ${{ secrets.AWS_REGION }} - - - name: Install openDAQ framework package - uses: ./.github/actions/framework-install - with: - opendaq-framework-package-filename: ${{ steps.opendaq-framework.outputs.artefact }} - - - name: Configure simple device module with CMake - run: cmake -B build/output -S . -G "${{ matrix.generator }}" -DEXAMPLE_MODULE_ENABLE_TESTS=ON -DCMAKE_BUILD_TYPE=Release - - - name: Build simple device module with CMake - run: cmake --build build/output --config Release + framework-filename: ${{ steps.normalize-framework-filename.outputs.asset }} - - name: Run simple device module tests with CMake - run: ctest --test-dir build/output --output-on-failure -C Release -V + - name: Build and test simple device module + uses: ./.github/actions/module-build-test diff --git a/.gitignore b/.gitignore index 295355a..72017e9 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,9 @@ bckp # cmake CMakeUserPresets.json -CMakeSettings.json \ No newline at end of file +CMakeSettings.json + +# Secrets +.secrets +# Local configs +.actrc From f5f3492ae783e3bc9d9afe7f7c6e4bf488a1bc16 Mon Sep 17 00:00:00 2001 From: Aliaksandr Adziareika <8034372+alexadereyko@users.noreply.github.com> Date: Wed, 29 Oct 2025 16:49:55 +0100 Subject: [PATCH 2/2] Update README with CI/CD documentation - Document build process and testing - Describe ci.yml and ci-framework.yml workflows - Add CI and license badges --- LICENSE | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 343 insertions(+), 8 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1c17a0a --- /dev/null +++ b/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/README.md b/README.md index d982f87..ebf70d7 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,173 @@ -# Example device module +# SimpleDeviceModule -Simple example that builds an openDAQ module giving access to an example device. Said device contains 2 channels, each with a value and time signal. The value signal outputs a counter signal, increasing at a rate of 1 per second. +[![CI](https://github.com/openDAQ/SimpleDeviceModule/actions/workflows/ci.yml/badge.svg)](https://github.com/openDAQ/SimpleDeviceModule/actions/workflows/ci.yml) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) -## Testing the module +**SimpleDeviceModule** is an example module demonstrating how to build and test a device module using the **openDAQ framework**. -To test the module, enable the `OPENDAQ_DEVICE_EXAMPLE_ENABLE_SERVER_APP` cmake flag. Doing so will add an openDAQ native server module to your build targets, and add an additional "server_application" executable. Running the executable will create a device, add an openDAQ server, and enable discovery. +The module provides a simple device with 2 channels, each containing value and time signals. The value signal outputs a counter that increments at 1 Hz. -To connect to the device, the openDAQ Python GUI application can be used (Latest Python version is recommended): +This repository serves as a template for building custom openDAQ modules and includes: +- Example device implementation +- Unit tests +- CI/CD workflows for automated testing +--- + +## Prerequisites + +- **CMake** (>= 3.25) +- **Git** +- **C++ compiler** (Visual Studio on Windows, GCC/Clang on Linux/macOS) +- **openDAQ framework** (installed locally or built automatically) + +--- + +## Building the Project + +There are two ways to provide the openDAQ framework: + +### 1. Using a local openDAQ installation + +Install the openDAQ package and set the `OPENDAQ_ROOT` environment variable: + +```bash +export OPENDAQ_ROOT=/path/to/opendaq + +cmake -S . -B build/output \ + -G "Ninja" \ + -DEXAMPLE_MODULE_ENABLE_TESTS=ON \ + -DCMAKE_BUILD_TYPE=Release +``` + +### 2. Using a specific openDAQ version + +CMake will automatically download and build the required openDAQ version: + +```bash +cmake -S . -B build/output \ + -G "Ninja" \ + -DEXAMPLE_MODULE_ENABLE_TESTS=ON \ + -DSIMPLE_DEVICE_MODULE_OPENDAQ_SDK_VER=3.20.4 \ + -DCMAKE_BUILD_TYPE=Release +``` + +### Building + +```bash +cmake --build build/output --config Release +``` + +**Note:** +- `EXAMPLE_MODULE_ENABLE_TESTS=ON` enables unit test compilation +- Without `OPENDAQ_ROOT` or `SIMPLE_DEVICE_MODULE_OPENDAQ_SDK_VER`, the build will fail + +--- + +## Running Tests + +After building: + +```bash +ctest --test-dir build/output --output-on-failure -C Release -V +``` + +--- + +## Testing the Module with Server Application + +You can build an example server application to test the module with the openDAQ GUI. + +**Note:** This requires building openDAQ from source, so you must use `SIMPLE_DEVICE_MODULE_OPENDAQ_SDK_VER`: + +```bash +cmake -S . -B build/output \ + -G "Ninja" \ + -DSIMPLE_DEVICE_MODULE_OPENDAQ_SDK_VER=3.20.4 \ + -DSIMPLE_DEVICE_MODULE_ENABLE_SERVER_APP=ON \ + -DCMAKE_BUILD_TYPE=Release + +cmake --build build/output --config Release +./build/output/server_application/server_application ``` -py -m pip install openDAQ -py -m openDAQ -``` \ No newline at end of file + +Connect using the openDAQ Python GUI: + +```bash +pip install openDAQ +python -m openDAQ +``` + +--- + +## CI/CD Workflows + +This repository includes two GitHub Actions workflows for automated testing: + +### `ci.yml` - Continuous Integration + +Automatically runs on push to `main` and pull requests: +- Downloads the latest openDAQ framework release +- Builds the module on Ubuntu and Windows +- Runs unit tests +- Configured with `fail-fast: false` to run all platform tests independently + +### `ci-framework.yml` - Integration Testing with Custom openDAQ Builds + +Reusable workflow (`workflow_call` and `workflow_dispatch`) for testing with specific openDAQ framework builds: + +**Inputs:** +- `runner` - GitHub runner label (e.g., `ubuntu-latest`) +- `branch` - Branch to checkout (optional, defaults to current branch) +- `artifact-run-id` - GitHub Actions run ID containing the artifact +- `artifact-name` - Name of the openDAQ framework artifact +- `file-name` - Filename of the openDAQ installer + +**Usage from openDAQ repository:** + +```yaml +jobs: + test-module: + uses: openDAQ/SimpleDeviceModule/.github/workflows/ci-framework.yml@main + with: + runner: ubuntu-latest + branch: main + artifact-run-id: ${{ github.run_id }} + artifact-name: opendaq-v3.31.0-ubuntu24.04-x86_64.deb + file-name: opendaq-v3.31.0-ubuntu24.04-x86_64.deb +``` + +### Composite Action: `module-build-test` + +Both workflows use the `.github/actions/module-build-test` composite action that: +1. Detects the appropriate CMake generator (Ninja for Linux, Visual Studio for Windows) +2. Configures the module with CMake +3. Builds the module +4. Runs unit tests with CTest + +--- + +## Project Structure + +``` +SimpleDeviceModule/ +├── .github/ +│ ├── actions/ +│ │ └── module-build-test/ # Composite action for build and test +│ └── workflows/ +│ ├── ci.yml # CI workflow with latest release +│ └── ci-framework.yml # Reusable workflow for custom builds +├── example_module/ +│ ├── src/ # Module implementation +│ └── tests/ # Unit tests +├── server_application/ # Example server app +└── CMakeLists.txt +``` + +--- + +## License + +Copyright © 2024 openDAQ + +Licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.