Skip to content

Keep WordPress auto-updates on for sites created before the setting existed - #4715

Open
gcsecsey wants to merge 7 commits into
trunkfrom
stu-2348-fix-stale-wordpress-on-site-create
Open

Keep WordPress auto-updates on for sites created before the setting existed#4715
gcsecsey wants to merge 7 commits into
trunkfrom
stu-2348-fix-stale-wordpress-on-site-create

Conversation

@gcsecsey

@gcsecsey gcsecsey commented Aug 28, 2026

Copy link
Copy Markdown
Member

Related issues

How AI was used in this PR

I used Opus 5 for implementation and tests.

Proposed Changes

Studio decides whether a site auto-updates from isWpAutoUpdating. If this was unset, the settings UI read it as auto-updating and showed "latest", while the mu-plugin writer read it as falsy and installed 0-disable-auto-updates.php. Sites created before the flag existed have no value, so those sites had auto-updates switched off while the UI showed the opposite.

This PR updates this logic so only an explicit false disables auto-updates now.

  • Sites with no flag start auto-updating from their next start. That is what Settings showed all along, but it is a behavior change for anyone who assumed those sites were frozen.
  • Creating a site on "latest" now bypasses the 24 hour dependency-check throttle. That path installs by copying the cached wordpress-versions/latest directory rather than downloading a numbered release, so the cache has to be verified before it is used. Pinned versions keep the throttle, since they download by exact version and cannot go stale.

Testing Instructions

  • Build the CLI with npm run cli:build

A "latest" site installs the current release, even inside the throttle window

  • Make the cached copy look stale. Open ~/.studio/server-files/wordpress-versions/latest/wp-includes/version.php and change the version line to:
$wp_version = '99.0';

The number has to be higher than the WordPress release bundled in the CLI. On every startup Studio compares the bundled copy against the cache and replaces the cache if the bundled one is newer. It also has to be a version that will never exist, because Studio uses the version for the backup directory name. A real-looking number would overwrite a real cached release.

  • Run date +%s000 to get the current time in milliseconds, then open ~/.studio/cli.json and set lastDependencyCheckTime to that. Add the field at the top level if it is not already there:
"lastDependencyCheckTime": 1788268859000,
  • Create a site on the default "latest" version, and check the version:
node apps/cli/dist/cli/main.mjs site create --path ~/Studio/stu2348 --name stu2348 --wp latest --no-start
grep "wp_version =" ~/Studio/stu2348/wp-includes/version.php

Expected Dependencies updated in the output, and the current release from https://wordpress.org/download/releases/. On trunk it prints 99.0, because the throttle skipped the check and the site was built from the stale cache.

trunk this branch
CleanShot 2026-09-01 at 14 33 51@2x CleanShot 2026-09-01 at 14 31 10@2x
CleanShot 2026-09-01 at 16 32 35@2x CleanShot 2026-09-01 at 14 30 14@2x

An unset auto-update flag means auto-updating

  • Re-do the file changes to ~/.studio/server-files/wordpress-versions/latest/wp-includes/version.php and ~/.studio/cli.json
  • Make it look like a site created before the setting existed. Still in ~/.studio/cli.json, find the entry under sites whose name is stu2348, and delete its isWpAutoUpdating line.
  • Start the site so the mu-plugins are rewritten:
node apps/cli/dist/cli/main.mjs site start --path ~/Studio/stu2348 --skip-browser
  • Check which auto-update plugin Studio wrote. Studio keeps its mu-plugins in a temp directory and points a loader at it. Open ~/Studio/stu2348/wp-content/mu-plugins/99-studio-loader.php and find this line:
$studio_mu_plugins_dir = '/var/folders/../T/studio-mu-plugins-AbCdEf';
  • List that directory:
ls /var/folders/../T/studio-mu-plugins-AbCdEf | grep auto-update
trunk this branch
CleanShot 2026-09-01 at 16 36 18@2x CleanShot 2026-09-01 at 16 37 54@2x

Expected 0-enable-auto-updates.php. On trunk it prints 0-disable-auto-updates.php, which is the bug: Settings shows "latest" for that same site while WordPress has auto-updates switched off.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the CLI’s WordPress dependency management so that creating an “auto-updating” (latest) site uses the current WordPress release at creation time, rather than potentially using a stale cached wordpress-versions/latest directory.

