Skip to content

chore: slim Filament per-render queries and gate CI coverage via pcov#228

Merged
dan2k3k4 merged 1 commit into
devfrom
chore/filament-slimming-ci-coverage
Jul 17, 2026
Merged

chore: slim Filament per-render queries and gate CI coverage via pcov#228
dan2k3k4 merged 1 commit into
devfrom
chore/filament-slimming-ci-coverage

Conversation

@dan2k3k4

@dan2k3k4 dan2k3k4 commented Jul 17, 2026

Copy link
Copy Markdown
Member

What

PR 3 of 6 executing the advisory plan set (plans/, committed in #226). Implements plans 005 + 006.

Changes

  • Plan 005 — Filament query slimming
    • Instance list tab badges: 6 COUNT(*) per render → 1 grouped query; badges derived in PHP. New InstanceListTabBadgesTest seeds mixed statuses and pins every badge number (incl. the in-progress bucket sum and the empty-table case).
    • StatsOverview: 3 uncached full-table counts per dashboard render → cached 60s (staleness accepted by maintainer decision).
    • Store-app infolist: reuse the withCount value getEloquentQuery() already loads instead of re-counting.
  • Plan 006 — real CI coverage
    • coverage: xdebug (loaded, never used — pure slowdown) → coverage: pcov.
    • Test step now php artisan test --coverage --min=35. Baseline honestly measured at 37.15% lines via a php:8.4-cli + pcov container against this branch; floor = baseline−2 per the grilling decision. The commit/workflow comment documents the ratchet rule.

Testing

  • php artisan test — 435 passed (2 new)
  • ./vendor/bin/phpstan analyse — no errors; Pint clean
  • Coverage figure reproducible via: docker run --rm -v $PWD:/app -w /app php:8.4-cli sh -c "pecl install pcov && docker-php-ext-enable pcov && php -d memory_limit=1G vendor/bin/phpunit --coverage-text"
  • Note: setup-php defaults memory_limit=-1 in CI, so the coverage collector's memory appetite is covered there.

Greptile Summary

This PR implements two optimization plans: Filament query slimming (Plan 005) and gating CI coverage via pcov (Plan 006). It collapses 6 per-tab COUNT(*) badge queries into a single grouped status query with PHP-side derivation, caches dashboard stat counts for 60 s, and reuses a withCount value in the store-app infolist.

  • Badge query consolidationgetTabs() now issues one GROUP BY status query and derives all five badge values in PHP, including a ->unique() guard that restores the set semantics whereIn previously enforced for the duplicated NEW status.
  • Stats cachingStatsOverview::getStats() wraps all three count() calls in Cache::remember('admin-stats-overview', 60, …), accepting 60 s of staleness as explicitly signed off by the maintainer.
  • CI coverage gate — switches the setup-php driver from xdebug (loaded but unused) to pcov and adds --coverage --min=35 to the test step, with baseline documented as 37.15%.

Confidence Score: 5/5

Safe to merge — the optimisations are mechanical query reductions with no change to business logic, all previously flagged correctness issues have been addressed, and a new test pins the exact badge values including the deduplication case.

The badge consolidation is correct: ->unique() restores the set semantics that whereIn used to enforce for the duplicated NEW status, and the new test seeds a NEW instance alongside a PENDING_DEPLOY instance and asserts in_progress === 2, which would fail if the deduplication were absent. The withCount-based read in the store-app infolist is safe because Filament's view and edit record paths always resolve records through getEloquentQuery().

No files require special attention.

Important Files Changed

Filename Overview
app/Filament/Admin/Resources/PolydockAppInstanceResource/Pages/ListPolydockAppInstances.php Replaces per-tab COUNT queries with one grouped status query; ->unique() correctly deduplicates NEW from the in-progress set; all edge cases now covered by the new test.
app/Filament/Admin/Widgets/StatsOverview.php Wraps three full-table counts in a 60 s cache; cache key is static and correct for a single-tenant admin panel.
app/Filament/Admin/Resources/PolydockStoreAppResource.php Reads allocated_instances_count from the withCount already applied in getEloquentQuery() instead of firing a separate relationship count; Filament's view/edit record path always goes through getEloquentQuery(), so the attribute is always populated.
.github/workflows/tests.yml Swaps xdebug (was loaded but never used for coverage) to pcov and enforces a 35% line-coverage floor with baseline and ratchet rule documented in-line.
tests/Feature/Filament/InstanceListTabBadgesTest.php New test that seeds a mixed-status dataset including NEW (the duplicated status), pins all six badge values, and also covers the empty-table case; assertSame ensures correct integer types.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Browser
    participant getTabs as getTabs()
    participant DB

    Note over Browser,DB: Before (6 COUNT queries per render)
    Browser->>getTabs: render tab list
    getTabs->>DB: "COUNT(*) WHERE status != REMOVED"
    getTabs->>DB: "COUNT(*) WHERE status IN (inProgress)"
    getTabs->>DB: "COUNT(*) WHERE status = RUNNING_HEALTHY_CLAIMED"
    getTabs->>DB: "COUNT(*) WHERE status = RUNNING_HEALTHY_UNCLAIMED"
    getTabs->>DB: "COUNT(*) WHERE status = REMOVED"
    getTabs->>DB: "COUNT(*) all"
    DB-->>getTabs: 6 results
    getTabs-->>Browser: tabs with badges

    Note over Browser,DB: After (1 grouped query + PHP derivation)
    Browser->>getTabs: render tab list
    getTabs->>DB: "SELECT status COUNT(*) GROUP BY status"
    DB-->>getTabs: one row per distinct status
    getTabs->>getTabs: "derive active = total minus removed"
    getTabs->>getTabs: derive in_progress via unique and sum
    getTabs-->>Browser: tabs with badges
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Browser
    participant getTabs as getTabs()
    participant DB

    Note over Browser,DB: Before (6 COUNT queries per render)
    Browser->>getTabs: render tab list
    getTabs->>DB: "COUNT(*) WHERE status != REMOVED"
    getTabs->>DB: "COUNT(*) WHERE status IN (inProgress)"
    getTabs->>DB: "COUNT(*) WHERE status = RUNNING_HEALTHY_CLAIMED"
    getTabs->>DB: "COUNT(*) WHERE status = RUNNING_HEALTHY_UNCLAIMED"
    getTabs->>DB: "COUNT(*) WHERE status = REMOVED"
    getTabs->>DB: "COUNT(*) all"
    DB-->>getTabs: 6 results
    getTabs-->>Browser: tabs with badges

    Note over Browser,DB: After (1 grouped query + PHP derivation)
    Browser->>getTabs: render tab list
    getTabs->>DB: "SELECT status COUNT(*) GROUP BY status"
    DB-->>getTabs: one row per distinct status
    getTabs->>getTabs: "derive active = total minus removed"
    getTabs->>getTabs: derive in_progress via unique and sum
    getTabs-->>Browser: tabs with badges
Loading

Comments Outside Diff (1)

  1. app/Filament/Admin/Resources/PolydockAppInstanceResource/Pages/ListPolydockAppInstances.php, line 95-102 (link)

    P1 NEW status double-counted in the in_progress badge

    $inProgressStatuses prepends PolydockAppInstanceStatus::NEW explicitly at line 96, but $stageCreateStatuses (spread at line 97) starts with the same NEW constant. That means NEW appears twice in the collected slice. The old whereIn scope was immune because SQL deduplicates values inside an IN (…) clause, but the new PHP sum() loop iterates every element, so any instance in NEW status is counted twice in the badge. The test seed doesn't exercise NEW, so the test suite still passes despite the inflated count.

Reviews (2): Last reviewed commit: "chore: slim Filament per-render queries ..." | Re-trigger Greptile

Comment thread tests/Feature/Filament/InstanceListTabBadgesTest.php
Implements plans 005 and 006 from the advisory audit:

- The instance list fired six separate COUNT queries per render for its
  tab badges; all badges now derive from one grouped status-count query,
  pinned by a new badge-correctness test with mixed-status fixtures.
- Dashboard StatsOverview ran three uncached full-table COUNT(*) per
  render; the totals are now cached for 60 seconds.
- The store-app infolist re-counted allocatedInstances although
  getEloquentQuery() already eager-counts it; reuse the withCount value.
- CI loaded xdebug but never collected coverage — paying the slowdown for
  nothing. Switch to pcov and gate with --min=35: baseline measured at
  37.15% lines (via a php:8.4-cli + pcov container run), floor set two
  points under per the maintainer decision. Ratchet upward deliberately;
  never lower silently.
@dan2k3k4
dan2k3k4 force-pushed the chore/filament-slimming-ci-coverage branch from 21cdca5 to 2017ef2 Compare July 17, 2026 15:33
@dan2k3k4
dan2k3k4 merged commit 2cb8fc1 into dev Jul 17, 2026
5 checks passed
@dan2k3k4
dan2k3k4 deleted the chore/filament-slimming-ci-coverage branch July 17, 2026 16:18
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