Skip to content

WooCommerce Migrator scaffolding and commands #59741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 23, 2025

Conversation

naman03malhotra
Copy link
Contributor

Changes proposed in this Pull Request:

This pull request introduces the initial scaffolding for a new, core Data Migrator feature for WooCommerce Core.
This foundational PR includes:

  • The necessary directory structure under src/Internal/CLI/Migrator/.
  • A set of WP-CLI commands (wc migrator products, wc migrator setup, wc migrator reset) to manage the migration process.
  • A CredentialManager service for handling platform API credentials, which are stored securely in the database.
  • Adherence to core WooCommerce patterns, including the use of the Dependency Injection container for managing command classes.
  • The entire feature is placed behind the WOOCOMMERCE_MIGRATOR_ENABLED constant for safe, isolated development.

This initial structure is being submitted for an architectural review before proceeding with the implementation of the data fetching and importing logic.

How to test the changes in this Pull Request:

  1. Enable the Feature Flag: Open your wp-config.php file and add the following line:
    define( 'WOOCOMMERCE_MIGRATOR_ENABLED', true );
  2. Verify Commands: Open your terminal and confirm the new commands are registered by running wp wc migrator. You should see products, reset, and setup in the list of subcommands.
  3. Test Credential Setup:
    • Run wp wc migrator setup.
    • The command will prompt you for a "Shopify API Access Token" and a "Shopify store URL".
    • Enter any string for each prompt (e.g., "test_token" and "test.myshopify.com").
    • Confirm you see the success message: Credentials saved successfully.
  4. Test Credential Check:
    • Run the wp wc migrator products command.
    • Verify that it now recognizes the credentials and outputs the success message: Credentials found. Proceeding with migration...
  5. Test Credential Reset:
    • Run wp wc migrator reset.
    • Verify you see the success message: Credentials for the 'shopify' platform have been cleared.
  6. Confirm Reset:
    • Run wp wc migrator products one more time.
    • Verify that it once again prompts you to set up credentials, confirming they were successfully deleted.
  7. Disable the Feature Flag: Comment out or remove the line from wp-config.php and run wp wc migrator again to confirm the commands are no longer registered.

@github-actions github-actions bot added the plugin: woocommerce Issues related to the WooCommerce Core plugin. label Jul 17, 2025
@naman03malhotra naman03malhotra changed the title WooCommerce Migrator code moved from WooCommerce Migrator basic scafolding and commands Jul 17, 2025
Copy link
Contributor

coderabbitai bot commented Jul 17, 2025

Warning

Rate limit exceeded

@naman03malhotra has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 18 minutes and 30 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between e22ae77 and f10905a.

📒 Files selected for processing (5)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ProductsCommand.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ResetCommand.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Commands/SetupCommand.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Core/CredentialManager.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Runner.php (1 hunks)
📝 Walkthrough

Walkthrough

The changes introduce a new CLI migrator subsystem for WooCommerce, enabling product migration and credential management via WP-CLI commands. This includes new command classes for product migration, credential setup, and reset, a credential manager, and a runner for registering these commands conditionally based on a feature flag.

Changes

File(s) Change Summary
plugins/woocommerce/includes/class-wc-cli.php Added conditional loading of migrator CLI commands via the new Runner class and feature constant.
plugins/woocommerce/src/Internal/CLI/Migrator/Runner.php Introduced Runner class to register migrator CLI commands.
plugins/woocommerce/src/Internal/CLI/Migrator/Core/CredentialManager.php Added CredentialManager class for managing platform credentials in CLI workflows.
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/BaseCommand.php Added abstract BaseCommand class with common logic for migrator commands and credential setup.
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ProductsCommand.php Added ProductsCommand class for handling product migration CLI command.
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ResetCommand.php Added ResetCommand class for CLI-based credential reset.
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/SetupCommand.php Added SetupCommand class for interactive CLI credential setup.
plugins/woocommerce/changelog/feat-init-wc-migrator Added changelog entry for initial migrator CLI tool scaffolding and feature flag.
.gitignore Added .specstory to ignore patterns.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WP_CLI
    participant Runner
    participant ProductsCommand
    participant SetupCommand
    participant ResetCommand
    participant CredentialManager

    Note over User,WP_CLI: CLI migrator commands enabled if WOOCOMMERCE_MIGRATOR_ENABLED is true

    User->>WP_CLI: wp wc migrator products --platform=shopify
    WP_CLI->>ProductsCommand: __invoke(args, assoc_args)
    ProductsCommand->>CredentialManager: has_credentials(platform)
    alt No credentials
        ProductsCommand->>User: Log prompt to set up credentials
        ProductsCommand->>SetupCommand: handle_credential_setup(platform)
        SetupCommand->>CredentialManager: prompt_for_credentials(fields)
        CredentialManager->>User: Prompt for API key, shop URL
        CredentialManager-->>SetupCommand: Save credentials
        ProductsCommand->>User: Output setup success, instruct rerun
    else Credentials exist
        ProductsCommand->>User: Output migration will proceed
    end

    User->>WP_CLI: wp wc migrator setup --platform=shopify
    WP_CLI->>SetupCommand: __invoke(args, assoc_args)
    SetupCommand->>CredentialManager: prompt_for_credentials(fields)
    CredentialManager->>User: Prompt for credentials
    CredentialManager-->>SetupCommand: Save credentials
    SetupCommand->>User: Output setup success

    User->>WP_CLI: wp wc migrator reset --platform=shopify
    WP_CLI->>ResetCommand: __invoke(args, assoc_args)
    ResetCommand->>CredentialManager: has_credentials(platform)
    alt Credentials exist
        ResetCommand->>CredentialManager: delete_credentials(platform)
        ResetCommand->>User: Output credentials cleared
    else No credentials
        ResetCommand->>User: Output warning
    end
