Skip to content
Draft
177 changes: 156 additions & 21 deletions .github/workflows/CI_build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ on:
required: false
default: 'NONE'
description: 'Json scructure with three parameters {"COMMIT_HASH":"fullhsashofthecommit", }'
# >>> CI-UPDATE-REF BEGIN
ci-update-ref:
type: string
required: false
default: ''
description: 'When not empty, only build and generate the regression references (JSON given by CI_generate_regression_references)'
secrets:
SOFA_BOT_TOKEN:
required: false
# <<< CI-UPDATE-REF END

jobs:
display-inputs:
Expand All @@ -76,6 +86,9 @@ jobs:
echo "external-plugins : ${{ inputs.external-plugins }}"
echo "additionnal-cmake-flags : ${{ inputs.additionnal-cmake-flags }}"
echo "builder-os : ${{ inputs.builder-os }}"
# >>> CI-UPDATE-REF BEGIN
echo "ci-update-ref : ${{ inputs.ci-update-ref != '' }}"
# <<< CI-UPDATE-REF END


build:
Expand All @@ -86,6 +99,17 @@ jobs:
runs-on: ${{ matrix.os }}
name: ${{ matrix.os }}
steps:
# >>> CI-UPDATE-REF BEGIN
- name: Export bot token
if: ${{ inputs.ci-update-ref != '' }}
shell: bash
env:
BOT_TOKEN: ${{ secrets.SOFA_BOT_TOKEN }}
run: |
echo "::add-mask::$BOT_TOKEN"
echo "GH_TOKEN=$BOT_TOKEN" >> $GITHUB_ENV
# <<< CI-UPDATE-REF END

- name: Configure builder
id: configure
shell: bash
Expand All @@ -103,7 +127,7 @@ jobs:

echo "Workspace folder for this build will be $WORKSPACE"

- name: Clone SOFA and CI
- name: Clone SOFA, CI and Regression
id: clone
shell: bash
run: |
Expand Down Expand Up @@ -169,6 +193,33 @@ jobs:

cd $WORKSPACE

## Clone Regression and use ci-depends-on structure
regression_branch=${{ inputs.sofa-branch-name }}
regression_repo_url="https://www.github.com/sofa-framework/Regression"


# check if ci has a ci-depends-on
regression_ci_depends_on=$(echo "${{ inputs.ci-depends-on }}" | jq .Regression)
if [ -n "${{ inputs.ci-depends-on }}" ] && [ "$regression_ci_depends_on" != "null" ]; then
echo "ci-depends-on for Regression repository detected."
regression_repo_url=$(echo "${{ inputs.ci-depends-on }}" | jq .Regression.repo_url)
regression_branch=$(echo "${{ inputs.ci-depends-on }}" | jq .Regression.branch_name)
fi
echo "REGRESSION_BRANCH=$regression_branch" >> $GITHUB_ENV


echo "Cloning Regression from remote ${regression_repo_url}, selecting branch ${regression_branch}"

if [ -d $WORKSPACE/Regression ]; then
rm -rf $WORKSPACE/Regression
fi
REGRESSION_DIR=$WORKSPACE/Regression
echo "REGRESSION_DIR=$REGRESSION_DIR" >> $GITHUB_ENV

