post

Trust the Pipeline

Every 'we need to ship faster' conversation is actually a 'we do not trust the pipeline' conversation. Five properties of a trusted CI, plus the AI-written Playwright and Testkube setup that gets you there.

A long dark stone corridor at night with stone archways receding into the distance, each archway lit by a small warm amber lantern, the path traceable through every gate.

Every time someone says "we need to ship faster", they are saying something else. They mean: "I do not trust the pipeline."

I spent a year pushing for more deploys per week before I understood the math. Throughput was capped by fear, not by mechanics. The deploy itself was three commands. The fear was the rest of the conversation. Every push to the queue was held back by one quiet question, do we trust the pipeline to catch us if this is wrong.

Pipeline trust has five properties, in order of importance.

Deterministic. A red build means a real failure. A green build means safe to ship. Flake is the first failure to fix, before anything else, because a single flaky test poisons every red build after it. People stop reading them. People start re-running them on a hunch. Once that habit forms, you have no signal left.

Comprehensive enough. The pipeline covers the flows that matter, not every method in the codebase. Coverage theater is worse than no coverage, because it ships bugs under a green check. The test pyramid is real, but for delivery throughput the load-bearing tests are the end-to-end flows the user walks through.

Fast enough. Feedback inside a developer's flow window. A 45-minute pipeline is a non-pipeline. It gets batched, ignored, worked around with manual checks. Under 10 minutes is the goal. Under 5 is the win.

Owned. Every test belongs to a person or a clearly named pattern. Orphan tests rot, and rotted tests get skipped, and skipped tests are how regressions slip in. The pattern matters more than the test itself.

Honest. No .skip annotations hiding regressions. No quarantine drawer of "we will fix it later." No green build covering a known failure. If a test is broken, fix it or delete it. The middle ground destroys trust.

A pipeline with all five gets trusted. A pipeline missing any one of them does not. Without trust, every deploy is a meeting.

I work in a regulated domain where wrong code has consequences. The cost of an untrusted pipeline there is not only slower delivery, it is the meeting becoming the safety mechanism. That is unsustainable, and it makes the case for trust an argument about safety, not speed.

So the question becomes: how do you build that trust at the rate features ship? Writing tests is one bottleneck. Running them is the other. AI changes the first, Testkube changes the second.

Record then refine.

The wrong way to use AI for tests is to ask the model to write one from scratch. "Write a Playwright test for the checkout flow." The model hallucinates selectors, invents assertions that pass by accident, generates await page.waitForTimeout(2000) because it sometimes works. You merge the test. It passes. Then it flakes. You stop trusting it. Back to square one.

The right way is the spec-driven loop applied to tests. Record the real interaction first with playwright codegen or a Playwright MCP session, then ask the model to refine the recording into idiomatic Playwright. The recording is the spec. The model rewrites it to the rules:

  • Selectors use getByRole, getByLabel, getByTestId. Never nth, first, last, or CSS-class chains.
  • Web-first assertions only. await expect(locator).toBeVisible(), not raw equality.
  • No waitForTimeout. The model loves it. The model is wrong.
  • Repeated steps extract to helpers. One test, one concern.

The architect owns the intent and the review. The model owns the rewrite. A generated test is a draft, not a commit.

Testkube above the runner.

Writing tests is one bottleneck. Running them is the other, and it is mechanical. A 200-test Playwright suite on a single GitHub Actions runner is a 25-minute serial run. The same suite sharded across 20 pods is 90 seconds. Property three lives or dies in that gap.

Testkube is a Kubernetes-native test orchestration platform. It runs the same Playwright tests, but as workloads in your cluster, with sharding and parallelism handled for you, and with traces, videos, logs, and flake history living somewhere that does not vanish when the CI job ends. The CI job collapses to a single line: trigger Testkube, wait, gate on the result. The testing complexity moves out of the YAML and into a place built to scale.

Be honest about fit. Testkube is the right answer when you already live on Kubernetes, when one runner cannot give you the parallelism you need, or when test artifacts need to outlive the CI run. If you are on a small Vercel project with no cluster, Testkube is more platform than the problem deserves. The honest tool there is a GitHub-Actions matrix.

The thread back to the series.

Frictionless adds Trust as the new metric for the AI era. The five properties above are what Trust looks like inside a CI pipeline.

The four Playwright rules are exactly the steering files the AI-DLC post talked about. A set of constraints the agent has to honor when it generates tests, written down once, reused forever.

The place those rules live, alongside the fixtures, the helpers, the testid convention, is the shared context layer from the last post. A pipeline only stays trusted because the conventions producing trustworthy tests are written once and read by every future session.

It is the spec-driven loop again, plus a runtime layer for scale.

You do not unlock delivery by deploying more. You unlock it by trusting the gate that decides whether you can. Trust comes from five properties, not from one trick. AI helps you write more of the tests that earn it. Testkube gives those tests somewhere to run that does not stall the pipeline you are trying to trust.

Every other delivery improvement is downstream.

cd ../ — all posts