Loading
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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: 10

🧹 Nitpick comments (6)
plugins/woocommerce/src/Internal/CLI/Migrator/Runner.php (2)

9-9: Remove unused import

The WC_Product_Factory import is not used in this file and should be removed.

-use WC_Product_Factory;

21-51: Consider adding error handling for container resolution

The command registration looks good and follows WooCommerce patterns. However, consider adding error handling in case the container fails to resolve the command classes.

 	public static function register_commands(): void {
 		$container = wc_get_container();
 
+		try {
 			// Products Command
 			WP_CLI::add_command(
 				'wc migrator products',
 				$container->get( ProductsCommand::class ),
 				array(
 					'shortdesc' => 'Migrate products from a source platform to WooCommerce.',
 					'longdesc'  => 'Migrate products from a source platform to WooCommerce. The migrator will fetch products from the source platform, map them to the WooCommerce product schema, and then import them into WooCommerce.',
 				)
 			);
 
 			// Reset Command
 			WP_CLI::add_command(
 				'wc migrator reset',
 				$container->get( ResetCommand::class ),
 				array(
 					'shortdesc' => 'Resets (deletes) the credentials for a given platform.',
 				)
 			);
 
 			// Setup Command
 			WP_CLI::add_command(
 				'wc migrator setup',
 				$container->get( SetupCommand::class ),
 				array(
 					'shortdesc' => 'Interactively sets up the credentials for a given platform.',
 				)
 			);
+		} catch ( Exception $e ) {
+			WP_CLI::error( 'Failed to register migrator commands: ' . $e->getMessage() );
+		}
 	}
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/BaseCommand.php (1)

26-28: Consider adding validation for CredentialManager dependency

The dependency injection should validate that the CredentialManager is properly initialized.

 	final public function init( CredentialManager $credential_manager ): void {
+		if ( ! $credential_manager instanceof CredentialManager ) {
+			WP_CLI::error( 'Invalid CredentialManager instance provided.' );
+		}
+		
 		$this->credential_manager = $credential_manager;
 	}
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ProductsCommand.php (2)

21-26: Remove unused parameter to clean up the method signature.

The static analysis correctly identifies that the $args parameter is unused. Since this is a WP-CLI command that only uses associative arguments, you can remove it from the signature.

-	 * @param array $args       The positional arguments.
 	 * @param array $assoc_args The associative arguments.
 	 *
 	 * @return void
 	 */
