diff --git a/.github/workflows/benchmarker.yml b/.github/workflows/benchmarker.yml new file mode 100644 index 00000000..a4831a5d --- /dev/null +++ b/.github/workflows/benchmarker.yml @@ -0,0 +1,183 @@ +name: Benchmark + +on: + workflow_call: + inputs: + shot_executable_path: + description: 'The path to the SHOT executable to run' + default: "/SHOT" + required: false + type: string + benchmark_folder: + description: 'The benchmark to run (folder name from: https://github.com/andreaslundell/SHOT_benchmark_problems)' + default: "MINLP-convex-small" + required: false + type: string + benchmark_type: + description: 'The benchmark type to run, can be gms, nl or osil' + default: "nl" + required: false + type: string + benchmarks: + description: 'The benchmarks to run, can be a list of benchmarks or a single benchmark, defaults to all benchmarks' + default: "all" + required: false + type: string + enable_gurobi: + description: 'Is this a Gurobi build (this will install Gurobi)' + default: false + required: false + type: boolean + enable_gams: + description: 'Is this a GAMS build (this will install GAMS)' + default: false + required: false + type: boolean + shot_artifact: + description: 'The SHOT artifact to use' + default: "" + required: false + type: string + gurobi_license_file: + description: 'The path to the Gurobi license file' + default: "" + required: false + type: string + gams_license_file: + description: 'The path to the GAMS license file' + default: "" + required: false + type: string + artifact_suffix: + description: 'The suffix to add to the artifact name' + default: '' + required: false + type: string + secrets: + gurobi_license: + description: 'Gurobi license file secret' + required: false + gams_license: + description: 'GAMS license file secret' + required: false + OS_USERNAME: + description: 'OpenStack username' + required: true + OS_PASSWORD: + description: 'OpenStack password' + required: true + + + outputs: + benchmarks: + description: 'The benchmarks that were run' + value: ${{ jobs.benchmark.outputs.benchmarks }} + + +env: + GRB_LICENSE_FILE: ${{inputs.gurobi_license_file}} + GAMS_LICENSE_FILE: ${{inputs.gams_license_file}} + +jobs: + benchmark: + outputs: + benchmarks: ${{ steps.benchmark.outputs.benchmarks }} + name: Benchmark SHOT + runs-on: [ self-hosted, linux, cmake ] + + steps: + - shell: bash + run: git -C shot-benchmarker pull || git clone https://github.com/maxemiliang/shot-benchmarker.git + + - name: Fetch SHOT artifact + if: ${{ inputs.shot_artifact != '' }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.shot_artifact }} + path: ${{ github.workspace }}/shot-benchmarker + + - name: Set the SHOT executable path if an artifact is used + if : ${{ inputs.shot_executable_path == '' }} + shell: bash + run: echo "SHOT_EXECUTABLE_PATH=${{ github.workspace }}/shot-benchmarker" >> $GITHUB_ENV + + # If the path is not an absolute path, we assume it is relative to the current working directory + - name: Set the SHOT executable path. + if: ${{ inputs.shot_executable_path != '' }} + shell: bash + run: | + if [[ ${{ inputs.shot_executable_path }} == /* ]]; then + echo "SHOT_EXECUTABLE_PATH=${{ inputs.shot_executable_path }}" >> $GITHUB_ENV + else + echo "SHOT_EXECUTABLE_PATH=${{ github.workspace }}/${{ inputs.shot_executable_path }}" >> $GITHUB_ENV + fi + + - name: Make SHOT executable + shell: bash + run: | + cd ${{ env.SHOT_EXECUTABLE_PATH }} + chmod +x SHOT + + - name: Show linked libraries + shell: bash + working-directory: ${{ env.SHOT_EXECUTABLE_PATH }} + run: ldd SHOT + + - uses: actions/setup-python@v4 + with: + python-version: 3.11 + cache: 'pip' + + - shell: bash + run: pip install -r requirements.txt + working-directory: ${{ github.workspace }}/shot-benchmarker + + # Add the license file to the GAMS installation directory + - name: Setup GAMS License file + if: ${{ inputs.enable_gams }} + shell: bash + working-directory: ${{ github.workspace }} + run: echo ${{ secrets.gams_license }} | base64 -d > $GAMS_LICENSE_FILE + + - name: Setup Gurobi License file + if: ${{ inputs.enable_gurobi }} + shell: bash + working-directory: ${{ github.workspace }} + run: echo ${{ secrets.gurobi_license }} | base64 -d > $GRB_LICENSE_FILE + + - shell: bash + id: benchmark + env: + INPUT_BENCHMARK_FOLDER: ${{ inputs.benchmark_folder }} + INPUT_BENCHMARK_TYPE: ${{ inputs.benchmark_type }} + INPUT_BENCHMARKS: ${{ inputs.benchmarks }} + INPUT_SHOT_EXECUTABLE: ${{ env.SHOT_EXECUTABLE_PATH }}/SHOT + INPUT_COMPARISON_SUFFIX: ${{ inputs.artifact_suffix }} + INPUT_IS_GAMS: ${{ inputs.enable_gams }} + INPUT_IS_GUROBI: ${{ inputs.enable_gurobi }} + OS_AUTH_URL: 'https://pouta.csc.fi:5001/v3' + OS_PROJECT_ID: '230dabcfb234424cb77e7de501ef7efc' + OS_PROJECT_NAME: 'project_2001223' + OS_USER_DOMAIN_NAME: "Default" + OS_PROJECT_DOMAIN_ID: "default" + OS_USERNAME: '${{ secrets.OS_USERNAME }}' + OS_PASSWORD: '${{ secrets.OS_PASSWORD }}' + OS_REGION_NAME: "regionOne" + OS_INTERFACE: "public" + OS_IDENTITY_API_VERSION: "3" + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' + working-directory: ${{ github.workspace }}/shot-benchmarker + run: python main.py -c -s --runs 5 + + - name: Upload benchmarks + uses: actions/upload-artifact@v4 + with: + name: benchmarks-${{ github.sha }}${{ inputs.artifact_suffix }} + path: ${{ github.workspace }}/shot-benchmarker/benchmarks + + - name: Cleanup license files + if: ${{ success() || failure() }} + shell: bash + run: | + rm -f $GRB_LICENSE_FILE + rm -f $GAMS_LICENSE_FILE diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml new file mode 100644 index 00000000..78c55b10 --- /dev/null +++ b/.github/workflows/build-push.yml @@ -0,0 +1,62 @@ +name: Build + +# Build this on push +on: [ push, workflow_dispatch ] + +# Only build one build at a time +concurrency: push-build + +jobs: + # First, we build and test using the default build options and only open source external libraries + build-test: + name: Build & Test + uses: ./.github/workflows/build-workflow.yml + with: + job_count: 4 + build_type: Release + retention: 30 + upload_artifacts: true + run_benchmarks: true + secrets: + OS_USERNAME: ${{ secrets.OS_USERNAME }} + OS_PASSWORD: ${{ secrets.OS_PASSWORD }} + + # Then, we build and test using all licenses included proprietary ones + build-proprietary: + name: Build & Test (Proprietary licenses) + needs: [ build-test ] + uses: ./.github/workflows/build-workflow.yml + with: + job_count: 4 + build_type: Release + retention: 30 + upload_artifacts: false + enable_gurobi: true + enable_gams: true + artifact_suffix: '-proprietary' + run_benchmarks: true + secrets: + gurobi_license: ${{ secrets.GUROBI_LICENSE_FILE }} + gams_license: ${{ secrets.GAMS_LICENSE_FILE }} + OS_USERNAME: ${{ secrets.OS_USERNAME }} + OS_PASSWORD: ${{ secrets.OS_PASSWORD }} + + + # Publish the test results as an output + publish-test: + name: Publish test results + needs: [ build-test, build-proprietary ] + runs-on: [ self-hosted, docker ] + steps: + - uses: actions/download-artifact@v4 + name: Download artifacts + with: + path: artifacts + + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: | + artifacts/test-*/*.xml + diff --git a/.github/workflows/build-workflow.yml b/.github/workflows/build-workflow.yml new file mode 100644 index 00000000..f5399291 --- /dev/null +++ b/.github/workflows/build-workflow.yml @@ -0,0 +1,390 @@ +name: Build and Test + +on: + workflow_call: + inputs: + build_type: + description: 'The CMake build type, can be either: Release, Debug, RelWithDebInfo, etc.' + default: Release + required: false + type: string + build_args: + description: 'Additional build parameters' + default: '-DHAS_GAMS=off -DHAS_CPLEX=off -DHAS_GUROBI=off -DCOMPILE_TESTS=on -DSPDLOG_STATIC=on' + required: false + type: string + job_count: + description: 'The amount of jobs to use when building the program and dependencies.' + default: 1 + required: false + type: number + # Map the workflow outputs to job outputs + version: + description: 'The version to build SHOT as.' + default: ${{ github.sha }} + required: false + type: string + retention: + description: 'The artifact retention period (in days)' + default: 60 + required: false + type: number + upload_artifacts: + description: 'Should the artifacts be uploaded' + default: true + required: false + type: boolean + enable_gurobi: + description: 'Is this a Gurobi build (this will install Gurobi)' + default: false + required: false + type: boolean + enable_gams: + description: 'Is this a GAMS build (this will install GAMS)' + default: false + required: false + type: boolean + artifact_suffix: + description: 'The suffix to add to the artifact name' + default: '' + required: false + type: string + gurobi_version: + description: 'The version of Gurobi to use' + default: '11.0.1' + required: false + type: string + gams_version: + description: 'The version of GAMS to use' + default: '42.3.0' + required: false + type: string + run_benchmarks: + description: 'Should the benchmarks be run' + default: false + required: false + type: boolean + secrets: + gurobi_license: + description: 'Gurobi license file secret' + required: false + gams_license: + description: 'GAMS license file secret' + required: false + OS_USERNAME: + description: 'OpenStack username' + required: false + OS_PASSWORD: + description: 'OpenStack password' + required: false + + outputs: + test-artifact: + description: "Test artifact ID" + value: ${{ jobs.build.outputs.test-artifact }} + options-artifact: + description: "SHOT Optionsfile artifact ID" + value: ${{ jobs.build.outputs.options-artifact }} + binary-artifact: + description: "SHOT Binary artifact ID" + value: ${{ jobs.build.outputs.binary-artifact }} + package-artifact: + description: "SHOT Package artifact ID" + value: ${{ jobs.build.outputs.package-artifact }} + library-artifact: + description: "SHOT Libraries artifact ID" + value: ${{ jobs.build.outputs.library-artifact }} + + +env: + BUILD_TYPE: ${{ inputs.build_type }} + JOB_COUNT: ${{ inputs.job_count }} + VERSION: ${{ inputs.version }} + ARTIFACT_SUFFIX: ${{ inputs.artifact_suffix }} + EXTRA_BUILD_ARGS: ${{ inputs.build_args }} + GRB_LICENSE_FILE: ${{ github.workspace }}/gurobi.lic + GUROBI_VERSION: ${{ inputs.gurobi_version }} + GAMS_VERSION: ${{ inputs.gams_version }} + +jobs: + build: + outputs: + test-artifact: ${{ steps.output-artifacts.test }} + options-artifact: ${{ steps.output-artifacts.options }} + binary-artifact: ${{ steps.output-artifacts.binary }} + package-artifact: ${{ steps.output-artifacts.package }} + library-artifact: ${{ steps.output-artifacts.library }} + gurobi_license_file: ${{ steps.licensefiles.outputs.gurobi}} + gams_license_file: ${{ steps.licensefiles.outputs.gams }} + name: Build SHOT + runs-on: [ self-hosted, linux, cmake ] + + env: + GAMS_OPTIONS: -DHAS_GAMS=off + GUROBI_OPTIONS: -DHAS_GUROBI=off + + steps: + - name: Cleanup workspace + run: | + sudo rm -rf ./* || true + sudo rm -rf ./.??* || true + + - uses: actions/checkout@v3 + + - name: Checkout submodules + run: git submodule update --init --recursive + + - name: Create Build Environment + # Some projects don't allow in-source building, so create a separate build directory + # We'll use this as our working directory for all subsequent commands + run: cmake -E make_directory ${{github.workspace}}/build + + - name: Install dependencies + shell: bash + run: sudo apt-get update ; sudo apt-get install -y libc6-dev libbz2-dev zlib1g-dev liblapack-dev libnauty2-dev libopenblas-base libopenblas-dev libmumps-dev pkgconf + + - name: Cache Cbc + id: cache-cbc + uses: actions/cache@v3 + with: + path: ${{github.workspace}}/ThirdParty/Cbc + key: ${{ runner.os }}-cbc + + - name: Cache Ipopt + id: cache-ipopt + uses: actions/cache@v3 + with: + path: ${{github.workspace}}/ThirdParty/Ipopt + key: ${{ runner.os }}-ipopt + + - name: Setup Coinbrew + if: steps.cache-ipopt.outputs.cache-hit != 'true' || steps.cache-cbc.outputs.cache-hit != 'true' + shell: bash + working-directory: ${{github.workspace}}/build + run: git -C "coinbrew" pull || git clone https://github.com/coin-or/coinbrew + + - name: Download and build Ipopt + if: steps.cache-ipopt.outputs.cache-hit != 'true' + shell: bash + working-directory: ${{github.workspace}}/build/coinbrew + run: ./coinbrew build Ipopt --verbosity 2 --prefix=${{github.workspace}}/ThirdParty/Ipopt -j $JOB_COUNT --no-prompt --tests none + + - name: Download and build Cbc + if: steps.cache-cbc.outputs.cache-hit != 'true' + shell: bash + working-directory: ${{github.workspace}}/build/coinbrew + run: rm -rf build dist ; ./coinbrew build Cbc@stable/2.10 --verbosity 2 -j $JOB_COUNT --prefix=${{github.workspace}}/ThirdParty/Cbc --no-prompt --tests none --no-third-party + + # Proprietary software setup happens here (GAMS and Gurobi) + # First we create the license files from the base64 encoded secrets. + - name: Setup Gurobi License file + if: ${{ inputs.enable_gurobi }} + shell: bash + working-directory: ${{github.workspace}} + run: echo ${{ secrets.gurobi_license }} | base64 -d > $GRB_LICENSE_FILE + + - name: Extract Version + id: get_version + run: | + version=${{ env.GUROBI_VERSION }} + major_minor=$(echo $version | awk -F '.' '{print $1 "." $2}') + version_without_dot=$(echo $version | tr -d .) + echo "GUROBI_SHORT_VERSION=$major_minor" >> $GITHUB_ENV + echo "GUROBI_VERSION_WITHOUT_DOT=$version_without_dot" >> $GITHUB_ENV + echo "GRB_INSTALL_PATH=${{ github.workspace }}/ThirdParty/gurobi${version_without_dot}" >> $GITHUB_ENV + + # Then we download and install Gurobi + - name: Download Gurobi + if: ${{ inputs.enable_gurobi }} + shell: bash + working-directory: ${{github.workspace}}/ThirdParty + run: wget -q https://packages.gurobi.com/${{ env.GUROBI_SHORT_VERSION }}/gurobi${{ env.GUROBI_VERSION }}_linux64.tar.gz ; tar -xvf gurobi${{ env.GUROBI_VERSION }}_linux64.tar.gz ; rm gurobi${{ env.GUROBI_VERSION }}_linux64.tar.gz + + # Finally, we set the environment variables needed for Gurobi to work. + - name: Setup Gurobi environment variables + if: ${{ inputs.enable_gurobi }} + shell: bash + working-directory: ${{github.workspace}}/ThirdParty + run: | + echo "${{ github.workspace }}/ThirdParty/gurobi${{ env.GUROBI_VERSION_WITHOUT_DOT }}/linux64/bin" >> $GITHUB_PATH + echo "GUROBI_HOME=${{ github.workspace }}/ThirdParty/gurobi${{ env.GUROBI_VERSION_WITHOUT_DOT }}/linux64" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=${{ github.workspace }}/ThirdParty/gurobi${{ env.GUROBI_VERSION_WITHOUT_DOT }}/linux64/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV + + - name: Set Gurobi options + if: ${{ inputs.enable_gurobi }} + shell: bash + run: echo "GUROBI_OPTIONS=-DHAS_GUROBI=on" >> $GITHUB_ENV + + - name: Get GAMS short version + id: get_gams_short_version + run: | + version=${{ env.GAMS_VERSION }} + major_minor=$(echo $version | awk -F '.' '{print $1 "." $2}') + echo "GAMS_SHORT_VERSION=$major_minor" >> $GITHUB_ENV + echo "GAMS_INSTALL_PATH=${{ github.workspace }}/ThirdParty/gams${major_minor}_linux_x64_64_sfx" >> $GITHUB_ENV + echo "GAMS_LICENSE_FILE=${{ github.workspace }}/ThirdParty/gams${major_minor}_linux_x64_64_sfx/gamslice.txt" >> $GITHUB_ENV + + # Next, we set up GAMS + # Download GAMS + - name: Download GAMS + if: ${{ inputs.enable_gams }} + shell: bash + working-directory: ${{github.workspace}}/ThirdParty + run: wget -q https://d37drm4t2jghv5.cloudfront.net/distributions/${{ env.GAMS_VERSION }}/linux/linux_x64_64_sfx.exe ; chmod +x linux_x64_64_sfx.exe ; ./linux_x64_64_sfx.exe ; rm linux_x64_64_sfx.exe + + # Add the license file to the GAMS installation directory + - name: Setup GAMS License file + if: ${{ inputs.enable_gams }} + shell: bash + working-directory: ${{github.workspace}} + run: echo ${{ secrets.gams_license }} | base64 -d > $GAMS_LICENSE_FILE + + - name: Install GAMS + if: ${{ inputs.enable_gams }} + shell: bash + working-directory: ${{ github.workspace }}/ThirdParty/gams${{ env.GAMS_SHORT_VERSION }}_linux_x64_64_sfx/ + run: ./gamsinst -a + + - name: Add GAMS to the path + if: ${{ inputs.enable_gams }} + shell: bash + run: echo "$GAMS_INSTALL_PATH" >> $GITHUB_PATH + + - name: Set GAMS options + if: ${{ inputs.enable_gams }} + shell: bash + run: echo "GAMS_OPTIONS=-DHAS_GAMS=on" >> $GITHUB_ENV + + - name: Output License files + id: licensefiles + shell: bash + run: | + echo "gurobi=${{ github.workspace }}/ThirdParty/gurobi${{ env.GUROBI_VERSION_WITHOUT_DOT }}/linux64/bin/gurobi.lic" >> $GITHUB_OUTPUT + echo "gams=${{ github.workspace }}/ThirdParty/gams${{ env.GAMS_SHORT_VERSION }}_linux_x64_64_sfx/gamslice.txt" >> $GITHUB_OUTPUT + + - name: Configure CMake + # Uses bash shell, so we can use the same syntax for environment variable + # access regardless of the host operating system + shell: bash + working-directory: ${{github.workspace}}/build + # Here we configure the build, we set the build type, + # enable the tests and set the path to the external libraries. + run: cmake -S $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DHAS_CBC=on -DCBC_DIR=${{github.workspace}}/ThirdParty/Cbc -DHAS_IPOPT=ON -DIPOPT_DIR=${{github.workspace}}/ThirdParty/Ipopt -DGAMS_DIR=$GAMS_INSTALL_PATH -DGUROBI_DIR=$GRB_INSTALL_PATH -DCOMPILE_TESTS=on -DSPDLOG_STATIC=on $GAMS_OPTIONS $GUROBI_OPTIONS -DHAS_CPLEX=off + + - name: Build + working-directory: ${{github.workspace}}/build + shell: bash + # We build the job, $BUILD_TYPE can be Release, Debug, RelWithDebInfo. + # $JOB_COUNT is the amount of jobs to use when building the program and dependencies, + # this can be set as an input. + run: cmake --build . --config $BUILD_TYPE -j $JOB_COUNT + + - name: Generate Optionsfile + working-directory: ${{github.workspace}}/build + shell: bash + run: ./SHOT --opt + + - name: Test + id: test + working-directory: ${{github.workspace}}/build + shell: bash + run: ctest -C $BUILD_TYPE --output-on-failure --output-junit test-output/ctest-junit-output.xml --output-log test-output/ctest-test.log + + - name: Construct package + working-directory: ${{github.workspace}}/build + shell: bash + run: make package + + - name: Show linked libraries + working-directory: ${{github.workspace}}/build + shell: bash + run: ldd SHOT + + # This will always run as we always want the test output, however if the files are not found, we just warn the user. + - uses: actions/upload-artifact@v4 + if: ${{ always() }} + name: Upload test results + with: + name: test-logs-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }} + path: | + ${{github.workspace}}/build/test-output/*.log + ${{github.workspace}}/build/test-output/*.xml + retention-days: ${{ inputs.retention }} + + - uses: actions/upload-artifact@v4 + if: ${{ inputs.upload_artifacts }} + name: Upload SHOT Optionsfile + with: + name: shot-optsfile-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }} + path: ${{github.workspace}}/build/SHOT.opt + retention-days: ${{ inputs.retention }} + + - uses: actions/upload-artifact@v4 + if: ${{ inputs.upload_artifacts }} + name: Upload SHOT File + with: + name: shot-binary-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }} + path: ${{github.workspace}}/build/SHOT + retention-days: ${{ inputs.retention }} + + - uses: actions/upload-artifact@v4 + if: ${{ inputs.upload_artifacts }} + name: Upload SHOT Package file + with: + name: shot-package-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }} + path: ${{github.workspace}}/build/SHOT-*-Linux.zip + retention-days: ${{ inputs.retention }} + + - uses: actions/upload-artifact@v4 + if: ${{ inputs.upload_artifacts }} + name: Upload SHOT Libraries + with: + name: shot-libraries-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }} + path: | + ${{github.workspace}}/build/*.so + ${{github.workspace}}/build/*.a + retention-days: ${{ inputs.retention }} + + - name: Output artifact names + id: output-artifacts + if: ${{ inputs.upload_artifacts }} + shell: bash + run: | + echo "test=test-logs-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }}" >> $GITHUB_OUTPUT + echo "options=shot-optsfile-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }}" >> $GITHUB_OUTPUT + echo "binary=shot-binary-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }}" >> $GITHUB_OUTPUT + echo "package=shot-package-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }}" >> $GITHUB_OUTPUT + echo "library=shot-libraries-${{ env.VERSION }}${{ env.ARTIFACT_SUFFIX }}" >> $GITHUB_OUTPUT + + - name: Output test artifacts + if: ${{ inputs.upload_artifacts }} != true && steps.output-artifacts.outcome != 'success' + shell: bash + run: echo "test=test-logs-${{ env.VERSION }}" >> $GITHUB_OUTPUT + + - name: Cleanup license files + if: ${{ success() || failure() }} + shell: bash + run: | + rm -f $GRB_LICENSE_FILE + rm -f $GAMS_LICENSE_FILE + + # Finally, we run some simple benchmarks + benchmark: + if: ${{ inputs.run_benchmarks }} + name: Benchmark + uses: ./.github/workflows/benchmarker.yml + needs: [ build ] + with: + shot_executable_path: build + benchmark_folder: "MINLP-convex-small" + benchmark_type: "nl" + enable_gurobi: ${{ inputs.enable_gurobi }} + enable_gams: ${{ inputs.enable_gams }} + gurobi_license_file: ${{ needs.build.outputs.gurobi_license_file }} + gams_license_file: ${{ needs.build.outputs.gams_license_file }} + artifact_suffix: ${{ inputs.artifact_suffix }} + secrets: + gurobi_license: ${{ secrets.gurobi_license }} + gams_license: ${{ secrets.gams_license }} + OS_USERNAME: ${{ secrets.OS_USERNAME }} + OS_PASSWORD: ${{ secrets.OS_PASSWORD }} diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml deleted file mode 100644 index 4334942b..00000000 --- a/.github/workflows/cmake.yml +++ /dev/null @@ -1,86 +0,0 @@ -name: CMake - -on: [push] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - -jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Checkout submodules - run: git submodule update --init --recursive - - - name: Create Build Environment - # Some projects don't allow in-source building, so create a separate build directory - # We'll use this as our working directory for all subsequent commands - run: cmake -E make_directory ${{runner.workspace}}/build - - - name: Install dependencies - shell: bash - run: sudo apt-get update ; sudo apt-get install libc6-dev libbz2-dev zlib1g-dev liblapack-dev libnauty2-dev libopenblas-base libopenblas-dev libmumps-dev - - - name: Cache Cbc - id: cache-cbc - uses: actions/cache@v2 - with: - path: ${{runner.workspace}}/ThirdParty/Cbc - key: ${{ runner.os }}-cbc - - - name: Cache Ipopt - id: cache-ipopt - uses: actions/cache@v2 - with: - path: ${{runner.workspace}}/ThirdParty/Ipopt - key: ${{ runner.os }}-ipopt - - - name: Download Coinbrew - if: steps.cache-ipopt.outputs.cache-hit != 'true' || steps.cache-cbc.outputs.cache-hit != 'true' - - shell: bash - working-directory: ${{runner.workspace}}/build - run: git clone https://github.com/coin-or/coinbrew - - - name: Download and build Ipopt - if: steps.cache-ipopt.outputs.cache-hit != 'true' - shell: bash - working-directory: ${{runner.workspace}}/build/coinbrew - run: ./coinbrew build Ipopt --verbosity 2 --prefix=${{runner.workspace}}/ThirdParty/Ipopt --no-prompt --tests none - - - name: Download and build Cbc - if: steps.cache-cbc.outputs.cache-hit != 'true' - shell: bash - working-directory: ${{runner.workspace}}/build/coinbrew - run: rm -rf build dist ; ./coinbrew build Cbc@stable/2.10 --verbosity 2 --prefix=${{runner.workspace}}/ThirdParty/Cbc --no-prompt --tests none --no-third-party - - - name: Configure CMake - # Use a bash shell so we can use the same syntax for environment variable - # access regardless of the host operating system - shell: bash - working-directory: ${{runner.workspace}}/build - # Note the current convention is to use the -S and -B options here to specify source - # and build directories, but this is only available with CMake 3.13 and higher. - # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DHAS_CBC=on -DCBC_DIR=${{runner.workspace}}/ThirdParty/Cbc -DHAS_IPOPT=ON -DIPOPT_DIR=${{runner.workspace}}/ThirdParty/Ipopt -DHAS_GAMS=off -DHAS_CPLEX=off -DHAS_GUROBI=off -DCOMPILE_TESTS=on -DSPDLOG_STATIC=on - - - name: Build - working-directory: ${{runner.workspace}}/build - shell: bash - # Execute the build. You can specify a specific target with "--target " - run: cmake --build . --config $BUILD_TYPE - - - name: Test - working-directory: ${{runner.workspace}}/build - shell: bash - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest -C $BUILD_TYPE --output-on-failure diff --git a/.gitignore b/.gitignore index 58c4171e..40a14ae0 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ build/* /.vs /out/build +/.cache/ \ No newline at end of file diff --git a/misc/runner-init.yml b/misc/runner-init.yml new file mode 100644 index 00000000..13468376 --- /dev/null +++ b/misc/runner-init.yml @@ -0,0 +1,73 @@ +#cloud-config: +package_update: true +package_upgrade: true + +packages: + # Requirements for GitHub runner + - zlib1g + - libssl1.1 + - libkrb5-3 + - liblttng-ust-ctl4 + - liblttng-ust0 + - libssl-dev + # Required for the setup of GitHub Runner. + - build-essential + - jq + # Docker packages + - ca-certificates + - curl + - gnupg + - lsb-release + - ccache + +users: + - default + - name: ghrunner + groups: sudo + shell: /bin/bash + sudo: ['ALL=(ALL) NOPASSWD:ALL'] + +runcmd: + # Install docker + - mkdir -m 0755 -p /etc/apt/keyrings + - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg + - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + - chmod a+r /etc/apt/keyrings/docker.gpg + - apt-get update + - apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + # Install CMake + - 'curl -O -L https://github.com/Kitware/CMake/releases/download/v3.26.0/cmake-3.26.0-linux-x86_64.sh' + - mv cmake-3.26.0-linux-x86_64.sh /opt/ + - cd /opt/ + - chmod +x cmake-3.26.0-linux-x86_64.sh + - bash ./cmake-3.26.0-linux-x86_64.sh --skip-license + - ln -s /opt/bin/* /usr/local/bin + - echo "Installed CMake" + - cd /home/ghrunner + # Create the GH Runner directory. + - su 'ghrunner' -c "mkdir actions-runner" + - echo "Directory created" + - cd actions-runner + - echo "Swapped directory" + # We fetch a temporary runner creation token to allow adding the runner to the repo see: https://developer.github.com/v3/actions/self-hosted-runners/ for more information. + - 'export RUNNERTOKEN=$(curl -s -XPOST -H "authorization: token _REPLACE_TOKEN_" https://api.github.com/repos/coin-or/SHOT/actions/runners/registration-token | jq -r .token)' + - echo "Fetched token" + # Fetch the runner code + - su 'ghrunner' -c "curl -O -L https://github.com/actions/runner/releases/download/v2.302.1/actions-runner-linux-x64-2.302.1.tar.gz" + - echo "Fetched the installer" + # Extract the code as the runner user + - su 'ghrunner' -c "tar xzf ./actions-runner-linux-x64-2.302.1.tar.gz" + - echo "Installing the runner and dependencies" + # Config the runner and install it as a service. + - ./bin/installdependencies.sh + - su 'ghrunner' -c './config.sh --url https://github.com/coin-or/SHOT --token $RUNNERTOKEN --unattended --labels docker,x64,linux,cmake' + - ./svc.sh install ghrunner + - ./svc.sh start + - chown -R ghrunner /home/ghrunner/actions-runner + # Post install steps for docker + - groupadd docker + - usermod -aG docker ghrunner + - systemctl enable docker.service + - systemctl enable containerd.service + # Finally reboot the VM to correctly enable permissions for Docker. + - reboot now