Time to add code formatter, checkers, linters and other tools that help to keep python code runnable, less buggy and more resilient to evolution.
Setup formatter for Editor
psf/black: The uncompromising Python code formatter will be used. Add it to thrid_party/requirements.txt
...
#tools
black==20.8b1
Relaunch ./setup_localdev.sh
and configure your editor to use it (if its can use virtual env), for example for vscode .vscode/settings.json
{
"python.pythonPath": ".venv/bin/python",
"python.formatting.provider": "black"
}
Setup formatter for Bazel with bazel-linting-system
But bazel currently doesn't use it (to format or to check the format). After a quick search, thundergolfer/bazel-linting-system: πΏπ Experimental system for registering, configuring, and invoking source-code linters in Bazel. seems to be the solution, it's based on bazel's aspect something that we didn't explore or experiment yet. So give it a try by following instruction
Add to WORKSPACE.bazel
http_archive(
name = "linting_system",
sha256 = "",
strip_prefix = "bazel-linting-system-0.4.0",
url = "https://github.com/thundergolfer/bazel-linting-system/archive/v0.4.0.zip",
)
load("@linting_system//repositories:repositories.bzl", linting_sys_repositories = "repositories")
linting_sys_repositories()
load("@linting_system//repositories:go_repositories.bzl", linting_sys_deps = "go_deps")
linting_sys_deps()
Create tools/linting/aspect.bzl
load("@linting_system//:generator.bzl", "linting_aspect_generator")
lint = linting_aspect_generator(
name = "lint",
linters = [
"@//tools/linting:python",
]
)
Create tools/linting/BUILD.bazel
load("@linting_system//:rules.bzl", "linter")
package(default_visibility = ['//visibility:public'])
linter(
name = "python",
executable_path = "/usr/local/bin/black",
)
Run it to test
bazel build //... \
--aspects //tools/linting:aspect.bzl%lint \
--output_groups=report
...
bazel-out/k8-fastbuild/bin/exp_python/double/test_linter_exe: line 26: /usr/local/bin/black: No such file or directory
...
As expected π it failed because we do not have black
installed on the system, and it's better when the build system take care of the installation of tool (for repeatability, and to ease the developer setup (less step and
Create tools/linting/python_linter.py
import black
import sys
if __name__ == "__main__":
sys.exit(black.main())
manual operation)). But we can try to create a tool that will call black (or any other linter).
Modify tools/linting/BUILD.bazel
to build python_linter
and to use it as linter.
load("@linting_system//:rules.bzl", "linter")
load("@rules_python//python:defs.bzl", "py_binary")
load("@my_python_deps//:requirements.bzl", "requirement")
package(default_visibility = ["//visibility:public"])
py_binary(
name = "python_linter",
srcs = ["python_linter.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
requirement("black"),
],
)
...
Try to run it python_linter
β― bazel run //tools/linting:python_linter -- --version
...
python_linter.py, version 20.8b1
OK, seems to work, update linter to use python_linter
...
linter(
name = "python",
executable = "python_linter",
)
Note that we use executable
and not executable_path
, after look at the rule description
linter = rule(
implementation = _linter_impl,
attrs = {
"executable_path": attr.string(
doc="Absolute path to the linter that will run",
mandatory=False,
),
"executable": attr.label(
executable=True,
cfg="host",
doc="Label for an executable linter",
),
"config": attr.label(
allow_files=True,
doc="Configuration file for linter",
),
"config_option": attr.string(
doc="The option used by the linter to pass a path to a configuration file",
),
"config_str": attr.string(
doc="Raw string configuration options to be passed to linter",
)
},
)
Try again
β― bazel build //... \ 20:48:18
--aspects //tools/linting:aspect.bzl%lint \
--output_groups=report
DEBUG: Rule 'linting_system' indicated that a canonical reproducible form can be obtained by modifying arguments sha256 = "a254c73bdde03214b62cacdb570229ed1a1814a2ed749448a1db4e90b18ac0a1"
DEBUG: Repository linting_system instantiated at:
/home/david/src/github.com/davidB/sandbox_bazel/WORKSPACE.bazel:41:13: in <toplevel>
Repository rule http_archive defined at:
/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/external/bazel_tools/tools/build_defs/repo/http.bzl:336:31: in <toplevel>
INFO: Analyzed 9 targets (0 packages loaded, 0 targets configured).
INFO: Found 9 targets...
ERROR: /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/BUILD.bazel:32:10: MirrorAndLint exp_python/webapp/__linting_system/run/exp_python/webapp/run.py failed: (Exit 1): run_linter_exe failed: error executing command bazel-out/k8-fastbuild/bin/exp_python/webapp/run_linter_exe 'exp_python/webapp/run.py;bazel-out/k8-fastbuild/bin/exp_python/webapp/__linting_system/run/exp_python/webapp/run.py'
Use --sandbox_debug to see verbose messages from the sandbox run_linter_exe failed: error executing command bazel-out/k8-fastbuild/bin/exp_python/webapp/run_linter_exe 'exp_python/webapp/run.py;bazel-out/k8-fastbuild/bin/exp_python/webapp/__linting_system/run/exp_python/webapp/run.py'
Use --sandbox_debug to see verbose messages from the sandbox
Traceback (most recent call last):
File "/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/sandbox/linux-sandbox/38/execroot/__main__/bazel-out/host/bin/tools/linting/python_linter", line 388, in <module>
Main()
File "/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/sandbox/linux-sandbox/38/execroot/__main__/bazel-out/host/bin/tools/linting/python_linter", line 288, in Main
module_space = FindModuleSpace()
File "/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/sandbox/linux-sandbox/38/execroot/__main__/bazel-out/host/bin/tools/linting/python_linter", line 118, in FindModuleSpace
raise AssertionError('Cannot find .runfiles directory for %s' % sys.argv[0])
AssertionError: Cannot find .runfiles directory for bazel-out/host/bin/tools/linting/python_linter
INFO: Elapsed time: 0.151s, Critical Path: 0.04s
INFO: 5 processes: 5 internal.
FAILED: Build did NOT complete successfully
What does it mean ? I don't know and I don't know how to fix it. I tried without success
-
executable = "//tools/linting:python_linter",
same error -
executable_path = "$(location //tools/linting:python_linter)",
failed withlocation: command not found
.
I keep the experimentation on a branch exp/linting_system and we'll try something different, make out own tools.
Make a build tool as part of project
It's something interesting to try, create as part of the project a tool to build the project. Start by revert changes made in the previous section, but keep it as inspiration to start.
Create tools/python_check/BUILD.bazel
load("@rules_python//python:defs.bzl", "py_binary")
load("@my_python_deps//:requirements.bzl", "requirement")
package(default_visibility = ["//visibility:public"])
py_binary(
name = "python_check",
srcs = ["python_check.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
requirement("black"),
],
)
Create tools/python_check/python_check.py
import black
import sys
if __name__ == "__main__":
sys.exit(black.main())
Try it
β― bazel run //tools/python_check -- --version
python_check.py, version 20.8b1
Now try to use it in exp_python/webapp/BUILD.bazel
by adding
genrule(
name = "check",
srcs = glob(["**/*.py"]),
outs = ["check.log"],
cmd_bash = """(
$(location //tools/python_check) --check --verbose $(SRCS)
) | tee $@
""",
tools = ["//tools/python_check"],
)
Try
β― bazel build //exp_python/webapp:check
...
/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/main.py already well formatted, good job.
would reformat /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/run.py
would reformat /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/test.py
Oh no! π₯ π π₯
2 files would be reformatted, 1 file would be left unchanged.
...
Basic seems to work. What happens if instead of "--check", we let black format the code ?
/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/main.py already well formatted, good job.
error: cannot format /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/run.py: [Errno 30] Read-only file system: '/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/run.py'
error: cannot format /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/test.py: [Errno 30] Read-only file system: '/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/test.py'
Oh no! π₯ π π₯
1 file left unchanged, 2 files failed to reformat.
Bazel block us to change source file, it's a pain for a formatter, but it's not a bad idea and it follows the way that bazel build commands could be run on remote build server (via CI or bazel remote execution), and that source is own and managed by the developer. But maybe bazel run could ?
β― bazel run //tools/python_check -- --check $PWD/exp_python/**/*.py
...
would reformat /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/run.py
would reformat /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/test.py
Oh no! π₯ π π₯
2 files would be reformatted, 1 file would be left unchanged.
-
$PWD
because when running, the current folder is modified, so without absolute path we gotError: Invalid value for '[SRC]...': Path 'exp_python/webapp/main.py' does not exist.
-
**/*.py
should be change if your shell doesn't support this syntax.
Try to format
β― bazel run //tools/python_check -- $PWD/exp_python/**/*.py
...
INFO: Build completed successfully, 1 total action
reformatted /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/run.py
reformatted /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/test.py
All done! β¨ π° β¨
2 files reformatted, 1 file left unchanged.
sandbox_bazel on ξ development [!?β‘] via π v3.9.4
β― bazel run //tools/python_check -- --check $PWD/exp_python/**/*.py
...
INFO: Build completed successfully, 1 total action
All done! β¨ π° β¨
3 files would be left unchanged.
Hourra, we have a bazel build
command able to check the code and some bazel run
able to check or to update the source code.
Linting & check as test
The goal all of checkers and linters is to evaluate the quality of the code and to detect issue and to suggest improvement, like for test. So it'll make more sens to run checks via bazel test
than bazel build
.
β― bazel test //exp_python/...
INFO: Analyzed 4 targets (0 packages loaded, 0 targets configured).
INFO: Found 3 targets and 1 test target...
INFO: Elapsed time: 0.091s, Critical Path: 0.01s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
//exp_python/webapp:test (cached) PASSED in 0.7s
Executed 0 out of 1 test: 1 test passes.
There were tests whose specified size is too big. Use the --test_verbose_timeout_warnings command line option to see which ones these aINFO: Build completed successfully, 1 total action
We can add a test_suite into exp_python/webapp/BUILD.bazel
that depends of both py_test(name="test"...)
and our genrule(name="check"...)
.
test_suite(
name = "quality",
tests = [
"check",
"test",
],
)
β― bazel test //exp_python/... 12:07:31
ERROR: /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/BUILD.bazel:55:11: in test_suite rule '//exp_python/webapp:quality': expecting a test or a test_suite rule but '//exp_python/webapp:check' is not one.
WARNING: Target pattern parsing failed.
INFO: Analyzed 4 targets (1 packages loaded, 7 targets configured).
INFO: Found 3 targets and 1 test target...
INFO: From Executing genrule //exp_python/webapp:check:
/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/main.py wasn't modified on disk since last run.
/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/run.py wasn't modified on disk since last run.
/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/test.py wasn't modified on disk since last run.
All done! β¨ π° β¨
3 files would be left unchanged.
ERROR: command succeeded, but there were errors parsing the target pattern
INFO: Elapsed time: 0.408s, Critical Path: 0.27s
INFO: 2 processes: 1 internal, 1 linux-sandbox.
FAILED: Build did NOT complete successfully
//exp_python/webapp:test (cached) PASSED in 0.7s
Executed 0 out of 1 test: 1 test passes.
There were tests whose specified size is too big. Use the --test_verbose_timeout_warnings command line option to see which ones these are.
All tests passed but there were other errors during the build.
FAILED: Build did NOT complete successfully
check
is executed but bazel is not happy in accordance to the doc of test_suite.tests (genrule are like *_binary
)
No *_binary targets are accepted however, even if they happen to run a test.
It's time create our first custom rule (inspired by the Rules Tutorial - Bazel and the examples/rules at master Β· bazelbuild/examples.
Create tools/python_check/defs.bzl
where we create a rule python_check
that try to mimic the genrule that we want to convert
"""Launch the python_check tool"""
def _python_check_test_impl(ctx):
args = ["--check", "--verbose"] + [f.path for f in ctx.files.srcs]
ctx.actions.run_shell(
inputs = ctx.files.srcs,
outputs = [ctx.outputs.log],
progress_message = "Check into %s" % ctx.outputs.log.short_path,
command = "(%s %s) | tee '%s'" %
(ctx.executable.tool.path, " ".join(args), ctx.outputs.log.path),
)
python_check = rule(
implementation = _python_check_test_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
"log": attr.output(mandatory = True),
"tool": attr.label(
executable = True,
cfg = "exec",
allow_files = True,
default = Label("//tools/python_check"),
),
},
)
A rule is composed of the declaration xxx = rule(...)
and its implementation.
Then replace the genrule(name="check"...)
by a call to python_check
into exp_python/webapp/BUILD.bazel
load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
load("@my_python_deps//:requirements.bzl", "requirement")
load("//tools/python_check:defs.bzl", "python_check")
...
python_check(
name = "check",
srcs = glob(["**/*.py"]),
log = "check.log",
)
...
β― bazel build //exp_python/webapp:check 13:31:43
INFO: Analyzed target //exp_python/webapp:check (1 packages loaded, 4 targets configured).
INFO: Found 1 target...
Target //exp_python/webapp:check up-to-date:
bazel-bin/exp_python/webapp/check.log
INFO: Elapsed time: 0.092s, Critical Path: 0.01s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
now make python_check a test rule:
python_check = rule(
...
test = True,
)
Re-try
β― bazel test //exp_python/...
ERROR: /home/david/src/github.com/davidB/sandbox_bazel/tools/python_check/defs.bzl:14:20: Invalid rule class name 'python_check', test rule class names must end with '_test' and other rule classes must not
...
OK so we need to rename python_check
into python_check_test
into tools/python_check/defs.bzl
and exp_python/webapp/BUILD.bazel
and re-try
β― bazel test //exp_python/...
ERROR: /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/BUILD.bazel:45:18: in python_check_test rule //exp_python/webapp:check:
/home/david/src/github.com/davidB/sandbox_bazel/tools/python_check/defs.bzl:3:5: The rule 'python_check_test' is executable. It needs to create an executable File and pass it as the 'executable' parameter to the DefaultInfo it returns.
...
Seems that from the error message and the sample examples/line_length.bzl at master Β· bazelbuild/examples, that we should modify also our _impl
function to return a DefaultInfo instead of running the command directly. As a test we can also remove the log
attributes because the output of test is the exit code and stdout/stderr managed by bazel directly. So Update tools/python_check/defs.bzl
to
"""Launch the python_check tool"""
def _python_check_test_impl(ctx):
args = ["--check", "--verbose"] + [f.path for f in ctx.files.srcs]
command = "%s %s" % (ctx.executable.tool.path, " ".join(args))
# Write the file, it is executed by 'bazel test'.
ctx.actions.write(
output = ctx.outputs.executable,
content = command,
)
# To ensure the files needed by the command are available, we put them in
# the runfiles.
runfiles = ctx.runfiles(files = [ctx.executable.tool] + ctx.files.srcs)
return [DefaultInfo(runfiles = runfiles)]
python_check_test = rule(
implementation = _python_check_test_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
"tool": attr.label(
executable = True,
cfg = "exec",
allow_files = True,
default = Label("//tools/python_check"),
),
},
test = True,
)
Remove the log
attribute on the caller side
python_check_test(
name = "check",
srcs = glob(["**/*.py"]),
)
Re-try
β― bazel test //exp_python/... 14:54:01
INFO: Analyzed 4 targets (1 packages loaded, 7 targets configured).
INFO: Found 2 targets and 2 test targets...
FAIL: //exp_python/webapp:check (see /home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/execroot/__main__/bazel-out/k8-fastbuild/testlogs/exp_python/webapp/check/test.log)
INFO: From Testing //exp_python/webapp:check:
==================== Test output for //exp_python/webapp:check:
/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/sandbox/linux-sandbox/15/execroot/__main__/bazel-out/k8-fastbuild/bin/exp_python/webapp/check.runfiles/__main__/exp_python/webapp/check: line 1: bazel-out/k8-opt-exec-2B5CBBC6/bin/tools/python_check/python_check: No such file or directory
================================================================================
INFO: Elapsed time: 0.210s, Critical Path: 0.06s
INFO: 2 processes: 2 linux-sandbox.
INFO: Build completed, 1 test FAILED, 2 total actions
//exp_python/webapp:test (cached) PASSED in 0.7s
//exp_python/webapp:check FAILED in 0.0s
/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/execroot/__main__/bazel-out/k8-fastbuild/testlogs/exp_python/webapp/check/test.log
Executed 1 out of 2 tests: 1 test passes and 1 fails locally.
There were tests whose specified size is too big. Use the --test_verbose_timeout_warnings command line option to see which ones these a
INFO: Build completed, 1 test FAILED, 2 total actions
Failed but looks like what we expect check
is now part of the test flow. But we still have issues with the path of our python_check executable or/and the way we defined the runfiles.
try to replace ctx.executable.tool.path
by ctx.executable.tool.short_path
β― bazel test //exp_python/... 16:29:55
INFO: Analyzed 4 targets (1 packages loaded, 7 targets configured).
INFO: Found 2 targets and 2 test targets...
FAIL: //exp_python/webapp:check (see /home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/execroot/__main__/bazel-out/k8-fastbuild/testlogs/exp_python/webapp/check/test.log)
INFO: From Testing //exp_python/webapp:check:
==================== Test output for //exp_python/webapp:check:
Traceback (most recent call last):
File "/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/sandbox/linux-sandbox/44/execroot/__main__/bazel-out/k8-fastbuild/bin/exp_python/webapp/check.runfiles/__main__/tools/python_check/python_check", line 388, in <module>
Main()
File "/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/sandbox/linux-sandbox/44/execroot/__main__/bazel-out/k8-fastbuild/bin/exp_python/webapp/check.runfiles/__main__/tools/python_check/python_check", line 322, in Main
assert os.path.exists(main_filename), \
AssertionError: Cannot exec() '/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/sandbox/linux-sandbox/44/execroot/__main__/bazel-out/k8-fastbuild/bin/exp_python/webapp/check.runfiles/__main__/tools/python_check/python_check.py': file not found.
It means that short_path
works but the tool is missing some dependencies. In fact we only include the entry file and not its runtime dependencies. So change the way to build runfiles by
runfiles = ctx.runfiles(files = ctx.files.srcs)
runfiles = runfiles.merge(ctx.attr.tool[DefaultInfo].default_runfiles)
Then
β― bazel test //exp_python/...
INFO: Analyzed 4 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets and 2 test targets...
INFO: Elapsed time: 0.895s, Critical Path: 0.80s
INFO: 3 processes: 4 linux-sandbox.
INFO: Build completed successfully, 3 total actions
//exp_python/webapp:check PASSED in 0.3s
//exp_python/webapp:test PASSED in 0.7s
Executed 2 out of 2 tests: 2 tests pass.
There were tests whose specified size is too big. Use the --test_verbose_timeout_warnings command line option to see which ones these aINFO: Build completed successfully, 3 total actions
Seems to work, try to introduce issue format issue (like previously) to check if detected.
β― bazel test //exp_python/...
INFO: Analyzed 4 targets (0 packages loaded, 0 targets configured).
INFO: Found 2 targets and 2 test targets...
FAIL: //exp_python/webapp:check (see /home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/execroot/__main__/bazel-out/k8-fastbuild/testlogs/exp_python/webapp/check/test.log)
INFO: From Testing //exp_python/webapp:check:
==================== Test output for //exp_python/webapp:check:
/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/run.py wasn't modified on disk since last run.
/home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/test.py wasn't modified on disk since last run.
would reformat /home/david/src/github.com/davidB/sandbox_bazel/exp_python/webapp/main.py
Oh no! π₯ π π₯
1 file would be reformatted, 2 files would be left unchanged.
================================================================================
INFO: Elapsed time: 0.907s, Critical Path: 0.78s
INFO: 3 processes: 4 linux-sandbox.
INFO: Build completed, 1 test FAILED, 3 total actions
//exp_python/webapp:test PASSED in 0.7s
//exp_python/webapp:check FAILED in 0.3s
/home/david/.cache/bazel/_bazel_david/76e87152cc51687aee6e05b5bdcf89aa/execroot/__main__/bazel-out/k8-fastbuild/testlogs/exp_python/webapp/check/test.log
Executed 2 out of 2 tests: 1 test passes and 1 fails locally.
There were tests whose specified size is too big. Use the --test_verbose_timeout_warnings command line option to see which ones these aINFO: Build completed, 1 test FAILED, 3 total actions
π issue is detected.
After reading the documentation for the cfg
, we thing that the target
is maybe a better value (simply because python always mixe all dependencies (tools, test, runtime,...) it's crappy but it's is way to work). So we now have tools/python_check/defs.bzl
like
"""Launch the python_check tool"""
def _python_check_test_impl(ctx):
# TODO find a better way to build the command/script and to escape/enclose args
args = ["--check"] + [f.path for f in ctx.files.srcs]
command = "%s '%s'" % (ctx.executable.tool.short_path, "' '".join(args))
# Write the file, it is executed by 'bazel test'.
# ctx.outputs.executable is the default value for DefaultInfo.executable
ctx.actions.write(
output = ctx.outputs.executable,
content = command,
)
# To ensure the files needed by the command are available, we put them in
# the runfiles.
runfiles = ctx.runfiles(files = ctx.files.srcs)
runfiles = runfiles.merge(ctx.attr.tool[DefaultInfo].default_runfiles)
return [DefaultInfo(
runfiles = runfiles,
)]
python_check_test = rule(
implementation = _python_check_test_impl,
attrs = {
"srcs": attr.label_list(allow_files = True),
"tool": attr.label(
executable = True,
cfg = "target",
default = Label("//tools/python_check"),
),
},
test = True,
)
We also remove the test_suite from exp_python/webapp/BUILD.bazel
to simplify.
On more thing before the pause, we can enable CI to run test in .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
# virtual environments: https://github.com/actions/virtual-environments
runs-on: ubuntu-20.04
steps:
# Caches and restores the bazelisk download directory, the bazel build directory.
- name: Cache bazel
uses: actions/cache@v2.1.4
with:
path: |
~/.cache/bazelisk
~/.cache/bazel
key: ${{ runner.os }}-bazel-cache
# Checks-out your repository under $GITHUB_WORKSPACE, which is the CWD for
# the rest of the steps
- uses: actions/checkout@v2
- name: Run the test
run: bazel test //...
- name: Build the code
run: bazel build //...
To be continued
It's not the end, we'll continue to setup linter and other stuff, but we're in a state enough to pause (it'was a long article again).
The sandbox_bazel is hosted on github (not with the same history, due to errors), use tag to have the expected view at end of article: article/5_python_2. I'll be happy to have your comments on this article, or to discuss on github repo.
Top comments (0)