bazel-contrib / bazel-contrib/rules_go

Bug: "missing strict dependencies" using import public and go_proto_library

Open
#4,357 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.