Skip to content

Conversation

@manhphuc
Copy link

Summary

This PR ensures that WP_CLI::launch() forwards environment variables to the spawned process so that child processes can still access configuration defined via getenv() / $_ENV (for example DB_NAME, DB_USER, and DB_PASSWORD inside wp-config.php).

Previously, WP_CLI::launch() always called Process::create( $command ) without passing an environment array. In environments where WordPress DB credentials (and other settings) are provided exclusively through environment variables (common in Docker setups), a child process spawned via WP_CLI::launch() would not see those variables, leading to database connection errors similar to issue #5362.

What this change does

  • Reads the current environment from $_ENV.
  • When $_ENV is not empty, calls:
    • Process::create( $command, null, $env );
      so the spawned process inherits the parent environment.
  • When $_ENV is empty, falls back to the previous behaviour:
    • Process::create( $command );
      to avoid affecting setups that rely on default environment propagation.

Rationale and backward compatibility

  • Fixes the scenario described in Database connection error caused by unset env vars in process #5362 where a WP_CLI::launch_self() call (and other usage of launch()) would fail with “Error establishing a database connection” because DB_* variables were not passed to child processes.
  • Maintains backward compatibility by:
    • Only passing an explicit env array when $_ENV is non-empty.
    • Preserving previous behaviour for systems where $_ENV is empty.

Testing

Manual testing performed inside a Docker-based environment:

  1. Installed WordPress using env-based DB configuration (DB_NAME, DB_USER, DB_PASSWORD, etc.) and wp-config.php reading them via getenv().

  2. Confirmed core commands behave normally:

    export HTTP_HOST=localhost
    /wp-cli-src/bin/wp core version --allow-root
    /wp-cli-src/bin/wp plugin list --allow-root
    /wp-cli-src/bin/wp db tables --allow-root

    All commands executed successfully.

  3. Verified that child processes now propagate the environment correctly, resolving the issue outlined in Database connection error caused by unset env vars in process #5362.

Related issue

@manhphuc manhphuc requested a review from a team as a code owner December 10, 2025 14:35
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @manhphuc, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a crucial enhancement to WP_CLI::launch() by enabling the forwarding of environment variables to child processes. This change directly addresses a long-standing issue where child processes, particularly in Dockerized WordPress setups, would fail to access essential configuration variables (like database credentials) defined in the environment. By conditionally passing the $_ENV array, the PR ensures robust functionality and compatibility with modern deployment practices without disrupting existing setups.

Highlights

  • Environment Variable Forwarding: The WP_CLI::launch() method now forwards environment variables from the parent process's $_ENV superglobal to any spawned child processes. This ensures that configurations, such as database credentials (DB_NAME, DB_USER, DB_PASSWORD), defined via environment variables are accessible to child processes, resolving issues like database connection errors in environments like Docker.
  • Backward Compatibility: The change is implemented with backward compatibility in mind. Environment variables are only explicitly passed to Process::create() if the $_ENV array is not empty. If $_ENV is empty, the method falls back to its previous behavior, avoiding unintended side effects on systems that rely on default environment propagation or where $_ENV is not populated.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Dec 10, 2025

Codecov Report

❌ Patch coverage is 75.00000% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
php/class-wp-cli.php 75.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a critical issue where environment variables were not being correctly forwarded to child processes spawned by WP_CLI::launch(). The change correctly captures the parent process's $_ENV variables and passes them to the child process. However, there's a logical flaw in the fallback mechanism when $_ENV is empty, which could still prevent environment variables from being inherited, thus not fully resolving the underlying problem.

Comment on lines 1153 to 1154
// Fallback to previous behavior if no environment array is available.
$proc = Process::create( $command );
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The else block currently falls back to Process::create( $command );. In Process::create, the $env parameter defaults to an empty array ([]). When an empty array is passed to proc_open (via Utils\proc_open_compat), the child process starts with an empty environment, meaning it will not inherit any environment variables from the parent process's actual shell environment.

This behavior would reintroduce the problem described in issue #5362 if $_ENV happens to be empty (e.g., due to variables_order settings in php.ini), as the child process would still not receive necessary environment variables like DB_NAME.

To ensure proper environment variable propagation (inheritance from the parent's actual environment) when $_ENV is empty, proc_open needs to be called with null for the $env argument. Therefore, the Process::create call in this else block should explicitly pass null for the environment.

This is a high-severity issue because it prevents the complete resolution of the problem this PR aims to fix, potentially leading to continued database connection errors in certain setups.

            // If $_ENV is empty, explicitly pass null to inherit the parent's environment.
            // This ensures environment variables are propagated even if $_ENV is not populated.
            $proc = Process::create( $command, null, null );

Copy link
Author

Choose a reason for hiding this comment

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

Good catch — thanks!

You're right that when $_ENV is empty, Process::create() needs to receive
null for the env argument so the child process inherits the parent
environment. Passing an empty array would wipe the environment entirely
and could reintroduce the issue from #5362.

I've updated the fallback branch to call:

$proc = Process::create( $command, null, null );

so that env vars are still propagated when $_ENV is not populated.
Thanks again for the detailed explanation!

@swissspidy
Copy link
Member

Thanks a lot for your PR! I know you've already tested this manually but would it be possible to add some Behat tests for this as well?

@manhphuc
Copy link
Author

Thanks a lot for the review and the kind words! 🙌

Yes, adding Behat coverage makes sense here.

My plan is to:

  • Add a scenario that verifies the forwarded environment variables are available to the child process started via WP_CLI::launch().
  • Add a scenario where $_ENV is initially empty and confirm that the fallback still forwards environment variables correctly.

I’ll update the PR with these Behat tests and ping you once they’re pushed.

@manhphuc manhphuc force-pushed the fix/5362-forward-env-to-process branch from 294d238 to 784e373 Compare December 11, 2025 01:21
@manhphuc
Copy link
Author

manhphuc commented Dec 11, 2025

Hi @swissspidy! 👋

Quick update — I’ve just pushed the Behat coverage we discussed. 😊

The new feature file is:
features/launch-env-forwarding.feature

It includes two scenarios that directly exercise the behaviour of WP_CLI::launch() when forwarding environment variables to spawned processes:

  1. Scenario: Forwards environment variables when $_ENV is populated

    • The parent shell sets WPCLI_ENV_FWD=ok
    • WP_CLI::launch( "php env-dump.php", true, true ) is used to capture the child process output
    • We echo $result->stdout so Behat can assert that the spawned PHP process receives the environment variable via getenv()
  2. Scenario: Still forwards env vars when $_ENV is empty

    • PHP is invoked with variables_order=GPCS, meaning "E" is omitted and $_ENV may be empty
    • Even in this case, WP_CLI::launch() should fall back to inheriting the OS-level environment
    • The test confirms that the child process still receives WPCLI_ENV_FWD=ok

Both scenarios are passing locally with:

vendor/bin/behat --profile=default --colors features/launch-env-forwarding.feature

Here is a screenshot of the passing test run:

Screenshot 2025-12-11 at 13 58 16

Please let me know if you'd like any adjustments to the wording, structure, or coverage — happy to update anything! 🙌

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Database connection error caused by unset env vars in process

2 participants