Changes:

  • Replace the “latest” resolution logic to always fetch the currently reported latest version from wordpress.org and treat missing/failed resolution as an error.
  • Reduce the dependency refresh throttle window from 24 hours to 1 hour and avoid persisting the throttle timestamp when the update fails.
  • Add a filesystem lock around wordpress-versions/ access and extend test coverage for the new behaviors.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/cli/lib/dependency-management/wordpress.ts Simplifies “latest” version resolution and makes inability to determine latest an explicit error.
apps/cli/lib/dependency-management/tests/wordpress.test.ts Adds focused tests for latest-version resolution and update behaviors.
apps/cli/lib/dependency-management/tests/setup.test.ts Updates throttling expectations and ensures timestamp isn’t persisted on failure.
apps/cli/lib/dependency-management/setup.ts Changes throttle interval to 1 hour and applies locking around WordPress version refresh/setup.
apps/cli/lib/dependency-management/lock.ts Introduces a lockfile-based critical section for wordpress-versions/ operations.
apps/cli/commands/site/tests/create.test.ts Mocks the new lock helper for site creation tests.
apps/cli/commands/site/create.ts Uses the new lock to prevent concurrent reads/writes of cached WordPress versions during site creation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/cli/lib/dependency-management/lock.ts Outdated
Comment thread apps/cli/commands/site/create.ts Outdated
@wpmobilebot

wpmobilebot commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing 21af72c vs trunk

app-size

Metric trunk 21af72c Diff Change
App Size (Mac) 1425.05 MB 1425.05 MB +0.00 MB ⚪ 0.0%

site-editor

Metric trunk 21af72c Diff Change
load 1150 ms 1175 ms +25 ms ⚪ 0.0%

site-startup

Metric trunk 21af72c Diff Change
siteCreation 7513 ms 7502 ms 11 ms ⚪ 0.0%
siteStartup 2872 ms 2869 ms 3 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@gcsecsey gcsecsey changed the title Install the current WordPress release when creating an auto-updating site Retry the WordPress version check instead of silently caching a stale copy Aug 28, 2026
@gcsecsey
gcsecsey requested a balanced review from Copilot August 28, 2026 16:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 7 out of 7 changed files in this pull request and generated 3 comments.

Suppressed comments (1)

apps/cli/lib/dependency-management/lock.ts:24

  • The lock can become stale while its owner is still legitimately downloading. The guarded operation is explicitly expected to take minutes, but nothing refreshes the lock mtime; after 10 minutes another process may break the lock and mutate/copy latest concurrently, recreating the partial-directory race this lock is intended to prevent. Add a heartbeat for the duration of run (as withSessionsMigrationLock does in packages/common/ai/sessions/root-migration.ts:205-220) and clear it before unlocking.
	await lockFileAsync( lockfilePath, { stale: STALE_TIME, wait: WAIT_TIME } );

Comment thread apps/cli/lib/dependency-management/setup.ts Outdated
Comment thread apps/cli/commands/site/create.ts Outdated
Comment thread apps/cli/lib/dependency-management/lock.ts Outdated
@gcsecsey gcsecsey changed the title Retry the WordPress version check instead of silently caching a stale copy Keep WordPress auto-updates on for sites created before the setting existed Aug 31, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 9 out of 9 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

apps/cli/commands/site/create.ts:672

  • updateServerFiles() now catches lookup/update failures and resolves false, so this catch never receives the failure and the new production logger.reportError is not called. The failure is indistinguishable from a throttled skip, contrary to the stated behavior that site creation reports “Failed to update dependencies.” Preserve the no-timestamp behavior, but propagate an error or return a distinct failure result that this caller reports.
		logger.reportError( new LoggerError( 'Failed to update dependencies', error ), false );

apps/cli/lib/dependency-management/lock.ts:19

  • This lock does not cover every reader of the guarded directory. apps/cli/commands/import.ts:47-60 copies wordpress-versions/latest without withWordPressVersionsLock, so a concurrent refresh can still rewrite the source while an import copies it. Guard that import path with the same lock and add coverage for it.
 * Serialize access to `wordpress-versions/`. The `latest` directory is shared
 * mutable state: a refresh rewrites it in place, while a site create may be
 * copying files out of it at the same time. Without this, a create started
 * just as a new WordPress release lands can copy a half-written directory.

Comment thread apps/cli/lib/dependency-management/lock.ts Outdated
@gcsecsey
gcsecsey marked this pull request as draft August 31, 2026 11:39
@gcsecsey
gcsecsey requested a review from a team September 1, 2026 15:38
@gcsecsey
gcsecsey marked this pull request as ready for review September 1, 2026 15:39
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.

3 participants