Skip to content

🎨 Palette: Handle KeyboardInterrupt gracefully and improve prompt guidance#184

Closed
abhimehro wants to merge 5 commits intomainfrom
palette-micro-ux-keyboard-interrupt-18017526019155954203
Closed

🎨 Palette: Handle KeyboardInterrupt gracefully and improve prompt guidance#184
abhimehro wants to merge 5 commits intomainfrom
palette-micro-ux-keyboard-interrupt-18017526019155954203

Conversation

@abhimehro
Copy link
Owner

This PR improves the CLI UX by:

  1. Handling KeyboardInterrupt (Ctrl+C) gracefully during the interactive setup phase and cache warmup, displaying a friendly "Cancelled by user" message instead of a traceback.
  2. Providing a clickable URL in the Profile ID prompt to help users find their ID easily.
  3. Fixing a flaky test (test_print_plan_details_no_colors) that failed when running the full suite due to module reloading side effects.

PR created automatically by Jules for task 18017526019155954203 started by @abhimehro

- Added a `try...except KeyboardInterrupt` block around interactive prompts and cache warmup to prevent ugly tracebacks when users cancel.
- Updated the Profile ID prompt to include the direct URL to the Control D dashboard.
- Fixed `tests/test_plan_details.py` to correctly patch `main.USE_COLORS` when `main` module is reloaded by other tests.

Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
@google-labs-jules
Copy link

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings February 9, 2026 22:51
@trunk-io
Copy link

trunk-io bot commented Feb 9, 2026

🚫 This pull request was closed by @abhimehro, so it was removed from the merge queue. See more details here.

@gemini-code-assist
Copy link

Summary of Changes

Hello @abhimehro, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the command-line interface's user experience by making it more robust to user interruptions and providing clearer guidance during setup. Additionally, it improves the stability of the test suite by addressing a specific flaky test.

Highlights

  • Graceful KeyboardInterrupt Handling: The CLI now gracefully handles KeyboardInterrupt (Ctrl+C) during interactive setup and cache warmup, displaying a "Sync cancelled by user" message instead of a traceback.
  • Improved Profile ID Prompt: The interactive prompt for the Control D Profile ID now includes a direct, clickable URL to the Control D Dashboard profiles page, making it easier for users to find their ID.
  • Flaky Test Fix: A flaky test, test_print_plan_details_no_colors, has been fixed by ensuring the correct main module is referenced during patching, resolving issues caused by module reloading.
Changelog
  • main.py
    • Wrapped the interactive configuration prompts and the warm_up_cache call within a try...except KeyboardInterrupt block to catch Ctrl+C signals.
    • Added a user-friendly cancellation message and exit code (130) upon KeyboardInterrupt.
    • Updated the guidance for finding the Control D Profile ID to include the direct URL https://controld.com/dashboard/profiles.
  • tests/test_plan_details.py
    • Introduced a get_main() helper function to dynamically retrieve the main module from sys.modules, ensuring tests always operate on the correct module instance.
    • Modified test_print_plan_details_no_colors, test_print_plan_details_empty_folders, and test_print_plan_details_with_colors to use patch.object(current_main, ...) instead of patch("main.USE_COLORS", ...), resolving flakiness related to module reloading.
Activity
  • This pull request was automatically created by Jules for task 18017526019155954203, initiated by @abhimehro.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

github-actions bot commented Feb 9, 2026

👋 Development Partner is reviewing this PR. Will provide feedback shortly.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several user experience improvements and a test stability fix. The graceful handling of KeyboardInterrupt during the initial setup and cache warming is a great addition, preventing tracebacks and providing a clear message. The updated prompt for the Profile ID now includes a clickable URL, which is a thoughtful improvement. Additionally, the fix for the flaky test in test_plan_details.py by correctly handling reloaded modules is well-implemented and enhances the reliability of the test suite. The changes are clean, correct, and well-executed.