-	public function __invoke( array $args, array $assoc_args ): void {
+	public function __invoke( array $assoc_args ): void {

29-34: Consider adding error handling for credential setup failures.

The current implementation assumes that handle_credential_setup() will always succeed, but credential setup could fail for various reasons (network issues, validation errors, etc.).

		if ( ! $this->credential_manager->has_credentials( $platform ) ) {
			WP_CLI::log( "Credentials for '{$platform}' not found. Let's set them up." );
-			$this->handle_credential_setup( $platform );
-			WP_CLI::success( 'Credentials saved successfully. Please run the command again to begin the migration.' );
-			return;
+			try {
+				$this->handle_credential_setup( $platform );
+				WP_CLI::success( 'Credentials saved successfully. Please run the command again to begin the migration.' );
+			} catch ( Exception $e ) {
+				WP_CLI::error( 'Failed to set up credentials: ' . $e->getMessage() );
+			}
+			return;
		}
plugins/woocommerce/src/Internal/CLI/Migrator/Core/CredentialManager.php (1)

1-96: Consider adding credential cleanup and expiration mechanisms.

For production use, consider implementing:

  1. Credential expiration/rotation mechanisms
  2. Audit logging for credential access
  3. Rate limiting for credential operations
  4. Secure credential deletion (overwriting memory)

This could be implemented as additional methods:

public function cleanup_expired_credentials(): void {
    // Implementation for cleaning up expired credentials
}

public function audit_credential_access( string $platform_slug, string $action ): void {
    // Log credential access for security monitoring
}
📜 Review details

Configuration used: .coderabbit.yml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf1915f and 1277490.

📒 Files selected for processing (7)
  • plugins/woocommerce/includes/class-wc-cli.php (2 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Commands/BaseCommand.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ProductsCommand.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ResetCommand.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Commands/SetupCommand.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Core/CredentialManager.php (1 hunks)
  • plugins/woocommerce/src/Internal/CLI/Migrator/Runner.php (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{php,js,ts,jsx,tsx}

Instructions used from:

Sources:
⚙️ CodeRabbit Configuration File

🧠 Learnings (5)
📓 Common learnings
Learnt from: jorgeatorres
PR: woocommerce/woocommerce#59675
File: .github/workflows/release-bump-as-requirement.yml:48-65
Timestamp: 2025-07-15T15:39:21.815Z
Learning: In WooCommerce core repository, changelog entries for all PRs live in `plugins/woocommerce/changelog/` directory and are processed during releases, not at the repository root level.
Learnt from: mikejolley
PR: woocommerce/woocommerce#57961
File: plugins/woocommerce/includes/class-wc-session-handler.php:302-333
Timestamp: 2025-06-19T11:58:57.484Z
Learning: In WooCommerce's session handler, the cart merging behavior was revised to always merge guest and user carts when both contain items, rather than having the guest cart take precedence. The migrate_cart_data() method in class-wc-session-handler.php implements this by using array_merge() to combine both carts when neither is empty.
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-build.mdc:0-0
Timestamp: 2025-06-30T09:27:12.787Z
Learning: The commands to build the WooCommerce plugin must be run in the main repository directory
Learnt from: prettyboymp
PR: woocommerce/woocommerce#59048
File: .github/workflows/cherry-pick-milestoned-prs.yml:60-83
Timestamp: 2025-06-26T12:45:40.709Z
Learning: WooCommerce uses WordPress versioning conventions where minor versions in X.Y.Z format are constrained to 0-9 (Y cannot exceed 9). This means version increment logic should reset minor to 0 and increment major when minor reaches 9, rather than allowing two-digit minor versions like 9.10 or 9.11.
Learnt from: mreishus
PR: woocommerce/woocommerce#58817
File: plugins/woocommerce/includes/wc-product-functions.php:140-140
Timestamp: 2025-06-13T23:52:46.221Z
Learning: In WooCommerce's wc_delete_product_transients function, the context check includes both $is_admin_page (for regular admin screens) and $is_privileged_ajax (for AJAX requests from users with edit_products capability), ensuring that legitimate admin AJAX operations like product imports/exports can still delete transients.
Learnt from: gigitux
PR: woocommerce/woocommerce#58785
File: plugins/woocommerce/client/blocks/package.json:0-0
Timestamp: 2025-06-17T10:25:36.686Z
Learning: Do not suggest using `cross-env` in the WooCommerce repository as it's deprecated/archived and the team is working to remove it from blocks commands to reduce the dependency tree. Instead, inline environment variables like `WP_EXPERIMENTAL_MODULES=true knip` should work fine in supported environments.
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-phpunit.mdc:0-0
Timestamp: 2025-06-30T09:27:17.200Z
Learning: Applies to plugins/woocommerce/tests/**/*.php : Run WooCommerce PHPUnit tests for specific files or directories using the command: pnpm run test:php:env {relative_path} --verbose, and ensure the command is run in the plugins/woocommerce directory.
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/SetupCommand.php (1)
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-build.mdc:0-0
Timestamp: 2025-06-30T09:27:12.787Z
Learning: The commands to build the WooCommerce plugin must be run in the main repository directory
plugins/woocommerce/includes/class-wc-cli.php (2)
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-build.mdc:0-0
Timestamp: 2025-06-30T09:27:12.787Z
Learning: The commands to build the WooCommerce plugin must be run in the main repository directory
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-phpunit.mdc:0-0
Timestamp: 2025-06-30T09:27:17.200Z
Learning: Applies to plugins/woocommerce/tests/**/*.php : Run WooCommerce PHPUnit tests for specific files or directories using the command: pnpm run test:php:env {relative_path} --verbose, and ensure the command is run in the plugins/woocommerce directory.
plugins/woocommerce/src/Internal/CLI/Migrator/Runner.php (1)
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-build.mdc:0-0
Timestamp: 2025-06-30T09:27:12.787Z
Learning: The commands to build the WooCommerce plugin must be run in the main repository directory
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ProductsCommand.php (1)
Learnt from: CR
PR: woocommerce/woocommerce#0
File: .cursor/rules/woo-build.mdc:0-0
Timestamp: 2025-06-30T09:27:12.787Z
Learning: The commands to build the WooCommerce plugin must be run in the main repository directory
🪛 PHPMD (2.15.0)
plugins/woocommerce/src/Internal/CLI/Migrator/Commands/SetupCommand.php

26-26: Avoid unused parameters such as '$args'. (Unused Code Rules)

(UnusedFormalParameter)

plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ResetCommand.php

26-26: Avoid unused parameters such as '$args'. (Unused Code Rules)

(UnusedFormalParameter)

plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ProductsCommand.php

26-26: Avoid unused parameters such as '$args'. (Unused Code Rules)

(UnusedFormalParameter)

🔇 Additional comments (4)
plugins/woocommerce/includes/class-wc-cli.php (2)

13-13: LGTM: Clean import addition

The import follows the existing pattern and namespace conventions in the file.


69-71: LGTM: Proper feature flag implementation

The conditional registration follows WooCommerce patterns and safely gates the new functionality behind the WOOCOMMERCE_MIGRATOR_ENABLED constant. The hook registration is consistent with other CLI commands in the same method.

plugins/woocommerce/src/Internal/CLI/Migrator/Commands/ProductsCommand.php (1)

36-38: Implementation looks good for the initial scaffolding phase.

The placeholder implementation with the TODO comment is appropriate for this architectural review phase. The credential validation flow is well-structured and follows good CLI patterns.

plugins/woocommerce/src/Internal/CLI/Migrator/Core/CredentialManager.php (1)

88-95: The backward compatibility wrapper is well-implemented.

The fallback mechanism for older WP-CLI versions is thoughtful and properly handles the case where WP_CLI::readline() doesn't exist.

Copy link
Contributor

github-actions bot commented Jul 17, 2025

Test using WordPress Playground

The changes in this pull request can be previewed and tested using a WordPress Playground instance.
WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Test this pull request with WordPress Playground.

Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit.

@naman03malhotra naman03malhotra changed the title WooCommerce Migrator basic scafolding and commands WooCommerce Migrator scaffolding and commands Jul 17, 2025
Copy link
Contributor

github-actions bot commented Jul 18, 2025

Testing Guidelines

Hi @xristos3490 ,

Apart from reviewing the code changes, please make sure to review the testing instructions (Guide) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed.

Reminder: PR reviewers are required to document testing performed. This includes:

  • 🖼️ Screenshots or screen recordings.
  • 📝 List of functionality tested / steps followed.
  • 🌐 Site details (environment attributes such as hosting type, plugins, theme, store size, store age, and relevant settings).
  • 🔍 Any analysis performed, such as assessing potential impacts on environment attributes and other plugins, conducting performance profiling, or using LLM/AI-based analysis.

⚠️ Within the testing details you provide, please ensure that no sensitive information (such as API keys, passwords, user data, etc.) is included in this public issue.

@naman03malhotra naman03malhotra requested a review from a team as a code owner July 18, 2025 11:35
@naman03malhotra naman03malhotra requested review from albarin and removed request for a team July 18, 2025 11:35
@naman03malhotra naman03malhotra force-pushed the feat/init-wc-migrator branch from e22ae77 to 9883b65 Compare July 18, 2025 11:36
@naman03malhotra naman03malhotra removed the request for review from albarin July 18, 2025 11:36
Copy link
Member

@xristos3490 xristos3490 left a comment

Choose a reason for hiding this comment

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

Code looks good overall, @naman03malhotra!

As we discussed over huddle, a few nits, for separation of concerns:

  • The handle_credential_setup() looks like it could live under the creds manager.
  • The get_platform() might also live in a dedicated platform manager/registry.

Having said that, and assuming that different commands might have different DI needs, seems like we could eliminate the BaseCommand, too?

@naman03malhotra
Copy link
Contributor Author

Thanks @xristos3490, I've incorperted your feedback as part of this PR: #59803

Copy link
Member

@xristos3490 xristos3490 left a comment

Choose a reason for hiding this comment

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

Thanks for incorporating the review!

This PR tests well on my end:
Screenshot 2025-07-22 at 7 05 56 PM

@naman03malhotra naman03malhotra merged commit d3ae3ec into trunk Jul 23, 2025
41 checks passed
@naman03malhotra naman03malhotra deleted the feat/init-wc-migrator branch July 23, 2025 08:41
@github-actions github-actions bot added this to the 10.2.0 milestone Jul 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: woocommerce Issues related to the WooCommerce Core plugin.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Migrator]: Interactive Credential Setup [Migrator]: WP-CLI Command Bootstrapping [Migrator]: Feature: Plugin Foundation & CLI Command Registration
2 participants