TL;DR

Add .github/workflows/buf-ci.yaml to the repo:

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

This default config:

  • Runs build, lint, format, and breaking change checks on every PR
  • Pushes named modules to the BSR on git push/tag/branch
  • Archives BSR labels when a branch or tag is deleted

Skip breaking change detection

Via PR label

Add the label buf skip breaking to the PR. Requires labeled/unlabeled in the trigger (already in the default config above).

Via commit message

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

Disable label-skip entirely

breaking: ${{ github.event_name == 'pull_request' }}

Disable individual steps

Each step has a boolean parameter:

- uses: bufbuild/buf-action@v1
  with:
    format: false   # disable formatting
    lint: false     # disable linting

Trigger steps on specific events

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

Only push when proto files change

on:
  push:
    paths:
      - '**.proto'
      - '**/buf.yaml'
      - '**/buf.lock'
      - '**/buf.md'
      - '**/README.md'
      - '**/LICENSE'

Non-root module

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

Or check out both head and base locally:

- 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/proto/
    breaking_against: base/proto/

Setup only (run buf manually after)

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

Pin buf version

- uses: bufbuild/buf-action@v1
  with:
    version: "1.68.4"

If unset, resolution order: $BUF_VERSION env var → already installed on runner → latest GitHub release.

Disable PR summary comment

Remove pull-requests: write permission and set:

- uses: bufbuild/buf-action@v1
  with:
    pr_comment: false

See also

  • codegen-multi-service — generating Go code from protos across services, which this action validates and pushes
  • field-numbers — protobuf field number rules; breaking change detection catches violations of these
  • git-stacked-branch-merge — rebasing stacked branches before the CI run lands changes cleanly