Skip to content

Matched DDEV and Lando stacks by their env marker, not a container probe.#105

Merged
AlexSkrypnyk merged 5 commits into
mainfrom
feature/stack-marker-order
Jun 26, 2026
Merged

Matched DDEV and Lando stacks by their env marker, not a container probe.#105
AlexSkrypnyk merged 5 commits into
mainfrom
feature/stack-marker-order

Conversation

@AlexSkrypnyk

@AlexSkrypnyk AlexSkrypnyk commented Jun 26, 2026

Copy link
Copy Markdown
Member

Summary

Ddev and Lando stacks now match purely on the definitive environment marker their tooling sets (IS_DDEV_PROJECT, LANDO_INFO), removing a guard that required a generic container probe before the marker was even consulted. The generic Container and Native fallbacks are moved out of the STACKS constant and appended last in collectStacks(), so any specific stack - built-in, user-supplied, or a subclass - is always matched ahead of the generic it extends. Together these changes fix a latent false-negative on container runtimes that the generic probe cannot recognise, where detection would otherwise fall through to the native host.

Changes

Stack detection logic (src/Environment.php)

  • Removed the if ($stack instanceof Container && !$stack->isContainer()) guard from getActiveStack(); each stack's own active() now decides without a preceding container probe.
  • Moved Container::class out of the STACKS constant into the generic tail appended by collectStacks(), so specific stacks always run first; Native remains the final always-true fallback.

Container doc comment (src/Stacks/Container.php)

  • Updated isContainer() doc comment to be caller-agnostic; it no longer names DDEV/Lando as callers, since they no longer probe.

Tests (tests/Stacks/DdevTest.php, tests/Stacks/LandoTest.php, tests/Stacks/ContainerTest.php)

  • DdevTest and LandoTest marker-alone cases now assert TRUE (was FALSE under the old guard).
  • ContainerTest comment updated to reflect that a specific marker activates that specific stack, not the generic container.

Docs (README.md, benchmarks/README.md)

  • README.md Stacks section updated: DDEV and Lando match by their tool marker; Container matches by probing.
  • benchmarks/README.md: added a "Cost in context" section explaining that detection is a tiny fraction of a page request and that OPcache amortises structural overhead to near-zero in production; updated Optimization notes item 1 to reflect the two-part fix; corrected a stale section cross-reference and a ~41 μs figure now ~28 μs.

Before / After

BEFORE - DDEV on a runtime the generic probe cannot recognise
─────────────────────────────────────────────────────────────────────────────
getActiveStack()
  ┌──────────────────────────────────────────────────────────────────┐
  │  foreach STACKS: [Ddev, Lando, Container, ..., Native]           │
  │                                                                  │
  │  stack = Ddev                                                    │
  │    instanceof Container? YES                                     │
  │    isContainer() ──► probe for containerisation ──► FALSE ◄──┐  │
  │    guard fires: SKIP                                          │  │
  │                                                               │  │
  │  stack = Lando                                                │  │
  │    instanceof Container? YES                                  │  │
  │    isContainer() ──► (memoised) FALSE ◄───────────────────────┘  │
  │    guard fires: SKIP                                             │
  │                                                                  │
  │  stack = Container                                               │
  │    instanceof Container? YES                                     │
  │    isContainer() ──► (memoised) FALSE                            │
  │    guard fires: SKIP                                             │
  │                                                                  │
  │  stack = Native  active()=TRUE ──► MATCH (wrong!)               │
  └──────────────────────────────────────────────────────────────────┘

AFTER - DDEV on a runtime the generic probe cannot recognise
─────────────────────────────────────────────────────────────────────────────
collectStacks() appends: [...STACKS (Ddev, Lando), ...user, Container, Native]

getActiveStack()
  ┌──────────────────────────────────────────────────────────────────┐
  │  foreach [Ddev, Lando, ..., Container, Native]                   │
  │                                                                  │
  │  stack = Ddev                                                    │
  │    active() ──► IS_DDEV_PROJECT set? YES ──► MATCH (correct!)   │
  │    ──► done, no probe needed                                     │
  │                                                                  │
  │  (Lando, Container, Native never reached)                        │
  └──────────────────────────────────────────────────────────────────┘

Summary by CodeRabbit

  • Bug Fixes
    • Improved active stack detection when only DDEV or Lando markers are present, ensuring correct stack selection.
    • Refined container-vs-native fallback ordering to reduce misclassification.
  • Documentation
    • Updated README guidance for stack precedence and how container probing is interpreted.
    • Refreshed benchmark documentation (corrected cross-reference, updated timing, added context for microsecond-scale results).
  • Tests
    • Updated/expanded tests to confirm marker-driven activation for DDEV and Lando without extra container probing.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2d7a16f5-d05b-41d6-8231-1cd14c5d0a24

📥 Commits

Reviewing files that changed from the base of the PR and between 7a25a97 and 0c63379.

📒 Files selected for processing (1)
  • benchmarks/README.md

📝 Walkthrough

Walkthrough

The PR changes stack selection so DDEV and Lando activate from their markers before the generic container fallback, updates Environment fallback ordering, and revises related docs and benchmark notes.

Changes

Stack detection and docs

Layer / File(s) Summary
Specific-first stack list
src/Environment.php
STACKS now excludes the generic Container fallback, and collectStacks() appends Container and Native after specific and user-provided stacks.
Marker-based stack selection
src/Environment.php, src/Stacks/Container.php, tests/Stacks/*.php, tests/EnvironmentTest.php
getActiveStack() no longer skips container-family stacks on bare metal, the container cache comment is updated, and the DDEV/Lando/container tests now expect marker-driven activation.
README and benchmark text
README.md, benchmarks/README.md
The stack description and benchmark notes are rewritten, including the cold timing, the new cost context section, and the updated optimization note wording.

Sequence Diagram(s)

sequenceDiagram
  participant Environment
  participant Ddev
  participant Lando
  participant Container

  Environment->>Ddev: active()
  alt IS_DDEV_PROJECT marker is present
    Ddev-->>Environment: true
  else
    Environment->>Lando: active()
    alt LANDO_INFO marker is present
      Lando-->>Environment: true
    else
      Environment->>Container: active()
      alt container probe matches
        Container-->>Environment: true
      else
        Environment-->>Environment: Native fallback
      end
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • drevops/environment-detector#77 — Changes the same stack-detection precedence and container-family activation rules in Environment::getActiveStack().
  • drevops/environment-detector#104 — Shares the same container-probe caching and benchmark documentation context around Container::isContainer() and Environment::reset().
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main behavioral change: DDEV and Lando now match via env markers instead of a container probe.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/stack-marker-order

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Performance comparison (informational)

A tracking signal, not a pass/fail gate: microsecond benchmarks land on a different shared CI runner each run, so percentages vs the committed baseline shift run-to-run regardless of the code.

benchmark subject set revs its mem_peak mode rstdev
DiscoveryBenchmark benchCustomPlatforms 0 custom platform 50 20 2.000mb -0.00% 10.941μs +20.18% ± 1.91% -27.45%
DiscoveryBenchmark benchCustomPlatforms 1 custom platform 50 20 2.000mb -0.00% 11.928μs +22.28% ± 1.88% -15.70%
DiscoveryBenchmark benchCustomPlatforms 2 custom platforms 50 20 2.000mb -0.00% 11.419μs +15.60% ± 2.58% +9.16%
DiscoveryBenchmark benchCustomPlatforms 5 custom platforms 50 20 2.000mb -0.00% 13.284μs +17.83% ± 3.12% +40.16%
DiscoveryBenchmark benchCustomPlatforms 10 custom platforms 50 20 2.000mb -0.00% 15.145μs +17.57% ± 2.72% +84.76%
DiscoveryBenchmark benchCustomStacks 0 custom stack 50 20 2.000mb -0.00% 10.253μs +7.67% ± 3.20% +35.12%
DiscoveryBenchmark benchCustomStacks 1 custom stack 50 20 2.000mb -0.00% 10.911μs +9.25% ± 2.77% +7.75%
DiscoveryBenchmark benchCustomStacks 2 custom stacks 50 20 2.000mb -0.00% 12.062μs +23.31% ± 3.31% +69.22%
DiscoveryBenchmark benchCustomStacks 5 custom stacks 50 20 2.000mb -0.00% 12.877μs +17.46% ± 2.89% +59.91%
DiscoveryBenchmark benchCustomStacks 10 custom stacks 50 20 2.000mb -0.00% 14.584μs +16.55% ± 1.95% +12.66%
DiscoveryBenchmark benchCustomContexts 0 custom context 50 20 2.000mb -0.00% 10.327μs +12.54% ± 2.90% +28.98%
DiscoveryBenchmark benchCustomContexts 1 custom context 50 20 2.000mb -0.00% 11.558μs +19.09% ± 2.88% +14.65%
DiscoveryBenchmark benchCustomContexts 2 custom contexts 50 20 2.000mb -0.00% 11.928μs +17.33% ± 2.14% +5.97%
DiscoveryBenchmark benchCustomContexts 5 custom contexts 50 20 2.000mb -0.00% 12.974μs +15.86% ± 2.48% +47.72%
DiscoveryBenchmark benchCustomContexts 10 custom contexts 50 20 2.000mb -0.00% 15.145μs +17.73% ± 2.23% +10.60%
DetectionBenchmark benchDetectLocal 50 20 1.999mb -0.00% 10.486μs +14.41% ± 2.88% +2.92%
DetectionBenchmark benchDetectDrupalNative 50 20 1.999mb -0.00% 28.079μs -9.75% ± 1.56% +1.76%
DetectionBenchmark benchDetectDrupalContainer 50 20 1.999mb -0.00% 17.031μs +16.87% ± 2.28% +12.48%
DetectionBenchmark benchDetectPlatform 50 20 1.999mb -0.00% 10.811μs +16.74% ± 2.51% +23.13%
DetectionBenchmark benchDetectFullStack 50 20 1.999mb -0.00% 16.865μs +19.90% ± 1.85% +5.11%
InitBenchmark benchIsAfterInit 0, F 50 20 2.000mb -0.00% 0.100μs +25.00% ± 0.00% -20.00%
InitBenchmark benchIsAfterInit 1, F 50 20 2.000mb -0.00% 0.340μs +13.35% ± 2.86% +15440913008127000.00%
InitBenchmark benchIsAfterInit 2, F 50 20 2.000mb -0.00% 0.600μs +15.38% ± 0.73% -58.38%
InitBenchmark benchIsAfterInit 3, F 50 20 2.000mb -0.00% 0.820μs +13.89% ± 0.77% +27.58%
InitBenchmark benchIsAfterInit 4, F 50 20 2.000mb -0.00% 1.040μs +13.04% ± 1.49% +92.53%
InitBenchmark benchIsAfterInit 5, F 50 20 2.000mb -0.00% 1.279μs +14.23% ± 1.27% +3211434662357700.00%
InitBenchmark benchIsAfterInit 10, F 50 20 2.000mb -0.00% 2.457μs +13.78% ± 0.95% +50.32%
InitBenchmark benchIsAfterInit 100, F 50 20 2.000mb -0.00% 24.021μs +15.64% ± 1.24% +34.47%
InitBenchmark benchIsAfterInit 1000, F 50 20 2.000mb -0.00% 237.879μs +15.40% ± 1.26% +177.43%
InitBenchmark benchIsAfterInit 0, T 50 20 2.000mb -0.00% 0.100μs +25.00% ± 0.00% -20.00%
InitBenchmark benchIsAfterInit 1, T 50 20 2.000mb -0.00% 0.340μs +13.33% ± 2.51% +13566023254876000.00%
InitBenchmark benchIsAfterInit 2, T 50 20 2.000mb -0.00% 0.600μs +15.38% ± 0.00% -100.00%
InitBenchmark benchIsAfterInit 3, T 50 20 2.000mb -0.00% 0.820μs +13.88% ± 1.21% +100.95%
InitBenchmark benchIsAfterInit 4, T 50 20 2.000mb -0.00% 1.040μs +13.04% ± 1.78% +275.37%
InitBenchmark benchIsAfterInit 5, T 50 20 2.000mb -0.00% 1.282μs +14.47% ± 1.23% +93.58%
InitBenchmark benchIsAfterInit 10, T 50 20 2.000mb -0.00% 2.440μs +12.99% ± 0.83% +33.29%
InitBenchmark benchIsAfterInit 100, T 50 20 2.000mb -0.00% 23.932μs +15.40% ± 1.61% +36.25%
InitBenchmark benchIsAfterInit 1000, T 50 20 2.000mb -0.00% 236.892μs +14.82% ± 0.77% +46.85%

@codecov-commenter

codecov-commenter commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (e244b8b) to head (0c63379).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #105   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           19        19           
  Lines          264       262    -2     
=========================================
- Hits           264       262    -2     

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@benchmarks/README.md`:
- Line 42: The runtime-cost description is too narrow for the generic container
probe; update the prose to match src/Stacks/Container.php by stating that the
unlabelled-container path is a fallback chain, not a single filesystem check.
Reference the Container class behavior explicitly: it checks environment markers
first, then probes /.dockerenv and /.dockerinit, and finally inspects
/proc/1/cgroup when earlier checks miss. Keep the wording aligned with the
actual detection flow in the benchmark README.

In `@src/Environment.php`:
- Around line 447-454: Add an Environment-level regression test for marker-only
stack selection in getActiveStack(). The current EnvironmentTest coverage only
verifies generic container detection and DOCKER plus IS_DDEV_PROJECT, so it does
not exercise the reordered collectStacks()/active() path end-to-end for
marker-only activation. Update EnvironmentTest to include assertions for
IS_DDEV_PROJECT-only and LANDO_INFO-only cases, using
Environment::getActiveStack() to confirm the Ddev and Lando stacks are selected
correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8ef1b637-c990-43d4-ac45-f89320054526

📥 Commits

Reviewing files that changed from the base of the PR and between e244b8b and 99553cd.

📒 Files selected for processing (7)
  • README.md
  • benchmarks/README.md
  • src/Environment.php
  • src/Stacks/Container.php
  • tests/Stacks/ContainerTest.php
  • tests/Stacks/DdevTest.php
  • tests/Stacks/LandoTest.php

Comment thread benchmarks/README.md Outdated
Comment thread src/Environment.php
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Performance comparison (informational)

A tracking signal, not a pass/fail gate: microsecond benchmarks land on a different shared CI runner each run, so percentages vs the committed baseline shift run-to-run regardless of the code.

benchmark subject set revs its mem_peak mode rstdev
DiscoveryBenchmark benchCustomPlatforms 0 custom platform 50 20 2.000mb -0.00% 10.761μs +18.20% ± 2.37% -9.62%
DiscoveryBenchmark benchCustomPlatforms 1 custom platform 50 20 2.000mb -0.00% 11.987μs +22.88% ± 1.91% -14.48%
DiscoveryBenchmark benchCustomPlatforms 2 custom platforms 50 20 2.000mb -0.00% 11.847μs +19.93% ± 2.27% -3.79%
DiscoveryBenchmark benchCustomPlatforms 5 custom platforms 50 20 2.000mb -0.00% 13.321μs +18.15% ± 1.90% -14.91%
DiscoveryBenchmark benchCustomPlatforms 10 custom platforms 50 20 2.000mb -0.00% 15.035μs +16.72% ± 1.47% -0.20%
DiscoveryBenchmark benchCustomStacks 0 custom stack 50 20 2.000mb -0.00% 11.165μs +17.25% ± 2.58% +9.09%
DiscoveryBenchmark benchCustomStacks 1 custom stack 50 20 2.000mb -0.00% 11.755μs +17.71% ± 1.97% -23.38%
DiscoveryBenchmark benchCustomStacks 2 custom stacks 50 20 2.000mb -0.00% 11.989μs +22.56% ± 2.13% +9.15%
DiscoveryBenchmark benchCustomStacks 5 custom stacks 50 20 2.000mb -0.00% 12.893μs +17.60% ± 2.03% +12.25%
DiscoveryBenchmark benchCustomStacks 10 custom stacks 50 20 2.000mb -0.00% 14.567μs +16.41% ± 1.88% +8.49%
DiscoveryBenchmark benchCustomContexts 0 custom context 50 20 2.000mb -0.00% 10.923μs +19.04% ± 2.41% +7.14%
DiscoveryBenchmark benchCustomContexts 1 custom context 50 20 2.000mb -0.00% 11.691μs +20.45% ± 2.19% -12.64%
DiscoveryBenchmark benchCustomContexts 2 custom contexts 50 20 2.000mb -0.00% 12.223μs +20.23% ± 2.43% +20.57%
DiscoveryBenchmark benchCustomContexts 5 custom contexts 50 20 2.000mb -0.00% 13.212μs +17.98% ± 1.56% -7.06%
DiscoveryBenchmark benchCustomContexts 10 custom contexts 50 20 2.000mb -0.00% 15.294μs +18.89% ± 1.75% -13.18%
DetectionBenchmark benchDetectLocal 50 20 1.999mb -0.00% 11.242μs +22.66% ± 2.45% -12.46%
DetectionBenchmark benchDetectDrupalNative 50 20 1.999mb -0.00% 28.640μs -7.94% ± 2.31% +50.58%
DetectionBenchmark benchDetectDrupalContainer 50 20 1.999mb -0.00% 16.839μs +15.55% ± 1.63% -19.53%
DetectionBenchmark benchDetectPlatform 50 20 1.999mb -0.00% 11.346μs +22.51% ± 2.16% +6.08%
DetectionBenchmark benchDetectFullStack 50 20 1.999mb -0.00% 16.516μs +17.43% ± 2.28% +29.56%
InitBenchmark benchIsAfterInit 0, F 50 20 2.000mb -0.00% 0.100μs +25.00% ± 0.00% -20.00%
InitBenchmark benchIsAfterInit 1, F 50 20 2.000mb -0.00% 0.360μs +20.00% ± 2.59% +13991922842170000.00%
InitBenchmark benchIsAfterInit 2, F 50 20 2.000mb -0.00% 0.600μs +15.38% ± 0.73% -58.24%
InitBenchmark benchIsAfterInit 3, F 50 20 2.000mb -0.00% 0.859μs +19.35% ± 2.29% +278.40%
InitBenchmark benchIsAfterInit 4, F 50 20 2.000mb -0.00% 1.081μs +17.46% ± 1.42% +83.50%
InitBenchmark benchIsAfterInit 5, F 50 20 2.000mb -0.00% 1.320μs +17.85% ± 0.75% +1902482205121500.00%
InitBenchmark benchIsAfterInit 10, F 50 20 2.000mb -0.00% 2.510μs +16.22% ± 1.00% +59.56%
InitBenchmark benchIsAfterInit 100, F 50 20 2.000mb -0.00% 24.548μs +18.18% ± 1.27% +37.04%
InitBenchmark benchIsAfterInit 1000, F 50 20 2.000mb -0.00% 241.080μs +16.95% ± 0.86% +87.64%
InitBenchmark benchIsAfterInit 0, T 50 20 2.000mb -0.00% 0.100μs +25.00% ± 0.00% -20.00%
InitBenchmark benchIsAfterInit 1, T 50 20 2.000mb -0.00% 0.340μs +13.35% ± 2.86% +15440913008127000.00%
InitBenchmark benchIsAfterInit 2, T 50 20 2.000mb -0.00% 0.600μs +15.37% ± 1.28% -43.33%
InitBenchmark benchIsAfterInit 3, T 50 20 2.000mb -0.00% 0.840μs +16.73% ± 1.69% +179.26%
InitBenchmark benchIsAfterInit 4, T 50 20 2.000mb -0.00% 1.080μs +17.40% ± 1.85% +291.28%
InitBenchmark benchIsAfterInit 5, T 50 20 2.000mb -0.00% 1.319μs +17.78% ± 1.38% +116.25%
InitBenchmark benchIsAfterInit 10, T 50 20 2.000mb -0.00% 2.488μs +15.22% ± 1.34% +115.52%
InitBenchmark benchIsAfterInit 100, T 50 20 2.000mb -0.00% 24.384μs +17.58% ± 1.26% +6.07%
InitBenchmark benchIsAfterInit 1000, T 50 20 2.000mb -0.00% 241.764μs +17.18% ± 0.74% +41.37%

@AlexSkrypnyk AlexSkrypnyk added the Needs review Pull request needs a review from assigned developers label Jun 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Performance comparison (informational)

A tracking signal, not a pass/fail gate: microsecond benchmarks land on a different shared CI runner each run, so percentages vs the committed baseline shift run-to-run regardless of the code.

benchmark subject set revs its mem_peak mode rstdev
DiscoveryBenchmark benchCustomPlatforms 0 custom platform 50 20 2.000mb -0.00% 11.043μs +21.30% ± 2.37% -9.88%
DiscoveryBenchmark benchCustomPlatforms 1 custom platform 50 20 2.000mb -0.00% 11.508μs +17.98% ± 2.43% +8.78%
DiscoveryBenchmark benchCustomPlatforms 2 custom platforms 50 20 2.000mb -0.00% 12.277μs +24.28% ± 2.30% -2.66%
DiscoveryBenchmark benchCustomPlatforms 5 custom platforms 50 20 2.000mb -0.00% 12.919μs +14.59% ± 1.91% -14.28%
DiscoveryBenchmark benchCustomPlatforms 10 custom platforms 50 20 2.000mb -0.00% 15.161μs +17.69% ± 1.72% +16.39%
DiscoveryBenchmark benchCustomStacks 0 custom stack 50 20 2.000mb -0.00% 10.637μs +11.71% ± 2.26% -4.52%
DiscoveryBenchmark benchCustomStacks 1 custom stack 50 20 2.000mb -0.00% 11.631μs +16.46% ± 2.04% -20.47%
DiscoveryBenchmark benchCustomStacks 2 custom stacks 50 20 2.000mb -0.00% 11.535μs +17.92% ± 1.99% +1.68%
DiscoveryBenchmark benchCustomStacks 5 custom stacks 50 20 2.000mb -0.00% 12.969μs +18.30% ± 1.97% +9.25%
DiscoveryBenchmark benchCustomStacks 10 custom stacks 50 20 2.000mb -0.00% 14.684μs +17.35% ± 1.28% -25.78%
DiscoveryBenchmark benchCustomContexts 0 custom context 50 20 2.000mb -0.00% 10.651μs +16.07% ± 1.87% -16.70%
DiscoveryBenchmark benchCustomContexts 1 custom context 50 20 2.000mb -0.00% 11.778μs +21.35% ± 2.23% -11.16%
DiscoveryBenchmark benchCustomContexts 2 custom contexts 50 20 2.000mb -0.00% 11.998μs +18.02% ± 2.13% +5.79%
DiscoveryBenchmark benchCustomContexts 5 custom contexts 50 20 2.000mb -0.00% 13.256μs +18.38% ± 1.78% +5.93%
DiscoveryBenchmark benchCustomContexts 10 custom contexts 50 20 2.000mb -0.00% 15.304μs +18.97% ± 1.68% -16.70%
DetectionBenchmark benchDetectLocal 50 20 1.999mb -0.00% 11.014μs +20.17% ± 2.27% -18.94%
DetectionBenchmark benchDetectDrupalNative 50 20 1.999mb -0.00% 29.193μs -6.17% ± 1.40% -8.84%
DetectionBenchmark benchDetectDrupalContainer 50 20 1.999mb -0.00% 17.035μs +16.89% ± 1.28% -36.91%
DetectionBenchmark benchDetectPlatform 50 20 1.999mb -0.00% 11.011μs +18.90% ± 2.22% +9.08%
DetectionBenchmark benchDetectFullStack 50 20 1.999mb -0.00% 16.787μs +19.35% ± 2.03% +15.10%
InitBenchmark benchIsAfterInit 0, F 50 20 2.000mb -0.00% 0.100μs +25.00% ± 0.00% -20.00%
InitBenchmark benchIsAfterInit 1, F 50 20 2.000mb -0.00% 0.360μs +20.00% ± 2.59% +13991922842170000.00%
InitBenchmark benchIsAfterInit 2, F 50 20 2.000mb -0.00% 0.600μs +15.38% ± 1.66% -4.67%
InitBenchmark benchIsAfterInit 3, F 50 20 2.000mb -0.00% 0.838μs +16.40% ± 2.24% +270.66%
InitBenchmark benchIsAfterInit 4, F 50 20 2.000mb -0.00% 1.108μs +20.46% ± 1.90% +145.79%
InitBenchmark benchIsAfterInit 5, F 50 20 2.000mb -0.00% 1.319μs +17.75% ± 1.64% +4148381874871700.00%
InitBenchmark benchIsAfterInit 10, F 50 20 2.000mb -0.00% 2.509μs +16.18% ± 0.92% +46.49%
InitBenchmark benchIsAfterInit 100, F 50 20 2.000mb -0.00% 24.214μs +16.56% ± 2.09% +125.82%
InitBenchmark benchIsAfterInit 1000, F 50 20 2.000mb -0.00% 239.973μs +16.42% ± 0.67% +47.87%
InitBenchmark benchIsAfterInit 0, T 50 20 2.000mb -0.00% 0.100μs +25.00% ± 0.00% -20.00%
InitBenchmark benchIsAfterInit 1, T 50 20 2.000mb -0.00% 0.360μs +19.99% ± 2.83% +15319743764074000.00%
InitBenchmark benchIsAfterInit 2, T 50 20 2.000mb -0.00% 0.600μs +15.38% ± 1.00% -55.96%
InitBenchmark benchIsAfterInit 3, T 50 20 2.000mb -0.00% 0.840μs +16.69% ± 1.39% +130.25%
InitBenchmark benchIsAfterInit 4, T 50 20 2.000mb -0.00% 1.081μs +17.46% ± 1.34% +182.35%
InitBenchmark benchIsAfterInit 5, T 50 20 2.000mb -0.00% 1.320μs +17.89% ± 1.46% +129.61%
InitBenchmark benchIsAfterInit 10, T 50 20 2.000mb -0.00% 2.541μs +17.64% ± 1.15% +84.15%
InitBenchmark benchIsAfterInit 100, T 50 20 2.000mb -0.00% 24.505μs +18.16% ± 1.49% +25.59%
InitBenchmark benchIsAfterInit 1000, T 50 20 2.000mb -0.00% 241.463μs +17.03% ± 1.32% +153.48%

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@benchmarks/README.md`:
- Line 50: The first optimization note in the benchmarks README is awkwardly
phrased; rewrite the sentence describing DDEV and Lando so it reads clearly and
grammatically while keeping the same meaning. Update the wording around the
container-family stack detection note in the benchmarks section, preserving the
explanation that DDEV and Lando are identified by their definitive markers and
do not need to probe.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 19dd199f-c398-464a-b215-b39c0a03ce56

📥 Commits

Reviewing files that changed from the base of the PR and between 340633f and 7a25a97.

📒 Files selected for processing (2)
  • benchmarks/README.md
  • src/Stacks/Container.php

Comment thread benchmarks/README.md Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Performance comparison (informational)

A tracking signal, not a pass/fail gate: microsecond benchmarks land on a different shared CI runner each run, so percentages vs the committed baseline shift run-to-run regardless of the code.

benchmark subject set revs its mem_peak mode rstdev
DiscoveryBenchmark benchCustomPlatforms 0 custom platform 50 20 2.000mb -0.00% 9.015μs -0.98% ± 2.58% -1.59%
DiscoveryBenchmark benchCustomPlatforms 1 custom platform 50 20 2.000mb -0.00% 10.035μs +2.87% ± 2.03% -9.38%
DiscoveryBenchmark benchCustomPlatforms 2 custom platforms 50 20 2.000mb -0.00% 10.416μs +5.45% ± 2.30% -2.74%
DiscoveryBenchmark benchCustomPlatforms 5 custom platforms 50 20 2.000mb -0.00% 11.003μs -2.40% ± 2.44% +9.37%
DiscoveryBenchmark benchCustomPlatforms 10 custom platforms 50 20 2.000mb -0.00% 12.979μs +0.76% ± 1.90% +28.72%
DiscoveryBenchmark benchCustomStacks 0 custom stack 50 20 2.000mb -0.00% 8.980μs -5.69% ± 2.68% +13.31%
DiscoveryBenchmark benchCustomStacks 1 custom stack 50 20 2.000mb -0.00% 9.469μs -5.19% ± 2.56% -0.37%
DiscoveryBenchmark benchCustomStacks 2 custom stacks 50 20 2.000mb -0.00% 9.865μs +0.85% ± 2.23% +14.19%
DiscoveryBenchmark benchCustomStacks 5 custom stacks 50 20 2.000mb -0.00% 11.094μs +1.20% ± 2.19% +21.54%
DiscoveryBenchmark benchCustomStacks 10 custom stacks 50 20 2.000mb -0.00% 12.435μs -0.62% ± 1.75% +1.16%
DiscoveryBenchmark benchCustomContexts 0 custom context 50 20 2.000mb -0.00% 8.975μs -2.20% ± 1.83% -18.80%
DiscoveryBenchmark benchCustomContexts 1 custom context 50 20 2.000mb -0.00% 9.627μs -0.81% ± 1.84% -26.71%
DiscoveryBenchmark benchCustomContexts 2 custom contexts 50 20 2.000mb -0.00% 10.152μs -0.14% ± 1.49% -26.07%
DiscoveryBenchmark benchCustomContexts 5 custom contexts 50 20 2.000mb -0.00% 10.963μs -2.10% ± 1.72% +2.11%
DiscoveryBenchmark benchCustomContexts 10 custom contexts 50 20 2.000mb -0.00% 12.851μs -0.11% ± 1.50% -25.55%
DetectionBenchmark benchDetectLocal 50 20 1.999mb -0.00% 9.080μs -0.93% ± 2.18% -22.28%
DetectionBenchmark benchDetectDrupalNative 50 20 1.999mb -0.00% 19.004μs -38.92% ± 1.41% -8.05%
DetectionBenchmark benchDetectDrupalContainer 50 20 1.999mb -0.00% 14.181μs -2.69% ± 1.79% -11.85%
DetectionBenchmark benchDetectPlatform 50 20 1.999mb -0.00% 9.652μs +4.22% ± 2.25% +10.49%
DetectionBenchmark benchDetectFullStack 50 20 1.999mb -0.00% 13.959μs -0.76% ± 1.88% +6.91%
InitBenchmark benchIsAfterInit 0, F 50 20 2.000mb -0.00% 0.080μs 0.00% ± 0.00% 0.00%
InitBenchmark benchIsAfterInit 1, F 50 20 2.000mb -0.00% 0.300μs 0.00% ± 0.00% 0.00%
InitBenchmark benchIsAfterInit 2, F 50 20 2.000mb -0.00% 0.520μs 0.00% ± 1.15% -34.03%
InitBenchmark benchIsAfterInit 3, F 50 20 2.000mb -0.00% 0.720μs 0.00% ± 0.00% -100.00%
InitBenchmark benchIsAfterInit 4, F 50 20 2.000mb -0.00% 0.920μs 0.00% ± 1.16% +49.84%
InitBenchmark benchIsAfterInit 5, F 50 20 2.000mb -0.00% 1.120μs 0.00% ± 0.77% +1941448661364400.00%
InitBenchmark benchIsAfterInit 10, F 50 20 2.000mb -0.00% 2.154μs -0.28% ± 0.90% +43.22%
InitBenchmark benchIsAfterInit 100, F 50 20 2.000mb -0.00% 20.925μs +0.73% ± 0.90% -2.32%
InitBenchmark benchIsAfterInit 1000, F 50 20 2.000mb -0.00% 206.661μs +0.26% ± 0.51% +12.44%
InitBenchmark benchIsAfterInit 0, T 50 20 2.000mb -0.00% 0.080μs 0.00% ± 0.00% 0.00%
InitBenchmark benchIsAfterInit 1, T 50 20 2.000mb -0.00% 0.300μs 0.00% ± 0.00% 0.00%
InitBenchmark benchIsAfterInit 2, T 50 20 2.000mb -0.00% 0.520μs -0.02% ± 1.48% -34.60%
InitBenchmark benchIsAfterInit 3, T 50 20 2.000mb -0.00% 0.720μs 0.00% ± 0.83% +37.46%
InitBenchmark benchIsAfterInit 4, T 50 20 2.000mb -0.00% 0.920μs 0.00% ± 0.87% +82.94%
InitBenchmark benchIsAfterInit 5, T 50 20 2.000mb -0.00% 1.120μs 0.00% ± 0.71% +11.92%
InitBenchmark benchIsAfterInit 10, T 50 20 2.000mb -0.00% 2.160μs +0.00% ± 0.74% +19.42%
InitBenchmark benchIsAfterInit 100, T 50 20 2.000mb -0.00% 20.823μs +0.41% ± 1.07% -9.86%
InitBenchmark benchIsAfterInit 1000, T 50 20 2.000mb -0.00% 207.119μs +0.39% ± 0.81% +56.09%

@AlexSkrypnyk AlexSkrypnyk merged commit 64bf513 into main Jun 26, 2026
11 checks passed
@AlexSkrypnyk AlexSkrypnyk deleted the feature/stack-marker-order branch June 26, 2026 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs review Pull request needs a review from assigned developers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants