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

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

yaml
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

yaml
- 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

yaml
- 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

yaml
- 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

yaml
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

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:
          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

yaml
- uses: bufbuild/buf-action@v1
  with:
      # Set up the Action and do nothing else.
      setup_only: false
ParameterDescriptionDefault
versionVersion of the buf CLI to use.Latest version
checksumChecksum of the buf CLI to verify (sha256).
tokenAPI token for logging into the BSR.
domainDomain for logging into the BSR, enterprise only.buf.build
inputInput for the buf command.
pathsLimit to specific files or directories (separated by newlines).
exclude_importsExclude files imported by the target modules.False
exclude_pathsExclude specific files or directories, e.g. "proto/a/a.proto", "proto/a" (separated by newlines).
pr_commentComment the results on the pull request. The workflow and job name combination must be unique.Only on pull requests (non forks)
formatWhether to run the formatting step.Runs on pushes to Git PR
lintWhether to run the linting step.Runs on pushes to Git PR
breakingWhether to run the breaking change detection step.Runs on pushes to Git PR
breaking_againstInput to compare against.Base of the PR or the commit before the event
breaking_against_registryWhether to use the Buf Schema Registry for breaking change detection. If true, the breaking_against parameter is ignored.False
pushWhether to run the push step.Runs on Git pushes (non forks)
push_disable_createDisables repository creation if it does not exist.False
archiveWhether to run the archive step.Runs on Git deletes (non forks)
setup_onlySetup only the buf environment, optionally logging into the BSR, but without executing other commands.
github_actorGitHub actor for API requests.Actor from GitHub context
github_tokenGitHub token for API requests. Ensures requests aren't rate limitedToken from GitHub context
public_github_tokenGitHub 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

yaml
-   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

yaml
- 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

yaml
- 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

yaml
- 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

yaml
- 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.