Skip to content

Build/test tools: copy the local environment configuration synchronously - #12697

Open
lancewillett wants to merge 3 commits into
WordPress:trunkfrom
lancewillett:fix/env-start-env-copy-race
Open

Build/test tools: copy the local environment configuration synchronously#12697
lancewillett wants to merge 3 commits into
WordPress:trunkfrom
lancewillett:fix/env-start-env-copy-race

Conversation

@lancewillett

Copy link
Copy Markdown
Contributor

Trac ticket: https://core.trac.wordpress.org/ticket/65716

Summary

On a fresh checkout, start.js begins copying .env.example asynchronously, then immediately loads .env. The read can finish first, leaving configuration values unset for that process.

This changes the initial copy to copyFileSync(), ensuring .env exists before dotenv.config() runs. Existing .env files remain untouched because COPYFILE_EXCL is preserved.

Branch behavior

The race is latent on trunk because the old-PHP authentication helper is no longer present.

On 6.9, missing LOCAL_DB_VERSION can make PHP 7.2 or 7.3 select --default-authentication-plugin=mysql_native_password. MySQL 8.4 removed this option and exits during startup.

This should be backported to 6.9 after landing on trunk.

Testing

  • Confirmed a fresh trunk fixture copied and loaded .env before Docker startup.
  • Reproduced the 6.9 delayed-copy path and wrong authentication option.
  • Confirmed MySQL 8.4 rejects the removed option with exit code 1.
  • Confirmed the patched 6.9 environment started with PHP 7.2 and healthy MySQL 8.4.
  • Confirmed npm run env:install completed.

…sly.

On a fresh checkout, the asynchronous copy of .env.example can race with dotenv loading .env. This leaves configuration values unset for the process.

Use copyFileSync() to ensure .env exists before dotenv loads it.

Fixes #65716.

Props lance.willett@automattic.com
Copilot AI review requested due to automatic review settings July 26, 2026 17:54
@github-actions

github-actions Bot commented Jul 26, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props lancewillett, jonsurrell, lucasbustamante, mukesh27, adrianmoldovanwp.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copilot AI left a 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.

Pull request overview

Ensures the local environment startup script reliably loads configuration on fresh checkouts by making the initial .env.example.env creation step synchronous before dotenv.config() executes, avoiding a race that can leave env vars unset.

Changes:

  • Replace async copyFile() with copyFileSync() for initial .env creation.
  • Wrap the copy operation in a try/catch to preserve COPYFILE_EXCL behavior (do not overwrite existing .env).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +10 to +14
try {
copyFileSync( '.env.example', '.env', constants.COPYFILE_EXCL );
} catch ( e ) {
console.log( '.env file already exists. .env.example was not copied.' );
});
}

@sirreal sirreal Jul 27, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is good feedback. A better approach is probably to check whether the file already exists at the destination and copy if it doesn't, the try/catch should be safe to remove then, any errors that surface are useful information.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@Luc45

Luc45 commented Jul 26, 2026

Copy link
Copy Markdown

Reviewing.

@lancewillett lancewillett changed the title Build/Test Tools: Copy the local environment configuration synchronously Build/test tools: copy the local environment configuration synchronously Jul 26, 2026

@Luc45 Luc45 left a 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.

Looks good. Fix is minimal and precise.

Copilot AI review requested due to automatic review settings July 27, 2026 13:00

Copilot AI left a 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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

tools/local-env/scripts/start.js:14

  • The try/catch treats every copy failure as “.env already exists” and then continues. That can silently mask real problems (e.g. missing .env.example, permission errors), leaving the process running with an unexpected or empty configuration. Consider only swallowing the expected EEXIST error from COPYFILE_EXCL, and rethrow anything else.
try {
	copyFileSync( '.env.example', '.env', constants.COPYFILE_EXCL );
} catch ( e ) {
	console.log( '.env file already exists. .env.example was not copied.' );
}

@lancewillett
lancewillett requested a review from johnbillion July 27, 2026 17:18
Copilot AI review requested due to automatic review settings July 27, 2026 21:33

Copilot AI left a 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.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

tools/local-env/scripts/start.js:14

  • The catch block currently treats any copyFileSync() failure as “.env already exists”. With COPYFILE_EXCL, EEXIST is expected when .env is present, but other errors (e.g. missing .env.example (ENOENT), permissions (EACCES), etc.) should be surfaced to avoid masking real setup problems. Consider only swallowing EEXIST and rethrowing other errors.
try {
	copyFileSync( '.env.example', '.env', constants.COPYFILE_EXCL );
} catch ( e ) {
	console.log( '.env file already exists. .env.example was not copied.' );
}

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.

6 participants