From 33a446c7ade52d4df667da77d8243a3b15c3b88c Mon Sep 17 00:00:00 2001 From: Niket <15953349+niketagrawal@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:04:04 +0100 Subject: [PATCH 1/7] Trigger automated build and test using GitHub Actions upon push and pull request. Cache the conda environment to speed up the build across subsequent runs. Data files in tudat-resources are not cached. They are downloaded separately in an event of a cache hit. Failing tests in MacOS are temporarily ignored to let the workflow pass and the cache feature to be tested. --- .github/workflows/build_and_test.yml | 151 +++++++++++++++++++++++++++ environment.yml | 11 ++ 2 files changed, 162 insertions(+) create mode 100644 .github/workflows/build_and_test.yml create mode 100644 environment.yml diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml new file mode 100644 index 0000000000..b32235d65e --- /dev/null +++ b/.github/workflows/build_and_test.yml @@ -0,0 +1,151 @@ +# This workflow builds and tests the tudat source code on Windows, Linux, and MacOS using GitHub Actions. It is triggered upon push and pull requests to master, develop, and feature branches. +# The workflow is built on top of the GitHub starter workflow for CMake on multiple platforms https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml + + +name: Build and Test + +on: + push: + branches: [ "master", "develop", "*/*" ] + pull_request: + branches: [ "master", "develop", "*/*"] + +jobs: + build-and-test: + + env: + CACHE_NUMBER: 0 + + 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. + fail-fast: false + + # Set up a matrix to run the following 3 configurations: + # 1. + # 2. + # 3. + # + # To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list. + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + build_type: [Release] + c_compiler: [gcc, clang, cl] + include: + - os: windows-latest + c_compiler: cl + cpp_compiler: cl + label: win-64 + path_conda_env: C:\Miniconda3\envs\tudat + - os: ubuntu-latest + c_compiler: gcc + cpp_compiler: g++ + label: linux-64 + path_conda_env: /usr/share/miniconda3/envs/tudat + - os: macos-latest + c_compiler: clang + cpp_compiler: clang++ + label: osx-64 + path_conda_env: /Users/runner/miniconda3/envs/tudat + exclude: + - os: windows-latest + c_compiler: gcc + - os: windows-latest + c_compiler: clang + - os: ubuntu-latest + c_compiler: cl + - os: macos-latest + c_compiler: gcc + - os: macos-latest + c_compiler: cl + - os: ubuntu-latest + c_compiler: clang + + steps: + - uses: actions/checkout@v4 + + + - name: Setup conda environment using mamba + # This step sets up a conda environment using mamba, a faster alternative to conda. It creates an empty conda environment with the name 'tudat' and activates it. The environment is created using the latest version of Mambaforge, a conda distribution that includes mamba. + uses: conda-incubator/setup-miniconda@v2 + with: + miniforge-variant: Mambaforge + miniforge-version: latest + activate-environment: tudat + use-mamba: true + + + - name: Get date + # Get the current date and time in UTC format. This step is used to create a unique cache key for the conda environment cache by appending the date to the cache key. + # GitHub cache action doucmentation recommends refreshing the cache every 24 hours to avoid inconsistencies of package versions between the CI pipeline and local installations. This is ensured by appending the date to the cache key.See https://github.com/marketplace/actions/setup-miniconda#caching-environments for more detail. + id: get-date + run: echo "today=$(/bin/date -u '+%Y%m%d')" >> $GITHUB_OUTPUT + shell: bash + + + - name: Cache conda environment + # Cache the conda environment to avoid re-installing the same packages every time the workflow runs. The cache key is based on the environment.yml file, the operating system, and the date. The cache is restored if the cache key matches the cache key of the previous run. + uses: actions/cache@v4 + with: + path: ${{ matrix.path_conda_env }} + key: ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }}-${{steps.get-date.outputs.today}} + id: cache + + + - name: Create conda environment from environment.yml + # Update the tudat conda environment created using the environment.yml file if the cache is not restored + run: mamba env update -n tudat -f environment.yml + if: steps.cache.outputs.cache-hit != 'true' + + + - name: Download tudat resources data files for Linux and MacOS + # The data files in tudat-resources are downloaded upon the installation of + # the tudat-resources conda package in the previous step, but the data files are + # not cached by the cache action. When the cache is hit, the update environment + # step is skipped, skipping the installation of the tudat-resources package, + # thereby skipping the download of the data files. Therefore, the data files must + # be downloaded manually when the cache is hit. + # This step downloads the data files in the tudat-resources package by running + # the post-link scripts in https://github.com/tudat-team/tudat-resources-feedstock/blob/master/recipe/ + if: (runner.os == 'Linux' || runner.os == 'MacOS') && steps.cache.outputs.cache-hit == 'true' + run: bash -c "$(curl -fsSL https://raw.githubusercontent.com/tudat-team/tudat-resources-feedstock/master/recipe/post-link.sh)" + + + - name: Download tudat-resources data files for Windows + if: runner.os == 'Windows' && steps.cache.outputs.cache-hit == 'true' + run: cmd /c "curl -fsSL https://raw.githubusercontent.com/tudat-team/tudat-resources-feedstock/master/recipe/post-link.bat | cmd" + + + - 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. + id: strings + shell: bash -l {0} + run: | + echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + + + - name: 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 + shell: bash -l {0} + run: > + cmake -B "${{ steps.strings.outputs.build-output-dir }}" + -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + -S "${{ github.workspace }}" + + + - name: 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). Use multiple cpu cores available in the runner. + shell: bash -l {0} + run: cmake --build "${{ steps.strings.outputs.build-output-dir }}" --config "${{ matrix.build_type }}" -j4 + + + - name: Test + 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 + # Prevent the action from failing if any of the tests fail by using `|| true`. This is placed temporarily because currently, some tests fail on MacOS, and if the action fails, the cache is not updated, which prevents testing of the cache feature on MacOS. + run: ctest --build-config ${{ matrix.build_type }} --output-on-failure -j4 || true \ No newline at end of file diff --git a/environment.yml b/environment.yml new file mode 100644 index 0000000000..b21c5a7358 --- /dev/null +++ b/environment.yml @@ -0,0 +1,11 @@ +name: tudat +channels: + - conda-forge + - tudat-team +dependencies: + - eigen + - boost-cpp + - tudat-resources + - sofa-cmake + - nrlmsise-00 + - cspice-cmake \ No newline at end of file From aee1c8a1b86ccce39bda77ab83b952ce2623fb2e Mon Sep 17 00:00:00 2001 From: Yasel Quintero Date: Wed, 6 Mar 2024 21:16:31 +0100 Subject: [PATCH 2/7] Use ccache to speed up the GitHub Actions workflow build process ccache works out of the box for the GNU compilers in Ubuntu and the Clang compiler in MacOS. The MSVC compilers require an extra configuration step which was added to the CMakeLists file. --- .github/workflows/build_and_test.yml | 16 +++++++++++----- CMakeLists.txt | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index b32235d65e..a95cffc5db 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -124,6 +124,11 @@ jobs: run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" + - name: Setup ccache + # This third party action will setup ccache on the runner and restore any previously saved cache. Caches are saved automatically by the action after a build. + uses: hendrikmuhs/ccache-action@v1.2.12 + with: + key: ${{ matrix.os }}-${{ matrix.type }} - name: 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. @@ -131,18 +136,19 @@ jobs: shell: bash -l {0} run: > cmake -B "${{ steps.strings.outputs.build-output-dir }}" + -S "${{ github.workspace }}" + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - -S "${{ github.workspace }}" - - + -DCMAKE_C_COMPILER_LAUNCHER=ccache + -DTUDAT_BUILD_GITHUB_ACTIONS=ON + - name: 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). Use multiple cpu cores available in the runner. shell: bash -l {0} run: cmake --build "${{ steps.strings.outputs.build-output-dir }}" --config "${{ matrix.build_type }}" -j4 - - name: Test 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). diff --git a/CMakeLists.txt b/CMakeLists.txt index ba7e2f837e..217e82a328 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,31 @@ else() option(TUDAT_BUILD_WITH_EXTENDED_PRECISION_PROPAGATION_TOOLS "Build tudat with extended precision propagation tools." OFF) endif() +# Build as part of a GitHub Actions workflow +# Option enables the use of ccache by MSVC +# see https://github.com/ccache/ccache/wiki/MS-Visual-Studio +option(TUDAT_BUILD_GITHUB_ACTIONS "Build as part of GitHub Actions workflow." OFF) +if (TUDAT_BUILD_GITHUB_ACTIONS AND MSVC) + find_program(ccache_exe ccache) + if(ccache_exe) + message(STATUS "CONFIGURING MSVC FOR CCACHE") + file(COPY_FILE ${ccache_exe} ${CMAKE_BINARY_DIR}/cl.exe ONLY_IF_DIFFERENT) + + # By default Visual Studio generators will use /Zi which is not compatible + # with ccache, so tell Visual Studio to use /Z7 instead. + message(STATUS "Setting MSVC debug information format to 'Embedded'") + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$:Embedded>") + + set(CMAKE_VS_GLOBALS + "CLToolExe=cl.exe" + "CLToolPath=${CMAKE_BINARY_DIR}" + "TrackFileAccess=false" + "UseMultiToolTask=true" + "DebugInformationFormat=OldStyle" + ) + endif() +endif() + message(STATUS "******************** BUILD CONFIGURATION ********************") message(STATUS "TUDAT_BUILD_TESTS ${TUDAT_BUILD_TESTS}") message(STATUS "TUDAT_BUILD_WITH_PROPAGATION_TESTS ${TUDAT_BUILD_WITH_PROPAGATION_TESTS}") From c7628e89372cd1e21d1ad549fa14229d78d2b21c Mon Sep 17 00:00:00 2001 From: Yasel Quintero Date: Wed, 13 Mar 2024 14:26:27 +0100 Subject: [PATCH 3/7] Remove 'Set reusable strings' step from workflow --- .github/workflows/build_and_test.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index a95cffc5db..7d5859b870 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -117,25 +117,19 @@ jobs: run: cmd /c "curl -fsSL https://raw.githubusercontent.com/tudat-team/tudat-resources-feedstock/master/recipe/post-link.bat | cmd" - - 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. - id: strings - shell: bash -l {0} - run: | - echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - - name: Setup ccache # This third party action will setup ccache on the runner and restore any previously saved cache. Caches are saved automatically by the action after a build. uses: hendrikmuhs/ccache-action@v1.2.12 with: key: ${{ matrix.os }}-${{ matrix.type }} + - name: 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 shell: bash -l {0} run: > - cmake -B "${{ steps.strings.outputs.build-output-dir }}" + cmake -B "${{ github.workspace }}/build" -S "${{ github.workspace }}" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} @@ -143,14 +137,16 @@ jobs: -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DTUDAT_BUILD_GITHUB_ACTIONS=ON - + + - name: 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). Use multiple cpu cores available in the runner. shell: bash -l {0} - run: cmake --build "${{ steps.strings.outputs.build-output-dir }}" --config "${{ matrix.build_type }}" -j4 + run: cmake --build "${{ github.workspace }}/build" --config "${{ matrix.build_type }}" -j4 + - name: Test - working-directory: ${{ steps.strings.outputs.build-output-dir }} + working-directory: "${{ github.workspace }}/build" # 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 # Prevent the action from failing if any of the tests fail by using `|| true`. This is placed temporarily because currently, some tests fail on MacOS, and if the action fails, the cache is not updated, which prevents testing of the cache feature on MacOS. From 4582bfe7ac428dd362b8c1f36176043b9c3674de Mon Sep 17 00:00:00 2001 From: Niket <15953349+niketagrawal@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:00:22 +0100 Subject: [PATCH 4/7] Ignoring failed test in MacOS was for debugging purposes only. Rename the ccache step to describe what it does. Fix typo in referencing the matrix variable build type. --- .github/workflows/build_and_test.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 7d5859b870..6b74b7e646 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -117,11 +117,11 @@ jobs: run: cmd /c "curl -fsSL https://raw.githubusercontent.com/tudat-team/tudat-resources-feedstock/master/recipe/post-link.bat | cmd" - - name: Setup ccache + - name: Cache previous compilation results using ccache # This third party action will setup ccache on the runner and restore any previously saved cache. Caches are saved automatically by the action after a build. uses: hendrikmuhs/ccache-action@v1.2.12 with: - key: ${{ matrix.os }}-${{ matrix.type }} + key: ${{ matrix.os }}-${{ matrix.build_type }} - name: Configure CMake @@ -149,5 +149,4 @@ jobs: working-directory: "${{ github.workspace }}/build" # 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 - # Prevent the action from failing if any of the tests fail by using `|| true`. This is placed temporarily because currently, some tests fail on MacOS, and if the action fails, the cache is not updated, which prevents testing of the cache feature on MacOS. - run: ctest --build-config ${{ matrix.build_type }} --output-on-failure -j4 || true \ No newline at end of file + run: ctest --build-config ${{ matrix.build_type }} --output-on-failure -j4 \ No newline at end of file From db5d1e15052cc2d2fdcbc68a761c161a189c6c35 Mon Sep 17 00:00:00 2001 From: Niket <15953349+niketagrawal@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:53:23 +0100 Subject: [PATCH 5/7] This step restores compiler cache form previous runs if available, else proceeds with the build step. Caching of compilation results of the current run happens post completion of the build step. --- .github/workflows/build_and_test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 6b74b7e646..3badf72e34 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -1,4 +1,6 @@ # This workflow builds and tests the tudat source code on Windows, Linux, and MacOS using GitHub Actions. It is triggered upon push and pull requests to master, develop, and feature branches. +# This Github actions workflow automates the build and test process of the tudat source code on Windows, Linux, and MacOS. The workflow is triggered upon push and pull requests to master, develop, and feature branches. The workflow is built on top of the GitHub starter workflow for CMake on multiple platforms. +# ccache is used to cache previous compilation results to speed up the build process across s # The workflow is built on top of the GitHub starter workflow for CMake on multiple platforms https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml @@ -117,7 +119,7 @@ jobs: run: cmd /c "curl -fsSL https://raw.githubusercontent.com/tudat-team/tudat-resources-feedstock/master/recipe/post-link.bat | cmd" - - name: Cache previous compilation results using ccache + - name: Restore cached compilation results # This third party action will setup ccache on the runner and restore any previously saved cache. Caches are saved automatically by the action after a build. uses: hendrikmuhs/ccache-action@v1.2.12 with: From b6b3f09f4ce37cfa9d3d9fe8aebfb2a5c811505f Mon Sep 17 00:00:00 2001 From: Niket <15953349+niketagrawal@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:59:54 +0100 Subject: [PATCH 6/7] Avoid triggering two simultaneous CI workflows upon pushing commits to a feature branch that is also a source in a pull request --- .github/workflows/build_and_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 3badf72e34..374c0612ab 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -8,9 +8,9 @@ name: Build and Test on: push: - branches: [ "master", "develop", "*/*" ] + branches: [ "master", "develop" ] pull_request: - branches: [ "master", "develop", "*/*"] + branches: [ "master", "develop"] jobs: build-and-test: From 44273498dd404254e83e78342502b8f58e82a1eb Mon Sep 17 00:00:00 2001 From: Niket <15953349+niketagrawal@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:00:33 +0100 Subject: [PATCH 7/7] remove whitespace --- .github/workflows/build_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 374c0612ab..b1f27ab5d3 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -8,7 +8,7 @@ name: Build and Test on: push: - branches: [ "master", "develop" ] + branches: [ "master", "develop"] pull_request: branches: [ "master", "develop"]