diff --git a/docs/image.md b/docs/image.md
index a04b9e60..6bdc2649 100644
--- a/docs/image.md
+++ b/docs/image.md
@@ -112,10 +112,14 @@ Can by configured using either dict(key->value) or a file that contains key=v
deterministic) information when running with `--stamp` flag. See the example in
[/examples/labels/BUILD.bazel](https://github.com/bazel-contrib/rules_oci/blob/main/examples/labels/BUILD.bazel).
-**LIST_OR_LABEL**: `cmd`, `entrypoint`, `workdir`, `exposed_ports`, `volumes`
+**LIST_OR_LABEL**: `cmd`, `entrypoint`, `exposed_ports`, `volumes`
Can be a list of strings, or a file with newlines separating entries.
+**STRING_OR_LABEL**: `workdir`
+
+A string, or a target text file whose output contains a single line
+
**PARAMETERS**
@@ -128,7 +132,7 @@ Can be a list of strings, or a file with newlines separating entries.
| env | DICT_OR_LABEL
Environment variables provisioned by default to the running container. | None
|
| cmd | LIST_OR_LABEL
Command & argument configured by default in the running container. | None
|
| entrypoint | LIST_OR_LABEL
Entrypoint configured by default in the running container. | None
|
-| workdir | LIST_OR_LABEL
Workdir configured by default in the running container. Only 1 list entry allowed. | None
|
+| workdir | STRING_OR_LABEL
Workdir configured by default in the running container. | None
|
| exposed_ports | LIST_OR_LABEL
Exposed ports in the running container. | None
|
| volumes | LIST_OR_LABEL
Volumes for the container. | None
|
| kwargs | other named arguments to [oci_image_rule](#oci_image_rule) and [common rule attributes](https://bazel.build/reference/be/common-definitions#common-attributes). | none |
diff --git a/examples/assertion/BUILD.bazel b/examples/assertion/BUILD.bazel
index 72dbf299..fde1bddf 100644
--- a/examples/assertion/BUILD.bazel
+++ b/examples/assertion/BUILD.bazel
@@ -190,7 +190,7 @@ oci_image(
volumes = ["/srv/data"],
# user & workdir
user = "root",
- workdir = ["/root"],
+ workdir = "/root",
# labels & annotations
labels = {
"org.opencontainers.image.version": "0.0.0",
@@ -620,7 +620,7 @@ build_test(
],
)
-# Case 21: accept workdir param as a target (list input tested in case8)
+# Case 21: accept workdir param as a target label (string input is tested in case8)
genrule(
name = "case21_workdir_target",
outs = ["case21_workdir_target.txt"],
@@ -630,7 +630,7 @@ genrule(
oci_image(
name = "case21",
base = ":case8",
- workdir = ":case21_workdir_target",
+ workdir = "case21_workdir_target",
)
assert_oci_config(
diff --git a/oci/defs.bzl b/oci/defs.bzl
index f6f0c1dd..5a8093d2 100644
--- a/oci/defs.bzl
+++ b/oci/defs.bzl
@@ -33,6 +33,38 @@ def _write_nl_seperated_file(name, kind, elems, forwarded_kwargs):
)
return label
+
+# There's no "is this a label or just a string?" check in macro land, so
+# approximate it with some silly string heuristics. See
+# https://bazel.build/concepts/labels for label name rules
+def _is_a_workdir_label(input):
+ if input[0] in (":", "@") or input[:2] in ("@@", "//") or '/' not in input:
+ return True
+ return False
+
+
+def test_is_a_workdir_label():
+ testdata = {
+ # Corner case: "foo" could be either a string or a target. This
+ # implementation chooses target. If you want a relative workdir "foo"
+ # use "./foo"
+ "foo": True,
+ "//foo": True,
+ "@@foo//bar": True,
+ ":foo": True,
+ # These are all not labels
+ "/foo": False,
+ "./foo": False,
+ "foo/bar": False,
+ "../foo": False,
+ }
+
+ for input, expected in testdata.items():
+ value = _is_a_workdir_label(input)
+ if value != expected:
+ fail("_is_a_workdir_label(%s) returned %s, expected %s" % (input, value, expected))
+
+
def oci_image(name, labels = None, annotations = None, env = None, cmd = None, entrypoint = None, workdir = None, exposed_ports = None, volumes = None, **kwargs):
"""Macro wrapper around [oci_image_rule](#oci_image_rule).
@@ -50,10 +82,14 @@ def oci_image(name, labels = None, annotations = None, env = None, cmd = None, e
deterministic) information when running with `--stamp` flag. See the example in
[/examples/labels/BUILD.bazel](https://github.com/bazel-contrib/rules_oci/blob/main/examples/labels/BUILD.bazel).
- **LIST_OR_LABEL**: `cmd`, `entrypoint`, `workdir`, `exposed_ports`, `volumes`
+ **LIST_OR_LABEL**: `cmd`, `entrypoint`, `exposed_ports`, `volumes`
Can be a list of strings, or a file with newlines separating entries.
+ **STRING_OR_LABEL**: `workdir`
+
+ A string, or a target text file whose output contains a single line
+
Args:
name: name of resulting oci_image_rule
labels: `DICT_OR_LABEL` Labels for the image config.
@@ -61,7 +97,7 @@ def oci_image(name, labels = None, annotations = None, env = None, cmd = None, e
env: `DICT_OR_LABEL` Environment variables provisioned by default to the running container.
cmd: `LIST_OR_LABEL` Command & argument configured by default in the running container.
entrypoint: `LIST_OR_LABEL` Entrypoint configured by default in the running container.
- workdir: `LIST_OR_LABEL` Workdir configured by default in the running container. Only 1 list entry allowed.
+ workdir: `STRING_OR_LABEL` Workdir configured by default in the running container.
exposed_ports: `LIST_OR_LABEL` Exposed ports in the running container.
volumes: `LIST_OR_LABEL` Volumes for the container.
**kwargs: other named arguments to [oci_image_rule](#oci_image_rule) and
@@ -115,15 +151,13 @@ def oci_image(name, labels = None, annotations = None, env = None, cmd = None, e
forwarded_kwargs = forwarded_kwargs,
)
- if types.is_list(workdir):
- if len(workdir) > 1:
- fail("workdir MUST only include 1 list element")
-
+ # Support a string for convenience. Create a label on the fly.
+ if workdir != None and not _is_a_workdir_label(workdir):
workdir_label = "_{}_write_workdir".format(name)
write_file(
name = workdir_label,
out = "_{}.workdir.txt".format(name),
- content = workdir,
+ content = [workdir],
**forwarded_kwargs
)
workdir = workdir_label
diff --git a/oci/tests/BUILD.bazel b/oci/tests/BUILD.bazel
index 14819d04..2c558ed3 100644
--- a/oci/tests/BUILD.bazel
+++ b/oci/tests/BUILD.bazel
@@ -2,6 +2,7 @@ load("@aspect_bazel_lib//lib:diff_test.bzl", "diff_test")
load("@aspect_bazel_lib//lib:run_binary.bzl", "run_binary")
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load(":pull_tests.bzl", "parse_image_test")
+load("//oci:defs.bzl", "test_is_a_workdir_label")
IMAGES_TO_TEST = {
"linux/amd64": {
@@ -83,3 +84,5 @@ build_test(
)
parse_image_test(name = "parse_image_test")
+
+test_is_a_workdir_label()