Skip to content

test: simplify lifecycle and defer worktree isolation #676

Description

@jumski

Goal

Reduce the maintenance cost of the test lifecycle introduced in #675 without delaying product work. The maintainer accepts one active worktree for database/E2E work for now. Full worktree isolation is deferred, not a prerequisite for using the current system.

Current baseline: PR #675 at 3d5d5f01, with passing CI. Keep its readiness, ownership, cleanup, cache correctness, and full-test coverage guarantees while simplifying.

Phase 1: simplify the shared-environment implementation

  • Evaluate replacing custom database/stack fingerprints with straightforward uncached setup. Measure the setup cost first and define how stack configuration changes take effect; supabase db reset alone does not apply every configuration change. Preserve setup-to-consumer locking. Do not replace database fingerprints with a filesystem success marker that can outlive the database.
  • Reduce the E2E supervisor to one E2E-specific lifecycle owner. Preserve bounded startup, server failure propagation during both probe and suite, process-group interruption cleanup, immutable runtime-container ownership, and cleanup failure reporting.
  • Consolidate focused-file validation at one boundary, preferably the existing Node executor. Keep direct-argument spawning, supported-subtree and regular-file checks, symlink containment, Nx file visibility, untracked valid files, and nonzero failure propagation. Audit standalone runner callers before removing their validation.
  • Replace the central cleanup target allowlist with one opt-in target metadata boolean if it reduces maintenance. Nx 21.2.1 has project tags and extensible target metadata, not native target tags. Read the resolved graph once; retain workspace/user/ancestor/PID-reuse safeguards and fail closed.
  • Wire edge-worker:test:lifecycle into CI. The current workflow and edge-worker:test do not select it. Keep regression checks for all retained behavior, removing only checks for deleted mechanisms.

Cache behavior checked on Nx 21.2.1

An uncached dependency does not make its dependents uncached. A temporary workspace with an uncached setup dependency and cached check target produced actual execution counts:

Invocation Setup executions, cumulative Check executions, cumulative
First run 1 1
Unchanged repeat 2 1
Declared input changed 3 2

The repeat reruns setup but replays the consumer from cache. This used the repository's installed Nx, no cache-bypass flags, and external execution counters rather than replayed console output. No database was touched.

core:verify-migrations is already cache: false. Turning its current fingerprint fast path into an unconditional reset would add reset cost, not automatically disable downstream caching. Core pgTAP (full/focused), database type generation/verification, core unit tests through type verification, edge-worker integration (full/focused), and client preparation/E2E/benchmark depend on this path. Core pgTAP and type consumers also call migration setup within their locked commands, so a naive replacement can reset twice on a cache miss.

Edge-worker E2E already places its own setup inside the cached test command: that setup does not execute on a target cache hit. Portable-runtime E2E and client E2E are already uncached.

Avoid unnecessary setup before cached consumers where the graph allows it, but do not simply remove migration/schema verification dependencies or release the resource lock between setup and use. Any setup writes to declared inputs or dependency outputs must remain part of the hash analysis. Source/helper changes should invalidate affected caches normally.

Phase 2: optional worktree-isolated environments

Pursue this when concurrent worktrees become necessary. Prefer Supabase and Compose native configuration over another orchestration framework.

  • Allocate distinct Supabase project IDs per package/worktree and nonconflicting service port sets. Supabase CLI 2.63.1 accepts numeric env(...) values and native .env overrides such as SUPABASE_PROJECT_ID, SUPABASE_API_PORT, SUPABASE_DB_PORT, and SUPABASE_DB_SHADOW_PORT; check all enabled services and debug/shadow ports.
  • Give the integration Compose project, its published database port, and the upgrade fixture worktree-specific identities. Current shared names are pgflow-edge-worker-tests and pgflow-upgrade-fixture; integration currently publishes host port 5432.
  • Derive test/probe/database connection URLs from the same effective environment. Current edge-worker and client test helpers contain fixed ports. Lifecycle scripts currently parse raw TOML project IDs with sed, so native environment overrides require those consumers to change too.
  • Make fresh cleanup affect only the selected worktree's resources. Preserve same-worktree concurrency guards; per-worktree ports do not stop two commands in one worktree from resetting the same database.
  • Check allocation collisions and fail safely on occupied ports without stopping unrelated services. An .env file or truncated hash does not itself guarantee exclusive ports. Check two concurrent worktrees, interruptions, ownership, and resource cleanup before removing cross-worktree locks.

The env check above was a configuration parsing check against an unavailable Docker socket, not an end-to-end isolated stack test.

Acceptance

  1. Preserve current behavior and full Nx test coverage; run focused, batch, final, and post-commit checks according to repository guidance.
  2. Show a smaller implementation and measured cold/warm setup costs without stale database reuse or false cache hits.
  3. Make lifecycle regression checks part of CI, including focused-selector and server-cleanup failure paths.
  4. Keep worktree isolation independently deliverable. Single-worktree use of test: make Nx own test environments #675 does not wait for Phase 2.

References: #673, #675, and the maintainer's PR review at #675 (review).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions