name: Buf action CI on: push: pull_request: branches: - main permissions: contents: read pull-requests: write env: BUF_VERSION: "1.35.0" # Minimum version we support. BUF_MODULE: ${{ vars.BUF_MODULE }} jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Build run: | make build - name: Generate run: | make generate - name: Check diff run: | make checkgenerate test-setup: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - uses: ./ with: setup_only: true - run: buf --version | grep $BUF_VERSION test-setup-latest: runs-on: ubuntu-latest needs: test-setup env: BUF_VERSION: "" # Use the latest version steps: - uses: actions/checkout@v4 - uses: ./ with: setup_only: true - run: buf --version test-setup-macos: needs: test-setup if: github.event_name == 'push' runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: ./ with: setup_only: true - run: buf --version | grep $BUF_VERSION test-setup-windows: needs: test-setup if: github.event_name == 'push' runs-on: windows-latest steps: - uses: actions/checkout@v4 - uses: ./ with: setup_only: true - run: buf --version | Select-String -Pattern $env:BUF_VERSION -CaseSensitive -SimpleMatch test-setup-self-hosted: needs: test-setup # Disable this job, only for testing. if: false runs-on: self-hosted steps: - uses: actions/checkout@v4 - uses: ./ with: setup_only: true - run: buf --version | grep $BUF_VERSION test-empty-build: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - uses: ./ with: lint: false format: false breaking: false push: false archive: false pr_comment: false continue-on-error: true # build fails test-lint: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - run: | mkdir -p proto/test/v1 printf 'version: v2\nmodules:\n - path: proto' > buf.yaml printf 'syntax = "proto3"; package test.v1; message A { string a = 1; }' > proto/test/v1/test.proto - uses: ./ with: lint: true format: false breaking: false push: false archive: false pr_comment: false test-format: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - run: | mkdir -p proto printf 'version: v2\nmodules:\n - path: proto' > buf.yaml printf 'syntax = "proto3";\n\nmessage A {\n string a = 1;\n}\n' > proto/test.proto - uses: ./ with: lint: false format: true breaking: false push: false archive: false pr_comment: false test-breaking: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - run: | mkdir -p proto printf 'version: v2\nmodules:\n - path: proto' > buf.yaml printf 'syntax = "proto3"; message A { string a = 1; }' > proto/test.proto - uses: ./ with: lint: false format: false breaking: true breaking_against: . push: false archive: false pr_comment: false test-comment: runs-on: ubuntu-latest # Only run on pull requests from the same repository, comments from forks are not tested. Dependabot is skipped. if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' needs: - test-lint - test-format - test-breaking steps: - uses: actions/checkout@v4 - run: | # Lint skipped, format fails, breaking succeeds mkdir -p proto printf 'version: v2\nmodules:\n - path: proto' > buf.yaml printf 'syntax = "proto3"; message A { string a = 1; }' > proto/test.proto - uses: ./ continue-on-error: true # format fails with: token: ${{ secrets.BUF_TOKEN }} lint: false # lint skipped format: true breaking: true breaking_against: . push: false archive: false pr_comment: true - uses: actions/github-script@v7 with: script: | const expects = [ "The latest Buf updates on your PR.", "✅ passed", "❌ failed (1)", "⏩ skipped", ]; const commentTag = ""; const { owner, repo } = context.repo; const prNumber = context.payload.pull_request?.number; if (!prNumber) { core.setFailed('No pull request number found.'); return; } const comments = await github.paginate(github.rest.issues.listComments, { owner: owner, repo: repo, issue_number: prNumber, }); const previousComment = comments.find((comment) => comment.body?.includes(commentTag), ); if (!previousComment) { core.setFailed('Missing comment on pull request.'); return; } for (const line of expects) { if (!previousComment.body?.includes(line)) { core.setFailed(`Comment does not include expected line: ${line}`); return; } } await github.rest.issues.updateComment({ owner: owner, repo: repo, comment_id: previousComment.id, body: `${previousComment.body}\nNB: This is a test comment.`, }); console.log(await github.graphql(` mutation { minimizeComment(input:{subjectId:"${previousComment.node_id}",classifier:RESOLVED}) { clientMutationId minimizedComment { isMinimized minimizedReason viewerCanMinimize } } } `)) core.info('Updated comment.'); test-push: runs-on: ubuntu-latest if: ${{ github.event_name == 'push' }} # --git-metadata is only available on push needs: build steps: - uses: actions/checkout@v4 - run: | mkdir -p proto/foo/v1 printf "version: v2\nmodules:\n - path: proto\n name: ${BUF_MODULE}\n" > buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > proto/foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: true archive: false pr_comment: false test-push-token-only: needs: build runs-on: ubuntu-latest if: ${{ github.event_name == 'push' }} # --git-metadata is only available on push steps: - uses: actions/checkout@v4 - run: | mkdir -p proto/foo/v1 printf "version: v2\nmodules:\n - path: proto\n name: ${BUF_MODULE}\n" > buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > proto/foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: true archive: false pr_comment: false test-push-unnamed: needs: build runs-on: ubuntu-latest if: ${{ github.event_name == 'push' }} # --git-metadata is only available on push steps: - uses: actions/checkout@v4 # Test v2 buf.yaml config. - run: | mkdir -p proto/foo/v1 printf "version: v2\nmodules:\n - path: proto\n" > buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > proto/foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: true archive: false pr_comment: false # Test v1 buf.yaml config. - run: | rm -rf proto mkdir -p proto/foo/v1 printf "version: v1\n" > proto/buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > proto/foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: true archive: false pr_comment: false input: proto # Test v2 with multiple modules, one without a name. - run: | mkdir -p foo/foo/v1 bar/bar/v1 printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > foo/foo/v1/bar.proto printf "syntax = \"proto3\";\npackage bar.v1;\nmessage Foo {}\n" > bar/bar/v1/foo.proto printf "version: v2\nmodules:\n - path: foo\n name: ${BUF_MODULE}\n - path: bar\n" > buf.yaml - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: true archive: false pr_comment: false test-archive: if: github.event_name == 'push' && github.ref_name != github.event.repository.default_branch runs-on: ubuntu-latest needs: - test-push - test-push-token-only - test-push-unnamed steps: - uses: actions/checkout@v4 - run: | mkdir -p proto/foo/v1 printf "version: v2\nmodules:\n - path: proto\n name: ${BUF_MODULE}\n" > buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > proto/foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: false archive: true pr_comment: false test-archive-unnamed: if: github.event_name == 'push' runs-on: ubuntu-latest needs: - test-push - test-push-token-only - test-push-unnamed steps: - uses: actions/checkout@v4 - run: | mkdir -p proto/foo/v1 printf "version: v2\nmodules:\n - path: proto\n" > buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > proto/foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: false archive: true pr_comment: false - run: | rm -rf proto mkdir -p proto/foo/v1 printf "version: v1\n" > proto/buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > proto/foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: false archive: true pr_comment: false input: proto test-archive-root: # Check the archive command parses non-module names. runs-on: ubuntu-latest needs: - test-archive steps: - uses: actions/checkout@v4 - run: | mkdir -p foo/v1 printf "version: v2\nname: ${BUF_MODULE}\n" > buf.yaml printf "syntax = \"proto3\";\npackage foo.v1;\nmessage Bar {}\n" > foo/v1/bar.proto - uses: ./ with: token: ${{ secrets.BUF_TOKEN }} lint: false format: false breaking: false push: true # Push to re-create. archive: true # Archive the pushed module. comment: false