From 1922833cd1a0ac94828f0786e045e9a1681df3f5 Mon Sep 17 00:00:00 2001 From: Luke Hackwell Date: Tue, 29 Apr 2025 15:28:27 +0100 Subject: [PATCH 1/2] docs(runner): add custom runner example --- docs/custom-runners.md | 2 + .../archive-transfer/BUILD.bazel | 43 +++++++++++++++++ .../custom-runners/archive-transfer/run.py | 48 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 examples/custom-runners/archive-transfer/BUILD.bazel create mode 100644 examples/custom-runners/archive-transfer/run.py diff --git a/docs/custom-runners.md b/docs/custom-runners.md index 30ec82cc..f7d0974b 100644 --- a/docs/custom-runners.md +++ b/docs/custom-runners.md @@ -1,5 +1,7 @@ # Custom Runners A runner is a `py_binary` target that, when used with a `rules_labgrid` workflow rule (e.g. `labgrid_genrule`, `labgrid_run_binary`), controls how programs are executed on a device. [`@rules_labgrid//labgrid/run`](/labgrid/run/run.py) is an example of a generic runner that supports file transfer and program execution. Custom runners are user-defined and allow for more specialised tasks. +See [run.py](/examples/custom-runners/archive-transfer/run.py), [BUILD.bazel](/examples/custom-runners/archive-transfer/BUILD.bazel) for an example of a custom runner that creates a zipped archive of a program and its data, transfers and unpacks it on the device, and executes the program. + ## Runner Library The `@rules_labgrid//bazel/labgrid/runner` library provides a high-level abstraction over labgrid. It handles device configuration - transitioning the device to the desired state using the strategy defined in the config and preparing a clean execution root - and offers methods for file transfer and command execution. It is the recommended way to build custom runners and is used internally by `@rules_labgrid//labgrid/run`. Most of the functionality is exposed via the `Runner` class, which is instantiated by the `runner` context manager. diff --git a/examples/custom-runners/archive-transfer/BUILD.bazel b/examples/custom-runners/archive-transfer/BUILD.bazel new file mode 100644 index 00000000..a79f2bd5 --- /dev/null +++ b/examples/custom-runners/archive-transfer/BUILD.bazel @@ -0,0 +1,43 @@ +load("@bazel_skylib//rules:write_file.bzl", "write_file") +load("@rules_diff//diff/file/test:defs.bzl", "diff_file_test") +load("@rules_labgrid//labgrid/genrule:defs.bzl", "labgrid_genrule") +load("@rules_python//python:defs.bzl", "py_binary") + +py_binary( + name = "run", + srcs = ["run.py"], + data = [ + "@ape//ape:unzip", + ], + deps = [ + "@rules_labgrid//bazel/labgrid/runner", + ], +) + +write_file( + name = "hello", + out = "data.txt", + content = [ + "hello", + "", + ], +) + +labgrid_genrule( + name = "read-hello", + srcs = [ + ":data.txt", + "@ape//ape:cat", + ], + outs = ["actual.out"], + cmd = "$(location :run) --put=$(location data.txt) --out=$(location :actual.out) $(location @ape//ape:cat) data.txt", + platform = "@rules_labgrid//labgrid/platform:localhost", + tools = [":run"], +) + +diff_file_test( + name = "test", + size = "small", + a = "actual.out", + b = "data.txt", +) diff --git a/examples/custom-runners/archive-transfer/run.py b/examples/custom-runners/archive-transfer/run.py new file mode 100644 index 00000000..57db6575 --- /dev/null +++ b/examples/custom-runners/archive-transfer/run.py @@ -0,0 +1,48 @@ +import argparse +from zipfile import ZipFile +from pathlib import Path + +from python.runfiles import Runfiles + +from bazel.labgrid.runner import FileTransfer, runner + + +def arguments(): + parser = argparse.ArgumentParser() + parser.add_argument("program", type=Path) + parser.add_argument("arguments", nargs=argparse.REMAINDER) + parser.add_argument("--put", nargs="+", dest="puts", type=Path) + parser.add_argument("--out", type=Path) + return parser.parse_args() + + +def main(): + args = arguments() + + runfiles = Runfiles.Create() + unzip = FileTransfer("unzip", runfiles.Rlocation("ape/ape/assimilate/unzip/unzip")) + archive = FileTransfer("archive.zip", "archive.zip") + + with ZipFile(archive.local, "w") as zipfile: + zipfile.write(args.program, arcname=args.program.name) + for put in args.puts: + zipfile.write(put, arcname=put.name) + + with runner() as r: + uploads = [archive, unzip] + + r.put(uploads) + + code, _ = r.run(f"{unzip.remote} {archive.remote}") + if code != 0: + raise Exception(code) + + code, stdout = r.run(f"{args.program.name} {''.join(args.arguments)}") + + with args.out.open("w") as f: + print(stdout, file=f) + + return code + + +main() -- GitLab From 43c4bd39b4413dab6e4ae4f7435e9f8bce823837 Mon Sep 17 00:00:00 2001 From: Luke Hackwell Date: Tue, 29 Apr 2025 14:15:24 +0100 Subject: [PATCH 2/2] docs(runner): alter custom runner user guide --- docs/custom-runners.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/custom-runners.md b/docs/custom-runners.md index f7d0974b..eb7d3cc3 100644 --- a/docs/custom-runners.md +++ b/docs/custom-runners.md @@ -4,4 +4,4 @@ A runner is a `py_binary` target that, when used with a `rules_labgrid` workflow See [run.py](/examples/custom-runners/archive-transfer/run.py), [BUILD.bazel](/examples/custom-runners/archive-transfer/BUILD.bazel) for an example of a custom runner that creates a zipped archive of a program and its data, transfers and unpacks it on the device, and executes the program. ## Runner Library -The `@rules_labgrid//bazel/labgrid/runner` library provides a high-level abstraction over labgrid. It handles device configuration - transitioning the device to the desired state using the strategy defined in the config and preparing a clean execution root - and offers methods for file transfer and command execution. It is the recommended way to build custom runners and is used internally by `@rules_labgrid//labgrid/run`. Most of the functionality is exposed via the `Runner` class, which is instantiated by the `runner` context manager. +The `@rules_labgrid//bazel/labgrid/runner` library provides the core components for building a custom runner. As a high-level abstraction over labgrid, it handles device configuration - transitioning the device to the desired state using the strategy defined in the config and preparing a clean execution root - and offers methods for file transfer and command execution. It is the recommended way to build custom runners and is used internally by `@rules_labgrid//labgrid/run`. Most of the functionality is exposed via the `Runner` class, which is instantiated by the `runner` context manager. -- GitLab