CI integration failed with Gurobi.jl in environment

I have a Julia package in development which has Gurobi.jl in environment as an available solver. Somehow, the github CI integration is against the Gurobi.jl pre-compilation since no license could be found on github action machine. However, the CI process will not use Gurobi for testing, instead HiGHS will be used. Is there a way to keep the Gurobi.jl in environment, while I could skip the license validation?

Here is the trace provided by github action.

Failed to precompile Gurobi [2e9cd046-0924-5485-92f1-d5272153d98b] to "/home/runner/.julia/compiled/v1.11/Gurobi/jl_jh7YaY".
ERROR: LoadError: Gurobi Error 10009: No Gurobi license found (user runner, host fv-az795-534, hostid 3a60c19e, cores 1)
Stacktrace:
  [1] _check_ret
    @ ~/.julia/packages/Gurobi/P8NrB/src/MOI_wrapper/MOI_wrapper.jl:442 [inlined]
  [2] Gurobi.Env(params::Nothing; started::Bool, output_flag::Int64, memory_limit::Nothing)
    @ Gurobi ~/.julia/packages/Gurobi/P8NrB/src/MOI_wrapper/MOI_wrapper.jl:176
  [3] Env (repeats 2 times)
    @ ~/.julia/packages/Gurobi/P8NrB/src/MOI_wrapper/MOI_wrapper.jl:143 [inlined]
  [4] Gurobi.Optimizer(env::Nothing; enable_interrupts::Bool)
    @ Gurobi ~/.julia/packages/Gurobi/P8NrB/src/MOI_wrapper/MOI_wrapper.jl:372
  [5] Optimizer (repeats 2 times)
    @ ~/.julia/packages/Gurobi/P8NrB/src/MOI_wrapper/MOI_wrapper.jl:366 [inlined]
  [6] _instantiate_and_check
    @ ~/.julia/packages/MathOptInterface/zRYzr/src/instantiate.jl:94 [inlined]
  [7] #instantiate#36
    @ ~/.julia/packages/MathOptInterface/zRYzr/src/instantiate.jl:175 [inlined]
  [8] instantiate
    @ ~/.julia/packages/MathOptInterface/zRYzr/src/instantiate.jl:160 [inlined]
  [9] macro expansion
    @ ~/.julia/packages/Gurobi/P8NrB/src/Gurobi.jl:120 [inlined]
 [10] macro expansion
    @ ~/.julia/packages/PrecompileTools/L8A3n/src/workloads.jl:78 [inlined]
 [11] macro expansion
    @ ~/.julia/packages/Gurobi/P8NrB/src/Gurobi.jl:118 [inlined]
 [12] macro expansion
    @ ~/.julia/packages/PrecompileTools/L8A3n/src/workloads.jl:140 [inlined]
 [13] top-level scope
    @ ~/.julia/packages/Gurobi/P8NrB/src/Gurobi.jl:117
 [14] include
    @ ./Base.jl:557 [inlined]
 [15] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt128}}, source::Nothing)
    @ Base ./loading.jl:2881
 [16] top-level scope
    @ stdin:6
in expression starting at /home/runner/.julia/packages/Gurobi/P8NrB/src/Gurobi.jl:7
in expression starting at stdin:6

I have a Julia package in development which has Gurobi.jl in environment as an available solver.

Don’t do this.

Let the user choose which solver to use. There is no need to add it to the Project.toml. Adding solvers to the Project.toml means that every user installs all of the solvers, even if they never end up using them, and it runs into license issues like the one you are experiencing.

2 Likes

Thank you for your helpful insight. I might made this mistake, I added PkgJuMPExt = ["GLPK", "HiGHS", "JuMP"] in project.toml but everything works fine and okay :slight_smile: I have dependency issues when adding SCIP.jl though.

So, we really don’t need to add any solver at all? Currently, I have opt = solver.Optimizer with default solver = HIGHS, and then I call model = Model(opt; add_bridges = false). So, the user can decide which solver to pass as solver.Optimizer? I hope I understood your comment correctly. Thank you for your time and consideration!

See this tutorial, but especially the linked section:

There is rarely a good reason to hard-code the choice of solver for the user. Even if you include a “default” solver like HiGHS, if the user chooses to use a different solver like SCIP or Gurobi, then installing your package will make them download and install HiGHS. Just let them choose, and document how to install some suggested packages.

“GLPK”

Also: can I ask why are you using GLPK?

1 Like

Thank you for your wonderful insights!

My apologies for the oversight! The paper, page 20 that applied the mixed-integer problem formulation used GLPK. Based on your insightful comment here, I now understand that we should use HIGHS instead :slight_smile: Thank you for your help!

1 Like

In my experience, only Gurobi.jl will have the issue problem. I also have Cbc, Clp, Ipopt, GLPK, COPT, and CPLEX solvers configured internally but the solver.Optimizer does not lead to the license issue.

Cbc, Clp, Ipopt, GLPK

These are open source, and do not require a license.

COPT

COPT is an official product of Cardinal. They provide automatic binaries on install.

CPLEX

This should almost certainly result in the same issue as Gurobi. Are you sure it works?

1 Like

But the moral of the story is don’t preselect a fixed set of solvers that you distribute to users. Let them choose. That’s one of the nice things about JuMP.

1 Like

I checked the codes, I do intend to use CPLEX but the license acquirance failed. So CPLEX is out of my scope.

I think I need to weigh the tradeoffs between the flexibility of users choosing solvers and convenience of specifying the solver with settings["Solver"]='Gurobi'. I have implemented the solver choice outside of the package and the CI passed. Much thanks!

Don’t use a string to control the optimizer. Just let the user do:

import Gurobi
settings["Solver"]=Gurobi.Optimizer
1 Like