From 3edda0ed556b7130182448271cbed949983f04ff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 15:23:19 +0000 Subject: [PATCH 1/9] Initial plan From 415fb600106c1bd1642590de21fecac47d4cd8c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 15:36:31 +0000 Subject: [PATCH 2/9] Add --no-interaction option to package commands Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/package-install.feature | 30 +++++++++++++++++++++ features/package-update.feature | 20 ++++++++++++++ features/package.feature | 19 +++++++++++++ src/Package_Command.php | 46 +++++++++++++++++++++++++++++--- 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/features/package-install.feature b/features/package-install.feature index fe76b4c5..1733dd25 100644 --- a/features/package-install.feature +++ b/features/package-install.feature @@ -1102,3 +1102,33 @@ Feature: Install WP-CLI packages Error: ZipArchive failed to unzip 'package-dir/zero.zip': Not a zip archive (19). """ And STDOUT should be empty + + Scenario: Install a package with --no-interaction flag + Given an empty directory + And a composer.json file: + """ + { + "repositories": { + "test" : { + "type": "path", + "url": "./dummy-package/" + }, + "wp-cli": { + "type": "composer", + "url": "https://wp-cli.org/package-index/" + } + } + } + """ + And a dummy-package/composer.json file: + """ + { + "name": "wp-cli/test-package", + "description": "Test package for no-interaction flag" + } + """ + When I run `WP_CLI_PACKAGES_DIR=. wp package install wp-cli/test-package --no-interaction` + Then STDOUT should contain: + """ + Success: Package installed + """ diff --git a/features/package-update.feature b/features/package-update.feature index c5981277..42d064ee 100644 --- a/features/package-update.feature +++ b/features/package-update.feature @@ -98,3 +98,23 @@ Feature: Update WP-CLI packages """ Success: Packages updated. """ + + Scenario: Update packages with --no-interaction flag + Given an empty directory + + When I run `wp package install danielbachhuber/wp-cli-reset-post-date-command` + Then STDOUT should contain: + """ + Success: Package installed. + """ + + When I run `wp package update --no-interaction` + Then STDOUT should contain: + """ + Using Composer to update packages... + """ + And STDOUT should contain: + """ + Packages updated. + """ + And STDERR should be empty diff --git a/features/package.feature b/features/package.feature index a45218b4..290997c0 100644 --- a/features/package.feature +++ b/features/package.feature @@ -208,3 +208,22 @@ Feature: Manage WP-CLI packages """ {NO_SUCH_PACKAGE_COMPOSER_JSON} """ + + Scenario: Uninstall a package with --no-interaction flag + Given an empty directory + + When I run `wp package install runcommand/hook` + Then STDERR should be empty + + When I run `wp package uninstall runcommand/hook --no-interaction` + Then STDERR should be empty + And STDOUT should contain: + """ + Success: Uninstalled package. + """ + + When I run `wp package list` + Then STDOUT should not contain: + """ + runcommand/hook + """ diff --git a/src/Package_Command.php b/src/Package_Command.php index 9e13c0d6..1081bbcc 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -199,6 +199,9 @@ public function browse( $_, $assoc_args ) { * [--insecure] * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * + * [--no-interaction] + * : Do not ask any interactive questions. Useful for scripting. + * * ## EXAMPLES * * # Install a package hosted at a git URL. @@ -216,7 +219,12 @@ public function browse( $_, $assoc_args ) { public function install( $args, $assoc_args ) { list( $package_name ) = $args; - $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); + $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); + $no_interaction = (bool) Utils\get_flag_value( $assoc_args, 'no-interaction', false ); + + if ( $no_interaction ) { + $this->set_non_interactive_mode(); + } $this->set_composer_auth_env_var(); $git_package = false; @@ -503,6 +511,11 @@ public function path( $args ) { /** * Updates all installed WP-CLI packages to their latest version. * + * ## OPTIONS + * + * [--no-interaction] + * : Do not ask any interactive questions. Useful for scripting. + * * ## EXAMPLES * * $ wp package update @@ -519,7 +532,13 @@ public function path( $args ) { * --- * Success: Packages updated. */ - public function update() { + public function update( $_, $assoc_args = [] ) { + $no_interaction = (bool) Utils\get_flag_value( $assoc_args, 'no-interaction', false ); + + if ( $no_interaction ) { + $this->set_non_interactive_mode(); + } + $this->set_composer_auth_env_var(); $composer = $this->get_composer(); @@ -562,6 +581,9 @@ public function update() { * [--insecure] * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * + * [--no-interaction] + * : Do not ask any interactive questions. Useful for scripting. + * * ## EXAMPLES * * # Uninstall package. @@ -574,7 +596,12 @@ public function update() { public function uninstall( $args, $assoc_args ) { list( $package_name ) = $args; - $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); + $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); + $no_interaction = (bool) Utils\get_flag_value( $assoc_args, 'no-interaction', false ); + + if ( $no_interaction ) { + $this->set_non_interactive_mode(); + } $this->set_composer_auth_env_var(); $package = $this->get_installed_package_by_name( $package_name ); @@ -1478,4 +1505,17 @@ private function get_github_default_branch( $package_name, $insecure = false ) { return $default_branch; } + + /** + * Sets environment variables to enable non-interactive mode. + * + * This prevents Git from prompting for credentials (e.g., SSH passwords), + * which is useful for scripting and automation. + */ + private function set_non_interactive_mode() { + // Prevent Git from prompting for credentials + putenv( 'GIT_TERMINAL_PROMPT=0' ); + // Prevent SSH from prompting for passwords + putenv( 'GIT_SSH_COMMAND=ssh -o BatchMode=yes' ); + } } From f8ca62d9ae4d5390f00af293d743f0fff88c6048 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 15:39:11 +0000 Subject: [PATCH 3/9] Add documentation for update() parameters and putenv() usage Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Package_Command.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Package_Command.php b/src/Package_Command.php index 1081bbcc..72d9dabc 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -531,6 +531,9 @@ public function path( $args ) { * Generating autoload files * --- * Success: Packages updated. + * + * @param array $_ Unused positional arguments (none expected). + * @param array $assoc_args Associative array of options. */ public function update( $_, $assoc_args = [] ) { $no_interaction = (bool) Utils\get_flag_value( $assoc_args, 'no-interaction', false ); @@ -1511,6 +1514,10 @@ private function get_github_default_branch( $package_name, $insecure = false ) { * * This prevents Git from prompting for credentials (e.g., SSH passwords), * which is useful for scripting and automation. + * + * Note: This uses putenv() which affects the entire PHP process, including + * any Git operations spawned by Composer. This is intentional to ensure + * non-interactive behavior propagates to all child processes. */ private function set_non_interactive_mode() { // Prevent Git from prompting for credentials From e68d8d6770fa8a43eefc4d76a9763e8d583e0721 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:14:58 +0000 Subject: [PATCH 4/9] Change flag to 'interaction' with default true, keep --no-interaction in tests Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- src/Package_Command.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index 72d9dabc..3e74231a 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -199,7 +199,7 @@ public function browse( $_, $assoc_args ) { * [--insecure] * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * - * [--no-interaction] + * [--] * : Do not ask any interactive questions. Useful for scripting. * * ## EXAMPLES @@ -219,10 +219,10 @@ public function browse( $_, $assoc_args ) { public function install( $args, $assoc_args ) { list( $package_name ) = $args; - $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); - $no_interaction = (bool) Utils\get_flag_value( $assoc_args, 'no-interaction', false ); + $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); + $interaction = Utils\get_flag_value( $assoc_args, 'interaction', true ); - if ( $no_interaction ) { + if ( ! $interaction ) { $this->set_non_interactive_mode(); } @@ -513,7 +513,7 @@ public function path( $args ) { * * ## OPTIONS * - * [--no-interaction] + * [--] * : Do not ask any interactive questions. Useful for scripting. * * ## EXAMPLES @@ -536,9 +536,9 @@ public function path( $args ) { * @param array $assoc_args Associative array of options. */ public function update( $_, $assoc_args = [] ) { - $no_interaction = (bool) Utils\get_flag_value( $assoc_args, 'no-interaction', false ); + $interaction = Utils\get_flag_value( $assoc_args, 'interaction', true ); - if ( $no_interaction ) { + if ( ! $interaction ) { $this->set_non_interactive_mode(); } @@ -584,7 +584,7 @@ public function update( $_, $assoc_args = [] ) { * [--insecure] * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * - * [--no-interaction] + * [--] * : Do not ask any interactive questions. Useful for scripting. * * ## EXAMPLES @@ -599,10 +599,10 @@ public function update( $_, $assoc_args = [] ) { public function uninstall( $args, $assoc_args ) { list( $package_name ) = $args; - $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); - $no_interaction = (bool) Utils\get_flag_value( $assoc_args, 'no-interaction', false ); + $insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false ); + $interaction = Utils\get_flag_value( $assoc_args, 'interaction', true ); - if ( $no_interaction ) { + if ( ! $interaction ) { $this->set_non_interactive_mode(); } From 60df40bcc52993afffad695f8355448478c3bb47 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sun, 2 Nov 2025 17:43:48 +0100 Subject: [PATCH 5/9] Fix synopsis --- src/Package_Command.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index 3e74231a..294de121 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -199,7 +199,7 @@ public function browse( $_, $assoc_args ) { * [--insecure] * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * - * [--] + * [--interaction] * : Do not ask any interactive questions. Useful for scripting. * * ## EXAMPLES @@ -513,7 +513,7 @@ public function path( $args ) { * * ## OPTIONS * - * [--] + * [--interaction] * : Do not ask any interactive questions. Useful for scripting. * * ## EXAMPLES @@ -584,7 +584,7 @@ public function update( $_, $assoc_args = [] ) { * [--insecure] * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * - * [--] + * [--interaction] * : Do not ask any interactive questions. Useful for scripting. * * ## EXAMPLES From 249e76eb8a7624b90c381fccf18274dba4926d87 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 2 Nov 2025 16:50:30 +0000 Subject: [PATCH 6/9] Fix test to use real package name from package index Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com> --- features/package-install.feature | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/package-install.feature b/features/package-install.feature index 1733dd25..2c1f10c1 100644 --- a/features/package-install.feature +++ b/features/package-install.feature @@ -1123,11 +1123,11 @@ Feature: Install WP-CLI packages And a dummy-package/composer.json file: """ { - "name": "wp-cli/test-package", + "name": "wp-cli/restful", "description": "Test package for no-interaction flag" } """ - When I run `WP_CLI_PACKAGES_DIR=. wp package install wp-cli/test-package --no-interaction` + When I run `WP_CLI_PACKAGES_DIR=. wp package install wp-cli/restful --no-interaction` Then STDOUT should contain: """ Success: Package installed From a6df039f5e87947a084ad477de990aff3b319dee Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 19 Dec 2025 13:26:00 +0100 Subject: [PATCH 7/9] Update src/Package_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Package_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index 294de121..d7f7e64d 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -200,7 +200,7 @@ public function browse( $_, $assoc_args ) { * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * * [--interaction] - * : Do not ask any interactive questions. Useful for scripting. + * : Control interactive mode. Use `--no-interaction` to disable prompts (interactive by default). Useful for scripting. * * ## EXAMPLES * From 27ab93454a04bb5048c3779786156cc1831fdfdc Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 19 Dec 2025 13:26:08 +0100 Subject: [PATCH 8/9] Update src/Package_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Package_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index d7f7e64d..cd364631 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -514,7 +514,7 @@ public function path( $args ) { * ## OPTIONS * * [--interaction] - * : Do not ask any interactive questions. Useful for scripting. + * : Boolean flag that controls interactive mode (enabled by default). Use `--no-interaction` to disable prompts, which is useful for scripting. * * ## EXAMPLES * From 1b8440795968ba770a706df38f215d1015cadb73 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 19 Dec 2025 13:26:15 +0100 Subject: [PATCH 9/9] Update src/Package_Command.php Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Package_Command.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Package_Command.php b/src/Package_Command.php index cd364631..769f902a 100644 --- a/src/Package_Command.php +++ b/src/Package_Command.php @@ -585,7 +585,7 @@ public function update( $_, $assoc_args = [] ) { * : Retry downloads without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack. * * [--interaction] - * : Do not ask any interactive questions. Useful for scripting. + * : Control interactive prompts. Use `--no-interaction` to disable interactive questions (useful for scripting). * * ## EXAMPLES *