Skip to content

Commit 07a52a8

Browse files
abossardCopilot
andcommitted
Improve GitHub device flow terminal output with clear banner and progress
- Suppress httpx INFO logs during device flow to avoid drowning the message - Display a box-drawn banner with numbered steps (URL + user code) - Show polling progress indicator so terminal doesn't appear frozen - Print success confirmation on authentication - Respect server's poll interval and increase timeout to 2 minutes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2f1508a commit 07a52a8

1 file changed

Lines changed: 30 additions & 8 deletions

File tree

backend/copilot_auth.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,22 @@ def _get_access_token(self) -> str:
106106

107107
def _run_device_flow(self) -> str:
108108
"""Run GitHub OAuth device-code flow. Prompts user to authenticate."""
109+
# Suppress noisy httpx INFO logs during device flow polling
110+
httpx_logger = logging.getLogger("httpx")
111+
prev_level = httpx_logger.level
112+
httpx_logger.setLevel(logging.WARNING)
113+
114+
try:
115+
return self._do_device_flow()
116+
finally:
117+
httpx_logger.setLevel(prev_level)
118+
119+
def _do_device_flow(self) -> str:
120+
"""Internal: run the device-code flow with clear terminal output."""
121+
max_polls = 24
122+
poll_interval = 5
123+
109124
with httpx.Client(timeout=30) as client:
110-
# Request device code
111125
resp = client.post(
112126
_GITHUB_DEVICE_CODE_URL,
113127
headers=self._github_headers(),
@@ -119,17 +133,25 @@ def _run_device_flow(self) -> str:
119133
device_code = data["device_code"]
120134
user_code = data["user_code"]
121135
verification_uri = data["verification_uri"]
136+
poll_interval = data.get("interval", poll_interval)
122137

123138
print( # noqa: T201
124-
f"\n🔑 GitHub Copilot authentication required.\n"
125-
f" Visit: {verification_uri}\n"
126-
f" Enter code: {user_code}\n",
139+
"\n"
140+
"╔══════════════════════════════════════════════════╗\n"
141+
"║ 🔑 GitHub Copilot Authentication ║\n"
142+
"╠══════════════════════════════════════════════════╣\n"
143+
f"║ 1. Open: {verification_uri:<37s}\n"
144+
f"║ 2. Enter: {user_code:<37s}\n"
145+
"╚══════════════════════════════════════════════════╝",
127146
flush=True,
128147
)
129148

130-
# Poll for access token (up to 60s)
131-
for _ in range(12):
132-
time.sleep(5)
149+
for attempt in range(1, max_polls + 1):
150+
time.sleep(poll_interval)
151+
print( # noqa: T201
152+
f" ⏳ Waiting for authentication… ({attempt}/{max_polls})",
153+
flush=True,
154+
)
133155
poll_resp = client.post(
134156
_GITHUB_ACCESS_TOKEN_URL,
135157
headers=self._github_headers(),
@@ -145,7 +167,7 @@ def _run_device_flow(self) -> str:
145167
if "access_token" in poll_data:
146168
token = poll_data["access_token"]
147169
self._write_file(self._access_token_path, token)
148-
logger.info("GitHub Copilot authentication successful")
170+
print(" ✅ Authentication successful!\n", flush=True) # noqa: T201
149171
return token
150172

151173
if poll_data.get("error") != "authorization_pending":

0 commit comments

Comments
 (0)