git clone -b ${regression_branch//\"} --single-branch ${regression_repo_url//\"}

cd $WORKSPACE

## Setup build folder
if [ "${{ inputs.force-full-build }}" == "true" ] && [ -d $WORKSPACE/build ]; then
rm -rf $WORKSPACE/build
Expand Down Expand Up @@ -285,11 +336,13 @@ jobs:
DOCKER_SRC_DIR="/workspace/$(realpath --relative-to=$WORKSPACE $SRC_DIR)"
DOCKER_BUILD_DIR="/workspace/$(realpath --relative-to=$WORKSPACE $BUILD_DIR)"
DOCKER_CI_DIR="/workspace/$(realpath --relative-to=$WORKSPACE $CI_DIR)"
DOCKER_REGRESSION_DIR="/workspace/$(realpath --relative-to=$WORKSPACE $REGRESSION_DIR)"
DOCKER_LOG_DIR="/workspace/$(realpath --relative-to=$WORKSPACE ${{ env.LOG_DIR }})"

echo "DOCKER_SRC_DIR=$DOCKER_SRC_DIR" >> $GITHUB_ENV
echo "DOCKER_BUILD_DIR=$DOCKER_BUILD_DIR" >> $GITHUB_ENV
echo "DOCKER_CI_DIR=$DOCKER_CI_DIR" >> $GITHUB_ENV
echo "DOCKER_REGRESSION_DIR=$DOCKER_REGRESSION_DIR" >> $GITHUB_ENV
echo "DOCKER_LOG_DIR=$DOCKER_LOG_DIR" >> $GITHUB_ENV

export XDG_CACHE_HOME="/cache"
Expand All @@ -308,7 +361,7 @@ jobs:

- name: Unit tests
id: unit-tests-step
if: always() && steps.build-step.outcome == 'success' && inputs.generate-binaries == false
if: always() && steps.build-step.outcome == 'success' && inputs.generate-binaries == false && inputs.ci-update-ref == '' # CI-UPDATE-REF
shell: bash
run: |
# If os has got docker then use it
Expand All @@ -319,20 +372,27 @@ jobs:
docker run --rm \
--user 1000:1000 --network=host -v $WORKSPACE:/workspace \
${DOCKER_IMAGE} \
/bin/bash -c "env ; cd /workspace; /bin/bash $DOCKER_CI_DIR/scripts/test.sh $DOCKER_BUILD_DIR $DOCKER_SRC_DIR $DOCKER_CI_DIR/scripts/ ${NODE_NAME} ${{ inputs.python-version }} UNIT"
/bin/bash -c "cd /workspace; . ${DOCKER_CI_DIR}/scripts/tests/setup-test-env.sh \"${DOCKER_BUILD_DIR}\" \"${DOCKER_CI_DIR}/scripts/\" \"${NODE_NAME}\" \"${{ inputs.python-version }}\"; env; \${VM_PYTHON3_EXECUTABLE} ${DOCKER_CI_DIR}/scripts/tests/sofa_unit_tests.py --build-dir ${DOCKER_BUILD_DIR} --results-dir \${RESULTS_DIR}/unit -j \${VM_MAX_PARALLEL_TESTS}"
else
echo "Launching unit test suite."

bash ${CI_DIR}/scripts/test.sh "${BUILD_DIR}" "${SRC_DIR}" "${CI_DIR}/scripts/" "${NODE_NAME}" "${{ inputs.python-version }}" "UNIT"
. ${CI_DIR}/scripts/tests/setup-test-env.sh "${BUILD_DIR}" "${CI_DIR}/scripts/" "${NODE_NAME}" "${{ inputs.python-version }}"
env
${VM_PYTHON3_EXECUTABLE} ${CI_DIR}/scripts/tests/sofa_unit_tests.py --build-dir "${BUILD_DIR}" --results-dir "${RESULTS_DIR}/unit" -j ${VM_MAX_PARALLEL_TESTS}
fi

if [[ "$(cd "${{ env.BUILD_DIR }}/tests_results/" && find . -maxdepth 1 -type f)" == *"unit-tests_"* ]]; then
if [[ ! "$(cd "${{ env.BUILD_DIR }}/tests_results/unit" && find . -maxdepth 1 -type f)" == *"summary"* ]]; then
exit 1
else
if [[ "$(awk -F= '$1=="crashes" {print $2}' ${{ env.BUILD_DIR }}/tests_results/unit/summary.txt)" != '0' || "$(awk -F= '$1=="failures" {print $2}' ${{ env.BUILD_DIR }}/tests_results/unit/summary.txt)" != "0" ]]; then
exit 1
fi
fi


- name: Scene tests
id: scene-tests-step
if: always() && steps.build-step.outcome == 'success' && inputs.generate-binaries == false && inputs.with-all-tests == true
if: always() && steps.build-step.outcome == 'success' && inputs.generate-binaries == false && inputs.with-all-tests == true && inputs.ci-update-ref == '' # CI-UPDATE-REF
shell: bash
run: |
# If os has got docker then use it
Expand All @@ -343,20 +403,26 @@ jobs:
docker run --rm \
--user 1000:1000 --network=host -v $WORKSPACE:/workspace \
${DOCKER_IMAGE} \
/bin/bash -c "env ; cd /workspace; /bin/bash $DOCKER_CI_DIR/scripts/test.sh $DOCKER_BUILD_DIR $DOCKER_SRC_DIR $DOCKER_CI_DIR/scripts/ ${NODE_NAME} ${{ inputs.python-version }} SCENE"
/bin/bash -c "cd /workspace; . ${DOCKER_CI_DIR}/scripts/tests/setup-test-env.sh \"${DOCKER_BUILD_DIR}\" \"${DOCKER_CI_DIR}/scripts/\" \"${NODE_NAME}\" \"${{ inputs.python-version }}\"; env ; \${VM_PYTHON3_EXECUTABLE} ${DOCKER_CI_DIR}/scripts/tests/sofa_scene_tests.py --src-dir "${DOCKER_SRC_DIR}" --build-dir \"${DOCKER_BUILD_DIR}\" --results-dir \"\${RESULTS_DIR}/scene\" -j \${VM_MAX_PARALLEL_TESTS}"
else
echo "Launching scene test suite."

bash ${CI_DIR}/scripts/test.sh "${BUILD_DIR}" "${SRC_DIR}" "${CI_DIR}/scripts/" "${NODE_NAME}" "${{ inputs.python-version }}" "SCENE"
. ${CI_DIR}/scripts/tests/setup-test-env.sh "${BUILD_DIR}" "${CI_DIR}/scripts/" "${NODE_NAME}" "${{ inputs.python-version }}"
env
${VM_PYTHON3_EXECUTABLE} ${CI_DIR}/scripts/tests/sofa_scene_tests.py --src-dir "${SRC_DIR}" --build-dir "${BUILD_DIR}" --results-dir "${RESULTS_DIR}/scene" -j ${VM_MAX_PARALLEL_TESTS}
fi

if [[ "$(cd "${{ env.BUILD_DIR }}/tests_results/" && find . -maxdepth 1 -type f)" == *"scene-tests_"* ]]; then
if [[ ! "$(cd "${{ env.BUILD_DIR }}/tests_results/scene" && find . -maxdepth 1 -type f)" == *"summary"* ]]; then
exit 1
else
if [[ "$(awk -F= '$1=="crashes" {print $2}' ${{ env.BUILD_DIR }}/tests_results/scene/summary.txt)" != '0' || "$(awk -F= '$1=="failures" {print $2}' ${{ env.BUILD_DIR }}/tests_results/scene/summary.txt)" != "0" ]]; then
exit 1
fi
fi

- name: Regression tests
id: regression-tests-step
if: always() && steps.build-step.outcome == 'success' && inputs.generate-binaries == false && inputs.with-all-tests == true
if: always() && steps.build-step.outcome == 'success' && inputs.generate-binaries == false && inputs.with-all-tests == true && inputs.ci-update-ref == '' # CI-UPDATE-REF
shell: bash
run: |
# If os has got docker then use it
Expand All @@ -367,18 +433,75 @@ jobs:
docker run --rm \
--user 1000:1000 --network=host -v $WORKSPACE:/workspace \
${DOCKER_IMAGE} \
/bin/bash -c "env ; cd /workspace; /bin/bash $DOCKER_CI_DIR/scripts/test.sh $DOCKER_BUILD_DIR $DOCKER_SRC_DIR $DOCKER_CI_DIR/scripts/ ${NODE_NAME} ${{ inputs.python-version }} REGRESSION"
/bin/bash -c "export REGRESSION_DIR="$DOCKER_REGRESSION_DIR"; cd /workspace;. ${DOCKER_CI_DIR}/scripts/tests/setup-test-env.sh \"${DOCKER_BUILD_DIR}\" \"${DOCKER_CI_DIR}/scripts/\" \"${NODE_NAME}\" \"${{ inputs.python-version }}\"; env ; \${VM_PYTHON3_EXECUTABLE} ${DOCKER_REGRESSION_DIR}/SofaRegressionProgram/SofaRegressionProgram.py --input "${DOCKER_SRC_DIR}/examples" --input "${DOCKER_SRC_DIR}/applications" --input "${DOCKER_BUILD_DIR}/external_directories/fetched" --output-logs-errors "\${RESULTS_DIR}/regression" --jobs \${VM_MAX_PARALLEL_TESTS} "
else
echo "Launching regression test suite"

bash ${CI_DIR}/scripts/test.sh "${BUILD_DIR}" "${SRC_DIR}" "${CI_DIR}/scripts/" "${NODE_NAME}" "${{ inputs.python-version }}" "REGRESSION"
. ${CI_DIR}/scripts/tests/setup-test-env.sh "${BUILD_DIR}" "${CI_DIR}/scripts/" "${NODE_NAME}" "${{ inputs.python-version }}"
env
${VM_PYTHON3_EXECUTABLE} ${REGRESSION_DIR}/SofaRegressionProgram/SofaRegressionProgram.py --input "${SRC_DIR}/examples" --input "${SRC_DIR}/applications" --input "${BUILD_DIR}/external_directories/fetched" --output-logs-errors "${RESULTS_DIR}/regression" -j ${VM_MAX_PARALLEL_TESTS}
fi

if [[ "$(cd "${{ env.BUILD_DIR }}/tests_results/" && find . -maxdepth 1 -type f)" == *"regression-tests_"* ]]; then
exit 1
if [[ ! "$(cd "${{ env.BUILD_DIR }}/tests_results/regression" && find . -maxdepth 1 -type f)" == *"summary"* ]]; then
exit 1
else
if [[ "$(awk -F= '$1=="crashes" {print $2}' ${{ env.BUILD_DIR }}/tests_results/regression/summary.txt)" != '0' || "$(awk -F= '$1=="failures" {print $2}' ${{ env.BUILD_DIR }}/tests_results/regression/summary.txt)" != "0" ]]; then
exit 1
fi
fi


# >>> CI-UPDATE-REF BEGIN
- name: Update references - prepare
id: update-ref-prepare
if: always() && steps.build-step.outcome == 'success' && inputs.ci-update-ref != ''
shell: bash
env:
CI_UPDATE_REF: ${{ inputs.ci-update-ref }}
run: |
# The reference folder is named after the OS of the (docker) image running the regression
echo "CI_UPDATE_REF_OS=$(echo ${{ matrix.os }} | sed -E 's/^sh-([a-z]+)_.*/\1/')" >> $GITHUB_ENV
export CI_UPDATE_REF_OS=$(echo ${{ matrix.os }} | sed -E 's/^sh-([a-z]+)_.*/\1/')
python3 ${CI_DIR}/scripts/ci_update_ref_build.py prepare

- name: Update references - generate
id: update-ref-generate
if: always() && steps.update-ref-prepare.outcome == 'success'
shell: bash
run: |
if [ ! -s "${BUILD_DIR}/ci_update_ref/filter.txt" ]; then
echo "No scene to generate."
exit 0
fi
# If os has got docker then use it
if [[ "${{ matrix.os }}" == *"ubuntu"* ]] || [[ "${{ matrix.os }}" == *"fedora"* ]]; then
echo "Generating references through docker using image ${DOCKER_IMAGE}."
docker run --rm \
--user 1000:1000 --network=host -v $WORKSPACE:/workspace \
${DOCKER_IMAGE} \
/bin/bash -c "export REGRESSION_DIR="$DOCKER_REGRESSION_DIR"; cd /workspace;. ${DOCKER_CI_DIR}/scripts/tests/setup-test-env.sh \"${DOCKER_BUILD_DIR}\" \"${DOCKER_CI_DIR}/scripts/\" \"${NODE_NAME}\" \"${{ inputs.python-version }}\"; env ; \${VM_PYTHON3_EXECUTABLE} ${DOCKER_REGRESSION_DIR}/SofaRegressionProgram/SofaRegressionProgram.py --input "${DOCKER_SRC_DIR}/examples" --input "${DOCKER_SRC_DIR}/applications" --input "${DOCKER_BUILD_DIR}/external_directories/fetched" --filter \"\$(cat ${DOCKER_BUILD_DIR}/ci_update_ref/filter.txt)\" --write-references --output-logs-errors "\${RESULTS_DIR}/regression" --jobs \${VM_MAX_PARALLEL_TESTS} "
else
. ${CI_DIR}/scripts/tests/setup-test-env.sh "${BUILD_DIR}" "${CI_DIR}/scripts/" "${NODE_NAME}" "${{ inputs.python-version }}"
${VM_PYTHON3_EXECUTABLE} ${REGRESSION_DIR}/SofaRegressionProgram/SofaRegressionProgram.py --input "${SRC_DIR}/examples" --input "${SRC_DIR}/applications" --input "${BUILD_DIR}/external_directories/fetched" --filter "$(cat ${BUILD_DIR}/ci_update_ref/filter.txt)" --write-references --output-logs-errors "${RESULTS_DIR}/regression" -j ${VM_MAX_PARALLEL_TESTS}
fi

if [[ ! "$(cd "${{ env.BUILD_DIR }}/tests_results/regression" && find . -maxdepth 1 -type f)" == *"summary"* ]]; then
exit 1
elif [[ "$(awk -F= '$1=="crashes" {print $2}' ${{ env.BUILD_DIR }}/tests_results/regression/summary.txt)" != '0' ]]; then
exit 1
fi

- name: Update references - commit and push
id: update-ref-commit
if: always() && steps.update-ref-generate.outcome == 'success'
shell: bash
env:
CI_UPDATE_REF: ${{ inputs.ci-update-ref }}
BUILD_COMMIT: ${{ (inputs.pr-commit-sha != '' && inputs.pr-commit-sha) || inputs.sofa-commit-sha }}
run: |
python3 ${CI_DIR}/scripts/ci_update_ref_build.py commit
# <<< CI-UPDATE-REF END

- name: Publish artifacts
if: steps.build-step.outcome == 'success' && inputs.generate-binaries == true
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -431,11 +554,23 @@ jobs:
echo "✅ Build OK."
fi

# >>> CI-UPDATE-REF BEGIN
if [[ -n "${{ inputs.ci-update-ref }}" ]]; then
if [[ "${{ steps.update-ref-prepare.outcome }}" == "failure" || "${{ steps.update-ref-generate.outcome }}" == "failure" || "${{ steps.update-ref-commit.outcome }}" == "failure" ]]; then
echo "❌ References generation failed"
exit 1
fi
echo "✅ References generated and pushed."
exit 0
fi
# <<< CI-UPDATE-REF END

if [[ "${{ inputs.generate-binaries }}" == "false" ]]; then
if [[ "$(cd "${{ env.BUILD_DIR }}/tests_results/" && find . -maxdepth 1 -type f)" != "" ]]; then
if [[ "${{ steps.unit-tests-step.outcome }}" == "failure" || "${{ steps.scene-tests-step.outcome }}" == "failure" || "${{ steps.regression-tests-step.outcome }}" == "failure" ]] &&
[[ -f "${{ env.SOFA_BUILD_DIR }}/tests_results/unit/summary.txt" && -f "${{ env.SOFA_BUILD_DIR }}/tests_results/scene/summary.txt" && -f "${{ env.SOFA_BUILD_DIR }}/tests_results/regression/summary.txt" ]]; then
echo "❌ Tests have resulted in : "
echo ""
python3 ${{ env.CI_DIR }}/scripts/generate-tests-table.py "${{ env.BUILD_DIR }}/tests_results/"
python3 ${{ env.CI_DIR }}/scripts/tests/generate-tests-table.py "${{ env.SOFA_BUILD_DIR }}/tests_results/"
echo ""
echo "#----------------------------------------#"
echo "#---------------Quick Logs---------------#"
Expand All @@ -444,12 +579,12 @@ jobs:
do
for errorType in 'errors' 'crashes' 'failures';
do
if [ -f "${{ env.BUILD_DIR }}/tests_results/${testType}-tests_${errorType}" ]; then
if [ -f "${{ env.SOFA_BUILD_DIR }}/tests_results/${testType}/${testType}_${errorType}.txt" ]; then
capitalized="$(echo "${testType:0:1}" | tr '[:lower:]' '[:upper:]')${testType:1}"
echo ""
echo -e "${bold}${capitalized} ${errorType}:${normal}"
echo ""
cat "${{ env.BUILD_DIR }}/tests_results/${testType}-tests_${errorType}"
cat "${{ env.SOFA_BUILD_DIR }}/tests_results/${testType}/${testType}_${errorType}.txt"
echo ""
echo "#----------------------------------------#"
fi
Expand All @@ -458,13 +593,13 @@ jobs:
echo -e "${bold}You can download all logs here : ${{ steps.publish-tests-logs.outputs.artifact-url }}${normal}"
exit 1
elif [[ "${{ steps.unit-tests-step.outcome }}" == "failure" || "${{ steps.scene-tests-step.outcome }}" == "failure" || "${{ steps.regression-tests-step.outcome }}" == "failure" ]]; then
echo "❌ Something whent wrong during one of the tests steps"
echo "❌ Something went wrong during one of the tests steps"
echo -e "${bold}Please check this action logs, and download tests logs here: ${{ steps.publish-tests-logs.outputs.artifact-url }}${normal}"
exit 1
else
echo "✅ Tests where successful : "
echo "✅ Tests were successful : "
echo ""
python3 ${{ env.CI_DIR }}/scripts/generate-tests-table.py "${{ env.BUILD_DIR }}/tests_results/"
python3 ${{ env.CI_DIR }}/scripts/tests/generate-tests-table.py "${{ env.SOFA_BUILD_DIR }}/tests_results/"
echo ""
fi
fi
Loading
Loading