on: [push, pull_request]
env:
  # Set this to "on" to enable integration tests and "off" to skip integration tests
  RUN_INTEGRATION_TESTS: "on"
name: Build
jobs:
  set-lib3mf-version:
    runs-on: ubuntu-24.04
    outputs:
      lib3mf-version: ${{ steps.set-version.outputs.LIB3MF_VERSION }}
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - name: Run version extraction script and set environment variable
        id: set-version
        run: |
          LIB3MF_VERSION=$(python CI/ci_cd_helper.py extract-version)
          echo "LIB3MF_VERSION=$LIB3MF_VERSION" >> $GITHUB_OUTPUT
      - name: Echo version for debug
        run: echo "LIB3MF_VERSION=${{ steps.set-version.outputs.LIB3MF_VERSION }}"

  build-linux-memtest:
    runs-on: ubuntu-24.04
    needs: [set-lib3mf-version]
    steps:
      - run: sudo apt update
      - run: sudo apt install -y valgrind uuid-dev
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: sh cmake/GenerateMake.sh
      - run: cmake --build . --target lib3mf_memcheck
        working-directory: ./build

  build-linux-ubi8-gcc12:
    runs-on: ubuntu-24.04
    needs: [set-lib3mf-version]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - run: sudo apt update
      - run: sudo apt install -y uuid-dev
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: mkdir -p build
      - run: zip -r build/bindings.zip Autogenerated/Bindings
      - name: Archive bindings
        uses: actions/upload-artifact@v4
        with:
          name: bindings.zip
          path: build/bindings.zip
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      -
        name: Docker Build
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./CI/Dockerfile
          platforms: linux/amd64
          tags: lib3mf_ubi8:latest
          load: true
      -
        name: Docker Extract
        uses: shrink/actions-docker-extract@v3.0.0
        id: extract
        with:
          image: lib3mf_ubi8:latest
          path: out.zip
          destination: dist

      - run: unzip out.zip
        working-directory: ./dist
      - name: Upload Artifact
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf.so
          path: dist/lib3mf.so.2
      - name: Extract File Name (CPacked Archive)
        run: |
          ZIP_FILE=$(ls dist/lib3mf-*.zip)
          echo "ARTIFACT_NAME_ZIP=$(basename ${ZIP_FILE})" >> $GITHUB_ENV
        shell: bash
      - name: Upload Artifact (CPacked Archive)
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.ARTIFACT_NAME_ZIP }}
          path: dist/${{ env.ARTIFACT_NAME_ZIP }}
      - name: Extract File Name (Debian)
        run: |
          DEB_FILE=$(ls dist/lib3mf-*.deb)
          echo "ARTIFACT_NAME_DEB=$(basename ${DEB_FILE})" >> $GITHUB_ENV
        shell: bash
      - name: Upload Artifact (Debian Archive)
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.ARTIFACT_NAME_DEB }}
          path: dist/${{ env.ARTIFACT_NAME_DEB }}
      - name: Extract File Name (RPM)
        run: |
          RPM_FILE=$(ls dist/lib3mf-*.rpm)
          echo "ARTIFACT_NAME_RPM=$(basename ${RPM_FILE})" >> $GITHUB_ENV
        shell: bash
      - name: Upload Artifact (RPM Archive)
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.ARTIFACT_NAME_RPM }}
          path: dist/${{ env.ARTIFACT_NAME_RPM }}

  build-macos:
    runs-on: macos-15
    needs: [set-lib3mf-version]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: sh cmake/GenerateMake.sh
      - run: cmake --build .
        working-directory: ./build
      - run: ctest -V
        working-directory: ./build
      - run: cpack -G ZIP -C Release
        working-directory: ./build
      - name: Extract File Name
        run: |
          ZIP_FILE=$(ls build/lib3mf-*.zip)
          echo "ARTIFACT_NAME=$(basename ${ZIP_FILE})" >> $GITHUB_ENV
        shell: bash
      - run: ls -al build/
      - name: Determine macOS dylib
        id: find-mac-lib
        run: |
          set -euo pipefail
          MAC_LIB=$(ls build/lib3mf*.dylib | head -n 1)
          if [ -z "$MAC_LIB" ]; then
            echo "No macOS dylib found in build/" >&2
            exit 1
          fi
          echo "MAC_LIB=${MAC_LIB}" >> $GITHUB_ENV
      - name: Archive Mac binary
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf.dylib
          path: ${{ env.MAC_LIB }}
      - name: Upload Artifact (CPacked Archive)
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.ARTIFACT_NAME }}
          path: build/${{ env.ARTIFACT_NAME }}

  build-wasm:
    runs-on: ubuntu-24.04
    needs: [set-lib3mf-version]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - name: Setup Emscripten
        uses: mymindstorm/setup-emsdk@v14
        with:
          version: latest
      - name: Build lib3mf_wasm
        run: |
          emcmake cmake -S . -B build/wasm -DLIB3MF_BUILD_WASM=ON -DCMAKE_BUILD_TYPE=Release
          cmake --build build/wasm --target lib3mf_wasm -j"$(nproc)"
      - name: Package WASM artifact
        run: |
          mkdir -p build/wasm-artifact
          cp build/wasm/lib3mf.js build/wasm-artifact/
          cp build/wasm/lib3mf.wasm build/wasm-artifact/
          (
            cd build
            zip -r "lib3mf-wasm-${LIB3MF_VERSION}.zip" wasm-artifact
          )
      - name: Upload WASM Artifact
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf-wasm-${{ env.LIB3MF_VERSION }}.zip
          path: build/lib3mf-wasm-${{ env.LIB3MF_VERSION }}.zip

  build-macos-debug:
    runs-on: macos-15
    needs: [set-lib3mf-version]
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: sh cmake/GenerateMake.sh "Debug"
      - run: cmake --build .
        working-directory: ./build
      - run: ctest -V
        working-directory: ./build
      - name: Archive Mac binary
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf.debug.dylib
          path: build/lib3mf.dylib

  codecoverage-macos:
    runs-on: macos-15
    needs: [set-lib3mf-version]
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - name: Install Prerequisites
        run: |
          brew install lcov
          brew install gcovr
      - run: sh cmake/GenerateMake.sh -DBUILD_FOR_CODECOVERAGE=ON
      - run: cmake --build .
        working-directory: ./build
      - run: ./Tests/codecoverage/run_codecoverage.sh
      - name: Archive Code Coverage Results
        uses: actions/upload-artifact@v4
        with:
          name: codecoverage.zip
          path: build/codecoverage.zip
      - name: Upload code coverage to codecov
        uses: codecov/codecov-action@v3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: ./build/Test_CPP_Bindings_filtered.info
          fail_ci_if_error: false # optional (default = false)
          verbose: true # optional (default = false)
          
  build-windows-release:
    runs-on: windows-2022
    needs: [set-lib3mf-version]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: ./cmake/GenerateVS2022.bat
      - run: cmake --build . --config Release
        working-directory: ./build
      - run: ctest -V
        working-directory: ./build
      - run: cpack -G ZIP -C Release
        working-directory: ./build
      - name: Extract File Name
        run: |
          $zipFile = Get-ChildItem build\lib3mf-*.zip -Name
          echo "ARTIFACT_NAME=$zipFile" | Out-File -FilePath $env:GITHUB_ENV -Append
        shell: pwsh
      - name: Archive Windows Release binary
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf.dll
          path: build/Release/lib3mf.dll
      - name: Archive Windows Release lib
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf.lib
          path: build/Release/lib3mf.lib
      - name: Upload Artifact (CPacked Archive)
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.ARTIFACT_NAME }}
          path: build/${{ env.ARTIFACT_NAME }}

  build-windows-debug:
    runs-on: windows-2022
    needs: [set-lib3mf-version]
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: ./cmake/GenerateVS2022.bat
      - run: cmake --build . --config Debug
        working-directory: ./build
      - run: ctest -V
        working-directory: ./build
      - name: Archive Windows Debug binary
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf.debug.dll
          path: build/Debug/lib3mf.dll
      - uses: actions/upload-artifact@v4
        with:
          name: lib3mf.pdb
          path: build/Debug/lib3mf.pdb
      - uses: actions/upload-artifact@v4
        with:
          name: lib3mf.debug.lib
          path: build/Debug/lib3mf.lib
  build-windows-32bit:
    runs-on: windows-2022
    needs: [set-lib3mf-version]
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: ./cmake/GenerateVS2022_32bit.bat
      - run: cmake --build . --config Release
        working-directory: ./build_32bit
      - run: ctest -V
        working-directory: ./build_32bit
      - name: Archive Windows 32 bit Release binary
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf_32bit.dll
          path: build_32bit/Release/lib3mf.dll
      - name: Archive Windows 32 bit Release lib
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf_32bit.lib
          path: build_32bit/Release/lib3mf.lib
  build-mingw-w64:
    runs-on: windows-2022
    needs: [set-lib3mf-version]
    steps:
      - run: choco install mingw -y
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: ./cmake/GenerateMinGW.bat
      - run: cmake --build .
        working-directory: ./build
      - run: ctest -V
        working-directory: ./build


  assemble-sdk:
    runs-on: ubuntu-24.04
    needs: [set-lib3mf-version, build-windows-release, build-macos, build-linux-ubi8-gcc12]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - run: sudo apt install -y zip unzip
      - run: mkdir build
      - uses: actions/checkout@v4
        with:
          submodules: false
      - name: Download all workflow run artifacts
        uses: actions/download-artifact@v4
        with:
          path: ./build
      - run: ls -Rlh ./build
      - run: unzip bindings.zip/bindings.zip
        working-directory: ./build
      - run: python3 SDK/GenerateSDK_github.py
      - name: Archive SDK artifact (Comprehensive)
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf_sdk.zip
          path: build/lib3mf_sdk.zip


  deploy-linux:
    runs-on: ubuntu-24.04
    needs: [set-lib3mf-version, assemble-sdk]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - run: sudo apt install -y zip unzip file
      - run: pwd
      - run: ls -Rl .
      - name: Download lib3mf_sdk artifact
        uses: actions/download-artifact@v4
        with:
          name: lib3mf_sdk.zip
          path: lib3mf_sdk.zip
      - run: ls -Rl .
      - name: Unpack the SDK
        run: |
          unzip lib3mf_sdk.zip/lib3mf_sdk.zip
      - name: Build CppDynamic
        run: |
          sh Examples/CppDynamic/GenerateMake.sh
          cd Examples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../Files/Helix.3mf
      - name: Build Cpp
        run: |
          sh Examples/Cpp/GenerateMake.sh
          cd Examples/Cpp/build
          cmake --build .
          ./Example_ExtractInfo ../../Files/Helix.3mf
      - name: Python Bindings
        run: |
          python Examples/Python/extract_info.py Examples/Files/Helix.3mf
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: true
      - run: ls -Rl
      - name: Download lib3mf cpack (Linux)
        uses: actions/download-artifact@v4
        with:
          name: lib3mf-${{ env.LIB3MF_VERSION }}-Linux.zip
          path: lib3mf-${{ env.LIB3MF_VERSION }}-Linux.zip
      - name: Unpack the cpacked SDK
        run: |
          unzip lib3mf-${{ env.LIB3MF_VERSION }}-Linux.zip/lib3mf-${{ env.LIB3MF_VERSION }}-Linux.zip && ls -Rl
      - name: Build CppDynamic - CPack (Linux)
        run: | 
          sh SDK/CPackExamples/CppDynamic/GenerateMake.sh
          cd SDK/CPackExamples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../../Examples/Files/Helix.3mf
      - name: Build CDynamic - CPack (Linux)
        run: |
          sh SDK/CPackExamples/CDynamic/GenerateMake.sh
          cd SDK/CPackExamples/CDynamic/build
          cmake --build .
          ./Example_CDynamic
      - name: Build Cpp - CPack (Linux)
        run: |
          sh SDK/CPackExamples/Cpp/GenerateMake.sh
          cd SDK/CPackExamples/Cpp/build
          cmake --build .
          ./Example_ExtractInfo ../../../Examples/Files/Helix.3mf
      - name: Download lib3mf (Debian Linux)
        uses: actions/download-artifact@v4
        with:
          name: lib3mf-${{ env.LIB3MF_VERSION }}-Linux.deb
          path: lib3mf-${{ env.LIB3MF_VERSION }}-Linux.deb
      - name: Check the file type
        run: |
          file lib3mf-${{ env.LIB3MF_VERSION }}-Linux.deb
          file lib3mf-${{ env.LIB3MF_VERSION }}-Linux.deb/lib3mf-${{ env.LIB3MF_VERSION }}-Linux.deb
      - run: pwd
      - run: ls -Rl .
      - name: Install the debian package
        run: |
          sudo dpkg -i lib3mf-${{ env.LIB3MF_VERSION }}-Linux.deb/lib3mf-${{ env.LIB3MF_VERSION }}-Linux.deb
      - name: Build CppDynamic - CPack (Debian)
        run: |
          sh SDK/CPackExamples/CppDynamic/GenerateMake.sh
          cd SDK/CPackExamples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../../Examples/Files/Helix.3mf
      - name: Build CDynamic - CPack (Debian)
        run: |
          sh SDK/CPackExamples/CDynamic/GenerateMake.sh
          cd SDK/CPackExamples/CDynamic/build
          cmake --build .
          ./Example_CDynamic
      - name: Build Cpp - CPack (Debian)
        run: |
          sh SDK/CPackExamples/Cpp/GenerateMake.sh
          cd SDK/CPackExamples/Cpp/build
          cmake --build .
          ./Example_ExtractInfo ../../../Examples/Files/Helix.3mf
      - name: Setup Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.20'
      - name: Go Bindings
        run: |
          cd SDK/Examples/Go
          go mod init lib3mfExamples
          go get github.com/3MFConsortium/lib3mf.go/v2@v2.4.1
          go build -o create_cube create_cube.go
          ./create_cube

  deploy-windows:
    runs-on: windows-2022
    needs: [set-lib3mf-version, assemble-sdk]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - name: Download lib3mf_sdk artifact
        uses: actions/download-artifact@v4
        with:
          name: lib3mf_sdk.zip
          path: lib3mf_sdk.zip
      - name: Unpack the SDK
        run: |
          unzip lib3mf_sdk.zip/lib3mf_sdk.zip
      - name: Build CppDynamic
        run: |
          ./Examples/CppDynamic/GenerateVS2022.bat
          cd Examples/CppDynamic/build
          cmake --build . --config Release
          ./Release/Example_ExtractInfo.exe ../../Files/Helix.3mf
      - name: Build Cpp
        run: |
          ./Examples/Cpp/GenerateVS2022.bat
          cd Examples/Cpp/build
          cmake --build . --config Release
          ./Release/Example_ExtractInfo.exe ../../Files/Helix.3mf
      - name: Python Bindings
        run: |
          python Examples/Python/extract_info.py Examples/Files/Helix.3mf
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: true
      - name: Download lib3mf cpack (Windows)
        uses: actions/download-artifact@v4
        with:
          name: lib3mf-${{ env.LIB3MF_VERSION }}-Windows.zip
          path: lib3mf-${{ env.LIB3MF_VERSION }}-Windows.zip
      - name: Unpack the cpacked SDK
        run: |
          unzip lib3mf-${{ env.LIB3MF_VERSION }}-Windows.zip/lib3mf-${{ env.LIB3MF_VERSION }}-Windows.zip
      - name: Build CppDynamic - CPack (Windows)
        run: | 
          ./SDK/CPackExamples/CppDynamic/GenerateVS2022.bat
          cd SDK/CPackExamples/CppDynamic/build
          cmake --build . --config Release
          ./Release/Example_ExtractInfo.exe ../../../Examples/Files/Helix.3mf
      - name: Build CDynamic - CPack (Windows)
        run: |
          ./SDK/CPackExamples/CDynamic/GenerateVS2022.bat
          cd SDK/CPackExamples/CDynamic/build
          cmake --build . --config Release
          ./Release/Example_CDynamic.exe
      - name: Build Cpp - CPack (Windows)
        run: |
          ./SDK/CPackExamples/Cpp/GenerateVS2022.bat
          cd SDK/CPackExamples/Cpp/build
          cmake --build . --config Release
          ./Release/Example_ExtractInfo.exe ../../../Examples/Files/Helix.3mf
      - name: Setup Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.20'
      - name: Go Bindings
        run: |
          cd SDK/Examples/Go
          go mod init lib3mfExamples
          go get github.com/3MFConsortium/lib3mf.go/v2@v2.4.1
          go build -o create_cube.exe create_cube.go
          ./create_cube.exe


  deploy-macos:
    runs-on: macos-latest
    needs: [set-lib3mf-version, assemble-sdk]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - name: Download lib3mf_sdk artifact
        uses: actions/download-artifact@v4
        with:
          name: lib3mf_sdk.zip
          path: lib3mf_sdk.zip
      - name: Unpack the SDK
        run: |
          unzip lib3mf_sdk.zip/lib3mf_sdk.zip
      - name: Build CppDynamic
        run: |
          sh Examples/CppDynamic/GenerateMake.sh
          cd Examples/CppDynamic/build
          cmake --build .
          ls -al
          ./Example_ExtractInfo ../../Files/Helix.3mf
      - name: Build Cpp
        run: |
          sh Examples/Cpp/GenerateMake.sh
          cd Examples/Cpp/build
          cmake --build .
          ./Example_ExtractInfo ../../Files/Helix.3mf
      - name: Python Bindings
        run: |
          python Examples/Python/extract_info.py Examples/Files/Helix.3mf
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: true
      - name: Download lib3mf cpack (Darwin)
        uses: actions/download-artifact@v4
        with:
          name: lib3mf-${{ env.LIB3MF_VERSION }}-Darwin.zip
          path: lib3mf-${{ env.LIB3MF_VERSION }}-Darwin.zip
      - run: ls -Rl .
      - name: Unpack the cpacked SDK (Darwin)
        run: |
          unzip lib3mf-${{ env.LIB3MF_VERSION }}-Darwin.zip/lib3mf-${{ env.LIB3MF_VERSION }}-Darwin.zip
      - name: Build CppDynamic - CPack (Darwin)
        run: |
          sh SDK/CPackExamples/CppDynamic/GenerateMake.sh
          cd SDK/CPackExamples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../../Examples/Files/Helix.3mf
      - name: Build CDynamic - CPack (Darwin)
        run: |
          sh SDK/CPackExamples/CDynamic/GenerateMake.sh
          cd SDK/CPackExamples/CDynamic/build
          cmake --build .
          ./Example_CDynamic
      - name: Build Cpp - CPack (Darwin)
        run: |
          sh SDK/CPackExamples/Cpp/GenerateMake.sh
          cd SDK/CPackExamples/Cpp/build
          cmake --build .
          ./Example_ExtractInfo ../../../Examples/Files/Helix.3mf
      - name: Setup Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.20'
      - name: Go Bindings
        run: |
          cd SDK/Examples/Go
          go mod init lib3mfExamples
          go get github.com/3MFConsortium/lib3mf.go/v2@v2.4.1
          go build -o create_cube create_cube.go
          ./create_cube

  deploy-source-code-with-submodules:
    runs-on: ubuntu-24.04
    needs: [ set-lib3mf-version, assemble-sdk ]
    env:
      LIB3MF_VERSION: ${{ needs.set-lib3mf-version.outputs.lib3mf-version }}
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
      - run: |
          mkdir -p lib3mf-${{ env.LIB3MF_VERSION }}-source-with-submodules
          rsync -av --progress . ./lib3mf-${{ env.LIB3MF_VERSION }}-source-with-submodules --exclude .git --exclude .gitignore --exclude .github --exclude .gitmodules --exclude *.yml --exclude lib3mf-${{ env.LIB3MF_VERSION }}-source-with-submodules
      - name: Upload Artifact
        uses: actions/upload-artifact@v4
        with:
          name: lib3mf-${{ env.LIB3MF_VERSION }}-source-with-submodules
          path: lib3mf-${{ env.LIB3MF_VERSION }}-source-with-submodules



  set-integration-tests-status:
    runs-on: ubuntu-24.04
    needs: [ deploy-linux, deploy-windows, deploy-macos, deploy-source-code-with-submodules ]
    outputs:
      run_integration_tests: ${{ steps.set-status.outputs.run_integration_tests }}
    steps:
      - name: Install prerequisites
        if: env.RUN_INTEGRATION_TESTS == 'on'
        run: |
          sudo apt-get update
          sudo apt-get install -y unzip wget
      - name: Set status
        id: set-status
        run: |
          if [ "${{ env.RUN_INTEGRATION_TESTS }}" == "on" ]; then
            echo "run_integration_tests=true" >> $GITHUB_OUTPUT
          else
            echo "run_integration_tests=false" >> $GITHUB_OUTPUT
          fi

      - name: Cache 3MF test suite
        if: steps.set-status.outputs.run_integration_tests == 'true'
        uses: actions/cache@v5
        with:
          path: ~/.cache/3mf-test-suite
          key: 3mf-test-suite-v2.0.0

      - name: Download integration test suite
        if: steps.set-status.outputs.run_integration_tests == 'true'
        run: |
          USER="${{ secrets.THREEMF_TEST_SUITE_DOWNLOAD_USER }}"
          PASS="${{ secrets.THREEMF_TEST_SUITE_DOWNLOAD_TOKEN }}"
          CACHE_DIR="$HOME/.cache/3mf-test-suite"
          SUITE_ZIP="3MF_Conformance_Test_Suites_v2.0.0.zip"
          CACHE_ZIP="$CACHE_DIR/$SUITE_ZIP"

          mkdir -p "$CACHE_DIR"
          if [ ! -f "$CACHE_ZIP" ]; then
            wget --user "$USER" \
                 --password "$PASS" \
                 "https://storage.3mf.dev/remote.php/dav/files/$USER/3MF_CONSORTIUM/GITHUB/$SUITE_ZIP" \
                 -O "$CACHE_ZIP"
          fi
      

  integration-tests-latest-release:
    runs-on: ubuntu-24.04
    needs: [set-integration-tests-status]
    if: needs.set-integration-tests-status.outputs.run_integration_tests == 'true' # Single check before the job starts
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: true

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.8'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip

      - name: Get latest lib3mf SDK release info from GitHub API
        id: get_lib3mf_release
        run: |
          echo "LATEST_LIB3MF_URL=$(python CI/ci_cd_helper.py fetch-sdk-url 0 | xargs)" >> $GITHUB_ENV

      - name: Download latest lib3mf SDK zip
        run: |
          wget ${{ env.LATEST_LIB3MF_URL }} -O latest_lib3mf_sdk.zip

      - name: Unpack the SDK
        run: |
          unzip latest_lib3mf_sdk.zip -d lib3mf_sdk
          mv lib3mf_sdk/lib3mf_sdk/* lib3mf_sdk/
          rmdir lib3mf_sdk/lib3mf_sdk

      - name: Build CppDynamic
        run: |
          sh lib3mf_sdk/Examples/CppDynamic/GenerateMake.sh
          cd lib3mf_sdk/Examples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../Files/Helix.3mf

      - name: Restore 3MF test suite cache
        uses: actions/cache@v5
        with:
          path: ~/.cache/3mf-test-suite
          key: 3mf-test-suite-v2.0.0

      - name: Unzip integration test suite
        run: |
          rm -rf test_suites
          unzip -o "$HOME/.cache/3mf-test-suite/3MF_Conformance_Test_Suites_v2.0.0.zip" -d test_suites
      

      - name: List files
        run: |
          ls -al          

      - name: Copy integration test script
        run: |
          cp CI/integration_test.py test_suites/ && cp -r lib3mf_sdk/Examples/CppDynamic/build/* test_suites/

      - name: Run integration tests
        run: |
          cd test_suites && /usr/bin/time -v python integration_test.py 2>&1 | tee latest_sdk_test.log

      - name: List MUSTPASS failures and MUSTFAIL passes (latest release)
        run: |
          echo "MUSTPASS that failed (latest release):"
          grep -E 'MUSTPASS file ".*" does not work' test_suites/latest_sdk_test.log | sed -n 's/.*MUSTPASS file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_mp_failed.txt || true
          cat test_suites/latest_mp_failed.txt || true
          echo "\nMUSTFAIL that passed (latest release):"
          grep -E 'MUSTFAIL file ".*" works' test_suites/latest_sdk_test.log | sed -n 's/.*MUSTFAIL file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_mf_passed.txt || true
          cat test_suites/latest_mf_passed.txt || true
          {
            echo "### Latest release detailed results";
            echo "MUSTPASS failed: $(wc -l < test_suites/latest_mp_failed.txt 2>/dev/null || echo 0)";
            sed 's/^/- /' test_suites/latest_mp_failed.txt 2>/dev/null || true;
            echo;
            echo "MUSTFAIL passed: $(wc -l < test_suites/latest_mf_passed.txt 2>/dev/null || echo 0)";
            sed 's/^/- /' test_suites/latest_mf_passed.txt 2>/dev/null || true;
          } >> "$GITHUB_STEP_SUMMARY"

      - name: Print results (Checks the total python script execution time)
        run: |
          LATEST_TIME=$(grep "Elapsed (wall clock) time" test_suites/latest_sdk_test.log | awk '{print $8}')
          LATEST_TOTAL_SECONDS=$(echo $LATEST_TIME | awk -F: '{ print ($1 * 60) + $2 }')
          echo "Latest SDK execution time in seconds: ${LATEST_TOTAL_SECONDS}"

          LATEST_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_sdk_test.log | awk '{print $3}' | tr -d '()')
          LATEST_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_sdk_test.log | awk '{print $3}' | tr -d '()')

        
          echo "MUSTPASS: ${LATEST_MUSTPASS} / ${LATEST_TOTAL_MUSTPASS}"
          echo "MUSTFAIL: ${LATEST_MUSTFAIL} / ${LATEST_TOTAL_MUSTFAIL}"
          

  integration-tests-last-two-releases:
    runs-on: ubuntu-24.04
    needs: [set-integration-tests-status]
    if: needs.set-integration-tests-status.outputs.run_integration_tests == 'true' # Single check before the job starts
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: true

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.8'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip

      - name: Get latest lib3mf SDK release info from GitHub API
        id: get_latest_release
        run: |
          echo "LATEST_LIB3MF_URL=$(python CI/ci_cd_helper.py fetch-sdk-url 0 | xargs)" >> $GITHUB_ENV

      - name: Get second latest lib3mf SDK release info from GitHub API
        id: get_second_latest_release
        run: |
          echo "SECOND_LATEST_LIB3MF_URL=$(python CI/ci_cd_helper.py fetch-sdk-url 1 | xargs)" >> $GITHUB_ENV

      - name: Download latest lib3mf SDK zip
        run: |
          wget ${{ env.LATEST_LIB3MF_URL }} -O latest_lib3mf_sdk.zip

      - name: Download second latest lib3mf SDK zip
        run: |
          wget ${{ env.SECOND_LATEST_LIB3MF_URL }} -O second_latest_lib3mf_sdk.zip

      - name: Unpack the latest SDK
        run: |
          unzip latest_lib3mf_sdk.zip -d latest_lib3mf_sdk
          mv latest_lib3mf_sdk/lib3mf_sdk/* latest_lib3mf_sdk
          rmdir latest_lib3mf_sdk/lib3mf_sdk

      - name: Unpack the second latest SDK
        run: |
          unzip second_latest_lib3mf_sdk.zip -d second_latest_lib3mf_sdk
          mv second_latest_lib3mf_sdk/lib3mf_sdk/* second_latest_lib3mf_sdk
          rmdir second_latest_lib3mf_sdk/lib3mf_sdk

      - name: Restore 3MF test suite cache
        uses: actions/cache@v5
        with:
          path: ~/.cache/3mf-test-suite
          key: 3mf-test-suite-v2.0.0

      - name: Unzip integration test suite
        run: |
          rm -rf test_suites
          unzip -o "$HOME/.cache/3mf-test-suite/3MF_Conformance_Test_Suites_v2.0.0.zip" -d test_suites
      

      - name: Copy integration test script
        run: |
          cp CI/integration_test.py test_suites/

      - name: Build and run CppDynamic with latest SDK
        run: |
          sh latest_lib3mf_sdk/Examples/CppDynamic/GenerateMake.sh
          cd latest_lib3mf_sdk/Examples/CppDynamic/build
          cmake --build .
          cp -r * ../../../../test_suites/

      - name: Run integration tests with latest SDK
        run: |
          cd test_suites
          /usr/bin/time -v python integration_test.py 2>&1 | tee latest_sdk_test.log

      - name: Clean up latest SDK binaries
        run: |
          find test_suites -maxdepth 1 -type f ! -name 'integration_test.py' ! -name 'latest_sdk_test.log' ! -name 'second_latest_sdk_test.log' -exec rm -rf {} +

      - name: Build and run CppDynamic with second latest SDK
        run: |
          sh second_latest_lib3mf_sdk/Examples/CppDynamic/GenerateMake.sh
          cd second_latest_lib3mf_sdk/Examples/CppDynamic/build
          cmake --build .
          echo "First debug"
          ls -al ../../../../
          echo "This will fail"
          cp -r * ../../../../test_suites/

      - name: Run integration tests with second latest SDK
        run: |
          cd test_suites
          /usr/bin/time -v python integration_test.py 2>&1 | tee second_latest_sdk_test.log

      - name: Compare results (Checks the total python script execution time and must pass/fail counts)
        run: |
            # Extract detailed lists from logs for diffing
            grep -E 'MUSTPASS file ".*" does not work' test_suites/latest_sdk_test.log | sed -n 's/.*MUSTPASS file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_mp_failed.txt || true
            grep -E 'MUSTFAIL file ".*" works' test_suites/latest_sdk_test.log | sed -n 's/.*MUSTFAIL file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_mf_passed.txt || true
            grep -E 'MUSTPASS file ".*" does not work' test_suites/second_latest_sdk_test.log | sed -n 's/.*MUSTPASS file "\([^"]*\)".*/\1/p' | sort -u > test_suites/second_latest_mp_failed.txt || true
            grep -E 'MUSTFAIL file ".*" works' test_suites/second_latest_sdk_test.log | sed -n 's/.*MUSTFAIL file "\([^"]*\)".*/\1/p' | sort -u > test_suites/second_latest_mf_passed.txt || true

            echo "=== Latest MUSTPASS failed:"; cat test_suites/latest_mp_failed.txt || true
            echo "=== Second Latest MUSTPASS failed:"; cat test_suites/second_latest_mp_failed.txt || true
            echo "=== Latest MUSTFAIL passed:"; cat test_suites/latest_mf_passed.txt || true
            echo "=== Second Latest MUSTFAIL passed:"; cat test_suites/second_latest_mf_passed.txt || true

            # Compute regressions and improvements
            comm -23 test_suites/latest_mp_failed.txt test_suites/second_latest_mp_failed.txt > test_suites/regressions_mp_now_failing.txt || true
            comm -23 test_suites/latest_mf_passed.txt test_suites/second_latest_mf_passed.txt > test_suites/regressions_mf_now_passing.txt || true
            comm -13 test_suites/latest_mp_failed.txt test_suites/second_latest_mp_failed.txt > test_suites/improvements_mp_fixed.txt || true
            comm -13 test_suites/latest_mf_passed.txt test_suites/second_latest_mf_passed.txt > test_suites/improvements_mf_fixed.txt || true

            echo "=== Regressions - MUSTPASS now failing:"; cat test_suites/regressions_mp_now_failing.txt || true
            echo "=== Regressions - MUSTFAIL now passing:"; cat test_suites/regressions_mf_now_passing.txt || true
            echo "=== Improvements - MUSTPASS fixed:"; cat test_suites/improvements_mp_fixed.txt || true
            echo "=== Improvements - MUSTFAIL fixed:"; cat test_suites/improvements_mf_fixed.txt || true

            {
              echo "### Last two releases - detailed diffs";
              echo "#### Regressions - MUSTPASS now failing"; sed 's/^/- /' test_suites/regressions_mp_now_failing.txt 2>/dev/null || true; echo;
              echo "#### Regressions - MUSTFAIL now passing"; sed 's/^/- /' test_suites/regressions_mf_now_passing.txt 2>/dev/null || true; echo;
              echo "#### Improvements - MUSTPASS fixed"; sed 's/^/- /' test_suites/improvements_mp_fixed.txt 2>/dev/null || true; echo;
              echo "#### Improvements - MUSTFAIL fixed"; sed 's/^/- /' test_suites/improvements_mf_fixed.txt 2>/dev/null || true; echo;
            } >> "$GITHUB_STEP_SUMMARY"

            LATEST_TIME=$(grep "Elapsed (wall clock) time" test_suites/latest_sdk_test.log | awk '{print $8}')
            SECOND_LATEST_TIME=$(grep "Elapsed (wall clock) time" test_suites/second_latest_sdk_test.log | awk '{print $8}')
            LATEST_TOTAL_SECONDS=$(echo $LATEST_TIME | awk -F: '{ print ($1 * 60) + $2 }')
            SECOND_LATEST_TOTAL_SECONDS=$(echo $SECOND_LATEST_TIME | awk -F: '{ print ($1 * 60) + $2 }')
            echo "Latest SDK execution time in seconds: ${LATEST_TOTAL_SECONDS}"
            echo "Second Latest SDK execution time in seconds: ${SECOND_LATEST_TOTAL_SECONDS}"
        
            LATEST_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_sdk_test.log | awk '{print $1}')
            LATEST_TOTAL_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_sdk_test.log | awk '{print $3}' | tr -d '()')
            SECOND_LATEST_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/second_latest_sdk_test.log | awk '{print $1}')
            SECOND_LATEST_TOTAL_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/second_latest_sdk_test.log | awk '{print $3}' | tr -d '()')
            
            LATEST_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_sdk_test.log | awk '{print $1}')
            LATEST_TOTAL_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_sdk_test.log | awk '{print $3}' | tr -d '()')
            SECOND_LATEST_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/second_latest_sdk_test.log | awk '{print $1}')
            SECOND_LATEST_TOTAL_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/second_latest_sdk_test.log | awk '{print $3}' | tr -d '()')
        
            echo "Latest MUSTPASS: ${LATEST_MUSTPASS} / ${LATEST_TOTAL_MUSTPASS}"
            echo "Second Latest MUSTPASS: ${SECOND_LATEST_MUSTPASS} / ${SECOND_LATEST_TOTAL_MUSTPASS}"
            echo "Latest MUSTFAIL: ${LATEST_MUSTFAIL} / ${LATEST_TOTAL_MUSTFAIL}"
            echo "Second Latest MUSTFAIL: ${SECOND_LATEST_MUSTFAIL} / ${SECOND_LATEST_TOTAL_MUSTFAIL}"
        
            # Compare the total seconds
            if (( $(echo "$LATEST_TOTAL_SECONDS < $SECOND_LATEST_TOTAL_SECONDS" | bc -l) )); then
              echo "New release is better in execution time"
            else
              echo "New release is worse in execution time"
            fi
        
            # Compare MUSTPASS and MUSTFAIL counts
            # Allow improvements: pass if latest >= second latest for both metrics; fail only on regression
            if [ "$LATEST_MUSTPASS" -lt "$SECOND_LATEST_MUSTPASS" ] || [ "$LATEST_MUSTFAIL" -lt "$SECOND_LATEST_MUSTFAIL" ]; then
              echo "MUSTPASS or MUSTFAIL counts have regressed"
              echo "Regressions detected. See lists above and job summary for files."
              exit 1
            else
              echo "MUSTPASS and MUSTFAIL counts have improved or stayed the same"
            fi
        


  integration-tests-latest-commit:
    runs-on: ubuntu-24.04
    needs: [set-integration-tests-status]
    if: needs.set-integration-tests-status.outputs.run_integration_tests == 'true' # Single check before the job starts
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: true

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.8'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip

      - name: Download lib3mf_sdk artifact
        uses: actions/download-artifact@v4
        with:
          name: lib3mf_sdk.zip
          path: lib3mf_sdk.zip

      - name: Unpack the SDK
        run: |
          unzip lib3mf_sdk.zip/lib3mf_sdk.zip -d lib3mf_sdk && ls -al

      - name: Build CppDynamic
        run: |
          sh lib3mf_sdk/Examples/CppDynamic/GenerateMake.sh
          cd lib3mf_sdk/Examples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../Files/Helix.3mf

      - name: Restore 3MF test suite cache
        uses: actions/cache@v5
        with:
          path: ~/.cache/3mf-test-suite
          key: 3mf-test-suite-v2.0.0

      - name: Unzip integration test suite
        run: |
          rm -rf test_suites
          unzip -o "$HOME/.cache/3mf-test-suite/3MF_Conformance_Test_Suites_v2.0.0.zip" -d test_suites
      

      - name: Copy integration test script
        run: |
          cp CI/integration_test.py test_suites/ && cp -r lib3mf_sdk/Examples/CppDynamic/build/* test_suites/

      - name: Run integration tests
        run: |
          cd test_suites && /usr/bin/time -v python integration_test.py 2>&1 | tee latest_sdk_test.log

      - name: List MUSTPASS failures and MUSTFAIL passes (latest commit)
        run: |
          echo "MUSTPASS that failed (latest commit):"
          grep -E 'MUSTPASS file ".*" does not work' test_suites/latest_sdk_test.log | sed -n 's/.*MUSTPASS file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_commit_mp_failed.txt || true
          cat test_suites/latest_commit_mp_failed.txt || true
          echo "\nMUSTFAIL that passed (latest commit):"
          grep -E 'MUSTFAIL file ".*" works' test_suites/latest_sdk_test.log | sed -n 's/.*MUSTFAIL file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_commit_mf_passed.txt || true
          cat test_suites/latest_commit_mf_passed.txt || true
          {
            echo "### Latest commit detailed results";
            echo "MUSTPASS failed: $(wc -l < test_suites/latest_commit_mp_failed.txt 2>/dev/null || echo 0)";
            sed 's/^/- /' test_suites/latest_commit_mp_failed.txt 2>/dev/null || true;
            echo;
            echo "MUSTFAIL passed: $(wc -l < test_suites/latest_commit_mf_passed.txt 2>/dev/null || echo 0)";
            sed 's/^/- /' test_suites/latest_commit_mf_passed.txt 2>/dev/null || true;
          } >> "$GITHUB_STEP_SUMMARY"

      - name: Print results (Checks the total python script execution time)
        run: |
          LATEST_TIME=$(grep "Elapsed (wall clock) time" test_suites/latest_sdk_test.log | awk '{print $8}')
          LATEST_TOTAL_SECONDS=$(echo $LATEST_TIME | awk -F: '{ print ($1 * 60) + $2 }')
          echo "Latest SDK execution time in seconds: ${LATEST_TOTAL_SECONDS}"

          LATEST_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_sdk_test.log | awk '{print $3}' | tr -d '()')
          LATEST_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_sdk_test.log | awk '{print $3}' | tr -d '()')

          echo "MUSTPASS: ${LATEST_MUSTPASS} / ${LATEST_TOTAL_MUSTPASS}"
          echo "MUSTFAIL: ${LATEST_MUSTFAIL} / ${LATEST_TOTAL_MUSTFAIL}"

          # Save counts for comparison in other jobs
          echo "LATEST_MUSTPASS=${LATEST_MUSTPASS}" >> $GITHUB_ENV
          echo "LATEST_TOTAL_MUSTPASS=${LATEST_TOTAL_MUSTPASS}" >> $GITHUB_ENV
          echo "LATEST_MUSTFAIL=${LATEST_MUSTFAIL}" >> $GITHUB_ENV
          echo "LATEST_TOTAL_MUSTFAIL=${LATEST_TOTAL_MUSTFAIL}" >> $GITHUB_ENV

  integration-test-last-commit-and-last-release:
    runs-on: ubuntu-24.04
    needs: [set-integration-tests-status]
    if: needs.set-integration-tests-status.outputs.run_integration_tests == 'true' # Single check before the job starts
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          submodules: true

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.8'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip

      - name: Download lib3mf_sdk artifact
        uses: actions/download-artifact@v4
        with:
          name: lib3mf_sdk.zip
          path: lib3mf_sdk.zip

      - name: Unpack the SDK
        run: |
          unzip lib3mf_sdk.zip/lib3mf_sdk.zip -d latest_commit_lib3mf_sdk && ls -al


      - name: Build CppDynamic with latest commit SDK
        run: |
          sh latest_commit_lib3mf_sdk/Examples/CppDynamic/GenerateMake.sh
          cd latest_commit_lib3mf_sdk/Examples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../Files/Helix.3mf

      - name: Restore 3MF test suite cache
        uses: actions/cache@v5
        with:
          path: ~/.cache/3mf-test-suite
          key: 3mf-test-suite-v2.0.0

      - name: Unzip integration test suite
        run: |
          rm -rf test_suites
          unzip -o "$HOME/.cache/3mf-test-suite/3MF_Conformance_Test_Suites_v2.0.0.zip" -d test_suites
      

      - name: Copy integration test script
        run: |
          cp CI/integration_test.py test_suites/

      - name: Copy latest commit SDK to test suite
        run: |
          cp -r latest_commit_lib3mf_sdk/Examples/CppDynamic/build/* test_suites/

      - name: Run integration tests with latest commit SDK
        run: |
          cd test_suites && /usr/bin/time -v python integration_test.py 2>&1 | tee latest_commit_sdk_test.log

      - name: Clean up latest SDK binaries
        run: |
          find test_suites -maxdepth 1 -type f ! -name 'integration_test.py' ! -name '*.log' -exec rm -rf {} +

      - name: Get latest lib3mf SDK release info from GitHub API
        id: get_latest_release
        run: |
          echo "LATEST_LIB3MF_URL=$(python CI/ci_cd_helper.py fetch-sdk-url 0 | xargs)" >> $GITHUB_ENV
          LATEST_RELEASE_NAME=$(curl -s https://api.github.com/repos/3MFConsortium/lib3mf/releases/latest | grep '"tag_name"' | cut -d '"' -f 4)
          echo "LATEST_RELEASE_NAME=${LATEST_RELEASE_NAME}" >> $GITHUB_ENV

      - name: Download latest lib3mf SDK release zip
        run: |
          wget ${{ env.LATEST_LIB3MF_URL }} -O latest_release_lib3mf_sdk.zip

      - name: Unpack the SDK from latest release
        run: |
          unzip latest_release_lib3mf_sdk.zip -d latest_release_lib3mf_sdk
          mv latest_release_lib3mf_sdk/lib3mf_sdk/* latest_release_lib3mf_sdk/
          rmdir latest_release_lib3mf_sdk/lib3mf_sdk/

      - name: Build CppDynamic with latest release SDK
        run: |
          sh latest_release_lib3mf_sdk/Examples/CppDynamic/GenerateMake.sh
          cd latest_release_lib3mf_sdk/Examples/CppDynamic/build
          cmake --build .
          ./Example_ExtractInfo ../../Files/Helix.3mf

      - name: Copy latest release SDK to test suite
        run: |
          cp -r latest_release_lib3mf_sdk/Examples/CppDynamic/build/* test_suites/

      - name: Run integration tests with latest release SDK
        run: |
          cd test_suites && /usr/bin/time -v python integration_test.py 2>&1 | tee latest_release_sdk_test.log

      - name: Compare results (Checks the total python script execution time)
        id: compare_results
        run: |
          # Extract detailed lists from logs for diffing
          grep -E 'MUSTPASS file ".*" does not work' test_suites/latest_commit_sdk_test.log | sed -n 's/.*MUSTPASS file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_commit_mp_failed.txt || true
          grep -E 'MUSTFAIL file ".*" works' test_suites/latest_commit_sdk_test.log | sed -n 's/.*MUSTFAIL file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_commit_mf_passed.txt || true
          grep -E 'MUSTPASS file ".*" does not work' test_suites/latest_release_sdk_test.log | sed -n 's/.*MUSTPASS file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_release_mp_failed.txt || true
          grep -E 'MUSTFAIL file ".*" works' test_suites/latest_release_sdk_test.log | sed -n 's/.*MUSTFAIL file "\([^"]*\)".*/\1/p' | sort -u > test_suites/latest_release_mf_passed.txt || true

          echo "=== Latest commit MUSTPASS failed:"; cat test_suites/latest_commit_mp_failed.txt || true
          echo "=== Latest release MUSTPASS failed:"; cat test_suites/latest_release_mp_failed.txt || true
          echo "=== Latest commit MUSTFAIL passed:"; cat test_suites/latest_commit_mf_passed.txt || true
          echo "=== Latest release MUSTFAIL passed:"; cat test_suites/latest_release_mf_passed.txt || true

          LATEST_COMMIT_TIME=$(grep "Elapsed (wall clock) time" test_suites/latest_commit_sdk_test.log | awk '{print $8}')
          LATEST_RELEASE_TIME=$(grep "Elapsed (wall clock) time" test_suites/latest_release_sdk_test.log | awk '{print $8}')
          LATEST_COMMIT_TOTAL_SECONDS=$(echo $LATEST_COMMIT_TIME | awk -F: '{ print ($1 * 60) + $2 }')
          LATEST_RELEASE_TOTAL_SECONDS=$(echo $LATEST_RELEASE_TIME | awk -F: '{ print ($1 * 60) + $2 }')
          echo "Latest commit SDK execution time in seconds: ${LATEST_COMMIT_TOTAL_SECONDS}"
          echo "Latest release SDK execution time in seconds: ${LATEST_RELEASE_TOTAL_SECONDS}"

          LATEST_COMMIT_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_commit_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_COMMIT_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_commit_sdk_test.log | awk '{print $3}' | tr -d '()')
          LATEST_RELEASE_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_release_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_RELEASE_MUSTPASS=$(grep "MUSTPASS files passed" test_suites/latest_release_sdk_test.log | awk '{print $3}' | tr -d '()')

          LATEST_COMMIT_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_commit_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_COMMIT_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_commit_sdk_test.log | awk '{print $3}' | tr -d '()')
          LATEST_RELEASE_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_release_sdk_test.log | awk '{print $1}')
          LATEST_TOTAL_RELEASE_MUSTFAIL=$(grep "MUSTFAIL files failed" test_suites/latest_release_sdk_test.log | awk '{print $3}' | tr -d '()')

          echo "Latest commit MUSTPASS: ${LATEST_COMMIT_MUSTPASS} / ${LATEST_TOTAL_COMMIT_MUSTPASS}"
          echo "Latest release MUSTPASS: ${LATEST_RELEASE_MUSTPASS} / ${LATEST_TOTAL_RELEASE_MUSTPASS}"
          echo "Latest commit MUSTFAIL: ${LATEST_COMMIT_MUSTFAIL} / ${LATEST_TOTAL_COMMIT_MUSTFAIL}"
          echo "Latest release MUSTFAIL: ${LATEST_RELEASE_MUSTFAIL} / ${LATEST_TOTAL_RELEASE_MUSTFAIL}"

          # Compare MUSTPASS and MUSTFAIL counts
          # Allow improvements: pass if latest commit >= latest release for both metrics; fail only on regression
          if [ "$LATEST_COMMIT_MUSTPASS" -lt "$LATEST_RELEASE_MUSTPASS" ] || [ "$LATEST_COMMIT_MUSTFAIL" -lt "$LATEST_RELEASE_MUSTFAIL" ]; then
            echo "MUSTPASS or MUSTFAIL counts have regressed"
            # Highlight exactly which files changed outcome
            comm -23 test_suites/latest_commit_mp_failed.txt test_suites/latest_release_mp_failed.txt > test_suites/regressions_commit_mp_now_failing.txt || true
            comm -23 test_suites/latest_commit_mf_passed.txt test_suites/latest_release_mf_passed.txt > test_suites/regressions_commit_mf_now_passing.txt || true
            echo "=== Regressions (commit vs release) - MUSTPASS now failing:"; cat test_suites/regressions_commit_mp_now_failing.txt || true
            echo "=== Regressions (commit vs release) - MUSTFAIL now passing:"; cat test_suites/regressions_commit_mf_now_passing.txt || true
            {
              echo "### Latest commit vs latest release - regressions";
              echo "#### MUSTPASS now failing"; sed 's/^/- /' test_suites/regressions_commit_mp_now_failing.txt 2>/dev/null || true; echo;
              echo "#### MUSTFAIL now passing"; sed 's/^/- /' test_suites/regressions_commit_mf_now_passing.txt 2>/dev/null || true; echo;
            } >> "$GITHUB_STEP_SUMMARY"
            exit 1
          else
            echo "MUSTPASS and MUSTFAIL counts have improved or stayed the same"
          fi

          # Compare the total seconds
          if (( $(echo "$LATEST_COMMIT_TOTAL_SECONDS < $LATEST_RELEASE_TOTAL_SECONDS" | bc -l) )); then
            echo "Latest commit is better"
          else
            echo "Latest release is better"
          fi

          echo "Latest commit with SHA ${{ github.sha }} ran in ${LATEST_COMMIT_TOTAL_SECONDS} seconds" > results.txt
          echo "Latest release with tag ${{ env.LATEST_RELEASE_NAME }} ran in ${LATEST_RELEASE_TOTAL_SECONDS} seconds" >> results.txt
          echo "Latest commit MUSTPASS: ${LATEST_COMMIT_MUSTPASS} / ${LATEST_TOTAL_COMMIT_MUSTPASS}" >> results.txt
          echo "Latest release MUSTPASS: ${LATEST_RELEASE_MUSTPASS} / ${LATEST_TOTAL_RELEASE_MUSTPASS}" >> results.txt
          echo "Latest commit MUSTFAIL: ${LATEST_COMMIT_MUSTFAIL} / ${LATEST_TOTAL_COMMIT_MUSTFAIL}" >> results.txt
          echo "Latest release MUSTFAIL: ${LATEST_RELEASE_MUSTFAIL} / ${LATEST_TOTAL_RELEASE_MUSTFAIL}" >> results.txt

      - name: Upload results artifact
        uses: actions/upload-artifact@v4
        with:
          name: integration-test-results
          path: results.txt
