How do you set up deployment environments in Bitbucket and implement a promotion-based deployment workflow?
Quick Answer
Bitbucket deployment environments (test, staging, production) are defined in Repository Settings and referenced in pipeline steps via the 'deployment' keyword. Promotion workflows use manual triggers between stages, requiring a human to approve progression from staging to production, with environment-specific variables injected automatically.
Detailed Answer
Think of deployment environments like floors in a building with security checkpoints. Anyone can walk to the first floor (test), but to reach the second floor (staging) you need a badge, and to access the penthouse (production) you need both a badge and a manager's approval. Each floor has its own furniture (environment variables) even though the building (repository) is the same.
Bitbucket Pipelines supports three environment types: Test, Staging, and Production. These are configured in Repository Settings > Pipelines > Deployments. Each environment can have its own set of variables that override repository-level variables, allowing the same pipeline code to deploy to different targets based on which environment the step references. When a step includes 'deployment: staging', Bitbucket injects the staging environment's variables and records a deployment event in the deployment dashboard. The dashboard shows which commits are deployed to which environments, providing an audit trail of what is running where.
The promotion workflow is built using manual triggers between stages. A pipeline step can include 'trigger: manual', which pauses the pipeline at that step and waits for a human to click 'Run' in the Bitbucket UI. This is how teams implement approval gates: the staging deployment runs automatically when tests pass, but the production deployment requires someone with deployment permissions to manually trigger it. Bitbucket also supports environment locks, which prevent concurrent deployments to the same environment. If two pipelines try to deploy to production simultaneously, the second one waits until the first completes.
In production, teams configure this workflow with environment-specific secrets and rollback capabilities. Each environment has its own DATABASE_URL, API_KEY, and cloud credentials. The deployment dashboard becomes the source of truth for which version is live in each environment. Some teams extend this by adding a 'canary' custom environment before full production, deploying to a subset of servers first. The pipeline includes a manual step to promote from canary to full production, giving time to monitor metrics before full rollout.
A gotcha that causes incidents: manual trigger steps do not have a timeout by default. A pipeline can sit waiting for manual approval indefinitely, and if someone approves a weeks-old pipeline, it deploys an outdated version. Teams should establish a policy to decline stale pipelines and communicate clearly about which pipeline is pending approval. Another pitfall is forgetting that environment variables are only injected when the step has a 'deployment' keyword. If you reference $DATABASE_URL in a step without specifying the deployment environment, the variable will be empty, potentially causing the step to use a fallback value or fail silently.