Skip to content
obeyda@portfolio: ~/portfolio/workmain
Back to work
/ completed · 2022–2023

Giving pull requests preview environments on demand

An opt-in preview workflow that used Azure Pipelines and Helm to create, update, route, and remove pull-request environments.

Azure PipelinesKubernetesHelmPreview Environments

Why fixed test environments were not enough

Shared development and staging worked for broad integration, but not focused review. Branches competed for one deployment, obscuring which change produced the observed behavior.

Creating one for every pull request would waste capacity. The useful boundary was intent: provision only when a change needed runtime review.

A label as the product decision

The workflow used a pull-request label as its opt-in signal. Azure Pipelines detected it and started the lifecycle.

This kept the default path lightweight and made the advanced path discoverable. A human decided whether review value justified the environment.

Preview environment lifecycle
100%
A pull-request label creates one routed namespace, updates it in place, and removes it on closure.

Scroll to zoom · drag to pan · arrow keys to pan · Escape to close

A pull-request label creates one routed namespace, updates it in place, and removes it on closure.

Preview environment lifecycleA pull-request label creates one routed namespace, updates it in place, and removes it on closure.

One namespace and application stack per preview

Each selected pull request received a Kubernetes namespace and application Helm release, isolating workloads and release-level configuration from other previews.

Non-production platform services remained shared. The workflow did not provision a database, storage platform, or Vault hierarchy per pull request; previews consumed controlled shared dependencies and secrets.

This isolated branch-specific behavior while reusing expensive central services.

Predictable routing for reviewers

Each environment received a predictable pull-request subdomain through cluster ingress. Reviewers reached the stack without pod addresses or operator-only access.

Updating instead of multiplying environments

New commits rebuilt the artifact and upgraded the existing Helm release in place. One URL and namespace lasted for the pull request.

Closure or merge removed the environment. Cleanup depended on that event; there was no separate time-to-live sweeper.

Relationship to later GitOps work

The preview system was pipeline-controlled and predated broader Argo CD adoption.

It established useful patterns, including explicit triggers, repeatable Helm deployment, namespace boundaries, and predictable routing, even though the later control plane differed.

Result

Teams gained isolated runtime review without paying the cost for every pull request. The complete lifecycle made the preview part of review, not an unrelated temporary deployment.

Trade-offs

Previews were not production replicas because they shared non-production dependencies. Full service isolation would have been slower and costlier. Cleanup also relied on pull-request events, favoring one understandable lifecycle over a second system.

Part of: Building Azure Landing Zones, Then Expanding Across Clouds

Related work:

All case studies