bazel-contrib / bazel-contrib/rules_go
Bug: "missing strict dependencies" using import public and go_proto_library
- Dominant language
- Go
- Stars
- 1.5k
- Forks
- 760
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 12
Description
Given :
* three `go_proto_library()` targets **foo**, **bar**, and **baz**
* **foo** depends on **bar**, and **bar** depends on **baz**
* **bar** uses [import public "baz.proto"](https://protobuf.dev/programming-guides/proto3/#importing)
The `protoc-gen-go` tool generates code for **foo** (`foo.pb.go`) that looks like:
```golang
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.3
// protoc v5.27.0
// [...]
import (
baz "[...]/baz_go_proto"
_ "[...]/bar_go_proto"
```
The `compilepkg` strict dependencies check scans this file for imports, sees the import of **baz**, and then errors because **foo** did not declare a direct dependency on **baz**.
https://github.com/bazel-contrib/rules_go/blob/393faea31d43012fbb7887dfbddb869cb5cf58f5/go/tools/builders/importcfg.go#L100
However, I think this behavior is a bug. If I understand correctly, `import public` is supposed to enable moving messages without breaking downstream consumers. The alternative is to update all users atomically, but it can be difficult to impossible to do that in:
* a large and active monorepo, or
* an SDK where you've promised your customers backwards compatibility
## Steps to reproduce
Clone my fork
```
git clone -b sloretz_repro_import_public_issue https://github.com/sloretz/rules_go.git
```
Run this test
```
bazel test //tests/core/go_proto_library_import_public:import_public_test
```
Observe this failure:
```
compilepkg: missing strict dependencies:
/home/sloretz/.cache/bazel/_bazel_sloretz/e4e5127b5b9f1e33f9a706fce20cac1d/sandbox/linux-sandbox/4/execroot/io_bazel_rules_go/bazel-out/k8-fastbuild/bin/tests/core/go_proto_library_import_public/dog_go_proto_/github.com/bazelbuild/rules_go/tests/core/go_proto_library_import_public/dog_go_proto/dog.pb.go: import of "github.com/bazelbuild/rules_go/tests/core/go_proto_library_import_public/new_dir/dog_collar_go_proto"
No dependencies were provided.
Check that imports in Go sources match importpath attributes in deps.
```
## Suggested fix
The `proto_library()` rule has [an `exports` attribute](https://bazel.build/reference/be/protocol-buffer#proto_library) for the `import public` use case. How about `go_proto_library()` gets an `exports` attribute as well? Then **bar** could declare an export of **baz**, and **foo** can be ignorant of protos being moved upstream of it.
The `exports` attribute would need to set some provider such that **foo**'s call to `compilepkg` would get a new [-arc argument for **baz**](https://github.com/bazel-contrib/rules_go/blob/393faea31d43012fbb7887dfbddb869cb5cf58f5/go/tools/builders/compilepkg.go#L52)
Contributor guide
Research direction
Start with tests/core/go_proto_library_import_public:import_public_test and reproduce the failure described in the issue. Read go/tools/builders/importcfg.go around the strict-dependencies scan and go/tools/builders/compilepkg.go around the arc argument, then inspect how proto_library exports are represented. Done means the test passes for the import public scenario without requiring foo to declare baz directly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100