Skip to main content

Command Palette

Search for a command to run...

CI/CD with Bitbucket Pipelines: Build, Test, and Deploy

A practical guide to CI/CD concepts, pipeline triggers, YAML configuration, security checks, and deployment flow.

Updated
7 min read
CI/CD with Bitbucket Pipelines: Build, Test, and Deploy
E
Frontend Developer writing about Angular, Java, AI, cloud infrastructure, and what I learn while building software.

CI/CD can look complicated at first, but the main idea is simple:

Instead of building, testing, and deploying manually, we let an automated pipeline do it for us.

This reduces mistakes, catches problems earlier, and makes deployments more predictable.


What is CI/CD?

CI/CD usually means:

Term Meaning
CI Continuous Integration
CD Continuous Delivery or Continuous Deployment

Continuous Integration

CI means every code change is automatically checked.

A typical CI process:

Developer pushes code
  ↓
Pipeline starts
  ↓
Code is built
  ↓
Tests run
  ↓
Problems are reported

The goal is to catch issues early.

Continuous Delivery

Continuous Delivery means the application is automatically prepared for deployment.

The pipeline may build artifacts, run tests, create Docker images, and make the application ready to release.

Deployment might still require manual approval.

Continuous Deployment

Continuous Deployment goes one step further.

If all checks pass, the application is deployed automatically.

This is powerful, but it requires strong tests, monitoring, and rollback strategies.


Why CI/CD Matters

Without CI/CD, deployment often depends on manual steps:

Build locally
Run some tests manually
Copy files
Deploy manually
Hope nothing breaks

With CI/CD:

Push code
Pipeline builds
Pipeline tests
Pipeline checks security
Pipeline packages the app
Pipeline deploys or prepares deployment

That gives the team more confidence.


Main Benefits

Benefit Why it matters
Faster feedback Bugs are found minutes after pushing code
Safer releases Tests and checks run automatically
Repeatable deployments Same process every time
Less manual work Developers focus more on building features
Better visibility Pipeline logs show what happened

What is Bitbucket Pipelines?

Bitbucket Pipelines is Bitbucket’s built-in CI/CD tool.

It runs automated workflows when code is pushed to a repository.

The pipeline configuration is stored in a file called:

bitbucket-pipelines.yml

This file usually lives in the root of the project.


Basic Pipeline Flow

A simple pipeline can look like this:

Code push
  ↓
Install dependencies
  ↓
Build project
  ↓
Run tests
  ↓
Create artifact
  ↓
Deploy

For a Java project, this might include Maven commands.

For a frontend project, it might include npm commands.


Basic Bitbucket Pipeline Example

image: node:20

pipelines:
  default:
    - step:
        name: Install and Test
        script:
          - npm install
          - npm test

This means:

  1. Use a Node.js Docker image

  2. Run the pipeline on every push

  3. Install dependencies

  4. Run tests


Java / Maven Pipeline Example

image: maven:3.9-eclipse-temurin-17

pipelines:
  default:
    - step:
        name: Build and Test
        caches:
          - maven
        script:
          - mvn clean install

This pipeline:

  • uses Java 17

  • uses Maven

  • caches Maven dependencies

  • builds the project

  • runs tests


Important Pipeline Concepts

Concept Meaning
Pipeline The full automation workflow
Step One unit of work inside the pipeline
Script Commands executed inside a step
Cache Saved dependencies to speed up builds
Artifact Files saved after a step
Service Extra runtime dependency, like Docker
Trigger Event that starts the pipeline

Pipeline Triggers

Pipelines can run in different situations.

Trigger Example
Any push Run tests on every branch
Specific branch Deploy when code is merged to main
Git tag Release version v1.2.0
Manual trigger Run a pipeline from the Bitbucket UI
Pull request Validate code before merging

Example:

pipelines:
  default:
    - step:
        name: Run Tests
        script:
          - npm test

  branches:
    main:
      - step:
          name: Deploy
          script:
            - echo "Deploying..."

