Skip to content

Commit cd112c6

Browse files
Fix GitHub authentication I/O issues in autotune setup
- Separate token input from authentication testing to avoid repeated prompts - Implement systematic 3-attempt authentication to handle GitHub.jl warmup issues - Add clear user feedback during connection establishment process - Improve token validation with length checks and better error messages - Handle the "only third auth works" pattern more gracefully - Maintain environment variable state during authentication attempts - Add delays between authentication attempts for better stability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 280f69d commit cd112c6

File tree

1 file changed

+88
-87
lines changed

1 file changed

+88
-87
lines changed

lib/LinearSolveAutotune/src/telemetry.jl

Lines changed: 88 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,13 @@ Returns authentication object if successful, nothing if setup needed.
99
function setup_github_authentication()
1010
# Check if GITHUB_TOKEN environment variable exists
1111
if haskey(ENV, "GITHUB_TOKEN") && !isempty(ENV["GITHUB_TOKEN"])
12-
try
13-
auth = GitHub.authenticate(ENV["GITHUB_TOKEN"])
14-
@info "✅ GitHub authentication successful - ready to share results!"
15-
return auth
16-
catch e
17-
@warn "❌ GITHUB_TOKEN exists but authentication failed: $e"
18-
@info "Please check that your GITHUB_TOKEN is valid and has appropriate permissions"
19-
return nothing
20-
end
12+
return test_github_authentication(ENV["GITHUB_TOKEN"])
2113
end
2214

23-
# No environment variable - provide setup instructions and wait for token
24-
attempts = 0
25-
max_attempts = 3
15+
# No environment variable - provide setup instructions and get token
16+
max_input_attempts = 3
2617

27-
while attempts < max_attempts
18+
for input_attempt in 1:max_input_attempts
2819
println()
2920
println("🚀 Help Improve LinearSolve.jl for Everyone!")
3021
println("="^50)
@@ -41,101 +32,111 @@ function setup_github_authentication()
4132
println(" • Repository access: 'Public Repositories (read-only)'")
4233
println("4️⃣ Click 'Generate token' and copy it")
4334
println()
44-
println("🔑 Paste your GitHub token here (or press Enter to skip):")
35+
println("🔑 Paste your GitHub token here:")
4536
print("Token: ")
46-
flush(stdout) # Ensure the prompt is displayed before reading
37+
flush(stdout)
4738

48-
# Add a small safety delay to ensure prompt is fully displayed
49-
sleep(0.05)
50-
51-
# Read the token input
39+
# Get token input
5240
token = ""
5341
try
42+
sleep(0.1) # Small delay for I/O stability
5443
token = strip(readline())
5544
catch e
5645
println("❌ Input error: $e")
57-
println("🔄 Please try again...")
58-
flush(stdout)
59-
sleep(0.1)
6046
continue
6147
end
6248

6349
if !isempty(token)
64-
# Wrap everything in a protective try-catch to prevent REPL interference
65-
auth_success = false
66-
auth_result = nothing
67-
68-
try
69-
println("🔍 Testing token...")
70-
flush(stdout)
71-
72-
# Clean the token of any potential whitespace/newlines
73-
clean_token = strip(replace(token, r"\s+" => ""))
74-
ENV["GITHUB_TOKEN"] = clean_token
75-
76-
# Test authentication
77-
auth_result = GitHub.authenticate(clean_token)
78-
79-
println("✅ Perfect! Authentication successful - your results will help everyone!")
80-
flush(stdout)
81-
auth_success = true
82-
83-
catch e
84-
println("❌ Token authentication failed: $e")
85-
println("💡 Make sure the token:")
86-
println(" • Has 'public_repo' or 'Public Repositories' access")
87-
println(" • Was copied completely without extra characters")
88-
println(" • Is not expired")
89-
flush(stdout)
90-
91-
# Clean up on failure
92-
if haskey(ENV, "GITHUB_TOKEN")
93-
delete!(ENV, "GITHUB_TOKEN")
94-
end
95-
auth_success = false
50+
# Clean and validate token format
51+
clean_token = strip(replace(token, r"[\r\n\t ]+" => ""))
52+
if length(clean_token) < 10
53+
println("❌ Token seems too short. Please check and try again.")
54+
continue
9655
end
9756

