diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..720e520a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,135 @@ +name: CI + +on: + push: + +jobs: + build-and-test: + name: Run on ${{ matrix.os }} with SOFA ${{ matrix.sofa_branch }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04, macos-14, windows-2022] + sofa_branch: [master] + + steps: + - name: Setup SOFA and environment + id: sofa + uses: sofa-framework/sofa-setup-action@v5 + with: + sofa_root: ${{ github.workspace }}/sofa + sofa_version: ${{ matrix.sofa_branch }} + sofa_scope: 'standard' + - name: Checkout source code + uses: actions/checkout@v2 + with: + path: ${{ env.WORKSPACE_SRC_PATH }} + + - name: Build and install + id: build-install + shell: bash + run: | + if [[ "$RUNNER_OS" == "Windows" ]]; then + cmd //c "${{ steps.sofa.outputs.vs_vsdevcmd }} \ + && cd /d $WORKSPACE_BUILD_PATH \ + && cmake \ + -GNinja \ + -DCMAKE_PREFIX_PATH="$SOFA_ROOT/lib/cmake" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$WORKSPACE_INSTALL_PATH" \ + ../src \ + && ninja install" + else + cd "$WORKSPACE_BUILD_PATH" + ccache -z + cmake \ + -GNinja \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_PREFIX_PATH=$SOFA_ROOT/lib/cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="$WORKSPACE_INSTALL_PATH" \ + ../src + ninja install + echo ${CCACHE_BASEDIR} + ccache -s + fi + + - name: Sanitize artifact name + id: sanitize + # This step removes special characters from the artifact name to ensure compatibility with upload-artifact + # Characters removed: " : < > | * ? \r \n \ / + # Spaces are replaced with underscores + # This sanitization prevents errors in artifact creation and retrieval + shell: pwsh + run: | + $originalName = "CollisionAlgorithm_${{ steps.sofa.outputs.run_branch }}_for-SOFA-${{ steps.sofa.outputs.sofa_version }}_${{ runner.os }}" + $artifact_name = $originalName -replace '[":;<>|*?\r\n\\/]', '' -replace ' ', '_' + echo "artifact_name=$artifact_name" >> $env:GITHUB_OUTPUT + + - name: Create artifact + id: create-artifact + uses: actions/upload-artifact@v4.4.0 + with: + name: ${{ steps.sanitize.outputs.artifact_name }} + path: ${{ env.WORKSPACE_INSTALL_PATH }} + + - name: Install artifact + id: install-artifact + uses: actions/download-artifact@v4.1.7 + with: + name: ${{ steps.sanitize.outputs.artifact_name }} + path: ${{ env.WORKSPACE_ARTIFACT_PATH }} + + - name: Set env vars for tests + shell: bash + run: | + # Set env vars for tests + if [[ "$RUNNER_OS" == "Windows" ]]; then + echo "$WORKSPACE_ARTIFACT_PATH/lib" >> $GITHUB_PATH + echo "$WORKSPACE_ARTIFACT_PATH/bin" >> $GITHUB_PATH + echo "$SOFA_ROOT/plugins/SofaPython3/bin" >> $GITHUB_PATH + echo "SOFA_PLUGIN_PATH=$WORKSPACE_ARTIFACT_PATH/bin" | tee -a $GITHUB_ENV + else + echo "SOFA_PLUGIN_PATH=$WORKSPACE_ARTIFACT_PATH/lib" | tee -a $GITHUB_ENV + fi + + if [[ "$RUNNER_OS" == "macOS" ]]; then + echo "DYLD_LIBRARY_PATH=$WORKSPACE_ARTIFACT_PATH/lib:$SOFA_ROOT/lib:$SOFA_ROOT/plugins/SofaPython3/lib:$DYLD_LIBRARY_PATH" | tee -a $GITHUB_ENV + fi + + if [[ "$RUNNER_OS" == "Linux" ]]; then + echo "LD_LIBRARY_PATH=$WORKSPACE_ARTIFACT_PATH/lib:$SOFA_ROOT/lib:$SOFA_ROOT/plugins/SofaPython3/lib:$LD_LIBRARY_PATH" | tee -a $GITHUB_ENV + fi + + deploy: + name: Deploy artifacts + if: always() && startsWith(github.ref, 'refs/heads/main') # we are on a branch (not a PR) + needs: [build-and-test] + runs-on: ubuntu-latest + continue-on-error: true + steps: + - name: Get artifacts + uses: actions/download-artifact@v4.1.7 + with: + path: artifacts + + - name: Zip artifacts + shell: bash + run: | + cd $GITHUB_WORKSPACE/artifacts + for artifact in *; do + zip $artifact.zip -r $artifact/* + done + - name: Upload release + uses: softprops/action-gh-release@v1 + with: + name: ${{ github.ref_name }} + tag_name: release-${{ github.ref_name }} + fail_on_unmatched_files: true + files: | + artifacts/CollisionAlgorithm_*_Linux.zip + artifacts/CollisionAlgorithm_*_Windows.zip + artifacts/CollisionAlgorithm_*_macOS.zip + diff --git a/.github/workflows/delete-workflow-runs.yml b/.github/workflows/delete-workflow-runs.yml new file mode 100644 index 00000000..063fd64d --- /dev/null +++ b/.github/workflows/delete-workflow-runs.yml @@ -0,0 +1,66 @@ +name: Delete old workflow runs +on: + workflow_dispatch: + inputs: + days: + description: 'Days-worth of runs to keep for each workflow' + required: true + default: '30' + minimum_runs: + description: 'Minimum runs to keep for each workflow' + required: true + default: '6' + delete_workflow_pattern: + description: 'Name or filename of the workflow (if not set, all workflows are targeted)' + required: false + delete_workflow_by_state_pattern: + description: 'Filter workflows by state: active, deleted, disabled_fork, disabled_inactivity, disabled_manually' + required: true + default: "ALL" + type: choice + options: + - "ALL" + - active + - deleted + - disabled_inactivity + - disabled_manually + delete_run_by_conclusion_pattern: + description: 'Remove runs based on conclusion: action_required, cancelled, failure, skipped, success' + required: true + default: "ALL" + type: choice + options: + - "ALL" + - "Unsuccessful: action_required,cancelled,failure,skipped" + - action_required + - cancelled + - failure + - skipped + - success + dry_run: + description: 'Logs simulated changes, no deletions are performed' + required: false + +jobs: + del_runs: + runs-on: ubuntu-latest + permissions: + actions: write + contents: read + steps: + - name: Delete workflow runs + uses: Mattraks/delete-workflow-runs@v2 + with: + token: ${{ github.token }} + repository: ${{ github.repository }} + retain_days: ${{ github.event.inputs.days }} + keep_minimum_runs: ${{ github.event.inputs.minimum_runs }} + delete_workflow_pattern: ${{ github.event.inputs.delete_workflow_pattern }} + delete_workflow_by_state_pattern: ${{ github.event.inputs.delete_workflow_by_state_pattern }} + delete_run_by_conclusion_pattern: >- + ${{ + startsWith(github.event.inputs.delete_run_by_conclusion_pattern, 'Unsuccessful:') + && 'action_required,cancelled,failure,skipped' + || github.event.inputs.delete_run_by_conclusion_pattern + }} + dry_run: ${{ github.event.inputs.dry_run }} diff --git a/CMakeLists.txt b/CMakeLists.txt index fe18d332..e430f2b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ target_link_libraries(${PROJECT_NAME} ) ## Install rules for the library and headers; CMake package configurations files -set(${PROJECT_NAME}_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src") -target_include_directories(${PROJECT_NAME} PUBLIC "$") -target_include_directories(${PROJECT_NAME} PUBLIC "$") +set(${PROJECT_NAME}_INCLUDE_DIRS "include/${PROJECT_NAME}") +target_include_directories(${PROJECT_NAME} PUBLIC "$") +target_include_directories(${PROJECT_NAME} PUBLIC "$") sofa_create_package_with_targets(PACKAGE_NAME ${PROJECT_NAME} PACKAGE_VERSION 0.1 TARGETS ${PROJECT_NAME} INCLUDE_INSTALL_DIR ${${PROJECT_NAME}_INCLUDE_DIRS}) diff --git a/src/sofa/collisionAlgorithm/algorithm/InsertionAlgorithm.h b/src/sofa/collisionAlgorithm/algorithm/InsertionAlgorithm.h index a344dc73..b8e89f6c 100644 --- a/src/sofa/collisionAlgorithm/algorithm/InsertionAlgorithm.h +++ b/src/sofa/collisionAlgorithm/algorithm/InsertionAlgorithm.h @@ -136,9 +136,9 @@ class InsertionAlgorithm : public BaseAlgorithm const bool isProjective = d_projective.getValue(); const SReal punctureForceThreshold = d_punctureForceThreshold.getValue(); - for (const auto& itTip : *l_tipGeom) + for (auto itTip = l_tipGeom->begin(); itTip != l_tipGeom->end(); itTip++) { - BaseProximity::SPtr tipProx = createTipProximity(itTip.element()); + BaseProximity::SPtr tipProx = createTipProximity(itTip->element()); if (!tipProx) continue; const BaseProximity::SPtr surfProx = findClosestProxOnSurf( tipProx, l_surfGeom.get(), projectOnSurf, getFilterFunc()); @@ -167,7 +167,7 @@ class InsertionAlgorithm : public BaseAlgorithm // 1.2 If not, create a proximity pair for the tip-surface collision if (isProjective) { - tipProx = projectOnTip(surfProx->getPosition(), itTip.element()).prox; + tipProx = projectOnTip(surfProx->getPosition(), itTip->element()).prox; if (!tipProx) continue; tipProx->normalize(); } @@ -181,9 +181,9 @@ class InsertionAlgorithm : public BaseAlgorithm auto createShaftProximity = Operations::CreateCenterProximity::Operation::get(l_shaftGeom->getTypeInfo()); auto projectOnShaft = Operations::Project::Operation::get(l_shaftGeom); - for (const auto& itShaft : *l_shaftGeom) + for (auto itShaft = l_shaftGeom->begin(); itShaft != l_shaftGeom->end(); itShaft++) { - BaseProximity::SPtr shaftProx = createShaftProximity(itShaft.element()); + BaseProximity::SPtr shaftProx = createShaftProximity(itShaft->element()); if (!shaftProx) continue; const BaseProximity::SPtr surfProx = findClosestProxOnSurf( shaftProx, l_surfGeom.get(), projectOnSurf, getFilterFunc()); @@ -194,7 +194,7 @@ class InsertionAlgorithm : public BaseAlgorithm // 1.2 If not, create a proximity pair for the tip-surface collision if (d_projective.getValue()) { - shaftProx = projectOnShaft(surfProx->getPosition(), itShaft.element()).prox; + shaftProx = projectOnShaft(surfProx->getPosition(), itShaft->element()).prox; if (!shaftProx) continue; shaftProx->normalize(); }