Skip to content

feat(load): protovalidate messages on the load path#438

Merged
wenchy merged 3 commits into
masterfrom
feat/load-protovalidate
Jul 14, 2026
Merged

feat(load): protovalidate messages on the load path#438
wenchy merged 3 commits into
masterfrom
feat/load-protovalidate

Conversation

@Kybxd

@Kybxd Kybxd commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

What

Make the load (checker) path run protovalidate on fully-assembled messages, matching the coverage confgen already provides in its storeMessage step.

Why

The load path is typically used by checkers and never reaches confgen's storeMessage, so protovalidate constraints (e.g. required fields, CEL rules) were previously not enforced when loading from input formats. This closes that gap.

How

  • internal/confgen/util.go: export NewValidator and Validate (previously unexported validate). NewValidator builds a validator whose extension type resolver is derived from prFiles, shared across the generate and load paths.
  • internal/confgen/confgen.go: GenAll / GenWorkbook now call NewValidator(prFiles) instead of inlining protovalidate.New(...).
  • load/load.go: at the end of loadOrigin, validate the fully-assembled message via confgen.Validate(msg, protovalidate.GlobalValidator). The global validator resolves extensions via protoregistry.GlobalTypes, which already contains custom predefined rules compiled into the binary, so no dedicated validator instance is needed on this path.

Validation is intentionally placed after the message is fully assembled (not inside ParseMessage), to avoid false positives on intermediate patch fragments and duplicate validation.

Test

go build ./... and go test ./load/... ./internal/confgen/... pass.

Export confgen.NewValidator/Validate and reuse them so the load
(checker) path validates fully-assembled messages via protovalidate's
global validator, matching confgen's storeMessage coverage.
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf CI / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJul 14, 2026, 7:16 AM

@Kybxd
Kybxd requested a review from wenchy July 13, 2026 12:38
@codecov

codecov Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.61%. Comparing base (1c5fee6) to head (e8f49e6).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #438      +/-   ##
==========================================
+ Coverage   75.60%   75.61%   +0.01%     
==========================================
  Files          88       88              
  Lines        9527     9531       +4     
==========================================
+ Hits         7203     7207       +4     
  Misses       1749     1749              
  Partials      575      575              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread load/load.go Outdated
}
// protovalidate the fully-assembled message, giving the load path the same
// coverage as confgen's storeMessage step.
return confgen.Validate(msg, protovalidate.GlobalValidator)

@wenchy wenchy Jul 13, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd better add test case to cover the error condition of confgen.Validate, expect protovalidate error. This accounts for future regression.

Regression testing is typically conducted after bug fixes are implemented, and it involves re-running tests to ensure features function as expected after new code is added.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Added a regression test in load/load_test.go (TestLoadOriginProtovalidate) plus a new testdata/unittest/Unittest#ValidateConf.csv fixture whose Name exceeds max_len:10. Loading it through the full load path asserts the violation surfaces as xerrors.ErrE2027, so the test will fail if the confgen.Validate call in loadOrigin is ever dropped.

Actual output:

error[E2027]: protovalidate violation
Reason: "this name is too long" violates rule: name: must be at most 10 characters

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protovalidate should work both on input (origin formats: xlsx/csv/yaml/xml) and output file formats(json/binpb/txtpb), as protovalide works on the final in memory protobuf message structure.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Moved the confgen.Validate step out of loadOrigin and converged it at the single LoadMessagerInDir exit, right after the message is fully assembled (and after patch merging, to avoid false positives on intermediate state). Now both input (xlsx/csv/yaml/xml) and output (json/binpb/txtpb) formats validate the final in-memory protobuf message, matching confgen's storeMessage behavior.

Extended the regression test into TestLoadProtovalidate with two subcases and added a JSON fixture:

  • input-format-csv — loads ValidateConf via CSV
  • output-format-json — loads testdata/unittest/conf/ValidateConf.json

Both assert the violation surfaces as xerrors.ErrE2027:

error[E2027]: protovalidate violation
Reason: "this name is too long" violates rule: name: must be at most 10 characters

Add a ValidateConf CSV whose Name exceeds max_len:10 and a test that
loads it, asserting loadOrigin surfaces the violation as E2027. Guards
against regressions where the confgen.Validate call could be dropped.
Comment thread load/load.go Outdated
}
// protovalidate the fully-assembled message, giving the load path the same
// coverage as confgen's storeMessage step.
return confgen.Validate(msg, protovalidate.GlobalValidator)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protovalidate should work both on input (origin formats: xlsx/csv/yaml/xml) and output file formats(json/binpb/txtpb), as protovalide works on the final in memory protobuf message structure.

Move the protovalidate step out of loadOrigin and converge it at the
LoadMessagerInDir exit. protovalidate operates on the final in-memory
protobuf message, so both input (excel/csv/xml/yaml) and output
(json/binpb/txtpb) formats now get the same coverage as confgen's
storeMessage step. The check runs after patch merging to avoid false
positives on intermediate state.

Extend TestLoadOriginProtovalidate into TestLoadProtovalidate with
input-format-csv and output-format-json subcases, and add the
testdata/unittest/conf/ValidateConf.json fixture.
@Kybxd
Kybxd requested a review from wenchy July 14, 2026 08:25
@wenchy
wenchy merged commit 69da005 into master Jul 14, 2026
9 checks passed
@wenchy
wenchy deleted the feat/load-protovalidate branch July 14, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants