Configuring CI/CD for Your Website with Bitbucket Pipelines
Bitbucket Pipelines is built into Bitbucket Cloud — no separate CI server required. Configuration is described in bitbucket-pipelines.yml at the repository root. Each step runs in a Docker container; the free tier provides 50 minutes/month, paid plans remove limitations.
Basic Configuration
image: node:20-alpine
pipelines:
branches:
main:
- step:
name: Test
caches:
- node
script:
- npm ci
- npm test
- step:
name: Build
caches:
- node
script:
- npm ci
- npm run build
artifacts:
- dist/**
- step:
name: Deploy
deployment: production
script:
- apt-get update && apt-get install -y openssh-client rsync
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
- rsync -avz --delete dist/ deploy@$DEPLOY_HOST:/var/www/mysite/
pull-requests:
'**':
- step:
name: Test PR
script:
- npm ci
- npm test
- npm run lint
Artifacts Between Steps
- step:
name: Build
script:
- npm run build
artifacts:
- dist/** # glob pattern
- .env.production # specific file
- step:
name: Deploy
script:
- ls dist/ # files from previous step are available
Artifacts are automatically passed between steps in a single pipeline. Storage duration is 14 days.
Environment Variables
Configured in Repository Settings → Pipelines → Repository variables. The Secured flag hides the value in logs.
For multiple repositories — use Workspace variables (configured at workspace level).
script:
- echo "$DATABASE_URL" # from Repository variables
- echo "$WORKSPACE_TOKEN" # from Workspace variables
Parallel Steps
- parallel:
- step:
name: Unit Tests
script:
- npm test
- step:
name: E2E Tests
image: cypress/base:20
script:
- npm ci
- npm run test:e2e
- step:
name: Lint
script:
- npm run lint
Parallel steps execute simultaneously; the next step waits for all to complete.
Deployment Environments
Bitbucket supports named environments with manual approval:
- step:
name: Deploy to Staging
deployment: staging
script:
- ./deploy.sh staging
- step:
name: Deploy to Production
deployment: production
trigger: manual # button in UI
script:
- ./deploy.sh production
In Deployments (left panel in Bitbucket), you can see deployment history by environment, who deployed, and when.
Custom Pipelines (Manual Run)
pipelines:
custom:
rollback:
- variables:
- name: RELEASE_TAG
default: 'v1.0.0'
- step:
name: Rollback to tag
script:
- git fetch --tags
- git checkout $RELEASE_TAG
- npm ci && npm run build
- ./deploy.sh production
Run: Pipeline → Run pipeline → select rollback → enter variable. Useful for emergency rollbacks.
Docker Build
image: atlassian/default-image:4
pipelines:
branches:
main:
- step:
name: Build and push Docker image
services:
- docker
script:
- docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
- docker build -t myrepo/mysite:$BITBUCKET_COMMIT .
- docker push myrepo/mysite:$BITBUCKET_COMMIT
- docker tag myrepo/mysite:$BITBUCKET_COMMIT myrepo/mysite:latest
- docker push myrepo/mysite:latest
The docker service connects Docker daemon to the step.
PHP/Composer Project
image: php:8.3-cli
definitions:
caches:
composer: vendor
pipelines:
branches:
main:
- step:
caches:
- composer
script:
- apt-get update && apt-get install -y unzip libpq-dev
- docker-php-ext-install pdo_pgsql
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install --no-dev --optimize-autoloader
- php artisan config:cache
- php artisan migrate --force
Notifications
Bitbucket sends email on failure. For Slack/Telegram — use Webhook or Pipe:
- step:
script:
- npm run build
after-script:
- |
if [ $BITBUCKET_EXIT_CODE -ne 0 ]; then
curl -s -X POST $SLACK_WEBHOOK \
-H 'Content-type: application/json' \
-d '{"text":"Build failed: '"$BITBUCKET_REPO_FULL_NAME"'"}'
fi
Implementation Timeline
First working pipeline — 1 day: bitbucket-pipelines.yml, variables, SSH keys. Parallel steps, custom pipelines, Docker — another 1–2 days.