main.py Outdated
if not profile_ids:
print(f"{Colors.CYAN}ℹ Profile ID is missing.{Colors.ENDC}")
print(
f"{Colors.CYAN} You can find this in the URL of your profile in the Control D Dashboard at https://controld.com/dashboard/profiles (or just paste the URL).{Colors.ENDC}"

Check warning

Code scanning / Prospector (reported by Codacy)

line too long (190 > 159 characters) (E501)

line too long (190 > 159 characters) (E501)
)
exit(1)
if not TOKEN and not args.dry_run:
log.error(

Check warning

Code scanning / Prospector (reported by Codacy)

Consider using sys.exit() (consider-using-sys-exit)

Consider using sys.exit() (consider-using-sys-exit)
main.py Outdated
if not profile_ids:
print(f"{Colors.CYAN}ℹ Profile ID is missing.{Colors.ENDC}")
print(
f"{Colors.CYAN} You can find this in the URL of your profile in the Control D Dashboard at https://controld.com/dashboard/profiles (or just paste the URL).{Colors.ENDC}"

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (190/100)

Line too long (190/100)
print(
f"{Colors.CYAN} You can find this in the URL of your profile in the Control D Dashboard at https://controld.com/dashboard/profiles (or just paste the URL).{Colors.ENDC}"
)

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring

Missing function docstring
validate_profile_id(pid, log_errors=False) for pid in ids
p_input = get_validated_input(
f"{Colors.BOLD}Enter Control D Profile ID:{Colors.ENDC} ",
validate_profile_input,

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (127/100)

Line too long (127/100)
)
if not TOKEN:
print(f"{Colors.CYAN}ℹ API Token is missing.{Colors.ENDC}")
print(

Check warning

Code scanning / Pylint (reported by Codacy)

Line too long (115/100)

Line too long (115/100)
import main

# Helper to get current main module (handles reloading by other tests)
def get_main():

Check warning

Code scanning / Pylint (reported by Codacy)

Missing function docstring

Missing function docstring
main.py Outdated
if not profile_ids:
print(f"{Colors.CYAN}ℹ Profile ID is missing.{Colors.ENDC}")
print(
f"{Colors.CYAN} You can find this in the URL of your profile in the Control D Dashboard at https://controld.com/dashboard/profiles (or just paste the URL).{Colors.ENDC}"

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Line too long (190/100)

Line too long (190/100)
)
exit(1)
if not TOKEN and not args.dry_run:
log.error(

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Consider using sys.exit()

Consider using sys.exit()
import main

# Helper to get current main module (handles reloading by other tests)
def get_main():

Check warning

Code scanning / Pylintpython3 (reported by Codacy)

Missing function or method docstring

Missing function or method docstring
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves CLI user experience by adding graceful Ctrl+C handling during the initial interactive/configuration phase and cache warm-up, improves guidance for locating Profile IDs, and stabilizes a flaky plan-details test in the presence of main module reloads across the test suite.

Changes:

  • Wrap the interactive prompt + warm_up_cache() in a try/except KeyboardInterrupt to print a friendly cancellation message and exit with code 130.
  • Update the Profile ID hint text to include a direct dashboard URL.
  • Update tests/test_plan_details.py to patch USE_COLORS against the currently-loaded main module (via sys.modules) to avoid stale module references.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
main.py Adds early-phase KeyboardInterrupt handling and improves prompt guidance for Profile ID discovery.
tests/test_plan_details.py Adjusts patching/calls to target the active main module instance to reduce flakiness when other tests reload/delete main.

main.py Outdated
Comment on lines +1532 to +1536
except KeyboardInterrupt:
sys.stderr.write(
f"\n{Colors.WARNING}⚠️ Sync cancelled by user.{Colors.ENDC}\n"
)
sys.exit(130)
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new KeyboardInterrupt handling in main() changes observable behavior (message + exit code 130) during interactive prompts and cache warm-up, but it isn't covered by tests. Consider adding a unit test that simulates KeyboardInterrupt from input() / getpass.getpass() or warm_up_cache() and asserts the friendly cancellation message and exit status.

Copilot uses AI. Check for mistakes.
@abhimehro abhimehro enabled auto-merge (squash) February 13, 2026 02:07
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 13, 2026 03:05
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 13, 2026 03:13
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

main.py Outdated
if not profile_ids:
print(f"{Colors.CYAN}ℹ Profile ID is missing.{Colors.ENDC}")
print(
f"{Colors.CYAN} You can find this in the URL of your profile in the Control D Dashboard at https://controld.com/dashboard/profiles (or just paste the URL).{Colors.ENDC}"
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing test test_interactive_prompts_show_hints in test_main.py (line 247-248) should be updated to verify that the new Profile ID dashboard URL is displayed. Currently it only checks for the generic text "You can find this in the URL of your profile" and the Token URL. Consider adding an assertion like assert "https://controld.com/dashboard/profiles" in stdout to ensure the new helpful URL is properly shown to users.

Copilot uses AI. Check for mistakes.
Copilot AI added a commit that referenced this pull request Feb 13, 2026
Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
@abhimehro abhimehro closed this Feb 13, 2026
auto-merge was automatically disabled February 13, 2026 04:04

Pull request was closed

@abhimehro abhimehro deleted the palette-micro-ux-keyboard-interrupt-18017526019155954203 branch February 13, 2026 04:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants