Skip to content

Conversation

@bernattorras
Copy link
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
    • Added a CLI command to remove legacy modules from WordPress sites with support for batch processing via CSV, automated Git workflows, GitHub PR creation, and optional plugin uninstallation across multiple hosting providers.

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

coderabbitai bot commented Nov 6, 2025

Walkthrough

A new Symfony CLI command class is introduced that removes Atlantis legacy modules from WordPress sites. The command supports both single-site and multi-site (CSV-driven) processing modes. It includes functionality for site discovery across different hosts, git repository operations (clone/pull, branch management, file removal via direct deletion or submodules), GitHub PR creation, optional WordPress plugin uninstallation via WP-CLI, and local repository cleanup. The implementation contains helper methods for output handling, domain extraction, CSV processing, and error handling across various failure scenarios.

Pre-merge checks and finishing touches

✅ 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 specifically summarizes the main change: creation of a new CLI command for removing Atlantis legacy modules, which is the primary focus of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

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

Copy link

@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 +593 to +608
$wpcom_gh_repositories = get_wpcom_site_code_deployments( $this->site->ID );

if ( empty( $wpcom_gh_repositories ) ) {
// In CSV processing mode, throw exception instead of asking.
if ( $this->sites_csv_path ) {
throw new \Exception( 'Unable to find a WPCOM GitHub Deployments for the site.' );
}

// In interactive mode, ask user.
$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 );
}
return; // Exit early if user chooses to continue without repository.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Do not allow the “continue without repository” path.

If a WPCOM site has no GitHub Deployments and the user answers “yes” to continue, the method returns with $this->gh_repository still null. interact() (and later logic) immediately dereferences $this->gh_repository->name, causing a fatal error. We should abort instead of returning in that case.

 		if ( empty( $wpcom_gh_repositories ) ) {
 			// In CSV processing mode, throw exception instead of asking.
 			if ( $this->sites_csv_path ) {
 				throw new \Exception( 'Unable to find a WPCOM GitHub Deployments for the site.' );
 			}
 
 			// In interactive mode, ask user.
 			$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 );
-			}
-			return; // Exit early if user chooses to continue without repository.
+			if ( true !== $this->getHelper( 'question' )->ask( $input, $output, $question ) ) {
+				$output->writeln( '<comment>Command aborted by user.</comment>' );
+				exit( 1 );
+			}
+
+			throw new \RuntimeException( 'Unable to continue without a GitHub repository for the site.' );
 		}
🤖 Prompt for AI Agents
In commands/Site_Remove_Atlantis_Legacy_Modules.php around lines 593-608, the
code returns early when the site has no WPCOM GitHub Deployments and the user
elects to "continue", leaving $this->gh_repository null and causing a fatal
dereference later; replace the early "return" path with an abort (throw an
Exception or call exit(1)) so the command terminates instead of returning with a
null repository, and ensure any user-interactive branch that proceeds without
repositories does not allow execution to continue past this point.

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

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.

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