An opinionated template repo for multi-lingual projects using Bazel, built around the principle that wherever possible projects should be hermetic and reproducible. It includes:
go fmt
It does not seek to provide a continual submodule that can pick up upstream changes from the
template, but is more like a create-react-app
template where you can eject from the template and
proceed with your project. That being said, if you don't change any paths you can likely
git cherry-pick
or otherwise patch in changes from upstream and then run eject.sh
again to
update paths for your project.
bazelisk
to automatically install the proper bazel version./eject.sh <project_name>
Pull requests are welcome! Open one against this repo and it will be reviewed & merged.
To add a new python pip dependency:
requirements.in
bazel run //:requirements.update
requirements_lock.txt
To add a new golang dependency:
Begin using the dependency in your Go code
Run bazel run @rules_go//go get <dependency>
to add the dependency to go.mod
Run bazel run @rules_go//go mod tidy
to pull in the transitive deps and update go.mod to show
it as used
Run bazel run //:gazelle
to update your build files. This will print a warning like the
following
$ bazel run //:gazelle
WARNING: /Users/jcureton/development/personal/python_bazel_template/MODULE.bazel:39:24: The module extension go_deps defined in @gazelle//:extensions.bzl reported incorrect imports of repositories via use_repo():
Not imported, but reported as direct dependencies by the extension (may cause the build to fail):
io_rsc_quote
** You can use the following buildozer command to fix these issues:
buildozer 'use_repo_add @gazelle//:extensions.bzl go_deps io_rsc_quote' //MODULE.bazel:all
Run the printed buildozer command with bazel run -- //tools/buildozer ...
Commit the updates to go.mod, go.sum, MODULE.bazel, MODULE.bazel.lock, and any build files.
In general, lint by running the lint.sh
script.
The first time you run lint, you'll see a warning like:
UserWarning: `known_${project}` setting is defined, but ${project} is not included in `sections`
config option: ('FUTURE', 'STDLIB', 'THIRDPARTY', '${project}', 'FIRSTPARTY', 'LOCALFOLDER').
To resolve this, open pyproject.toml
in the repo root, and update the <project>
reference in
SECTIONS
on line 11 to be capitalized. This is a known issue with the basic templating script used
in the repo, and PRs are welcome if you have a resolution :)
You can manually run ${Buildifier/Flake8/Black/Isort/Prettier} with the following if you want to, though you'll have to handle paths manually to prevent them from working on the Bazel sandbox.
bazel run //tools/${tool}
Unit tests are run using the bazel test
command. A test wrapper is provided that invokes pytest
with reasonable defaults and configures the entrypoint. You just write pytest test cases in normal
Python files, and pass these as srcs
to a ${project}_py_test
rule. The test runner handles the rest.
Currently this Bazel workspace supports building/running on macOS and Linux. Windows support is explicitly unscoped. The currently-supported languages are:
You can run an interactive python session via either an ipython shell or a Jupyter notebook. By
default, both include the //${project}
bazel target so you can make use of ${project} code interactively.
bazel run //tools/ipython
. You'll be dropped into a python shell in the Bazel sandboxbazel run //tools/jupyter
. You'll be dropped into a Jupyter web interface. You can
create a new Notebook to experiment. In general, consider these environments to be ephemeral, but
if needed the notebook is created inside bazel-bin/tools/jupyter/jupyter.runfiles/__main__
.
Alternatively, consider downloading the notebook from the web UI if you will continue to need it.By default this includes the //${project}
target, so you can make use of ${project} code interactively
We provide builtin ${project}_py_image
and ${project}_go_image
macros that make it easy to containerize
any binary target. By default, these are built for the same architecture as the current host.
You can manually override this and build for a different platform using the
--platforms=//tools/platforms:container_{arch}_linux
build flag.
${project}_py_image(
name = "${project}_img",
binary = ":${project}_bin",
image_tags = ["${project}:latest"],
)
# Build default image for current host architecture and load it into docker
bazel run //${project}:${project}_img_load_docker
# Build default image for specific architecture
bazel run --platforms=//tools/platforms:container_x86_64_linux //${project}:${project}_img_load_docker