diff --git a/docs/custom-runners.md b/docs/custom-runners.md index 30ec82cc4ceca83dacaefb01512a85911c547fdf..eb7d3cc334b7b0653d8605631c0f4a980fd5a49f 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. +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. diff --git a/examples/custom-runners/archive-transfer/BUILD.bazel b/examples/custom-runners/archive-transfer/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..a79f2bd52219e1a25230b0e8f3eda70955959c2d --- /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 0000000000000000000000000000000000000000..57db6575437716f3058bfc9618bd232207971d01 --- /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()