sourcegraph/dev/write_generated_to_source_files.bzl
Noah S-C 19d9cfc73b
bazel: native go-mockgen in Bazel (#60386)
Adds a new:
- gazelle generator
- rule + rule targets + catchall target
for generating go-mockgen mocks & testing for their being up-to-date.

Each go_mockgen macro invocation adds targets for generating mocks, copying to the source tree, as well as testing whether the current source tree mocks are up-to-date.

How to use this: `bazel run //dev:go_mockgen` for the catch-all, or `bazel run //some/target:generate_mocks` for an individual package, and `bazel test //some/target:generate_mocks_tests` to test for up-to-date-ness. There is no catch-all for testing

This currently uses a fork of go-mockgen, with an open PR for upstream here: https://github.com/derision-test/go-mockgen/pull/50.

Closes https://github.com/sourcegraph/sourcegraph/issues/60099

## Test plan

Extensive testing during development, including the following cases:
- Deleting a generated file and its entry in a go_library/go_test `srcs` attribute list and then re-running `sg bazel configure`
- Adding a non-existent output directory to mockgen.test.yaml and running the bash one-liner emitted to prepare the workspace for rerunning `sg bazel configure`

The existing config tests a lot of existing paths anyway (creating mocks for a 3rd party library's interface, entries for a given output file in >1 config file etc)
2024-02-16 13:26:48 +00:00

40 lines
1.4 KiB
Python

load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
load("@aspect_bazel_lib//lib:directory_path.bzl", "make_directory_path")
load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
def write_generated_to_source_files(name, target, output_files, **kwargs):
"""Function description.
Args:
name: Name of the rule.
target: The target that generates files to copy.
output_files: A map of {dest: source} for files to copy.
**kwargs: Additional keyword arguments.
"""
for dest, orig in output_files.items():
if dest == orig:
fail("{} and {} must differ so we can detect source files needing to be regenerated".format(dest, orig))
# First we copy to a directory all outputs from the target, so we can refer to them
# individually without circular deps.
copy_to_directory(
name = name + "_copy",
srcs = [target],
)
# Write back the explicitly selected outputs to the source tree.
write_source_files(
name = name,
files = {
dest: make_directory_path(
orig + "_directory_path",
name + "_copy",
orig,
)
for dest, orig in output_files.items()
},
suggested_update_target = "//dev:write_all_generated",
visibility = ["//visibility:public"],
**kwargs
)