Skip to content

chore(ci): green the baseline — PHPCS HubClient + PHPUnit coverage timeout#344

Merged
detain merged 2 commits into
masterfrom
chore/ci-baseline-green
Jun 29, 2026
Merged

chore(ci): green the baseline — PHPCS HubClient + PHPUnit coverage timeout#344
detain merged 2 commits into
masterfrom
chore/ci-baseline-green

Conversation

@detain

@detain detain commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Why

phlix-server master CI is RED on two checks unrelated to feature work, blocking the plan_missing.md "all gates green per repo" prerequisite. This PR fixes the baseline only — no feature/refactor changes.

1) PHPCS (PSR-12) — src/Hub/HubClient.php

collectLibraries() and its body were indented one extra space (7 errors, lines ~451-465). Auto-fixed with phpcbf (pure whitespace, no logic change). The full tree is now clean:

vendor/bin/phpcs --standard=PSR12 -n src/   → exit 0

2) PHPUnit job exit 142 ("Alarm clock" / SIGALRM)

The real cause was not coverage/timeout slowness. Several units under test call Workerman\Timer::add() (HlsSegmentPrefetcher, HlsRelayManager, WebSocketServer, …). Run outside an event loop — exactly the PHPUnit situation — Timer::init() falls back to the pcntl signal scheduler: it registers a SIGALRM handler and arms pcntl_alarm(1) (vendor/workerman/workerman/src/Timer.php L88-89/127/161). With no event loop draining the timer, the alarm fires ~1s later and PHP terminates the process with the default SIGALRM disposition → exit 142. Because phpunit.xml uses executionOrder="random", whichever timer-arming test runs first kills everything after it — so the death point was non-deterministic and prior timeout-minutes bumps (aba08ac, 3e3d07a) never helped: the suite was being signal-killed, not timing out.

Verified locally: repeated --no-coverage runs died RC=142 at random points (31/50/69/95%) with no E/F beforehand; installing a no-op SIGALRM handler made the suite run to 3712/3712 completion.

Fixes (scoped):

  • tests/bootstrap.php (new) — loads the autoloader then installs an async no-op SIGALRM handler (pcntl_async_signals(true) + pcntl_signal(SIGALRM, no-op)) so a stray Workerman Timer alarm can't terminate the runner. Test-process only; production keeps its real event loop. phpunit.xml bootstrap= repointed to it.
  • HlsSegmentPrefetcherTest::testStartPrefetchDoesNotThrow — had no assertion; with failOnRisky="true" this alone kept the job red. Added a trailing assertTrue(true) matching sibling "does not throw" tests.
  • .github/workflows/phpunit.yml (defensive): coverage: xdebugpcov (much faster line coverage) + pcov added to extensions; timeout-minutes 10 → 25; test-server subset coverage: none; updated the misleading Xdebug-timeout comment.

Verification (local, all extensions loaded — swoole + uv + pcov; CI parity)

vendor/bin/phpcs  --standard=PSR12 -n src/                  → exit 0
vendor/bin/phpstan analyze src/ --level=9 --no-progress     → [OK] No errors (NO baseline)
php -d max_execution_time=0 vendor/bin/phpunit --no-coverage → Tests: 3712, Skipped: 13, RC=0
php ... vendor/bin/phpunit --coverage-clover ... (PCOV)      → RC=0, Lines 58.50%

No genuine test failures on master — the suite is fully green once SIGALRM can no longer kill it.

🤖 Generated with Claude Code

…meout

Two CI-baseline-only fixes, independent of any feature work.

1) PHPCS (PSR-12): src/Hub/HubClient.php had collectLibraries() indented one
   extra space (7 errors). phpcbf-fixed; `phpcs --standard=PSR12 -n src/` now
   exits 0 across the whole tree.

2) PHPUnit job exit 142 ("Alarm clock"): the real cause was NOT coverage/timeout
   slowness — it was a stray SIGALRM from Workerman's pcntl Timer fallback. Units
   that call Workerman\Timer::add() outside an event loop trigger Timer::init(),
   which arms pcntl_alarm(1) and registers a SIGALRM handler; with no event loop
   draining it the alarm fires ~1s later and the default disposition kills the
   process. executionOrder="random" made the death point non-deterministic, which
   is why prior timeout bumps never helped.
   - tests/bootstrap.php (new): installs an async no-op SIGALRM handler so a stray
     Workerman Timer alarm cannot terminate the runner; phpunit.xml bootstrap=
     repointed to it. The full ~3712-test suite now runs to completion (RC=0).
   - HlsSegmentPrefetcherTest::testStartPrefetchDoesNotThrow gained an assertion
     (was risky → failOnRisky kept the job red).
   - Workflow defensive margin: coverage xdebug→pcov (faster), timeout-minutes
     10→25, test-server coverage→none.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@codacy-production

codacy-production Bot commented Jun 29, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 3 high · 3 medium · 8 minor

Alerts:
⚠ 14 issues (≤ 0 issues of at least minor severity)

Results:
14 new issues

Category Results
BestPractice 2 medium
Documentation 3 minor
ErrorProne 1 medium
Security 3 high
CodeStyle 5 minor

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

