diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e815da269d..e0a751407b 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,7 +2,7 @@ # This file contains the script used by GitHub actions to execute the Continuous Integration (CI) # for RMG-Py. This includes building RMG and its dependencies, executing the unit tests, # functional tests, database tests, and regression tests. -# +# # This will run automatically on any push to any branch, but will only run one instance of # itself at a time per branch (to avoid spawning tons of runners, which prevents them from # executing). @@ -14,7 +14,7 @@ # # # Changelog: -# 2023-04 - Jackson Burns - Added this header, regression tests, cleanup of action in +# 2023-04 - Jackson Burns - Added this header, regression tests, cleanup of action in # in general, and documentation throughout the file. # 2023-05 - added Docker build steps # 2023-05-12 - added changes to allow running on forks @@ -54,6 +54,8 @@ env: RMG_DATABASE_BRANCH: main # RMS branch to use for ReactionMechanismSimulator installation RMS_BRANCH: for_rmg + # RMS mode used for install_rms.sh + RMS_MODE: CI # julia parallel pre-compilation leads to race conditions and hangs, so we limit it to run in serial JULIA_NUM_PRECOMPILE_TASKS: 1 @@ -64,7 +66,7 @@ jobs: fail-fast: false matrix: python-version: ["3.9"] - os: [macos-13, macos-latest, ubuntu-latest] + os: [macos-13, macos-latest, ubuntu-20.04, ubuntu-22.04, ubuntu-latest] include-rms: ["", "with RMS"] exclude: - os: macos-13 # GitHub's runners just aren't up to the task of installing Julia @@ -131,7 +133,7 @@ jobs: name: Regression Test # skip scheduled runs from forks if: ${{ !( github.repository != 'ReactionMechanismGenerator/RMG-Py' && github.event_name == 'schedule' ) }} - env: + env: # This is true only if this is a reference case for the regression testing: REFERENCE_JOB: ${{ github.ref == 'refs/heads/main' && github.repository == 'ReactionMechanismGenerator/RMG-Py' }} defaults: @@ -167,7 +169,7 @@ jobs: # RMG build step - run: make install - + - name: Make separate No-RMS conda env run: | conda create --name rmg_env_without_rms --clone rmg_env @@ -269,7 +271,7 @@ jobs: REFERENCE: stable_regression_results run: | conda activate rmg_env_without_rms - + exec 2> >(tee -a regression.stderr >&2) 1> >(tee -a regression.stdout) mkdir -p "test/regression-diff" for regr_test in aromatics liquid_oxidation nitrogen oxidation sulfur superminimal RMS_constantVIdealGasReactor_superminimal RMS_CSTR_liquid_oxidation fragment RMS_constantVIdealGasReactor_fragment minimal_surface; diff --git a/Dockerfile b/Dockerfile index 2e462e3475..199c5428a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -77,9 +77,11 @@ RUN make # setting this env variable fixes an issue with Julia precompilation on Windows ENV JULIA_CPU_TARGET="x86-64,haswell,skylake,broadwell,znver1,znver2,znver3,cascadelake,icelake-client,cooperlake,generic" ENV RMS_BRANCH=${RMS_Branch} +ENV RMS_MODE=CI # Usually this is set automatically, but we're not actually running # in an active conda environment when building the Docker so we need to set it manually ENV PYTHON_JULIAPKG_PROJECT="/miniconda/envs/rmg_env/julia_env" +ENV JULIA_PYTHONCALL_EXE="/miniconda/envs/rmg_env/bin/python" RUN source install_rms.sh # RMG-Py should now be installed and ready - trigger precompilation and test run diff --git a/install_rms.sh b/install_rms.sh old mode 100644 new mode 100755 index 9996cc694e..33125cbeea --- a/install_rms.sh +++ b/install_rms.sh @@ -39,16 +39,36 @@ echo "Julia 1.10 binary path: $julia_path" # Get current conda environment name current_env=$(conda info --envs | grep '\*' | awk '{print $1}') -echo "Current conda environment: $current_env" + +# Ask the user to confirm RMS is being installed in the correct +# conda environemnt. Skip if this is run under CI. +if [ "$RMS_MODE" != "CI" ]; then + echo " Please confirm that you want to install RMS into the current conda environment: '$current_env'" + echo " If this is not correct, abort and activate the correct environment before rerunning." + read -p "Proceed with installation in '$current_env'? (y/N): " confirm + case "$confirm" in + [yY][eE][sS]|[yY]) + echo "✅ Proceeding with installation in '$current_env'" + ;; + *) + echo "❌ Aborted. Please activate the correct conda environment and try again." + exit 1 + ;; + esac +else + echo "Current conda environment: $current_env" +fi # Set environment variables for the current environment, for future uses # https://juliapy.github.io/PythonCall.jl/stable/pythoncall/#If-you-already-have-Python-and-required-Python-packages-installed conda env config vars set JULIA_CONDAPKG_BACKEND=Null +conda env config vars set JULIA_CONDAPKG_EXE=$(which conda) conda env config vars set JULIA_PYTHONCALL_EXE=$CONDA_PREFIX/bin/python conda env config vars set PYTHON_JULIAPKG_EXE=$(which julia) conda env config vars set PYTHON_JULIAPKG_PROJECT=$CONDA_PREFIX/julia_env # Also export for current shell/session (needed for Docker/non-interactive use) export JULIA_CONDAPKG_BACKEND=Null +export JULIA_CONDAPKG_EXE="$(which conda)" export JULIA_PYTHONCALL_EXE="$CONDA_PREFIX/bin/python" export PYTHON_JULIAPKG_EXE="$(which julia)" export PYTHON_JULIAPKG_PROJECT="$CONDA_PREFIX/julia_env" @@ -58,11 +78,101 @@ conda install -y conda-forge::pyjuliacall echo "Environment variables referencing JULIA:" env | grep JULIA -# Use RMS_BRANCH environment variable if set, otherwise default to for_rmg +# Defaults to "standard" if no arg provided +RMS_MODE=${1:-standard} + +# Default RMS branch for standard install RMS_BRANCH=${RMS_BRANCH:-for_rmg} -echo "Installing ReactionMechanismSimulator from branch: $RMS_BRANCH" -julia -e "using Pkg; Pkg.add(Pkg.PackageSpec(name=\"ReactionMechanismSimulator\", url=\"https://github.com/ReactionMechanismGenerator/ReactionMechanismSimulator.jl.git\", rev=\"$RMS_BRANCH\")); using ReactionMechanismSimulator; Pkg.instantiate()" || echo "RMS install error - continuing anyway ¯\_(ツ)_/¯" +# Ask for local RMS path +if [ "$RMS_MODE" = "developer" ]; then + echo "Using developer mode for RMS installation" + read -e -p "Please enter full path to your local RMS source code: " RMS_PATH + if [ ! -d "$RMS_PATH" ]; then + echo "ERROR: '$RMS_PATH' is not a valid directory." + exit 1 + fi + echo "Using local RMS path: $RMS_PATH" +fi + +# Initialize the Julia environment from Python using juliacall +python << EOF +import sys +try: + from juliacall import Main + Main.seval('println("Active Julia environment: ", Base.active_project())') + Main.seval('println("Julia load path: ", Base.load_path())') + Main.seval('using Pkg') + Main.seval('Pkg.status()') +except Exception as e: + print("❌ Error while initialize Julia environment:") + print(e) + sys.exit(1) +EOF + +# Install RMS +if [ "$RMS_MODE" = "standard" ] || [ "$RMS_MODE" = "CI" ]; then + echo "Installing RMS from branch: $RMS_BRANCH" + julia << EOF || echo "RMS standard install error - continuing anyway ¯\\_(ツ)_/¯" + using Pkg + Pkg.activate(ENV["PYTHON_JULIAPKG_PROJECT"]) + Pkg.add(Pkg.PackageSpec(name="ReactionMechanismSimulator", url="https://github.com/ReactionMechanismGenerator/ReactionMechanismSimulator.jl.git", rev="$RMS_BRANCH")) + Pkg.instantiate() + try + @info "Loading RMS" + using ReactionMechanismSimulator + @info "RMS loaded successfully!" + catch err + @error "Failed to load RMS" exception=err + Base.show_backtrace(stderr, catch_backtrace()) + exit(1) + end +EOF +elif [ "$RMS_MODE" = "developer" ]; then + echo "Installing RMS in developer mode from path: $RMS_PATH" + julia << EOF || echo "RMS developer install error - continuing anyway ¯\\_(ツ)_/¯" + using Pkg + println(ENV["PYTHON_JULIAPKG_PROJECT"]) + Pkg.activate(ENV["PYTHON_JULIAPKG_PROJECT"]) + Pkg.develop(path="$RMS_PATH") + Pkg.instantiate() + try + @info "Loading RMS" + using ReactionMechanismSimulator + @info "RMS loaded successfully!" + catch err + @error "Failed to load RMS" exception=err + Base.show_backtrace(stderr, catch_backtrace()) + exit(1) + end +EOF +else + echo "Unknown RMS_MODE: $RMS_MODE. Must be either 'CI', 'standard' or 'developer'." + exit 1 +fi + +julia_status=$? +if [ $julia_status -ne 0 ]; then + echo "RMS installation failed!" + exit $julia_status +fi echo "Checking if ReactionMechanismSimulator is installed in the current conda environment for Python usage..." -python -c "from juliacall import Main; import sys; sys.exit(0 if Main.seval('Base.identify_package(\"ReactionMechanismSimulator\") !== nothing') and print('ReactionMechanismSimulator is installed in $current_env') is None else 1)" + +python << EOF +import sys +try: + from juliacall import Main + RMS_Pkg = Main.seval('Base.identify_package("ReactionMechanismSimulator")') + print("Package identify result: ", RMS_Pkg) + if RMS_Pkg is Main.nothing: + print("❌ ReactionMechanismSimulator is NOT installed correctly.") + sys.exit(1) + else: + print("✅ ReactionMechanismSimulator is succesfully installed!") + sys.exit(0) +except Exception as e: + print("❌ Error while checking ReactionMechanismSimulator installation:") + print(e) + sys.exit(1) +EOF