Repository navigation
Make the cloud SessionStart hook async; fix MariaDB test auth - #67
Conversation
Cloud sessions sat at their first turn for ~10 minutes because the synchronous SessionStart hook ran a cold `composer install`. The session's GitHub proxy refuses archive downloads (api.github.com zipball, codeload) with 403 for repos not attached to the session, so all 43 Composer packages fell back to sequential git clones. - Split the hook: session-env.sh (sync, instant) writes the test DB env vars and PATH; session-start.sh runs async and logs to /tmp/rfsd-session-setup.log, writing /tmp/rfsd-session-setup.done on success. - Skip composer/npm when composer.lock/package-lock.json are unchanged. - Use --prefer-source since dist downloads from GitHub always 403 here. - Each step is logged with its duration; one failure no longer stops the rest. - Fix the MariaDB password check: over the Unix socket, unix_socket auth lets OS root in with any password, so the password was never set and PHPUnit (TCP 127.0.0.1) got "Access denied". Check over TCP instead. - Document the background setup in CLAUDE.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QZq4ts3V2N5nh2sZeUHm2
Up to standards ✅🟢 Issues
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QZq4ts3V2N5nh2sZeUHm2
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Codacy (Agentlinter) flagged the 45-word sentence as overly complex. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QZq4ts3V2N5nh2sZeUHm2
There was a problem hiding this comment.
🔵 Needs a closer look
The DevOps hook's async-hook detach semantics and MariaDB TCP-to-localhost auth resolution are beyond static review and depend on the author's cloud-session test evidence to confirm.
No open issues 🎉
What changed in this PR
This PR fixes two problems that prevented Claude Code cloud sessions on this repo from starting work: (1) the SessionStart hook ran synchronously and blocked the first turn for ~10 minutes while Composer git-cloned every dependency (dist archives 403 behind the session's GitHub proxy), and (2) the MariaDB root-password check ran over the Unix socket where unix_socket auth masked the missing password, so PHPUnit's TCP connection kept failing with "Access denied". The change splits the hook into a fast synchronous env-writer and an async installer, and repairs the DB auth check. This is dev-tooling only — no runtime plugin code is touched.
Changes:
- Make
session-start.shrun async (emits{"async": true, "asyncTimeout": 1800000}), with per-step failure tolerance, duration logging to/tmp/rfsd-session-setup.log, a/tmp/rfsd-session-setup.donemarker, hash-based skip of unchanged installs, and--prefer-sourcefor Composer. - Add synchronous
session-env.shto writeWP_TESTS_DB_*andPATHinstantly, and register it in.claude/settings.json(timeouts reduced to 30s/60s). - Fix the MariaDB check to use TCP (
-h127.0.0.1) and setunix_socket OR mysql_native_password; document the async setup/wait-for-marker flow inCLAUDE.md.
I reviewed the shell logic (empty-array handling under set -u, the set -e removal with the tolerant step wrapper, hash-skip paths, and the MariaDB idempotency/auth path), confirmed both scripts pass bash -n, the new hook is executable, referenced lockfiles exist, and vendor//node_modules/ are git-ignored with /.claude already export-ignore. No blocking issues found. The duplicated DB credentials across session-env.sh and session-start.sh are a minor drift risk but are explicitly cross-referenced with "must match" comments, which is a reasonable mitigation for a hook that must stay fast and standalone.
| File | Description |
|---|---|
.claude/hooks/session-start.sh |
Reworked to run async with failure-tolerant steps, duration logging, done-marker, hash-based install skipping, --prefer-source, and a TCP-based MariaDB auth check. |
.claude/hooks/session-env.sh |
New synchronous hook writing static WP_TESTS_DB_* and PATH env vars so tests work before the async installs finish. |
.claude/settings.json |
Registers the new env hook and lowers hook timeouts (1800s → 30s/60s). |
CLAUDE.md |
Documents the background setup, the .done marker to wait on, and not to run composer install manually. |
Review effort: Balanced
Description
Claude Code cloud sessions on this repo seemed to "never start working": the initial prompt and follow-up messages never became a turn. The cause is the synchronous
SessionStarthook, which held the first turn for about 10 minutes, with a timeout of up to 30 minutes.Root cause (with evidence)
composer install --prefer-disttries to download all 43 packages as GitHub archives. The cloud session's GitHub proxy rejects every one with HTTP 403:"GitHub access to this repository is not enabled for this session". That applies toapi.github.com/repos/*/zipball/*,codeload.github.com/*andgithub.com/*/archive/*for any repo not attached to the session, i.e. every third-party package. Composer reports this asCould not authenticate against github.comand falls back to sequential git clones.Measured on a fresh container:
composer install --prefer-dist(all 43 dists 403 → git source)npm install(registry.npmjs.org bypasses the proxy)apt-get install mariadb-server+ startcomposer install --prefer-source, empty cacheNearly all the time goes into the git clones themselves, so no Composer flag can make a cold install fast here. The only real fix is to stop blocking the session on it. In the child sessions, the proxy's
curl error 28 … Proxy CONNECT aborted due to timeoutretries added more time on top.set -euo pipefaildid not abort startup in my run (exit 0). Even if it had, a failed hook doesn't block the session; the delay came from the hook running so long.Second bug found: PHPUnit couldn't connect to the DB
The hook checks whether root's password is set with
mysql -uroot -proot …over the Unix socket. MariaDB's defaultunix_socketauth lets OS root in with any password, so that check always passed and theALTER USERnever ran. PHPUnit connects over TCP (127.0.0.1:3306) and failed withError establishing a database connection/Access denied for user 'root'@'localhost'.Changes
.claude/hooks/session-env.sh(new, sync, ~0s): writesWP_TESTS_DB_*andPATHto$CLAUDE_ENV_FILE..claude/hooks/session-start.shnow runs async ({"async": true, "asyncTimeout": 1800000}), so the first turn starts immediately:/tmp/rfsd-session-setup.log, and writes/tmp/rfsd-session-setup.doneon success.vendor/andnode_modules/, both git-ignored).--prefer-source, because GitHub dist downloads always 403 in cloud sessions.unix_socket OR mysql_native_passwordso socket access keeps working..claude/settings.json: registers both hooks; the hook timeouts drop from 1800s to 30s and 60s.CLAUDE.md: tells agents to wait for the.donemarker instead of runningcomposer installthemselves.Related Issue
None.
Type of Change
Checklist
Testing Instructions
Results in a cloud container:
vendor/bin/phpcs -ilistsWordPress, WordPress-Core, WordPress-Docs, WordPress-Extra.package.jsonreruns npm.vendor/bin/phpcs includes/coverage.php: clean.vendor/bin/phpunit: OK (306 tests, 865 assertions). Before this change it failed with the DB auth error.npx jest: 31 passed.To reproduce:
CLAUDE_CODE_REMOTE=true CLAUDE_PROJECT_DIR=$PWD .claude/hooks/session-start.sh; tail -f /tmp/rfsd-session-setup.logAdditional Notes
Trade-off of async: during the first ~10 minutes of a fresh session,
phpcs/phpunitaren't available yet. CLAUDE.md now tells the agent to check/tmp/rfsd-session-setup.donefirst.Optional environment change (only the repo owner can make it). To make dependencies ready from the very first minute, add the installs to the cloud environment's Setup script: open the cloud environment menu in the session's title bar → Edit → Setup script. The script starts one directory above the repo:
The hook then finds everything up to date and finishes in seconds. Changing the network allowlist won't help: the 403s come from the session's per-repository GitHub access policy, not from a blocked host.
Generated by Claude Code