…ate-limit; pcov for component job

Running the full suite to completion (after the SIGALRM fix) exposed failures
previously masked by the early exit-142 death.

Problem A (real latent prod bug): Application::getArrSyncController() is invoked
eagerly during route registration and built `new RadarrClient($radarrUrl, ...)`
with an empty URL — the shipped config/arr.php uses a nested `radarr.url` schema,
not the flat `radarr_url` key the code reads, so the URL is empty on every
install. phlix-shared >=0.12.0 strictly validates the baseUrl scheme and throws,
so a fresh install with Radarr unconfigured crashed at bootstrap. Now: when no
valid http/https Radarr URL is configured, build against a harmless localhost
placeholder and disable the syncer so the integration is inactive, not fatal.
A configured URL is passed through unchanged; phlix-shared and its validation
are untouched. (Masked locally because BootstrapTest only runs the Application
constructor when MySQL is reachable.)

Problem A' (test-isolation flake, same exposure): AuthManager::$rateLimitStore
is a process-wide static keyed on client IP (default 127.0.0.1 in tests). Under
executionOrder="random", failed logins from other auth tests pre-trip the limiter
and AuthManagerEmailLoginTest/StatsTest fail intermittently. Added a public
AuthManager::resetRateLimitStore() and call it in those two classes' setUp().

Problem B: the Server Component Tests job used coverage: none, so PHPUnit's
"No code coverage driver available" warning tripped failOnWarning="true" -> exit 1.
Switched that job to coverage: pcov.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.18%. Comparing base (69b7027) to head (073e0ce).
⚠️ Report is 17 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #344      +/-   ##
============================================
+ Coverage     60.02%   60.18%   +0.16%     
- Complexity    13078    13155      +77     
============================================
  Files           483      485       +2     
  Lines         42333    42615     +282     
============================================
+ Hits          25411    25649     +238     
- Misses        16922    16966      +44     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@detain
detain merged commit 0bb5f59 into master Jun 29, 2026
16 of 17 checks passed
@detain
detain deleted the chore/ci-baseline-green branch June 29, 2026 22:14
detain added a commit that referenced this pull request Jul 12, 2026
…meout (#344)

* chore(ci): green the baseline — PHPCS HubClient + PHPUnit coverage timeout

Two CI-baseline-only fixes, independent of any feature work.

1) PHPCS (PSR-12): src/Hub/HubClient.php had collectLibraries() indented one
   extra space (7 errors). phpcbf-fixed; `phpcs --standard=PSR12 -n src/` now
   exits 0 across the whole tree.

2) PHPUnit job exit 142 ("Alarm clock"): the real cause was NOT coverage/timeout
   slowness — it was a stray SIGALRM from Workerman's pcntl Timer fallback. Units
   that call Workerman\Timer::add() outside an event loop trigger Timer::init(),
   which arms pcntl_alarm(1) and registers a SIGALRM handler; with no event loop
   draining it the alarm fires ~1s later and the default disposition kills the
   process. executionOrder="random" made the death point non-deterministic, which
   is why prior timeout bumps never helped.
   - tests/bootstrap.php (new): installs an async no-op SIGALRM handler so a stray
     Workerman Timer alarm cannot terminate the runner; phpunit.xml bootstrap=
     repointed to it. The full ~3712-test suite now runs to completion (RC=0).
   - HlsSegmentPrefetcherTest::testStartPrefetchDoesNotThrow gained an assertion
     (was risky → failOnRisky kept the job red).
   - Workflow defensive margin: coverage xdebug→pcov (faster), timeout-minutes
     10→25, test-server coverage→none.


* fix(ci): unconfigured Arr no longer crashes bootstrap; isolate auth rate-limit; pcov for component job

Running the full suite to completion (after the SIGALRM fix) exposed failures
previously masked by the early exit-142 death.

Problem A (real latent prod bug): Application::getArrSyncController() is invoked
eagerly during route registration and built `new RadarrClient($radarrUrl, ...)`
with an empty URL — the shipped config/arr.php uses a nested `radarr.url` schema,
not the flat `radarr_url` key the code reads, so the URL is empty on every
install. phlix-shared >=0.12.0 strictly validates the baseUrl scheme and throws,
so a fresh install with Radarr unconfigured crashed at bootstrap. Now: when no
valid http/https Radarr URL is configured, build against a harmless localhost
placeholder and disable the syncer so the integration is inactive, not fatal.
A configured URL is passed through unchanged; phlix-shared and its validation
are untouched. (Masked locally because BootstrapTest only runs the Application
constructor when MySQL is reachable.)

Problem A' (test-isolation flake, same exposure): AuthManager::$rateLimitStore
is a process-wide static keyed on client IP (default 127.0.0.1 in tests). Under
executionOrder="random", failed logins from other auth tests pre-trip the limiter
and AuthManagerEmailLoginTest/StatsTest fail intermittently. Added a public
AuthManager::resetRateLimitStore() and call it in those two classes' setUp().

Problem B: the Server Component Tests job used coverage: none, so PHPUnit's
"No code coverage driver available" warning tripped failOnWarning="true" -> exit 1.
Switched that job to coverage: pcov.


---------
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.

1 participant