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.
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.
Related
Part of: Building Azure Landing Zones, Then Expanding Across Clouds
Related work: