diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 89462e4f..6f6ac2f8 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -8,12 +8,18 @@ on: pull_request: branches: [ "main" ] +concurrency: + group: ${{ github.repository }}-${{ github.event.number || github.head_ref || github.sha }}-${{ github.workflow }} + cancel-in-progress: true + jobs: - build: + build_and_test: + name: Build/Test ${{ matrix.os }}-${{ matrix.build_type }}-py${{ matrix.python-version }} runs-on: ${{ matrix.os }} strategy: - # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable. + # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. + # Consider changing this to true when your workflow is stable. fail-fast: false # Set up a matrix to run the following 3 configurations: @@ -24,6 +30,7 @@ jobs: # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. matrix: os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ['3.13'] build_type: [RelWithDebInfo] c_compiler: [clang, cl] include: @@ -50,14 +57,18 @@ jobs: - os: macos-latest c_compiler: cl + env: + ALLURE_RESULTS_PATH: ${{github.workspace}}/build/allure-results + COVERAGE_REPORT_PATH: ${{github.workspace}}/build/python-coverage + steps: - uses: actions/checkout@v4 - + - name: "[C++] Ccache for gh actions" uses: hendrikmuhs/ccache-action@v1.2.14 with: key: ${{ github.job }}-${{ matrix.os }} # Eg. "some_build-ubuntu-latest" - + - name: "Set reusable strings" # Turn repeated input strings (such as the build output directory) into step outputs. # These step outputs can be used throughout the workflow file. @@ -66,12 +77,43 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + - name: "[C++] Cache CMake dependency source code" + uses: actions/cache@v4 + env: + cache-name: cache-cmake-dependency-sources + with: + # CMake cache is at ${{github.workspace}}/build/_deps but we only will cache folders ending in '-src' to cache source code + path: ${{github.workspace}}/build/_deps/*-src + # Cache hash is dependent on CMakeLists files anywhere as these can change what's in the cache, as well as cmake modules files + key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + # it's acceptable to reuse caches for different CMakeLists content if exact match is not available and unlike build caches, we + # don't need to restrict these by OS or compiler as it's only source code that's being cached + restore-keys: | + ${{ env.cache-name }}- + + - name: "[C++] Cache CMake dependency build objects" + uses: actions/cache@v4 + env: + cache-name: cache-cmake-dependency-builds + with: + # CMake cache is at ${{github.workspace}}/build/_deps but we only care about the folders ending in -build or -subbuild + path: | + ${{github.workspace}}/build/_deps/*-build + ${{github.workspace}}/build/_deps/*-subbuild + # Cache hash is dependent on CMakeLists files anywhere as these can change what's in the cache, as well as cmake modules files + key: ${{ env.cache-name }}-${{ matrix.os }}-${{ matrix.cxx }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} + # it's acceptable to reuse caches for different CMakeLists content if exact match is not available + # as long as the OS and Compiler match exactly + restore-keys: | + ${{ env.cache-name }}-${{ matrix.os }}-${{ matrix.cxx }}- + - name: "[C++] Configure CMake" # Configure CMake in a 'build' subdirectory. # `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type run: > - cmake -B ${{ steps.strings.outputs.build-output-dir }} + cmake + -B ${{ steps.strings.outputs.build-output-dir }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} @@ -82,11 +124,154 @@ jobs: - name: "[C++] Build" # Build your program with the given configuration. # Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). - run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} + run: > + cmake + --build ${{ steps.strings.outputs.build-output-dir }} + --config ${{ matrix.build_type }} - name: "[C++] Test" + continue-on-error: true working-directory: ${{ steps.strings.outputs.build-output-dir }} # Execute tests defined by the CMake configuration. # Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator). # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: ctest --build-config ${{ matrix.build_type }} + + # - name: "[C++] Save listing of build dir" + # run: find ${{github.workspace}}/build > ${{github.workspace}}/build/path_listing.txt + + # - name: "[C++] Store Build Products" + # uses: actions/upload-artifact@v4 + # with: + # name: ${{ github.job }}-${{ matrix.os }}_paths + # path: ${{github.workspace}}/build/path_listing.txt + + - name: "[C++] Generate PB Tech (Windows)" + if: ${{ matrix.os == 'windows-latest' }} + run: build\${{matrix.build_type}}\gen_tech_pb.exe + working-directory: ${{github.workspace}} + + - name: "[C++] Generate PB Tech (Unix)" + if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' }} + run: build/gen_tech_pb + working-directory: ${{github.workspace}} + + # - name: "[C++] Store Build Products" + # uses: actions/upload-artifact@v4 + # with: + # name: ${{ github.job }}-${{ matrix.os }} # -${{ matrix.build_type }} + # # Generated Python Protobuffer Classes + # # KPEX Tech Info Protobuffers + # path: | + # ${{github.workspace}}/build/python_kpex_protobuf/ + # ${{github.workspace}}/build/*_tech.pb.json + # if-no-files-found: error + # + # - name: "[Python] Retrieve C++ Build Artifact" + # uses: actions/download-artifact@v4 + # with: + # name: build-${{ matrix.os }} + + - name: "[Python] Setup python ${{ matrix.python-version }}" + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: "[Python] Install Poetry" + uses: snok/install-poetry@v1 + with: + virtualenvs-create: true + virtualenvs-in-project: true + virtualenvs-path: .venv + installer-parallel: true + + - name: "[Python] Load cached venv" + id: cached-poetry-dependencies + uses: actions/cache@v4 + with: + path: .venv + key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }} + + - name: "[Python] Install dependencies" + if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true' + run: poetry install --no-interaction --no-root + + - name: "[Python] Install project" + run: poetry install --no-interaction + + - name: "[Python] Run Unit tests" + continue-on-error: true + run: > + poetry run coverage run -m pytest + --alluredir ${{ env.ALLURE_RESULTS_PATH }} + --color no + + - name: "[Python] Create coverage report" + run: poetry run coverage html --directory ${{ env.COVERAGE_REPORT_PATH }} + + - name: "Print listing of build dir" + run: find ${{github.workspace}}/build -path ${{github.workspace}}/build/_deps -prune -o -print + + - name: "[Python] Store coverage results" + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: upload-python-coverage-report-${{ matrix.os }}_${{ matrix.python-version }} + path: ${{ env.COVERAGE_REPORT_PATH }} + retention-days: 1 + if-no-files-found: error + + - name: "[Python] Store allure test results" + continue-on-error: true + uses: actions/upload-artifact@v4 + with: + name: upload-python-allure-report-${{ matrix.os }}_${{ matrix.python-version }} + path: ${{ env.ALLURE_RESULTS_PATH }} + retention-days: 1 + if-no-files-found: error + + allure-report: + name: "Generate Allure Report (Aggregated Suites)" + needs: build_and_test + if: always() + runs-on: ubuntu-latest + + steps: + - name: "Merge test results (Allure)" + uses: actions/upload-artifact/merge@v4 + with: + name: merged-allure-reports + pattern: upload-python-allure-report-* + # delete-merged: true + retention-days: 1 + + - name: "Set up JDK (for Allure)" + uses: actions/setup-java@v3 + with: + distribution: zulu + java-version: 17 + + - name: "Load test report history (Allure)" + uses: actions/checkout@v4 + if: always() + continue-on-error: true + with: + ref: gh-pages + path: gh-pages + + - name: "Build test report" + uses: simple-elf/allure-report-action@v1.7 + if: always() + with: + gh_pages: gh-pages + allure_history: allure-history + allure_results: build/allure-results + + - name: "Publish test report" + uses: peaceiris/actions-gh-pages@v3 + if: always() + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: allure-history