Skip to content

CI/CD integration with the Buf GitHub Action#

The buf-action GitHub Action makes it easy to run the Buf CLI within a workflow to check for build, lint, format, and breaking change errors, and automatically publish schema changes to the Buf Schema Registry (BSR).

If you're not using GitHub, the Buf CLI is easy to integrate into other CI/CD systems.

Annotations example for lint and breaking changes

TL;DR#

To use the Buf GitHub Action, add a .github/workflows/buf-ci.yaml file to your repository with the following content:

.github/workflows/buf-ci.yaml
name: Buf CI
on:
  push:
  pull_request:
    types: [opened, synchronize, reopened, labeled, unlabeled]
  delete:
permissions:
  contents: read
  pull-requests: write
jobs:
  buf:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: bufbuild/buf-action@v1
        with:
          # Publishing schema changes to the BSR requires a BSR authentication token.
          token: ${{ secrets.BUF_TOKEN }}
          # Include this line if you only want to set up the Action and do nothing else.
          # setup_only: true
          # Include a GitHub token to ensure API requests aren't rate limited.
          # github_token: ${{ secrets.GITHUB_TOKEN }}

This default configuration:

  • Uses buf push to push named modules to the BSR when you push a Git commit, tag, or branch to GitHub.
  • Runs all Buf checks (build, lint, format, and breaking), posting a summary comment for any pull request.
  • Archives corresponding labels in the BSR when you delete a Git branch or tag.

Authentication and BSR Tokens#

To publish schema changes to the BSR, the Buf GitHub Action requires a BSR authentication token for "push" and "archive label" steps. Set the token parameter to its value. We recommend storing the token as a GitHub secret. A post-action step will logout from the BSR to ensure the token is not stored in the .netrc file.

Common workflows#

The Action is designed to suit a variety of workflows, often by configuring parameters, tailoring its configuration to suit your needs. Some of the most common workflows are documented below, and there's over a dozen complete buf-ci.yaml examples in the Action's GitHub repo.

Skip breaking change detection using labels#

By default, the action runs the breaking change detection step on every pull request. To skip this step for a specific pull request, you can add the buf skip breaking label to the PR. This is useful for cases where breaking changes are intentional or when you want to bypass the check temporarily, such as during prototyping or non-production changes.

Skip breaking changes example

Using labels provides a transparent way to bypass breaking change detection while making the decision visible and documented in the pull request.

Create the buf skip breaking label#

To enable skipping the breaking change detection step, you first need to add a label named buf skip breaking to your GitHub repository. This can be done through the GitHub UI on the current PR or via the repository settings. For the current PR, click on the "Labels" section in the right sidebar and select "Edit label". Add a new label with the name buf skip breaking and a color of your choice.

See GitHub documentation on managing labels for more information.

Ensure the workflow responds#

For the action to re-run checks when the buf skip breaking label is added or removed, ensure your workflow file includes the labeled and unlabeled event types in the pull_request trigger. This is already included in the default workflow configuration:

Ensure labeled and unlabeled pull_request types are included
on:
  pull_request:
    types: [opened, synchronize, reopened, labeled, unlabeled]

Disabling the ability to skip breaking change checks#

To disable the ability to skip breaking change checks via a label, set the breaking parameter to the value ${{ github.event_name == 'pull_request' }} so it runs on all PRs. See examples/disable-skip/buf-ci.yaml for an example.

Skip steps using commit messages#

To conditionally run steps based on user input, use the GitHub action context. For example, to disable breaking change detection on commits with messages containing buf skip breaking:

Skips steps with certain commit messages
- uses: bufbuild/buf-action@v1
  with:
    breaking: |
      contains(fromJSON('["push", "pull_request"]'), github.event_name) &&
      !contains(github.event.head_commit.message, 'buf skip breaking')

See GitHub Actions job context documentation.

Disable specific steps#

To disable parts of the workflow, each step corresponds to a boolean flag in the parameters. For example, to disable formatting, set the parameter format to false:

Disabling specific steps
- uses: bufbuild/buf-action@v1
  with:
    format: false

See Parameters for all available parameters.

Customize triggers for steps#

To trigger steps on different events, use the GitHub action context to determine the event type. For example, to run format on both push and pull_request:

Trigger steps on different events
- uses: bufbuild/buf-action@v1
  with:
    format: ${{ contains(fromJSON('["push", "pull_request"]'), github.event_name) }}

See GitHub Actions expressions documentation.

Only push when APIs change#

To push only when your module changes, restrict the push step for any changes to buf related files. This can be achieved by using the paths filter on the push event:

Only push when APIs change
push:
  paths:
    - '**.proto'
    - '**/buf.yaml'
    - '**/buf.lock'
    - '**/buf.md'
    - '**/README.md'
    - '**/LICENSE'

See the push on changes example for a full configuration file.

Configure summary comment#

