bazel_roller: Detect WORKSPACE / MODULE.bazel
Bug: b/359948624
Change-Id: Ibc6d8ed31e163a43744a70289bd7692c92508f9d
Reviewed-on: https://pigweed-review.googlesource.com/c/infra/recipes/+/229894
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Commit-Queue: Rob Mohr <mohrr@google.com>
Reviewed-by: Taylor Cramer <cramertj@google.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/recipes/bazel_roller.proto b/recipes/bazel_roller.proto
index f5717ca..5b16e08 100644
--- a/recipes/bazel_roller.proto
+++ b/recipes/bazel_roller.proto
@@ -26,7 +26,9 @@
// Auto roller module options.
recipe_modules.fuchsia.auto_roller.Options auto_roller_options = 2;
- // The path of the WORKSPACE file to update. Default: WORKSPACE.
+ // The path of the WORKSPACE file to update. If not provided the recipe will
+ // look for a top-level WORKSPACE or MODULE.bazel file. If provided and is a
+ // directory, looks for those files in that directory.
string workspace_path = 3;
// Name for project to be rolled. By default will extract from WORKSPACE.
diff --git a/recipes/bazel_roller.py b/recipes/bazel_roller.py
index 5dacd47..96d05c1 100644
--- a/recipes/bazel_roller.py
+++ b/recipes/bazel_roller.py
@@ -63,11 +63,69 @@
PROPERTIES = InputProperties
+def _workspace_path(
+ api: recipe_api.RecipeScriptApi,
+ root: config_types.Path,
+ value: str,
+) -> config_types.Path:
+ """Figure out the location of the WORKSPACE or MODULE.bazel file.
+
+ If value is '', look for root / 'WORKSPACE' and root / 'MODULE.bazel'. If
+ exactly one exists, return it. If not, error out.
+
+ If root / value is a file, return it.
+
+ If root / value is a directory, set root = root / value and apply the above
+ logic. This enables applying this logic to subdirectories.
+
+ Args:
+ api: Recipe API object.
+ root: Checkout root.
+ value: Relative path specified in properties.
+
+ Returns:
+ Path to the WORKSPACE or MODULE.bazel file.
+ """
+ if value:
+ value_path = root / value
+ api.path.mock_add_file(value_path)
+ if api.path.isfile(value_path):
+ return value_path
+ elif api.path.isdir(value_path): # pragma: no cover
+ root = value_path
+ else:
+ api.step.empty( # pragma: no cover
+ f'{value_path} does not exist',
+ status='FAILURE',
+ )
+
+ workspace = root / 'WORKSPACE'
+ module_bazel = root / 'MODULE.bazel'
+
+ api.path.mock_add_file(workspace)
+
+ if api.path.isfile(module_bazel) and api.path.isfile(workspace):
+ api.step.empty( # pragma: no cover
+ f'{module_bazel} and {workspace} both exist',
+ status='FAILURE',
+ )
+
+ if api.path.isfile(module_bazel):
+ return module_bazel # pragma: no cover
+
+ if api.path.isfile(workspace):
+ return workspace
+
+ api.step.empty( # pragma: no cover
+ 'no WORKSPACE or MODULE.bazel file found',
+ status='FAILURE',
+ )
+
+
def RunSteps( # pylint: disable=invalid-name
api: recipe_api.RecipeScriptApi,
props: InputProperties,
):
- workspace_path: str = props.workspace_path or 'WORKSPACE'
project_branch: str = props.project_branch or 'main'
# The checkout module will try to use trigger data to pull in a specific
@@ -78,6 +136,8 @@
props.checkout_options
)
+ workspace_path = _workspace_path(api, checkout.root, props.workspace_path)
+
new_revision: Optional[str] = None
# First, try to get new_revision from the trigger.
@@ -240,7 +300,7 @@
yield api.test(
'bad-trigger',
- properties(project_remote=_url('foo')),
+ properties(project_remote=_url('foo'), workspace_path='bar/WORKSPACE'),
trigger('bar'),
status='FAILURE',
)