#65745 closed defect (bug) (fixed)
"Start Docker environment" is not retried, and start.js discards the failure
| Reported by: | adrianmoldovanwp | Owned by: | lancewillett |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.2 |
| Component: | Build/Test Tools | Version: | trunk |
| Severity: | normal | Keywords: | has-patch |
| Cc: | Focuses: |
Description
Start Docker environment failed in 85 runs across 69 branches in 30 days. Of 92 sampled failures: 63 Docker Hub, 20 Packagist, 9 undetermined.
start.js never checks the exit status of docker compose up, so a failed pull does not fail the step:
LOCAL_PHP=this-tag-does-not-exist npm run env:start; echo $? # 0
docker.js has the same defect: process.exit( returns.status ) exits 0 when Docker cannot be spawned, because status is then null.
Commit d0a30472b0 added an env:pull retry, but only to reusable-phpunit-tests-v3.yml, and it covers image pulls only. env:start also runs composer update -W,
which reaches repo.packagist.org. Example: run 30353258811, where the pull step passed and
Start Docker environmentthen failed withcurl error 7 while downloading https://repo.packagist.org/packages.json.
Possible fix:
- Propagate the exit status in start.js:35 and docker.js:41.
- Retry
env:pullandenv:startin the five remaining workflows.
The retry has to stay in the workflow YAML. 30 branches (4.1-7.0) call these reusable workflows @trunk but check out their own tools/local-env/ and package.json, so a retry in trunk's scripts would only protect trunk.
6.9 and 7.0 ship an identical start.js and need the same backport.
Change History (33)
This ticket was mentioned in PR #12735 on WordPress/wordpress-develop by @adrianmoldovanwp.
6 weeks ago
#1
- Keywords has-patch added
This ticket was mentioned in PR #12736 on WordPress/wordpress-develop by @adrianmoldovanwp.
6 weeks ago
#2
Start Docker environment failed in 85 runs across 69 branches over 30 days. That spread rules out contributor code. Of 92 sampled failures, 63 were Docker Hub and 20 were repo.packagist.org.
env:pull was already retried in reusable-phpunit-tests-v3.yml. This PR extends that to the five remaining workflows, and also retries npm run env:start, which runs composer update -W in addition to starting the containers. Retrying only the pull leaves the Packagist failures uncovered.
## Why the retry stays in the workflows
30 released branches (4.1 through 7.0) call these reusable workflows as WordPress/wordpress-develop/.github/workflows/reusable-*.yml@trunk, and each job checks out its own branch. The workflow body comes from trunk. tools/local-env/ and package.json come from the released branch.
A retry added to trunk's start.js would therefore protect trunk and nothing else. The same constraint rules out a composite action and any new npm script: only env:pull and env:start exist in package.json on all 30 calling branches.
Keeping the retry in CI also keeps it away from contributors. Someone working offline gets an immediate error instead of waiting through the backoff.
The retry is bounded at three attempts with a 10s and 20s backoff, and the underlying error is printed on every attempt, so a bad tag or a malformed Compose file still fails loudly.
## The .env change
ensure_env_file() moves the .env bootstrap into utils.js and calls it from start.js, docker.js and install.js.
The new pull step runs before start.js has created .env, so env:pull resolved image tags from the Compose defaults while docker compose up resolved them from .env. On trunk that means mysql:latest is pulled and then mysql:9.7 is pulled again.
The synchronous copy also removes a race. The previous copyFile call was asynchronous, and dotenv.config() ran on the next line, so on a fresh clone the first run could read a .env that had not been written yet.
## Stacked on
The first commit is #12735, which propagates the exit status of docker compose up. Review that one first. The retry is only fully effective once a failed up actually fails the step.
## Testing instructions
Confirm the retry is bounded and reports the real error. Point the environment at a tag that does not exist and run the loop from the workflow. It should make three attempts, back off for 10 and 20 seconds, print the registry error each time, and exit 1.
LOCAL_PHP=this-tag-does-not-exist npm run env:pull
Confirm a normal cold start still works and is not slower.
npm run env:stop && docker compose down -v npm run env:pull && npm run env:start && npm run env:install
Confirm env:pull and env:start now resolve the same image tags. Delete .env, run npm run env:pull, and check that .env exists afterwards and that docker compose up does not pull a second database image.
Local Docker Environment, PHPUnit Tests and End-to-end Tests all exercise this step across large matrices.
## Note for reviewers
These six workflows are consumed at @trunk by every released branch, so this change takes effect on all 30 of them as soon as it is committed. There is no staged rollout.
## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Investigating the CI failures, writing the patch, and iterative code review. The cross-branch constraints described above were checked against every calling branch, and the behaviour was verified locally.
@lancewillett commented on PR #12735:
6 weeks ago
#3
This change looks correct, I'd like a 2nd review from a core committer on the backports since that will involve SVN commits to 7.0, 6.9, and 6.8. CC @aaronjorbin @desrosj @johnbillion
@adrianmoldovanwp commented on PR #12736:
4 weeks ago
#4
https://github.com/WordPress/wordpress-develop/pull/12937 partially changed the scope so I decided to fold the changes into https://github.com/WordPress/wordpress-develop/pull/12735 instead for easier landing. Both changes touch only tools/ and share Trac ticket 65745, so they are now on one branch.
Closing this one.
@adrianmoldovanwp commented on PR #12735:
4 weeks ago
#5
Tested with head a88479c
Confirmed failed image pulls and a missing Docker executable exit non-zero. SIGTERM exits non-zero, SIGINT remains clean for interactive commands, and a normal environment start and install > succeeded
The affected code shape was also verified on 6.8, 6.9, and 7.0.
Good to land.
@lancewillett this needs a new round of review, I just folded https://github.com/WordPress/wordpress-develop/pull/12736 into it.
@lancewillett commented on PR #12735:
11 days ago
#6
Re-reviewed and tested head 87734e38efc36e12526bbfed80510fd827497c91 after the Composer option-parsing follow-up and trunk refresh.
Confirmed:
- Missing Docker exits non-zero without retrying
- Failed pulls and starts retry three times, then exit non-zero
- Non-registry Composer commands run once
.envis created before Compose runs- A cold start and install succeed
No blocking issues. Looks good to land.
@lancewillett commented on PR #12735:
11 days ago
#10
https://core.trac.wordpress.org/changeset/63416 and https://core.trac.wordpress.org/changeset/63417 for trunk
I'll proceed to backport r63416 to older branches once I have a 2nd core committer review.
@lancewillett commented on PR #12735:
11 days ago
#11
Trunk landed in two revisions:
- r63416 contains the backportable bug fixes.
- r63417 adds retry behavior and will remain on trunk because it is an enhancement rather than a defect fix.
For the r63416 backports, the planned scope is:
| Branch | Changes |
|---|---|
| 7.1 | Exit-status fix |
| 7.0 | Exit-status and .env fixes
|
| 6.9 | Exit-status fix |
| 6.8 | Exit-status and .env fixes
|
| 6.7 | Optional .env fix only
|
The adapted backports will record mergeinfo for r63416. I’m keeping Trac #65745 open until the agreed backports land.
@johnbillion commented on PR #12735:
11 days ago
#12
Planned scope back to 6.7 looks good. Let's do this via a PR for each branch though so anything unexpected in CI gets caught.
This ticket was mentioned in PR #13350 on WordPress/wordpress-develop by @adrianmoldovanwp.
10 days ago
#13
This ticket was mentioned in PR #13351 on WordPress/wordpress-develop by @adrianmoldovanwp.
10 days ago
#14
This ticket was mentioned in PR #13352 on WordPress/wordpress-develop by @adrianmoldovanwp.
10 days ago
#15
This ticket was mentioned in PR #13353 on WordPress/wordpress-develop by @adrianmoldovanwp.
10 days ago
#16
This ticket was mentioned in PR #13354 on WordPress/wordpress-develop by @adrianmoldovanwp.
10 days ago
#17
@adrianmoldovanwp commented on PR #12735:
10 days ago
#18
Planned scope back to 6.7 looks good. Let's do this via a PR for each branch though so anything unexpected in CI gets caught.
Opened backport PRs:
| PR | Base | Backports |
| --- | --- | --- |
| #13350 | 6.7 | r62871 |
| #13353 | 6.8 | r63416 + r62871 |
| #13351 | 6.9 | r63416 |
| #13352 | 7.0 | r63416 + r62871 |
| #13354 | 7.1 | r63416 |
6.7 has no exit-status defect:
docker.jsthere usesexecSync, which throws. 6.9 and 7.1 already carry
r62871, so they take only the exit-status half of r63416.
@lancewillett commented on PR #12735:
10 days ago
#19
@adimoldovan Thanks for the PRs; I'll review, monitor, and land these today
@lancewillett commented on PR #13354:
10 days ago
#21
Committed to the 7.1 branch in r63421.
@desrosj commented on PR #12735:
10 days ago
#22
It may be worthwhile to task an LLM with analyzing the older numbered branches to create a list of the build tool-related changes that are missing from each. I believe the last time we backported a number of improvements to the local environment and build tools was ~3 years ago now.
Ideally these branches are all as consistent as possible. It used to take a lot of manual work. But AI can probably handle that pretty easily and doing that now will help us going forward by limiting how much trunk diverges from these old branches.
@lancewillett commented on PR #13352:
10 days ago
#24
Committed to the 7.0 branch in r63422.
@lancewillett commented on PR #13351:
10 days ago
#26
Committed to the 6.9 branch in r63423.
@lancewillett commented on PR #13353:
10 days ago
#28
Committed to the 6.8 branch in r63424.
@lancewillett commented on PR #13350:
10 days ago
#30
Committed to the 6.7 branch in r63425.
@lancewillett commented on PR #12735:
10 days ago
#31
@lancewillett commented on PR #12735:
10 days ago
#33
@desrosj Drafted here: https://github.com/orgs/WordPress/projects/293/views/1?pane=issue&itemId=238870759 and placed into backlog for WordPress Project Build Tooling project.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
tools/local-env/scripts/start.jsrunsdocker compose upthroughspawnSyncand never inspects the result. A failed pull therefore does not fail the script. Execution continues intocomposer update -Wwith containers that may not exist, and the error surfaces later and in the wrong step.tools/local-env/scripts/docker.jshas the same class of defect. It callsprocess.exit( returns.status ), andstatusisnullwhen Docker cannot be spawned.process.exit( null )exits 0, sonpm run env:pullreports success when the Docker CLI is missing.This PR checks and propagates the status in both files. It is deliberately kept to that one change so that it can be backported.
## Backport
start.jsanddocker.json the 6.8, 6.9 and 7.0 branches carry the same defect. Branches 6.7 and earlier run these commands throughexecSync, which throws on a non-zero exit, so they are not affected.start.jsdocker.jsexecSync)execSync)## Testing instructions
Reproduce the discarded status. Before this change the pull fails and the exit code is 0. After it, the exit code is 1.
Reproduce the
docker.jsdefect. Before this change the exit code is 0. After it, the exit code is 1.Confirm a normal start still works.
Ctrl+C during
npm run env:logsstill exits without an npm error block.## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5
Used for: Investigating the CI failures, writing the patch, and iterative code review. The behaviour described above was reproduced and verified locally before and after the change.