From f657dc7ffe27192dbc9b8814786fe712f7e9e4a8 Mon Sep 17 00:00:00 2001 From: Yongrui Lin Date: Tue, 10 Nov 2026 07:43:49 +0000 Subject: [PATCH] api: generate and verify protos with buf Add buf.yaml, buf.gen.yaml, and `make generate` (format, lint, generate), with the protoc plugins pinned as go.mod tools. CI regenerates and fails on any diff. Regenerated *.pb.go headers; ax.proto formatting only. --- .github/workflows/go.yml | 6 ++++++ AGENTS.md | 8 ++++---- CONTRIBUTING.md | 1 + Makefile | 14 +++++++++++++- buf.gen.yaml | 23 +++++++++++++++++++++++ buf.yaml | 31 +++++++++++++++++++++++++++++++ go.mod | 6 ++++++ go.sum | 2 ++ pkg/apis/v1alpha1/ax.pb.go | 4 ++-- pkg/apis/v1alpha1/ax.proto | 2 -- pkg/apis/v1alpha1/ax_grpc.pb.go | 2 +- pkg/apis/v1alpha1/common.pb.go | 4 ++-- pkg/apis/v1alpha1/model.pb.go | 4 ++-- pkg/apis/v1alpha1/task.pb.go | 4 ++-- pkg/apis/v1alpha1/workspace.pb.go | 4 ++-- 15 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 buf.gen.yaml create mode 100644 buf.yaml diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 79d1738f..1d6a4ae2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -53,6 +53,12 @@ jobs: go mod tidy git diff --exit-code go.mod go.sum + - name: Verify API + run: | + make generate + git diff --exit-code + test -z "$(git ls-files --others --exclude-standard)" + - name: Build local binaries run: | go build -v ./cmd/ax diff --git a/AGENTS.md b/AGENTS.md index d9363c20..c3902b0e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,6 +39,7 @@ skills/ Developer skills (SKILL.md format). .agents/skills, .clau ```bash export GOTOOLCHAIN=auto # go.mod wants 1.27.1; older local Go auto-downloads it go mod tidy && git diff --exit-code go.mod go.sum +make generate # format + lint .proto, regenerate *.pb.go (CI asserts no diff) go build ./cmd/ax ./cmd/ax-server ./cmd/ax-task-runner go test ./... # ~20 s, 16 packages with tests; Postgres + E2E tiers self-skip go vet ./... && gofmt -l . # not run by CI; both are clean at HEAD @@ -57,9 +58,8 @@ location is where to look. How-to lives in the skills. - `pkg/apis/v1alpha1/*.proto` are the source of truth: `ax.proto` is the `AX` service, and the messages are in `common.proto`, `task.proto`, `workspace.proto`, and `model.proto`. `*.pb.go` are generated (`DO NOT EDIT` - headers). There is no `make generate` target; run `protoc` from the repo root - with `-I .` (imports are repo-root-relative) on all of those files, at the - generator versions in the `*.pb.go` headers. + headers); run `make generate` after editing a `.proto`. Imports are + repo-root-relative. - `internal/store/postgres/schema.go` loads `schema.sql`; change them together. **B. Agent Substrate** (details: `/substrate`) @@ -106,7 +106,7 @@ skill source there. Adding a skill means adding a row above. ## Definition of done -1. The four CI commands above pass locally. +1. The five CI commands above pass locally. 2. Postgres or E2E tier passes if you touched `internal/store/postgres` or the E2E paths. 3. `/sync-contract` has been run against your diff so `AGENTS.md` and `skills/` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 353758f4..198d6f99 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,6 +122,7 @@ make deploy 4. **Make changes and verify**: - Run tests: `make test` - Ensure clean modules: `go mod tidy` and verify with `git diff --exit-code go.mod go.sum` + - After editing a `.proto` file: `make generate` - Build binaries: `make build` 5. **Commit and open a PR**: diff --git a/Makefile b/Makefile index c503e7cb..081e9325 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,9 @@ CLAUDE_CODE_BASE_IMAGE ?= # Prefer podman, fall back to docker. CONTAINER_CLI ?= $(shell command -v podman 2>/dev/null || command -v docker 2>/dev/null) -.PHONY: build install images check-image-repo build-claude-code-image push-claude-code-image deploy deploy-server deploy-postgres apply-example test test-e2e e2e-setup e2e-run e2e-cleanup clean +BUF := go run github.com/bufbuild/buf/cmd/buf@v1.75.0 + +.PHONY: build install images check-image-repo build-claude-code-image push-claude-code-image generate deploy deploy-server deploy-postgres apply-example test test-e2e e2e-setup e2e-run e2e-cleanup clean ## -------------------------------------- ## Build Targets @@ -143,6 +145,16 @@ apply-example: @echo "==> Applying example task and resources using bin/ax..." ./bin/ax apply -f examples/simple.yaml +## -------------------------------------- +## API Targets +## -------------------------------------- + +# Format and lint .proto files, and regenerate the Go code. +generate: + $(BUF) format -w + $(BUF) lint + $(BUF) generate + ## -------------------------------------- ## Test & Verification Targets ## -------------------------------------- diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 00000000..4381155c --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,23 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Plugin versions are pinned in go.mod. +version: v2 +plugins: + - local: ["go", "tool", "protoc-gen-go"] + out: . + opt: paths=source_relative + - local: ["go", "tool", "protoc-gen-go-grpc"] + out: . + opt: paths=source_relative diff --git a/buf.yaml b/buf.yaml new file mode 100644 index 00000000..df0757b9 --- /dev/null +++ b/buf.yaml @@ -0,0 +1,31 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +version: v2 +modules: + - path: . # imports are repo-root-relative + includes: + - pkg/apis +lint: + use: + - STANDARD + except: + - PACKAGE_DIRECTORY_MATCH # package ax.v1alpha1 is in pkg/apis/v1alpha1 + - SERVICE_SUFFIX # the service is named AX + - RPC_RESPONSE_STANDARD_NAME # standard methods return the resource itself + - RPC_REQUEST_RESPONSE_UNIQUE # same +# Not needed while the API is v1alpha1. +# breaking: +# use: +# - WIRE_JSON diff --git a/go.mod b/go.mod index 968855e5..3a12309b 100644 --- a/go.mod +++ b/go.mod @@ -23,4 +23,10 @@ require ( golang.org/x/sys v0.48.0 // indirect golang.org/x/text v0.42.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.0 // indirect +) + +tool ( + google.golang.org/grpc/cmd/protoc-gen-go-grpc + google.golang.org/protobuf/cmd/protoc-gen-go ) diff --git a/go.sum b/go.sum index 9c33c634..c8cf1128 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.0 h1:6Al3kEFFP9VJhRz3DID6quisgPnTeZVr4lep9kkxdPA= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.6.0/go.mod h1:QLvsjh0OIR0TYBeiu2bkWGTJBUNQ64st52iWj/yA93I= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/apis/v1alpha1/ax.pb.go b/pkg/apis/v1alpha1/ax.pb.go index aa012396..3404913f 100644 --- a/pkg/apis/v1alpha1/ax.pb.go +++ b/pkg/apis/v1alpha1/ax.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc-gen-go v1.36.12 +// protoc (unknown) // source: pkg/apis/v1alpha1/ax.proto package v1alpha1 diff --git a/pkg/apis/v1alpha1/ax.proto b/pkg/apis/v1alpha1/ax.proto index 2119c8d8..7e1ed4b8 100644 --- a/pkg/apis/v1alpha1/ax.proto +++ b/pkg/apis/v1alpha1/ax.proto @@ -35,7 +35,6 @@ service AX { rpc SuspendTask(SuspendTaskRequest) returns (Task); rpc ResumeTask(ResumeTaskRequest) returns (Task); - // Workspaces rpc GetWorkspace(GetWorkspaceRequest) returns (Workspace); rpc ListWorkspaces(ListWorkspacesRequest) returns (ListWorkspacesResponse); @@ -47,5 +46,4 @@ service AX { rpc ListModels(ListModelsRequest) returns (ListModelsResponse); rpc UpdateModel(UpdateModelRequest) returns (Model); rpc DeleteModel(DeleteModelRequest) returns (DeleteModelResponse); - } diff --git a/pkg/apis/v1alpha1/ax_grpc.pb.go b/pkg/apis/v1alpha1/ax_grpc.pb.go index 30628f94..e9eb0f9d 100644 --- a/pkg/apis/v1alpha1/ax_grpc.pb.go +++ b/pkg/apis/v1alpha1/ax_grpc.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.0 -// - protoc v7.34.1 +// - protoc (unknown) // source: pkg/apis/v1alpha1/ax.proto package v1alpha1 diff --git a/pkg/apis/v1alpha1/common.pb.go b/pkg/apis/v1alpha1/common.pb.go index 487762bc..68501538 100644 --- a/pkg/apis/v1alpha1/common.pb.go +++ b/pkg/apis/v1alpha1/common.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc-gen-go v1.36.12 +// protoc (unknown) // source: pkg/apis/v1alpha1/common.proto package v1alpha1 diff --git a/pkg/apis/v1alpha1/model.pb.go b/pkg/apis/v1alpha1/model.pb.go index b24e0717..269cbd06 100644 --- a/pkg/apis/v1alpha1/model.pb.go +++ b/pkg/apis/v1alpha1/model.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc-gen-go v1.36.12 +// protoc (unknown) // source: pkg/apis/v1alpha1/model.proto package v1alpha1 diff --git a/pkg/apis/v1alpha1/task.pb.go b/pkg/apis/v1alpha1/task.pb.go index ac7fc149..62f6280a 100644 --- a/pkg/apis/v1alpha1/task.pb.go +++ b/pkg/apis/v1alpha1/task.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc-gen-go v1.36.12 +// protoc (unknown) // source: pkg/apis/v1alpha1/task.proto package v1alpha1 diff --git a/pkg/apis/v1alpha1/workspace.pb.go b/pkg/apis/v1alpha1/workspace.pb.go index dbdc2656..10e19f37 100644 --- a/pkg/apis/v1alpha1/workspace.pb.go +++ b/pkg/apis/v1alpha1/workspace.pb.go @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 -// protoc v7.34.1 +// protoc-gen-go v1.36.12 +// protoc (unknown) // source: pkg/apis/v1alpha1/workspace.proto package v1alpha1