The Action reports the status of the most recent checks in a comment on each pull request.

Comment example showing the GitHub summary

To disable the comment, set the pr_comment parameter to false and remove the pull_request: write permission because it's no longer required.

Disable summary comment
name: Buf CI
on:
  push:
  pull_request:
    types: [opened, synchronize, reopened, labeled, unlabeled]
  delete:
permissions:
  contents: read
- pull-requests: write
jobs:
  buf:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: bufbuild/buf-action@v1
        with:
          token: ${{ secrets.BUF_TOKEN }}
+         pr_comment: false

Configuration#

Parameters#

To customize the behavior of the Action, use parameters in the workflow file, adding them to the with section:

Parameter usage example
- uses: bufbuild/buf-action@v1
  with:
      # Set up the Action and do nothing else.
      setup_only: false
Parameter Description Default
version Version of the buf CLI to use. Latest version
checksum Checksum of the buf CLI to verify (sha256).
token API token for logging into the BSR.
domain Domain for logging into the BSR, enterprise only. buf.build
input Input for the buf command.
paths Limit to specific files or directories (separated by newlines).
exclude_imports Exclude files imported by the target modules. False
exclude_paths Exclude specific files or directories, e.g. "proto/a/a.proto", "proto/a" (separated by newlines).
pr_comment Comment the results on the pull request. The workflow and job name combination must be unique. Only on pull requests (non forks)
format Whether to run the formatting step. Runs on pushes to Git PR
lint Whether to run the linting step. Runs on pushes to Git PR
breaking Whether to run the breaking change detection step. Runs on pushes to Git PR
breaking_against Input to compare against. Base of the PR or the commit before the event
breaking_against_registry Whether to use the Buf Schema Registry for breaking change detection. If true, the breaking_against parameter is ignored. False
push Whether to run the push step. Runs on Git pushes (non forks)
push_disable_create Disables repository creation if it does not exist. False
archive Whether to run the archive step. Runs on Git deletes (non forks)
setup_only Setup only the buf environment, optionally logging into the BSR, but without executing other commands.
github_actor GitHub actor for API requests. Actor from GitHub context
github_token GitHub token for API requests. Ensures requests aren't rate limited Token from GitHub context
public_github_token GitHub token for github.com. Must be set when running on a private GitHub Enterprise instance to authenticate requests, otherwise ignored.

Pinning the buf version#

For reproducible builds, you can pin to an explicit version of buf by setting version:

Pinning the buf version
-   uses: bufbuild/buf-action@v1
    with:
    version: 1.50.1

If no version is specified in the workflow config, the action resolves the version in this order of precedence:

  • A version specified in the environment variable ${BUF_VERSION}.
  • Any version of buf already installed on the runner.
  • The latest version of the buf binary from the official releases on GitHub.

Specifying an input directory#

To run the action for inputs not declared at the root of the repository, set the parameter input to the directory of your buf.yaml file.

Specifying an input
- uses: bufbuild/buf-action@v1
  with:
    input: <path/to/module>

Breaking change detection by default will use the input value as a subdirectory for the breaking against value. To customize this behavior, set the parameter breaking_against to the desired input.

Specifying breaking_against
- uses: bufbuild/buf-action@v1
  with:
    input: <path/to/module>
    breaking_against: ${{ github.event.repository.clone_url }}#format=git,commit=${{ github.event.pull_request.base.sha }},subdir=<path/to/module>

Alternatively, you can check out the base for the breaking comparison to a local folder and then set the value of breaking_against to the path of the base.

Using a local checkout for breaking_against
- uses: actions/checkout@v4
  with:
    path: head
- uses: actions/checkout@v4
  with:
    path: base
    ref: ${{ github.event.pull_request.base.sha }}
- uses: bufbuild/buf-action@v1
  with:
    input: head/<path/to/module>
    breaking_against: base/<path/to/module>

For more information on inputs, see the Buf Inputs Reference.

Running setup only#

To only set up the action without running any commands, set the parameter setup_only to true. This installs buf, optionally logging in to the schema registry, but no additional commands are run. Subsequent steps have buf available in their $PATH and can invoke buf directly.

Running setup only
- uses: bufbuild/buf-action@v1
  with:
    setup_only: true
- run: buf build --error-format github-actions

See the setup only example for a full configuration file.

Migrating from individual Buf actions#

If you're currently using any of our individual Actions (buf-setup-action, buf-breaking-action, buf-lint-action, buf-push-action), we recommend migrating to this consolidated action that has additional capabilities. Benefits include:

  • Less configuration and setup, with built-in best practices.
  • Enhanced integration with Git data when pushing to the BSR.
  • Status comments on pull requests.
  • Easy configuration for custom behavior.

See the migration guide for more information.

Debugging#

To debug the action, rerun the workflow with debug logging enabled. This runs all buf commands with the --debug flag. See the re-run jobs with debug logging for more information.