Configuration checker for Tableau.
This repository provides protoc-gen-go-tableau-checker, a protoc /
buf plugin that generates *.check.go stubs. You implement
Check / CheckCompatibility on those stubs; the generated hub loads configs
and runs the checks (including ProcessAfterLoadAll for derived / custom
messagers).
The test/ directory is an integration suite (proto → generate → go test).
It has no main package, so cd test && go run . does not work.
From the repo root:
The structured error integration uses the public github.com/tableauio/tableau API from
the Tableau revision pinned in go.mod (companion PR).
Standalone builds use that dependency directly. To develop both repositories
together, optionally use the sibling Tableau checkout:
go work init . ../tableauThe workspace files are local and ignored by Git. After the companion PR is merged, update the dependency to the merged revision or its next release.
# 1) Regenerate *.pb.go, loader *.pc.go, and *.check.go under test/
cd test && buf generate && cd ..
# 2) Run all tests (plugin unit tests + test/ examples & checks)
go test ./...
# 3) Run documented examples under test/ (stdout is matched to // Output:)
go test ./test/ -run 'Example_' -count=1Useful narrower commands:
go test ./cmd/protoc-gen-go-tableau-checker/ # plugin AST / generator tests
go test ./test/check/ # checker hub + customconf tests
go test ./test/ -run Example_customConf -v # single example (PASS still hides Output)Wire it into buf.gen.yaml (see test/buf.gen.yaml for a working local setup):
version: v2
plugins:
- local: ["go", "run", "github.com/tableauio/checker/cmd/protoc-gen-go-tableau-checker@v0.7.1"]
out: check
opt:
- paths=source_relative
- out=check # directory of existing *.check.go for incremental merge
strategy: allDuring local development against this repo (or before a release tag exists), point local at the tree instead:
- local: ["go", "run", "../cmd/protoc-gen-go-tableau-checker"]Common options:
| Option | Default | Meaning |
|---|---|---|
pkg |
check |
Go package name of generated checker files |
loader-pkg |
tableau |
Loader package name under each file’s Go import path |
out |
(empty) | Existing checker output dir used for incremental updates |
Check and CheckCompatibility return joined error chains on failure and nil
on success. Import github.com/tableauio/tableau.
Call tableau.Inspect(err) when reporting an error to obtain its
flat Details list. Tableau load errors already contain their source metadata,
including actual and primary workbooks, worksheets, and failing cells. Checker
preserves those details. Custom check, compatibility, and post-load failures
retain their original messages and carry the workbook and worksheet declared
by their protobuf schema. Source details also retain workbook/worksheet aliases
and configured merger/scatter sheet specifiers in text and JSON. Text appends
these settings to the workbook/worksheet lines as parenthesized key-value pairs.
These schema settings describe possible inputs; precise failing shard/cell locations remain
separate. Existing source details
take precedence; custom messagers without a protobuf source retain plain errors.
Failure limits count failed messagers, independently of detail count.
Progress logs identify each failed messager on one line. Detailed errors are
rendered once by the caller. Custom failures use Tableau code E0005
(custom check failed) and retain their original message as the reason. Existing
specific Tableau codes take precedence; aggregate numbering spans all failures.
Use errors.New or fmt.Errorf for custom failures. When a failure belongs to
a more specific workbook or sheet, attach its source with tableau.WrapKV:
return tableau.WrapKV(fmt.Errorf("task %d has no condition target", taskID),
tableau.KeyBookName, workbookName,
tableau.KeySheetName, sheetName)Checker supplies the schema workbook and worksheet when those fields are absent.
WrapKV captures its caller's stack if the error does not already have one.
Print the inspected error for Tableau's localized text, or marshal it for the
flat { "details": [...] } JSON representation. Original causes remain
reachable through errors.As and errors.Is before and after inspection.
if err := hub.Check(dir, format.JSON); err != nil {
serr := tableau.Inspect(err)
fmt.Print(serr)
// For JSON output, use json.Marshal(serr).
}Inspect the complete Check or CheckCompatibility result once at the reporting
boundary. Printing the raw joined error includes checker operation wrappers and
can restart numbering inside each load failure. Inspecting it produces Tableau's
flat, consistently numbered output, including reference and source metadata.
For a CLI that returns an error for its framework to print:
if err := hub.Check(dir, format.CSV); err != nil {
return fmt.Errorf("check failed, see errors below:\n%w", tableau.Inspect(err))
}| Path | Role |
|---|---|
cmd/protoc-gen-go-tableau-checker/ |
Plugin source + embedded hub template |
test/proto/ |
Sample Tableau workbooks (.proto) |
test/protoconf/ |
Generated *.pb.go + loader *.pc.go |
test/check/ |
Generated / hand-edited *.check.go hub and checkers |
test/customconf/ |
Example derived messager (CustomItemConf) |
test/testdata*/ |
JSON / CSV fixtures for load & compatibility examples |
test/example_test.go |
Runnable Example_* demos |
Prefer golangci-lint strict generated-file detection so *.check.go /
*.pc.go are excluded. Example .golangci.yaml:
version: "2"
linters:
exclusions:
generated: stricttest/buf generate runs three plugins (see test/buf.gen.yaml):
buf.build/protocolbuffers/go→test/protoconf/*.pb.goprotoc-gen-go-tableau-loader→test/protoconf/tableau/*.pc.goprotoc-gen-go-tableau-checker(this repo) →test/check/*.check.go
Hand-written logic in *.check.go (for example ActivityConf.Check) is kept
across regenerations via incremental AST merge when out=check points at the
existing checker directory.