Skip to content

Created the site:remove-atlantis-legacy-modules command#103

Open
bernattorras wants to merge 6 commits intotrunkfrom
add/command/atlantis-remove-legacy-modules
Open

Created the site:remove-atlantis-legacy-modules command#103
bernattorras wants to merge 6 commits intotrunkfrom
add/command/atlantis-remove-legacy-modules

Conversation

@bernattorras
Copy link
Copy Markdown
Contributor

@bernattorras bernattorras commented Nov 6, 2025

This is a temporary command designed to bulk remove the legacy modules replaced by Atlantis (Colophon and the Plugin Autoupdate Filter) automatically.

I'm still testing it, so adjustments may be added.

Summary by CodeRabbit

  • New Features
    • Adds a CLI tool to remove legacy Atlantis modules from WordPress sites, supporting single-site and CSV batch workflows.
    • Supports interactive and non-interactive modes with host/site/branch selection, CSV validation, per-site logs, and a final processing summary.
    • Automates repository updates and pull request creation (optional auto-merge and branch cleanup), can install/uninstall related plugins, and safely cleans up local working copies.

This is a temporary command designed to bulk remove the legacy modules replaced by Atlantis (Colophon and the Plugin Autoupdate Filter) automatically.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Nov 6, 2025

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new Symfony CLI command class Site_Remove_Atlantis_Legacy_Modules (file: commands/Site_Remove_Atlantis_Legacy_Modules.php). The command supports single-site and CSV bulk modes, interactive prompts (quiet mode and autocomplete), environment detection for base-branch selection, repository cloning and branch remove/atlantis-legacy-modules, detection and removal of Atlantis legacy mu-plugins/plugins, installation/activation of the Atlantis plugin, optional WordPress plugin uninstalls, PR creation with optional auto-merge and branch deletion, per-row CSV updates, autoupdate-filter checks, safe local cleanup, and lifecycle hooks configure, initialize, interact, and execute.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: creating a new CLI command for removing Atlantis legacy modules.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22f03b5 and fcbdfcd.

