diff --git a/lib/LinearSolveAutotune/Project.toml b/lib/LinearSolveAutotune/Project.toml index 6726a26cc..fa771b59d 100644 --- a/lib/LinearSolveAutotune/Project.toml +++ b/lib/LinearSolveAutotune/Project.toml @@ -10,6 +10,7 @@ Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" CPUSummary = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" GitHub = "bc5e4493-9b4d-5f90-b8aa-2b2bcaad7a26" +gh_cli_jll = "5d31d589-30fb-542f-b82d-10325e863e38" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" Preferences = "21216c6a-2e73-6563-6e65-726566657250" @@ -33,6 +34,7 @@ Base64 = "1" CPUSummary = "0.2" DataFrames = "1" GitHub = "5" +gh_cli_jll = "2" Plots = "1" PrettyTables = "2" Preferences = "1" diff --git a/lib/LinearSolveAutotune/src/LinearSolveAutotune.jl b/lib/LinearSolveAutotune/src/LinearSolveAutotune.jl index cf4810a84..85140f0fa 100644 --- a/lib/LinearSolveAutotune/src/LinearSolveAutotune.jl +++ b/lib/LinearSolveAutotune/src/LinearSolveAutotune.jl @@ -24,6 +24,7 @@ using Metal # Optional dependencies for telemetry and plotting using GitHub +using gh_cli_jll using Plots export autotune_setup, share_results, AutotuneResults, plot diff --git a/lib/LinearSolveAutotune/src/telemetry.jl b/lib/LinearSolveAutotune/src/telemetry.jl index 64d8f94b0..b49385e0c 100644 --- a/lib/LinearSolveAutotune/src/telemetry.jl +++ b/lib/LinearSolveAutotune/src/telemetry.jl @@ -1,5 +1,21 @@ # Telemetry functionality for sharing benchmark results +""" + get_gh_command() + +Get the gh command, preferring the system-installed version if available, +falling back to the JLL-provided version. +""" +function get_gh_command() + # First check if gh is installed on the system + if !isnothing(Sys.which("gh")) + return `gh` + else + # Use the JLL-provided gh + return `$(gh_cli_jll.gh())` + end +end + """ setup_github_authentication() @@ -7,21 +23,20 @@ Set up GitHub authentication for telemetry uploads. Returns an authentication method indicator if successful, nothing if setup fails. """ function setup_github_authentication() - # 1. Check for `gh` CLI - if !isnothing(Sys.which("gh")) - try - # Suppress output of gh auth status check - if success(pipeline(`gh auth status`; stdout=devnull, stderr=devnull)) - # Check if logged in to github.com - auth_status_output = read(`gh auth status`, String) - if contains(auth_status_output, "Logged in to github.com") - println("✅ Found active `gh` CLI session. Will use it for upload.") - return (:gh_cli, "GitHub CLI") - end + # 1. Check for `gh` CLI (system or JLL) + try + gh_cmd = get_gh_command() + # Suppress output of gh auth status check + if success(pipeline(`$gh_cmd auth status`; stdout=devnull, stderr=devnull)) + # Check if logged in to github.com + auth_status_output = read(`$gh_cmd auth status`, String) + if contains(auth_status_output, "Logged in to github.com") + println("✅ Found active `gh` CLI session. Will use it for upload.") + return (:gh_cli, "GitHub CLI") end - catch e - @debug "gh CLI check failed: $e" end + catch e + @debug "gh CLI check failed: $e" end # 2. Check for GITHUB_TOKEN environment variable @@ -532,6 +547,7 @@ function upload_plots_to_gist_gh(plot_files::Union{Nothing, Tuple, Dict}, eltype end try + gh_cmd = get_gh_command() # Handle different plot_files formats files_to_upload = if isa(plot_files, Tuple) # Legacy format: (png_file, pdf_file) @@ -585,7 +601,7 @@ The PNG images can be viewed directly in the browser. Click on any `.png` file a # Create initial gist with README out = Pipe() err = Pipe() - run(pipeline(`gh gist create -d $gist_desc -p $readme_file`, stdout=out, stderr=err)) + run(pipeline(`$gh_cmd gist create -d $gist_desc -p $readme_file`, stdout=out, stderr=err)) close(out.in) close(err.in) @@ -603,7 +619,7 @@ The PNG images can be viewed directly in the browser. Click on any `.png` file a temp_dir = mktempdir() try # Clone the gist - run(`gh gist clone $gist_id $temp_dir`) + run(`$gh_cmd gist clone $gist_id $temp_dir`) # Copy all plot files to the gist directory for (name, filepath) in existing_files @@ -622,7 +638,7 @@ The PNG images can be viewed directly in the browser. Click on any `.png` file a # Get username for constructing raw URLs username_out = Pipe() - run(pipeline(`gh api user --jq .login`, stdout=username_out)) + run(pipeline(`$gh_cmd api user --jq .login`, stdout=username_out)) close(username_out.in) username = strip(read(username_out, String)) @@ -673,13 +689,14 @@ function comment_on_issue_gh(target_repo, issue_number, body) err_str = "" out_str = "" try + gh_cmd = get_gh_command() # Use a temporary file for the body to avoid command line length limits mktemp() do path, io write(io, body) flush(io) # Construct and run the gh command - cmd = `gh issue comment $issue_number --repo $target_repo --body-file $path` + cmd = `$gh_cmd issue comment $issue_number --repo $target_repo --body-file $path` out = Pipe() err = Pipe() @@ -725,13 +742,14 @@ function create_benchmark_issue_gh(target_repo, title, body) err_str = "" out_str = "" try + gh_cmd = get_gh_command() # Use a temporary file for the body to avoid command line length limits mktemp() do path, io write(io, body) flush(io) # Construct and run the gh command - cmd = `gh issue create --repo $target_repo --title $title --body-file $path --label benchmark-data` + cmd = `$gh_cmd issue create --repo $target_repo --title $title --body-file $path --label benchmark-data` out = Pipe() err = Pipe() diff --git a/lib/LinearSolveAutotune/test/test_gh_fallback.jl b/lib/LinearSolveAutotune/test/test_gh_fallback.jl new file mode 100644 index 000000000..11f6339b1 --- /dev/null +++ b/lib/LinearSolveAutotune/test/test_gh_fallback.jl @@ -0,0 +1,41 @@ +using Test +using LinearSolveAutotune +using gh_cli_jll + +@testset "gh CLI fallback tests" begin + # Test get_gh_command function + @testset "get_gh_command" begin + gh_cmd = LinearSolveAutotune.get_gh_command() + @test gh_cmd isa Cmd + + # Test that the command can be executed + @test_nowarn begin + version = read(`$gh_cmd version`, String) + @test !isempty(version) + @test occursin("gh version", version) + end + end + + # Test JLL-provided gh directly + @testset "JLL gh" begin + jll_gh_cmd = `$(gh_cli_jll.gh())` + @test jll_gh_cmd isa Cmd + + # Test that JLL gh works + @test_nowarn begin + version = read(`$jll_gh_cmd version`, String) + @test !isempty(version) + @test occursin("gh version", version) + end + end + + # Test authentication setup (may fail if not authenticated) + @testset "Authentication setup" begin + auth_result = LinearSolveAutotune.setup_github_authentication() + @test auth_result isa Tuple + @test length(auth_result) == 2 + # We don't require authentication to succeed, just that the function works + end +end + +println("✅ All gh fallback tests passed!") \ No newline at end of file