98-
if auth_success && auth_result !== nothing
57+
# Set environment variable
58+
ENV["GITHUB_TOKEN"] = clean_token
59+
60+
# Test authentication with multiple attempts (addressing the "third attempt works" issue)
61+
auth_result = test_github_authentication(clean_token)
62+
if auth_result !== nothing
9963
return auth_result
64+
end
65+
66+
# If all authentication attempts failed, clean up and continue to next input attempt
67+
delete!(ENV, "GITHUB_TOKEN")
68+
end
69+
70+
# Handle skip attempts
71+
if input_attempt < max_input_attempts
72+
println()
73+
println("⏰ This really helps the LinearSolve.jl community!")
74+
println(" Your hardware's benchmark data improves algorithm selection for everyone.")
75+
println("🤝 Please try again - it only takes 30 seconds.")
76+
end
77+
end
78+
79+
println()
80+
println("📊 Continuing without telemetry. Results will be saved locally.")
81+
println("💡 You can set GITHUB_TOKEN environment variable and restart Julia later.")
82+
83+
return nothing
84+
end
85+
86+
"""
87+
test_github_authentication(token::String)
88+
89+
Test GitHub authentication with up to 3 attempts to handle connection warmup issues.
90+
Returns authentication object if successful, nothing otherwise.
91+
"""
92+
function test_github_authentication(token::String)
93+
max_auth_attempts = 3
94+
95+
println("🔍 Testing GitHub authentication...")
96+
println("📏 Token length: $(length(token))")
97+
flush(stdout)
98+
99+
for auth_attempt in 1:max_auth_attempts
100+
try
101+
if auth_attempt == 1
102+
println("🌐 Establishing connection to GitHub API...")
103+
elseif auth_attempt == 2
104+
println("🔄 Retrying connection (sometimes GitHub needs warmup)...")
100105
else
101-
attempts += 1
102-
if attempts < max_attempts
103-
println("🔄 Let's try again...")
104-
flush(stdout)
105-
continue
106-
end
106+
println("🎯 Final authentication attempt...")
107107
end
108-
else
109-
attempts += 1
110-
if attempts < max_attempts
111-
println()
112-
println("⏰ Hold on! This really helps the LinearSolve.jl community.")
113-
println(" Your hardware's benchmark data improves algorithm selection for everyone.")
114-
println(" It only takes 30 seconds and makes LinearSolve.jl better for all users.")
115-
println()
116-
println("🤝 Please help the community - try setting up the token?")
117-
print("Response (y/n): ")
118-
flush(stdout) # Ensure the prompt is displayed before reading
119-
response = strip(lowercase(readline()))
120-
if response == "n" || response == "no"
121-
attempts += 1
122-
if attempts < max_attempts
123-
println("🙏 One more chance - the community really benefits from diverse hardware data!")
124-
continue
125-
end
126-
else
127-
# Reset attempts if they want to try again
128-
attempts = 0
129-
continue
108+
flush(stdout)
109+
110+
# Add delay between attempts to handle timing issues
111+
if auth_attempt > 1
112+
sleep(0.5)
113+
end
114+
115+
# Test authentication
116+
auth_result = GitHub.authenticate(token)
117+
118+
# If we get here, authentication worked
119+
println("✅ Authentication successful - your results will help everyone!")
120+
flush(stdout)
121+
return auth_result
122+
123+
catch e
124+
println("❌ Attempt $auth_attempt failed: $(typeof(e))")
125+
if auth_attempt < max_auth_attempts
126+
println(" Retrying in a moment...")
127+
else
128+
println(" All authentication attempts failed.")
129+
# Show safe preview of token for debugging
130+
if length(token) > 8
131+
token_preview = token[1:4] * "..." * token[end-3:end]
132+
println("🔍 Token preview: $token_preview")
130133
end
134+
println("💡 Please verify your token has 'Issues' read permission and try again.")
131135
end
136+
flush(stdout)
132137
end
133138
end
134139

135-
println()
136-
println("📊 Okay, continuing without telemetry. Results will be saved locally.")
137-
println("💡 You can always run `export GITHUB_TOKEN=your_token` and restart Julia later.")
138-
139140
return nothing
140141
end
141142

0 commit comments

Comments
 (0)