diff --git a/CHANGELOG.md b/CHANGELOG.md index b95352b8..a732259a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- `test_persistent_tasks` now accepts an optional `succeed_on_precompilable_error::Bool=true` to control the behavior on the occurrence of a `PrecompilableError`. ([#285]) + ### Changed - The output of `test_ambiguities` now gets printed to stderr instead of stdout. ([#281]) diff --git a/src/persistent_tasks.jl b/src/persistent_tasks.jl index 7652ce93..73f7828a 100644 --- a/src/persistent_tasks.jl +++ b/src/persistent_tasks.jl @@ -20,6 +20,10 @@ On Julia version 1.9 and before, this test always succeeds. - `tmax::Real = 5`: the maximum time (in seconds) to wait after loading the package before forcibly shutting down the precompilation process (triggering a test failure). +- `succeed_on_precompilable_error::Bool = true`: If true, the test will pass if + the package has a precompilation error. The intended use is to keep your CI + green even if the case that a new release of a dependency introduces a + method overwrite that breaks precompilation of your package. - `expr::Expr = quote end`: An expression to run in the precompile package. !!! note @@ -43,10 +47,23 @@ function test_persistent_tasks(package::Module; kwargs...) test_persistent_tasks(PkgId(package); kwargs...) end -function has_persistent_tasks(package::PkgId; expr::Expr = quote end, tmax = 10) - root_project_path, found = root_project_toml(package) - found || error("Unable to locate Project.toml") - return !precompile_wrapper(root_project_path, tmax, expr) +function has_persistent_tasks( + package::PkgId; + expr::Expr = quote end, + succeed_on_precompilable_error::Bool = true, + tmax = 10, +) + @static if VERSION < v"1.10.0-" + return false + else + if Base.compilecache(package) isa Base.PrecompilableError + @error "Package $(package.name) has a precompilation error" + return !succeed_on_precompilable_error + end + root_project_path, found = root_project_toml(package) + found || error("Unable to locate Project.toml") + return !precompile_wrapper(root_project_path, tmax, expr) + end end """ @@ -75,9 +92,6 @@ function find_persistent_tasks_deps(package::Module; kwargs...) end function precompile_wrapper(project, tmax, expr) - @static if VERSION < v"1.10.0-" - return true - end prev_project = Base.active_project()::String isdefined(Pkg, :respect_sysimage_versions) && Pkg.respect_sysimage_versions(false) try diff --git a/test/pkgs/PersistentTasks/PrecompilableErrorPkg/Project.toml b/test/pkgs/PersistentTasks/PrecompilableErrorPkg/Project.toml new file mode 100644 index 00000000..d9514575 --- /dev/null +++ b/test/pkgs/PersistentTasks/PrecompilableErrorPkg/Project.toml @@ -0,0 +1,2 @@ +name = "PrecompilableErrorPkg" +uuid = "e5c298b6-d81d-47aa-a9ed-5ea983e22986" diff --git a/test/pkgs/PersistentTasks/PrecompilableErrorPkg/src/PrecompilableErrorPkg.jl b/test/pkgs/PersistentTasks/PrecompilableErrorPkg/src/PrecompilableErrorPkg.jl new file mode 100644 index 00000000..7b771663 --- /dev/null +++ b/test/pkgs/PersistentTasks/PrecompilableErrorPkg/src/PrecompilableErrorPkg.jl @@ -0,0 +1,5 @@ +module PrecompilableErrorPkg + +__precompile__(false) + +end # module PrecompilableErrorPkg diff --git a/test/test_persistent_tasks.jl b/test/test_persistent_tasks.jl index 1339f159..15f3b894 100644 --- a/test/test_persistent_tasks.jl +++ b/test/test_persistent_tasks.jl @@ -26,7 +26,6 @@ end result = Aqua.find_persistent_tasks_deps(getid("UsesBoth")) @test result == ["PersistentTask"] end - filter!(str -> !occursin("PersistentTasks", str), LOAD_PATH) end @testset "test_persistent_tasks(expr)" begin @@ -45,4 +44,35 @@ end end end +@testset "test_persistent_tasks(expr)" begin + if Base.VERSION >= v"1.10-" + @test !Aqua.has_persistent_tasks( + getid("TransientTask"), + expr = quote + fetch(Threads.@spawn nothing) + end, + ) + @test Aqua.has_persistent_tasks(getid("TransientTask"), expr = quote + Threads.@spawn while true + sleep(0.5) + end + end) + end +end + +@testset "test_persistent_tasks with precompilable error" begin + if Base.VERSION >= v"1.10-" + println("### Expected output START ###") + @test !Aqua.has_persistent_tasks( + getid("PrecompilableErrorPkg"); + succeed_on_precompilable_error = true, + ) + @test Aqua.has_persistent_tasks( + getid("PrecompilableErrorPkg"); + succeed_on_precompilable_error = false, + ) + println("### Expected output END ###") + end +end + end