Here:

  • every branch runs tests

  • only main runs deployment


YAML Basics

Bitbucket Pipelines uses YAML.

A few basics:

name: Example

script:
  - echo "First command"
  - echo "Second command"

step:
  name: Build
  script:
    - npm install
    - npm run build

Indentation matters a lot in YAML.

Wrong indentation can break the pipeline.


Reusable Steps

Pipelines can use anchors to avoid repeating code.

definitions:
  steps:
    - step: &build-step
        name: Build
        script:
          - npm install
          - npm run build

pipelines:
  default:
    - step: *build-step

  branches:
    main:
      - step: *build-step

&build-step defines a reusable step. *build-step uses it.

This is useful when multiple branches share the same build logic.


Caching

Caching makes pipelines faster.

For example:

caches:
  - maven

or:

caches:
  - node

Without cache, dependencies may be downloaded every time.

With cache, the pipeline can reuse previously downloaded dependencies.

Common caches:

Ecosystem Cache
Java / Maven maven
Node.js node
Python custom pip cache
Security tools custom cache

Artifacts

Artifacts are files saved from one step.

Examples:

  • build files

  • test reports

  • coverage reports

  • JAR files

  • generated frontend assets

Example:

artifacts:
  - target/*.jar
  - target/surefire-reports/**

Artifacts are useful for debugging and for passing files between pipeline steps.


Services

Some pipeline steps need extra services.

Example:

services:
  - docker

This is common when the pipeline needs to:

  • build Docker images

  • run integration tests

  • use Testcontainers

  • start temporary databases


Security Checks

A good pipeline should not only build and test the code.

It should also check for security problems.

Examples:

  • dependency vulnerability scanning

  • secret scanning

  • static analysis

  • container image scanning

For Java projects, OWASP Dependency Check is commonly used to scan dependencies for known vulnerabilities.

Example idea:

Pipeline
  ↓
Install dependencies
  ↓
Run tests
  ↓
Scan dependencies
  ↓
Build artifact

Security checks should happen before deployment, not after.


OIDC Authentication

Modern pipelines should avoid long-lived cloud credentials.

OIDC is a safer way for CI/CD systems to authenticate with cloud providers.

The idea:

Pipeline starts
  ↓
CI provider creates a short-lived identity token
  ↓
Cloud provider verifies the token
  ↓
Cloud provider gives temporary credentials
  ↓
Pipeline deploys safely

This is better than storing permanent AWS keys in repository variables.


Deployment with Tags

Some teams use Git tags to trigger deployments.

Example:

git tag v1.2.0
git push origin v1.2.0

Then the pipeline can detect the tag and run a release flow.

Example:

pipelines:
  tags:
    "v*":
      - step:
          name: Release
          script:
            - echo "Releasing version"

Tags are useful because they make releases explicit and traceable.


Debugging Failed Pipelines

When a pipeline fails, I usually check:

  1. Which step failed?

  2. What was the exact error message?

  3. Did dependencies install correctly?

  4. Did tests fail?

  5. Did the build run out of memory?

  6. Did authentication fail?

  7. Are required environment variables missing?

A failed pipeline is not just a blocker. It is feedback from the automation system.


Useful Commands

Run tests locally before pushing:

npm test

For Java/Maven:

mvn test

Build a Java project:

mvn clean install

Create a Git tag:

git tag v1.2.0
git push origin v1.2.0

Delete a local tag:

git tag -d v1.2.0

Delete a remote tag:

git push origin --delete v1.2.0

My Takeaway

The most useful way to think about CI/CD is:

CI/CD is an automated safety net for code changes.

It does not replace good engineering judgment, but it reduces avoidable mistakes.

A good pipeline should:

  • build the project

  • run tests

  • check security risks

  • create deployable artifacts

  • make deployment repeatable

  • provide clear logs when something fails

Once I understood the pipeline as a sequence of small automated checks, Bitbucket Pipelines became much easier to reason about.