1

I have a repo which uses bazel to build a bunch of Python code. I would like to introduce various flavors of static analysis into the build and have the build fail if these static analyses throw errors. What is the best way to do this?

For example, I'd like to declare something like:

py_library_with_static_analysis(
  name = "foo",
  srcs = ["foo.py"],
)
py_library_with_static_analysis(
  name = "bar",
  srcs = ["bar.py"],
  deps = [":foo"],
)

In a build file and have it error out if there are mypy/flake/etc errors in foo.py. I would like to be able to do this gradually, converting libraries/binaries to static analysis one target at a time. I'm not sure if I should do this via a new rule, a macro, an aspect or something else.

Essentially, I think I'm asking how to run an additional command while building a py_binary/py_library and fail if that command fails.

I could create my own version of a py_library rule and have it run static analysis within the implementation but that seems like something which is really easy to get wrong (my guess is that native.py_library is quite complex?) and there doesn't seem to be a way to instantiate a native.py_library within a custom rule.

I've also played around with macros a bit, but haven't been able to get that to work either. I think my issue there is that a macro doesn't actually specify new commands, only new targets and I can't figure out how to make the static analysis target get force built along with the py_library/py_binary I'm interested in.

1 Answers1

0

A macro that adds implicit test targets is not such a bad idea: The test targets will be picked up automatically when you run bazel test //..., which you could do in a gating CI to prevent imperfect code from merging.

Bazel supports a BUILD prelude (which is underdocumented) that you could use to replace all py_binary, py_library, and even py_test with your test-adding wrapper macros with minimal changes to existing code.

If you somehow fail the build instead it will make it harder to quickly prototype things. Sometimes you want to just quickly try something out, and you don't care about any pydoc violations yet.

In case you do want to fail the build, you might be able to use the Validations Output Group of a rule that you implement to wrap or replace your py_libraries.

Laurenz
  • 1,810
  • 12
  • 25
  • Thanks for the advice. I think that's a good idea for some flavor of static analysis (lint, flake, etc), but (IMO), for things like mypy/pytype, it's actually better for the build to break (analogous to statically typed languages). For that reason, I'd still like to come up with some solution which does static analysis at build time. – throwaway_20000 Feb 03 '22 at 17:43
  • I added a link that might help to achieve this. – Laurenz Feb 04 '22 at 13:47