📒 Files selected for processing (1)
  • commands/Site_Remove_Atlantis_Legacy_Modules.php (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: ahegyes
Repo: a8cteam51/team51-cli PR: 97
File: commands/WPCOM_Site_WP_User_Delete.php:180-199
Timestamp: 2025-08-06T12:00:14.638Z
Learning: In the WPCOM_Site_WP_User_Delete command, when no administrators are found on a site, the process intentionally exits entirely rather than skipping that site, as this is considered an anomaly that should be investigated before attempting the deletion operation again.
🧬 Code graph analysis (1)
commands/Site_Remove_Atlantis_Legacy_Modules.php (4)
includes/functions.php (4)
  • get_enum_input (318-330)
  • run_system_command (233-249)
  • validate_user_choice (459-465)
  • get_string_input (298-305)
includes/functions-pressable.php (3)
  • get_pressable_site (104-108)
  • get_pressable_site_deployhq_config (168-180)
  • run_pressable_site_wp_cli_command (612-623)
includes/functions-wpcom.php (3)
  • get_wpcom_site (69-71)
  • get_wpcom_site_code_deployments (582-584)
  • run_wpcom_site_wp_cli_command (631-642)
includes/functions-github.php (3)
  • get_github_repository_from_deployhq_project (245-257)
  • get_github_repository_branches (82-84)
  • get_github_repository (32-34)

Comment on lines +731 to +738
if ( ! file_exists( $this->repo_dir ) ) {
mkdir( $this->repo_dir, 0755, true );
$this->write_output( $output, "<info>Created folder: {$this->repo_dir}</info>" );

// Clone the repository.
\run_system_command( array( 'git', 'clone', $this->gh_repository->clone_url, $this->repo_dir ) );
$this->write_output( $output, "<info>Cloned repository: {$this->gh_repository->name} ({$this->gh_repository->clone_url}) into {$this->repo_dir}</info>" );
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix the clone path to avoid immediate failure.

We create $this->repo_dir before invoking git clone, but git clone refuses to run when the destination already exists (even if empty), so the first call throws a ProcessFailedException and the command aborts. Let Git create the directory instead.

 		// Create a folder named the repository name in the repos folder if it doesn't exist.
 		if ( ! file_exists( $this->repo_dir ) ) {
-			mkdir( $this->repo_dir, 0755, true );
-			$this->write_output( $output, "<info>Created folder: {$this->repo_dir}</info>" );
-
-			// Clone the repository.
-			\run_system_command( array( 'git', 'clone', $this->gh_repository->clone_url, $this->repo_dir ) );
+			// Clone the repository (git will create the target directory for us).
+			\run_system_command(
+				array( 'git', 'clone', $this->gh_repository->clone_url, $this->repo_dir ),
+				$this->repos_dir
+			);
 			$this->write_output( $output, "<info>Cloned repository: {$this->gh_repository->name} ({$this->gh_repository->clone_url}) into {$this->repo_dir}</info>" );
 		}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
commands/Site_Remove_Atlantis_Legacy_Modules.php lines 731-738: the code
currently creates $this->repo_dir before running git clone which causes git to
fail because the destination must not pre-exist; instead, ensure the clone's
parent directory exists (mkdir dirname($this->repo_dir), 0755, true) but do not
create $this->repo_dir itself, remove the "Created folder" message for
$this->repo_dir, then run
run_system_command(['git','clone',$this->gh_repository->clone_url,$this->repo_dir])
and keep the "Cloned repository" output after the clone succeeds.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@commands/Site_Remove_Atlantis_Legacy_Modules.php`:
- Around line 328-360: The progress messages use the CSV row index ($index)
instead of a sequential site counter, so create a separate counter (e.g.
$site_count) initialized before the foreach over $csv_data and increment it at
the start of each iteration, then replace uses of $index in the output->writeln
calls (and in update_csv_row note messages if they should reflect sequential
position) with the new $site_count variable; update all occurrences inside the
loop (the Processing, Skipping, and Already processed messages around the
foreach handling) and keep $index for CSV-key lookups and update_csv_row calls
that rely on the original CSV row index.
- Around line 485-500: The condition is using the hardcoded
$this->legacy_modules (always >0); change the check to use the runtime-detected
list (e.g. $found_modules or $this->removed_modules) so the prompt only appears
when plugins were actually found, and pass that specific list to
uninstall_plugins_from_wordpress; update the $plugins_list construction and the
ConfirmationQuestion to use the chosen runtime array (and ensure
uninstall_plugins_from_wordpress accepts/receives that array instead of relying
on $this->legacy_modules).
🧹 Nitpick comments (3)
commands/Site_Remove_Atlantis_Legacy_Modules.php (3)

765-773: Redundant empty check and unsafe continuation path.

The get_wpcom_repository() method is only called from initialize_repository() at line 624, after the empty repositories check at line 607. The check at line 765 is therefore redundant. Additionally, if somehow reached with empty repositories and the user continues, $this->gh_repository remains null.

Consider removing this redundant check since the caller already handles the empty case:

♻️ Suggested refactor
 	private function get_wpcom_repository( InputInterface $input, OutputInterface $output ): void {
 		$wpcom_gh_repositories = get_wpcom_site_code_deployments( $this->site->ID );
 		$gh_repository_name    = null;

-		if ( empty( $wpcom_gh_repositories ) ) {
-			$output->writeln( '<error>Unable to find a WPCOM GitHub Deployments for the site.</error>' );
-
-			$question = new ConfirmationQuestion( '<question>Do you want to continue anyway? [y/N]</question> ', false );
-			if ( true !== $this->getHelper( 'question' )->ask( $input, $output, $question ) ) {
-				$output->writeln( '<comment>Command aborted by user.</comment>' );
-				exit( 1 );
-			}
-		}
-
-		if ( $wpcom_gh_repositories && 1 < count( $wpcom_gh_repositories ) ) {
+		if ( 1 < count( $wpcom_gh_repositories ) ) {

1062-1063: Consider making the Atlantis plugin version configurable.

The plugin URL contains a hardcoded version (v1.0.2). If this command lives beyond its temporary purpose, consider extracting this to a constant or configuration option for easier updates.


1107-1131: Uninstalls all legacy modules regardless of what was found.

uninstall_plugins_from_wordpress() uses $this->legacy_modules to build the plugin list, which attempts to uninstall both legacy plugins even if only one (or neither) was found in the repository. This is related to the issue at line 486.

♻️ Consider passing the found plugins explicitly
-	private function uninstall_plugins_from_wordpress( OutputInterface $output ): void {
+	private function uninstall_plugins_from_wordpress( OutputInterface $output, array $plugins_to_uninstall = null ): void {
 		$site_identifier = 'atomic' === $this->host ? $this->site->ID : $this->site->id;
-		$plugins_list    = implode( ' ', $this->legacy_modules );
+		$plugins_to_uninstall = $plugins_to_uninstall ?? $this->legacy_modules;
+		$plugins_list    = implode( ' ', $plugins_to_uninstall );

Then call it with the specific plugins found:

$this->uninstall_plugins_from_wordpress( $output, array_keys( $found_modules ) );

Comment on lines +485 to +500
// Uninstall plugins from WordPress if --uninstall option is provided.
if ( $this->uninstall_plugins && count( $this->legacy_modules ) > 0 ) {
// In quiet mode, automatically uninstall plugins.
if ( $this->quiet ) {
$this->uninstall_plugins_from_wordpress( $output );
} else {
$output->writeln( '' );
$plugins_list = implode( ', ', $this->legacy_modules );
$question = new ConfirmationQuestion( "<question>Do you want to deactivate and uninstall these plugins from WordPress ({$plugins_list})? [y/N]</question> ", false );
if ( true === $this->getHelper( 'question' )->ask( $input, $output, $question ) ) {
$this->uninstall_plugins_from_wordpress( $output );
} else {
$output->writeln( '<comment>Skipping WordPress plugin uninstallation.</comment>' );
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Condition count( $this->legacy_modules ) > 0 is always true.

$this->legacy_modules is a hardcoded array with 2 elements, so this condition is always satisfied. The intent seems to be uninstalling plugins that were actually found on the site. Consider using $found_modules or $this->removed_modules instead.

💡 Suggested fix
 		// Uninstall plugins from WordPress if --uninstall option is provided.
-		if ( $this->uninstall_plugins && count( $this->legacy_modules ) > 0 ) {
+		if ( $this->uninstall_plugins && ! empty( $found_modules ) ) {
 			// In quiet mode, automatically uninstall plugins.
 			if ( $this->quiet ) {
 				$this->uninstall_plugins_from_wordpress( $output );

You may also want to pass the specific plugins to uninstall rather than using the full $this->legacy_modules list:

-		$plugins_list = implode( ', ', $this->legacy_modules );
+		$plugins_list = implode( ', ', array_keys( $found_modules ) );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Uninstall plugins from WordPress if --uninstall option is provided.
if ( $this->uninstall_plugins && count( $this->legacy_modules ) > 0 ) {
// In quiet mode, automatically uninstall plugins.
if ( $this->quiet ) {
$this->uninstall_plugins_from_wordpress( $output );
} else {
$output->writeln( '' );
$plugins_list = implode( ', ', $this->legacy_modules );
$question = new ConfirmationQuestion( "<question>Do you want to deactivate and uninstall these plugins from WordPress ({$plugins_list})? [y/N]</question> ", false );
if ( true === $this->getHelper( 'question' )->ask( $input, $output, $question ) ) {
$this->uninstall_plugins_from_wordpress( $output );
} else {
$output->writeln( '<comment>Skipping WordPress plugin uninstallation.</comment>' );
}
}
}
// Uninstall plugins from WordPress if --uninstall option is provided.
if ( $this->uninstall_plugins && ! empty( $found_modules ) ) {
// In quiet mode, automatically uninstall plugins.
if ( $this->quiet ) {
$this->uninstall_plugins_from_wordpress( $output );
} else {
$output->writeln( '' );
$plugins_list = implode( ', ', array_keys( $found_modules ) );
$question = new ConfirmationQuestion( "<question>Do you want to deactivate and uninstall these plugins from WordPress ({$plugins_list})? [y/N]</question> ", false );
if ( true === $this->getHelper( 'question' )->ask( $input, $output, $question ) ) {
$this->uninstall_plugins_from_wordpress( $output );
} else {
$output->writeln( '<comment>Skipping WordPress plugin uninstallation.</comment>' );
}
}
}
🤖 Prompt for AI Agents
In `@commands/Site_Remove_Atlantis_Legacy_Modules.php` around lines 485 - 500, The
condition is using the hardcoded $this->legacy_modules (always >0); change the
check to use the runtime-detected list (e.g. $found_modules or
$this->removed_modules) so the prompt only appears when plugins were actually
found, and pass that specific list to uninstall_plugins_from_wordpress; update
the $plugins_list construction and the ConfirmationQuestion to use the chosen
runtime array (and ensure uninstall_plugins_from_wordpress accepts/receives that
array instead of relying on $this->legacy_modules).

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@commands/Site_Remove_Atlantis_Legacy_Modules.php`:
- Around line 1124-1139: The code is passing the integer exit code returned by
run_pressable_site_wp_cli_command/run_wpcom_site_wp_cli_command into
json_decode; instead check the exit code stored in $result, return with
$this->write_output(...) if $result !== 0, then read the actual WP-CLI output
from $GLOBALS['wp_cli_output'] and pass that to json_decode; keep the existing
validation that json_decode($GLOBALS['wp_cli_output'], true) yields an array and
emit the same "Could not parse plugin list." message and return if it does not.
🧹 Nitpick comments (2)
commands/Site_Remove_Atlantis_Legacy_Modules.php (2)

765-777: Redundant API call for WPCOM code deployments.

get_wpcom_site_code_deployments() is already called at line 609 in initialize_repository() before calling this method. Calling it again here at line 766 is redundant.

♻️ Suggested optimization

Pass the already-fetched repositories as a parameter:

-	private function get_wpcom_repository( InputInterface $input, OutputInterface $output ): void {
-		$wpcom_gh_repositories = get_wpcom_site_code_deployments( $this->site->ID );
+	private function get_wpcom_repository( InputInterface $input, OutputInterface $output, array $wpcom_gh_repositories ): void {

Then update the call site at line 628:

-			$this->get_wpcom_repository( $input, $output );
+			$this->get_wpcom_repository( $input, $output, $wpcom_gh_repositories );

1195-1219: uninstall_plugins_from_wordpress always tries to uninstall all legacy modules.

This method uses $this->legacy_modules (line 1197) which includes all hardcoded legacy plugins, regardless of which were actually found on the site. This is related to the earlier issue at lines 489-504.

Consider passing the list of found plugins as a parameter to avoid attempting to uninstall plugins that don't exist on the site (though WP-CLI handles this gracefully with warnings).

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@commands/Site_Remove_Atlantis_Legacy_Modules.php`:
- Around line 430-436: The deployment error handling references an undefined
variable $site_host causing a warning; update the code in the error handling
block that computes $is_deployment_error and sets $deployment_type/$note to use
$this->host (or the appropriate property on the current class) instead of
$site_host so the check and message use the defined host value (replace all
occurrences of $site_host in that block with $this->host, e.g., where
$is_deployment_error is determined and when assigning $deployment_type).

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@commands/Site_Remove_Atlantis_Legacy_Modules.php`:
- Around line 454-466: When running in quiet/automation mode ($this->quiet),
avoid creating a ChoiceQuestion and prompting; instead default to a safe
non-interactive choice (e.g., set $deployment_choice = 'skip') and skip calling
$this->getHelper('question')->ask. Locate the block that builds the $choices
array and creates the ChoiceQuestion (uses ChoiceQuestion and
$deployment_choice) and add a conditional: if ($this->quiet) assign the default
string ('skip') to $deployment_choice and only construct/ask the ChoiceQuestion
when not quiet.
- Around line 1440-1459: In uninstall_plugins_from_wordpress, capture the
integer return value from run_pressable_site_wp_cli_command or
run_wpcom_site_wp_cli_command (depending on host) instead of ignoring it, then
check if it equals 0 before printing the success message; if non-zero, write an
error via $this->write_output (including the exit code and the original $command
for context) and throw or return to avoid reporting success erroneously. Ensure
you reference the $command variable and use the same write_output pattern
currently used for success/failure messages.

---

Duplicate comments:
In `@commands/Site_Remove_Atlantis_Legacy_Modules.php`:
- Around line 956-969: In clone_repo, stop pre-creating the destination folder
($this->repo_dir) before calling \run_system_command('git clone ...') because
git fails if the target directory already exists; instead only ensure the parent
repos folder ($this->repos_dir) exists, remove the mkdir of $this->repo_dir,
call
\run_system_command(array('git','clone',$this->gh_repository->clone_url,$this->repo_dir))
to let git create the directory, and move the success write_output for the clone
to after the command succeeds; also add a guard to detect if $this->repo_dir
already exists and fail with a clear message (or skip) before attempting clone.
- Around line 774-788: The early-return when $wpcom_gh_repositories is empty
leaves $this->gh_repository null and later dereferences
$this->gh_repository->name; instead of returning after the interactive
confirmation, abort the command consistently (throw an exception or exit with
non-zero status) so execution cannot continue with a null $this->gh_repository;
update the block that currently does "return;" (after the
ConfirmationQuestion/exit(1) path) to throw new \Exception('No WPCOM GitHub
repository available') or call exit(1) so downstream references to
$this->gh_repository->name are never reached.

Comment on lines +454 to +466
$deployment_type = ( 'pressable' === $host ) ? 'DeployHQ' : 'WPCOM GitHub';
$output->writeln( "<comment>⚠ {$site_name}: Unable to find a {$deployment_type} deployment for the site.</comment>" );

// Present the user with choices for how to proceed.
$choices = array(
'enter_repo' => 'Enter a repository URL or slug manually',
'site_only' => 'Skip repository, process site only (install Atlantis, handle plugins)',
'skip' => 'Skip this site entirely',
);

$question = new ChoiceQuestion( '<question>How would you like to proceed?</question> ', $choices, 'skip' );
$deployment_choice = $this->getHelper( 'question' )->ask( $input, $output, $question );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Honor --no-output by avoiding interactive prompts in CSV runs.
ChoiceQuestion will block in quiet/automation mode. Default to a safe non-interactive choice (e.g., skip) when $this->quiet is true.

🔧 Suggested adjustment
-					$question          = new ChoiceQuestion( '<question>How would you like to proceed?</question> ', $choices, 'skip' );
-					$deployment_choice = $this->getHelper( 'question' )->ask( $input, $output, $question );
+					if ( $this->quiet ) {
+						$deployment_choice = 'skip';
+					} else {
+						$question          = new ChoiceQuestion( '<question>How would you like to proceed?</question> ', $choices, 'skip' );
+						$deployment_choice = $this->getHelper( 'question' )->ask( $input, $output, $question );
+					}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commands/Site_Remove_Atlantis_Legacy_Modules.php` around lines 454 - 466,
When running in quiet/automation mode ($this->quiet), avoid creating a
ChoiceQuestion and prompting; instead default to a safe non-interactive choice
(e.g., set $deployment_choice = 'skip') and skip calling
$this->getHelper('question')->ask. Locate the block that builds the $choices
array and creates the ChoiceQuestion (uses ChoiceQuestion and
$deployment_choice) and add a conditional: if ($this->quiet) assign the default
string ('skip') to $deployment_choice and only construct/ask the ChoiceQuestion
when not quiet.

Comment on lines +1440 to +1459
private function uninstall_plugins_from_wordpress( OutputInterface $output ): void {
$site_identifier = 'atomic' === $this->host ? $this->site->ID : $this->site->id;
$plugins_list = implode( ' ', $this->legacy_modules );

$this->write_output( $output, '' );
$this->write_output( $output, '<fg=cyan;options=bold>Deactivating and uninstalling plugins from WordPress...</>' );

try {
// Run single command to deactivate and uninstall all plugins.
// The --uninstall flag will also deactivate if needed.
$command = "plugin uninstall {$plugins_list} --deactivate";

// Skip output in silent mode.
if ( 'pressable' === $this->host ) {
run_pressable_site_wp_cli_command( $site_identifier, $command, $this->quiet );
} else {
run_wpcom_site_wp_cli_command( $site_identifier, $command, $this->quiet );
}

$this->write_output( $output, ' <info>✓ Plugins deactivated and uninstalled from WordPress</info>' );
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the definitions of the WP-CLI command functions mentioned in the review
rg -n "function run_pressable_site_wp_cli_command|function run_wpcom_site_wp_cli_command" --type php -A 15

Repository: a8cteam51/team51-cli

Length of output: 2165


🏁 Script executed:

#!/bin/bash
# Also search for run_app_command as mentioned in the verification request
rg -n "function run_app_command" --type php -A 40

Repository: a8cteam51/team51-cli

Length of output: 2566


🏁 Script executed:

#!/bin/bash
# Look at the entire context of the reviewed method to understand the try-catch block
rg -n "uninstall_plugins_from_wordpress" --type php -B 5 -A 40

Repository: a8cteam51/team51-cli

Length of output: 8573


Check WP-CLI exit code before reporting uninstall success.

The functions run_pressable_site_wp_cli_command() and run_wpcom_site_wp_cli_command() return an integer exit code but the current code ignores it, printing the success message regardless of whether the command succeeded. The try-catch block only protects against exceptions, which these functions don't throw.

🔧 Suggested fix
-			if ( 'pressable' === $this->host ) {
-				run_pressable_site_wp_cli_command( $site_identifier, $command, $this->quiet );
-			} else {
-				run_wpcom_site_wp_cli_command( $site_identifier, $command, $this->quiet );
-			}
-
-			$this->write_output( $output, '  <info>✓ Plugins deactivated and uninstalled from WordPress</info>' );
+			$exit_code = ( 'pressable' === $this->host )
+				? run_pressable_site_wp_cli_command( $site_identifier, $command, $this->quiet )
+				: run_wpcom_site_wp_cli_command( $site_identifier, $command, $this->quiet );
+
+			if ( Command::SUCCESS !== $exit_code ) {
+				$this->write_output( $output, '  <comment>Plugin uninstall returned a non-zero exit code.</comment>' );
+				return;
+			}
+
+			$this->write_output( $output, '  <info>✓ Plugins deactivated and uninstalled from WordPress</info>' );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@commands/Site_Remove_Atlantis_Legacy_Modules.php` around lines 1440 - 1459,
In uninstall_plugins_from_wordpress, capture the integer return value from
run_pressable_site_wp_cli_command or run_wpcom_site_wp_cli_command (depending on
host) instead of ignoring it, then check if it equals 0 before printing the
success message; if non-zero, write an error via $this->write_output (including
the exit code and the original $command for context) and throw or return to
avoid reporting success erroneously. Ensure you reference the $command variable
and use the same write_output pattern currently used for success/failure
messages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants