Add support for -y/--yes flag to bypass confirmation prompts - #1544
Add support for -y/--yes flag to bypass confirmation prompts#1544DiegoDAF wants to merge 6 commits into
Conversation
This commit adds support for the -y/--yes option to pgcli, allowing users to bypass destructive command confirmation prompts. This is particularly useful for automated scripts and CI/CD pipelines. Features: - Single flag to skip all destructive confirmations: pgcli -y - Long form: pgcli --yes - Useful for automated environments - Maintains safety by default (flag must be explicitly set) - Does not override transaction requirements When the flag is set: - Destructive commands execute without prompting - Transaction requirements still apply - Error handling remains the same Comprehensive unit tests included to verify: - Flag initialization - Confirmation bypass behavior - Normal confirmation flow without flag Made with ❤️ and 🤖 Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
When using the --yes flag to auto-confirm destructive commands, pgcli should not display the "Your call!" message since no user interaction occurred. This message is now only shown when the user manually confirms the destructive warning prompt. Made with ❤️ and 🤖 Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
| message = "Destructive statements must be run within a transaction. Command execution stopped." | ||
| return [(None, None, None, message)] | ||
| destroy = confirm_destructive_query(query, self.destructive_warning, self.dsn_alias) | ||
| if self.force_destructive: |
There was a problem hiding this comment.
Rather than check self.force_destructive in two places, I'd change the signature of confirm_destructive_query to include it as a parameter.
There was a problem hiding this comment.
Done, confirm_destructive_query takes the flag now and owns the whole decision:
def confirm_destructive_query(queries, keywords, alias, force=False):It returns None when the query is not destructive, True when force is set, None when there is no tty, and otherwise prompts as before. Both call sites in main.py just pass self.force_destructive through.
One self.force_destructive check is left in main.py, but it is a different concern: it suppresses the Your call! message, which would otherwise be printed on every destructive statement in a script that never asked anything. Happy to move that too if you would rather have it inside the helper.
Ready for another look whenever you have time.
Address review feedback: instead of checking self.force_destructive at both call sites, confirm_destructive_query now takes a `force` parameter and owns the whole 'should we proceed?' decision. Behaviour is unchanged: non-destructive returns None, force returns True, a non-tty stdin returns None (no prompt), otherwise the user is prompted. The parameter defaults to False, so existing callers are unaffected.
# Conflicts: # pgcli/main.py
Port of the review feedback on upstream PR dbcli#1544. Instead of checking self.force_destructive at both call sites (execute_from_file and execute_command), confirm_destructive_query now takes a `force` parameter and owns the whole "should we proceed?" decision: non-destructive -> None force -> True non-tty stdin -> None (no prompt) otherwise -> prompt the user Behaviour is unchanged. The parameter defaults to False, so existing callers are unaffected. The only remaining self.force_destructive reference is the guard that suppresses the "Your call!" message, which is about output, not the proceed/abort decision. Also closes roadmap item dbcli#4 (Conexiones) in todo.md as redundant: post-connect SQL and .pg_service.conf already exist, keepalives/connect_timeout already work via the connection string, and SSL ~ expansion has no practical need. No version bump (held at 4.5.7 per Diego).
test_force_destructive_skips_confirmation asserted that confirm_destructive_query was never called with -y. Now that the helper takes the force parameter it IS called and decides internally not to prompt, so the old assertion encoded the previous structure rather than the behaviour. It now patches prompt_utils.confirm and asserts the user is never prompted, which is the actual guarantee -y makes.
# Conflicts: # tests/test_main.py
The "edit sql in file with external editor" scenario errors intermittently on slow CI runners: pexpect's expect_exact waited only 2 seconds for the ex-mode banner. It has bitten upstream's CI repeatedly (PRs dbcli#1543/dbcli#1544/dbcli#1609) and now our fork's CI on main (cee716d run: unit 3139 passed, 61 scenarios passed, the only error was this scenario on 3.10 while 3.11 was fully green). All expect timeouts in iocommands.py bumped to 10s. Passing runs are not slowed: pexpect returns as soon as the expected text appears; the timeout only bounds how long a FAILING wait lasts. Verified locally: behave features/iocommands.feature green against a throwaway PG (2 scenarios, 12 steps). Same patch offered to upstream in the dbcli#1543 review thread.
Summary
This PR adds support for the
-y/--yesoption to pgcli, allowing users to bypass destructive command confirmation prompts. This is particularly useful for automated scripts and CI/CD pipelines.Features
pgcli -yorpgcli --yes-yUse Cases
Implementation Details
force_destructiveparameter to PGCli classexecute_command()method for programmatic executionrun_cli()-yis set,confirm_destructive_query()is bypassed-y(no user interaction occurred)Testing
Comprehensive unit tests included:
Safety Considerations
Made with ❤️ and 🤖 Claude Code
Part of the feature list in discussion #1603: this is item 9 (
-y/--yes).