Skip to main content
GitHub Actions lets you automate API testing directly from your repository. Bruno ships an official GitHub Action that installs @usebruno/cli, runs your bru command, and exposes machine-readable test counts. PR comments, annotations, artifact upload, and soft-fail behavior are handled by standard GitHub Actions ecosystem tools documented in Pairing with downstream actions.

Official GitHub Action

PropertyValue
MarketplaceBruno CLI
Repositoryusebruno/bruno-cli-action
Referenceusebruno/bruno-cli-action@v1
The action is a composite action. It prepends bru to your command input, auto-injects --reporter-junit when absent, parses the JUnit summary, and exposes exit-code, passed, failed, total, and duration-ms as step outputs. The workflow step fails naturally when bru exits non-zero.
Write run --env prod, not bru run --env prod. The action prepends bru for you.

Quick start

name: API Tests
on: [pull_request, push]

jobs:
  bruno:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: usebruno/bruno-cli-action@v1
        with:
          working-directory: tests/payments
          command: 'run --env prod'
This minimal workflow installs the CLI, runs the collection, and populates count outputs. The step turns red on assertion failure and green on success. No PR comments, annotations, Step Summary, or uploaded artifacts are created by default. See Pairing with downstream actions for those patterns.

How this workflow works

A GitHub Actions workflow is a YAML file in .github/workflows/. Each line tells GitHub what to run and when. Here is what the quick start example means:
LineWhat it does
name: API TestsDisplay name shown in the GitHub Actions tab. You can pick any name.
on: [pull_request, push]When to run. This workflow triggers on every push and pull request.
jobs:A workflow is made of one or more jobs.
bruno:Job name. This is an identifier you choose (like bruno or api-tests).
runs-on: ubuntu-latestThe virtual machine GitHub spins up to run your steps. ubuntu-latest is a standard Linux runner.
steps:Ordered list of tasks inside the job. They run top to bottom.
uses: actions/checkout@v6A reusable GitHub Action that clones your repository onto the runner so Bruno can read your collection files.
uses: usebruno/bruno-cli-action@v1Bruno’s official action. Format is owner/repo@version: usebruno is the org, bruno-cli-action is the action repo, @v1 pins the major version (gets compatible updates automatically).
with:Inputs you pass into the action, like function arguments.
working-directory: tests/paymentsThe folder on the runner where Bruno runs. Point this at your collection root (the folder that contains opencollection.yml or bruno.json). Think of it as cd tests/payments before running bru.
command: 'run --env prod'The CLI command without the bru prefix. The action prepends bru, so this becomes bru run --env prod. --env prod selects the prod environment from your collection.
In plain terms: GitHub checks out your code, moves into your collection folder, installs Bruno CLI, runs your collection against the prod environment, and reports pass or fail.

Inputs

InputRequiredDefaultDescription
commandyesThe bru subcommand and flags (e.g. run --env prod). Reporter flags are optional; --reporter-junit is auto-injected if absent.
bru-versionnolatestVersion of @usebruno/cli to install.
working-directoryno.Shell working directory. Typically the Bruno collection root.
CLI flags such as --env, --env-var, --tags, --bail, --sandbox, and --reporter-* go in command, not as separate action inputs. Every CLI flag works the day it ships in the CLI.

Outputs

Available as ${{ steps.<id>.outputs.<name> }} in subsequent steps:
OutputDescription
exit-codeExit code from the bru process
passedNumber of passed requests
failedNumber of failed requests (assertion failures or runtime errors)
totalTotal requests run
duration-msTotal run duration in milliseconds
Report file paths are intentionally not outputs. Pass an explicit --reporter-junit <path> in command and reference that path in downstream steps.

Behavior

JUnit auto-injection (always-on). If command does not contain --reporter-junit, the action appends --reporter-junit "$RUNNER_TEMP/bruno-junit.xml" before invoking bru. A minimal command: 'run' still produces count outputs. If you pass --reporter-junit some/path.xml, the action uses your path. Exit code propagation. The step succeeds on exit 0 and fails on non-zero. To continue the workflow past failures, use GitHub’s built-in continue-on-error: true on the step.

Versioning

TagBehavior
@v1Floating major tag. Receives every backwards-compatible release.
@v1.2.3Immutable. Pinned to a specific release.
The v<major> tag is retagged automatically on every published release.

Workspace structure

The demo workspace is organized as a Bruno workspace with an OpenCollection layout:
bruno-automation-demo-workspace/
├── .github/
│   └── workflows/
│       └── bruno-api-tests.yml
├── collections/
│   └── bruno-automation-demo/
│       ├── 01-smoke-checks/
│       ├── 02-ci-workflow/
│       ├── 03-release-gates/
│       ├── environments/
│       │   ├── ci.bru
│       │   ├── local.bru
│       │   └── staging.bru
│       └── opencollection.yml
├── environments/
│   ├── ci.yml
│   ├── local.yml
│   └── staging.yml
├── workspace.yml
└── reports/
Key items:
  • workspace.yml defines the workspace and points to the collection at collections/bruno-automation-demo.
  • environments/ci.yml is a global environment with variables like bruno_echo_url, platform_name, and build_id.
  • collections/bruno-automation-demo/ contains folders of requests with tests and assertions.

Run the demo with the action

name: Bruno API Tests

on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  bruno-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - run: mkdir -p reports

      - uses: usebruno/bruno-cli-action@v1
        with:
          working-directory: collections/bruno-automation-demo
          command: >
            run
            --global-env ci
            --workspace-path ../..
            --tags smoke,workflow,release-gate
            --env-var platform_name="GitHub Actions"
            --env-var build_id="${{ github.run_id }}"
            --env-var commit_sha="${{ github.sha }}"
            --reporter-html ../../reports/github-actions-report.html

      - uses: actions/upload-artifact@v6
        if: ${{ !cancelled() }}
        with:
          name: bruno-report
          path: reports/github-actions-report.html
          if-no-files-found: error
What this does: A fuller real-world example using the demo workspace above. It runs tagged requests with a global environment, injects CI variables (build_id, commit_sha), generates an HTML report, and uploads it as an artifact.

Other CI platforms

Bruno CLI also works on Jenkins, Azure DevOps, GitLab CI, and Bitbucket Pipelines via direct CLI invocation or the Bruno CLI Docker image. See Jenkins Integration for Jenkins-specific examples.

Resources