https://github.com/usebruno/bruno-cli-action
Bruno CLI Github Action Runner
https://github.com/usebruno/bruno-cli-action
Last synced: about 1 month ago
JSON representation
Bruno CLI Github Action Runner
- Host: GitHub
- URL: https://github.com/usebruno/bruno-cli-action
- Owner: usebruno
- License: mit
- Created: 2024-08-14T08:31:59.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2026-06-09T13:12:11.000Z (about 2 months ago)
- Last Synced: 2026-06-09T15:12:22.523Z (about 2 months ago)
- Language: JavaScript
- Size: 14.6 KB
- Stars: 2
- Watchers: 2
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Bruno CLI GitHub Action
Official GitHub Action for running [Bruno CLI](https://docs.usebruno.com/bru-cli/overview) commands in CI/CD workflows with full support for collection runs and exposes machine-readable counts (`exit-code`, `passed`, `failed`, `total`, `duration-ms`) for downstream steps.
- [Usage](#usage)
- [Customize](#customize)
- [Inputs](#inputs)
- [Outputs](#outputs)
- [Behavior](#behavior)
- [Versioning](#versioning)
- [Examples](#examples)
- [Other CI Platforms](#other-ci-platforms)
- [Resources](#resources)
## Usage
The following shows the minimum setup to configure the GitHub Action with a command and return counts as outputs. Learn about the [supported inputs](#inputs) you can use to customize the GitHub Action.
```yaml
name: API Tests
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run Bruno Collection
uses: usebruno/bruno-cli-action@v1
with:
working-directory: tests/payments
command: 'run --env prod'
```
**What you'll see:** the workflow step turns red on assertion failure (green on success). Outputs are populated for downstream conditional steps.
UI rendering, artifact upload, PR comments, and soft-fail semantics are delegated to the GitHub Actions ecosystem (`EnricoMi/publish-unit-test-result-action`, `dorny/test-reporter`, `actions/upload-artifact`, `continue-on-error`). See [Examples](#examples) for canonical recipes.
## Customize
Customize the Bruno CLI GitHub Action to suit your API project's CI/CD workflow.
### Inputs
| Name | Type | Description |
|---|---|---|
| `command` | String | **Required.** The Bruno CLI command to run and its options (e.g. `run --env prod`). The action prepends `bru`. |
| `bru-version` | String | Version of `@usebruno/cli` to install. (Default: `latest`) |
| `working-directory` | String | Path of the Bruno collection directory. (Default: `.`) |
**Example using all inputs:**
```yaml
- name: Run Bruno collection
uses: usebruno/bruno-cli-action@v1
with:
command: 'run --env prod --reporter-junit results.xml'
bru-version: '3.5.0'
working-directory: tests/payments
```
### Outputs
Available as `${{ steps..outputs. }}` in subsequent steps:
| Name | Description |
|---|---|
| `exit-code` | Exit code from the Bruno CLI command. 0 indicates success, non-zero indicates failure. |
| `passed` | Number of passed requests. |
| `failed` | Number of failed requests (assertion failures or runtime errors). |
| `total` | Total number of requests run. |
| `duration-ms` | Total run duration in milliseconds. |
## Versioning
| Tag | Behaviour |
|---|---|
| `@v1` | Floating major. Receives every backwards-compatible release. |
| `@v1.0.0` | Immutable. Pinned to a specific release. |
The `v` tag is retagged automatically on every published release.
## Examples
The following examples cover some of the reporting and artifact use case. Use `--reporter-junit` flag to emit clean JUnit XML; downstream actions render it for the user-visible surface needed or upload it as a workflow artifact.
- [PR comment on every run (sticky)](#pr-comment-on-every-run-sticky)
- [Checks tab UI via dorny/test-reporter](#checks-tab-ui-via-dornytest-reporter)
- [Artifact upload with header sanitization](#artifact-upload-with-header-sanitization)
- [Multiple report formats (JUnit + HTML + JSON)](#multiple-report-formats-junit--html--json)
- [Slack notification on failure](#slack-notification-on-failure)
- [Simple non-sticky PR comment via gh CLI](#simple-non-sticky-pr-comment-via-gh-cli)
### PR comment on every run (sticky)
The most common ask. `EnricoMi/publish-unit-test-result-action` posts a single comment per PR with structured results, updated on re-runs. Adds a check run with rich annotations as a side benefit.
```yaml
name: API Tests
on: [pull_request]
permissions:
pull-requests: write
checks: write
contents: read
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 --reporter-junit results.xml'
- uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: tests/payments/results.xml
```
**What you'll see:** a single Bruno-themed comment in the PR Conversation tab that updates in place on every re-run, plus a check run with structured per-test results in the PR Checks tab.
### Checks tab UI via dorny/test-reporter
If you have a polyglot test stack (Jest, Pytest, Bruno) and want all results in the same Checks tab UI, dorny is the better tool than EnricoMi:
```yaml
- uses: usebruno/bruno-cli-action@v1
with:
working-directory: tests/payments
command: 'run --env prod --reporter-junit results.xml'
- uses: dorny/test-reporter@v1
if: always()
with:
name: Bruno API tests
path: tests/payments/results.xml
reporter: java-junit
```
**What you'll see:** a separate check run in the PR Checks tab labeled "Bruno API tests" with structured per-test results and expandable failure details. Visually consistent with check runs from your other JUnit-emitting test suites.
### Artifact upload with header sanitization
Bruno's CLI handles sensitive-header redaction; pass the flag in `command`. Chain `actions/upload-artifact@v7` to persist the report:
```yaml
- uses: usebruno/bruno-cli-action@v1
with:
working-directory: tests/payments
command: 'run --env prod --reporter-junit results.xml --reporter-skip-headers "Authorization Cookie X-Tenant-Token"'
- uses: actions/upload-artifact@v7
if: always()
with:
name: bruno-report-${{ github.run_id }}-${{ github.job }}
path: tests/payments/results.xml
```
**What you'll see:** an artifact named `bruno-report--` on the workflow run page, downloadable for 90 days (GitHub default retention).
### Multiple report formats (JUnit + HTML + JSON)
Pass multiple reporter flags in `command`. Chain `actions/upload-artifact@v7` with a path list:
```yaml
- uses: usebruno/bruno-cli-action@v1
with:
working-directory: tests/payments
command: 'run --env prod --reporter-junit results.xml --reporter-html report.html --reporter-json report.json'
- uses: actions/upload-artifact@v7
if: always()
with:
name: bruno-reports-${{ github.run_id }}
path: |
tests/payments/results.xml
tests/payments/report.html
tests/payments/report.json
```
**What you'll see:** an artifact containing all three report files. Download to a browser to view the rich HTML report; JSON is consumable by custom dashboards or aggregators.
### Slack notification on failure
Use the action's `failed` output as a conditional. Use `continue-on-error: true` so the notification step still runs:
```yaml
- id: bruno
uses: usebruno/bruno-cli-action@v1
continue-on-error: true
with:
working-directory: tests/payments
command: 'run --env prod'
- if: steps.bruno.outputs.failed != '0'
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Bruno tests failed: ${{ steps.bruno.outputs.failed }}/${{ steps.bruno.outputs.total }} requests failed on ${{ github.ref_name }}",
"blocks": [{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Bruno test failures on ${{ github.ref_name }}*\n${{ steps.bruno.outputs.failed }}/${{ steps.bruno.outputs.total }} requests failed in ${{ steps.bruno.outputs.duration-ms }}ms. <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>"
}
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
```
**Prerequisites:** `SLACK_WEBHOOK_URL` secret configured in the repository.
**What you'll see:** the Bruno step shows red on failure (honest signal) but the workflow continues; a Slack message lands in the channel mapped to the webhook with counts, branch, duration, and a link to the workflow run.
### Simple non-sticky PR comment via gh CLI
For users who do not want EnricoMi's full setup and only need a quick "post a comment with the counts" pattern (no stickiness, each run adds a new comment):
```yaml
- id: bruno
uses: usebruno/bruno-cli-action@v1
with:
working-directory: tests/payments
command: 'run --env prod'
- if: always() && github.event_name == 'pull_request'
run: |
if [ "${{ steps.bruno.outputs.failed }}" -gt 0 ]; then
ICON="โ"
STATUS="${{ steps.bruno.outputs.passed }}/${{ steps.bruno.outputs.total }} passed, ${{ steps.bruno.outputs.failed }} failed"
else
ICON="โ
"
STATUS="${{ steps.bruno.outputs.total }}/${{ steps.bruno.outputs.total }} passed"
fi
gh pr comment ${{ github.event.pull_request.number }} \
--body "${ICON} **Bruno:** ${STATUS} in ${{ steps.bruno.outputs.duration-ms }}ms ยท [view run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
**Prerequisites:** `pull-requests: write` permission and the workflow triggered on `pull_request`.
**What you'll see:** a new comment posted to the PR on every workflow run. Each re-run adds another comment (no in-place update). Use EnricoMi (above) if you want stickiness.
## Other CI platforms
Bruno's CLI works on Jenkins, Azure DevOps, GitLab CI, and Bitbucket Pipelines via direct CLI invocation. The [Bruno CLI Docker image](https://hub.docker.com/r/usebruno/cli) is the recommended primitive there. See the [Bruno CLI Docker docs](https://docs.usebruno.com/bru-cli/docker) for platform-specific examples.
## Resources
- [Bruno CLI documentation](https://docs.usebruno.com/bru-cli/overview)
- [Bruno CLI command options](https://docs.usebruno.com/bru-cli/commandOptions)
- [Bruno NPM package](https://www.npmjs.com/package/@usebruno/cli)
- [Main Bruno repo](https://github.com/usebruno/bruno)
## License
MIT