Setting Up MonoRepo Using Bazel (Part-2 Python)
--
In Part-1, I have explained how we can set up Monorepo using Bazel in Go-lang. Now, In this part, I will explain the same in Python.
Step 1: Install Bazel
Before we can begin setting up our monorepo, we need to make sure that Bazel is installed on our system. Bazel can be installed on Linux, macOS, and Windows. You can find the installation instructions for your platform on the official Bazel website.
Step 2: Create a Workspace
In Bazel, a workspace is a directory that contains all of the source code and build files for your projects. To create a new workspace, create a new directory and add a WORKSPACE
file to it. The WORKSPACE file tells Bazel that this directory is a workspace and specifies any external dependencies that your projects may have.
Step 3: Define the Project Directory
Each project in your monorepo should be defined as a Golang package. You can create a directory for each package and include a “BUILD” file in each directory to define the build rules for the package.
- Create your projects folder as in the below image.
2. In the python folder, create a directory sample_library and python_app.
3. In both the directory, create BUILD files and respective calculator.py and app.py files.
Step 4: Add Dependencies
- Define the external dependencies in the WORKSPACE file. (To load any external dependencies)
###############################################################################################
################################ PYTHON RULES LOADING #########################################
###############################################################################################
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
rules_python_version = "740825b7f74930c62f44af95c9a4c1bd428d2c53" # Latest @ 2021-06-23
http_archive(
name = "rules_python",
sha256 = "09a3c4791c61b62c2cbc5b2cbea4ccc32487b38c7a2cc8f87a794d7a659cc742", #"3474c5815da4cb003ff22811a36a11894927eda1c2e64bf2dac63e914bfdf30f",
strip_prefix = "rules_python-{}".format(rules_python_version),
url = "https://github.com/bazelbuild/rules_python/archive/{}.zip".format(rules_python_version),
)
# TO LOAD ANY EXTERNAL PYTHON LIBRARY, LOAD pip_parse rule
# DEFINE A REQUIREMENTS_LOCK.TXT FILE AND INSTALL THE DEPENCIES PRESENT IN IThon
load("@rules_python//python:pip.bzl", "pip_parse")
# Create a central repo that knows about the dependencies needed from
# requirements_lock.txt.
pip_parse(
name = "python_deps",
requirements_lock = "//:requirements_lock.txt",
)
# Load the starlark macro which will define your dependencies.
load("@python_deps//:requirements.bzl", "install_deps")
# Call it to define repos for your requirements.
install_deps()
This will load all the rules defined for python in bazel.
NOTE: Important points to know:
- pip_parse is the function in the python rules that will install dependencies from
requirements_lock.txt
file. - create a central external repo using the pip_parse function.
- this will create requirements.bzl file in the central external repo within which we have
install_deps
a function. - this function call will install dependencies in the requirements_lock.txt file.
2. To use the rules, write the following code in the BUILD file of the sample_library directory.
py_library(
name = "calculator",
srcs = ["calculator.py"],
visibility = ["//visibility:public"],
)
py_test(
name = "calculator_test",
srcs = ["calculator_test.py"],
deps = [
"//projects/python_folder/sample_library:calculator",
],
)
The py_library rule set the functions in the calcuator.py as library functions. If you want to use any function from this package, import the library using the path of the file.
Example: from projects.python_folder.sample_library.calculator import Calculator
3. Similarly, define the rules in the BUILD file of the python_app directory.
load("@python_deps//:requirements.bzl", "requirement")
py_binary(
name = "app",
srcs = ["app.py"],
deps = [
"//projects/python_folder/sample_library:calculator",
requirement("Flask"), #or '@python_deps_pypi__flask//:pkg'
],
main = "app.py"
)
py_image(
name = "samplepython_image",
srcs = ["app.py"],
main = "app.py",
# platform = "local",
deps = [
"//projects/python_folder/sample_library:calculator",
requirement("Flask"),
],
)
- py_binary function will set the corresponding file into the binary executable file.
- To use the external downloaded dependencies in code, load the central external repo (requirements) we created in the previous step in
BUILD
file of your project. And then add the respective dependency indeps
section
Note:
A) There are 2 ways to specify the dependency.1. Using requirement function
requirements("Flask")
2. Directly mentioning the package@python_deps_pypi__flask//:pkg
General: @{central_repo_name}_{package_ name}//:pkgB) This dependency on the libaray means, when you run app.py file in app folder, it will first build the files that are defined in the deps ( dependencies ), then after this build app.py file.
Step 5: Build and Run files
- To BUILD the Build. bazel files
Run
bazel build //Projects/python_folder/...
orbazel build //...
- To RUN all the test files in the python project
Run
bazel test //Projects/python_folder/calculator/...
- To RUN the Flask application
Run
bazel run //Projects/python_folder/python_app:app
The Localhost server is up and ready to listen to the GET request.
Github Repo Link: https://github.com/Akhilesh53/Monorepo
References: https://github.com/bazelbuild/rules_go
Follow on LinkedIn for more…