Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

colcon plugin: add ability to ignore packages #2687

Merged
merged 4 commits into from Sep 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions snapcraft/plugins/colcon.py
Expand Up @@ -27,6 +27,10 @@
List of colcon packages to build. If not specified, all packages in the
workspace will be built. If set to an empty list ([]), no packages will
be built, which could be useful if you only want ROS debs in the snap.
- colcon-packages-ignore:
(list of strings)
List of colcon packages to ignore. If not specified or set to an empty
list ([]), no packages will be ignored.
- colcon-source-space:
(string)
The source space containing colcon packages (defaults to 'src').
Expand Down Expand Up @@ -178,6 +182,14 @@ def schema(cls):
"default": [],
}

schema["properties"]["colcon-packages-ignore"] = {
"type": "array",
"minitems": 1,
"uniqueItems": True,
"items": {"type": "string"},
"default": [],
}

schema["required"] = ["source"]

return schema
Expand All @@ -196,6 +208,7 @@ def get_build_properties(cls):
"colcon-cmake-args",
"colcon-catkin-cmake-args",
"colcon-ament-cmake-args",
"colcon-packages-ignore",
]

@property
Expand Down Expand Up @@ -622,6 +635,11 @@ def _build_colcon_packages(self):
colconcmd.append("--packages-select")
colconcmd.extend(self._packages)

if self.options.colcon_packages_ignore:
colconcmd.extend(
["--packages-ignore"] + self.options.colcon_packages_ignore
)

# Don't clutter the real ROS workspace-- use the Snapcraft build
# directory
colconcmd.extend(["--build-base", self.builddir])
Expand Down
201 changes: 110 additions & 91 deletions tests/unit/plugins/test_colcon.py
Expand Up @@ -67,6 +67,7 @@ def setUp(self):
class props:
colcon_rosdistro = "crystal"
colcon_packages = ["my_package"]
colcon_packages_ignore = []
colcon_source_space = "src"
source_subdir = None
colcon_cmake_args = []
Expand Down Expand Up @@ -152,6 +153,7 @@ def test_schema(self):
"colcon-cmake-args",
"colcon-catkin-cmake-args",
"colcon-ament-cmake-args",
"colcon-packages-ignore",
)
self.assertThat(properties, HasLength(len(expected)))
for prop in expected:
Expand Down Expand Up @@ -271,6 +273,22 @@ def test_schema_colcon_ament_cmake_args(self):
self.assertThat(colcon_cmake_args["items"], Contains("type"))
self.assertThat(colcon_cmake_args["items"]["type"], Equals("string"))

def test_schema_colcon_packages_ignore(self):
schema = colcon.ColconPlugin.schema()

# check colcon-packages-ignore property
colcon_packages_ignore = schema["properties"]["colcon-packages-ignore"]
expected = ("type", "default", "minitems", "items", "uniqueItems")
self.assertThat(colcon_packages_ignore, HasLength(len(expected)))
for prop in expected:
self.assertThat(colcon_packages_ignore, Contains(prop))
self.assertThat(colcon_packages_ignore["type"], Equals("array"))
self.assertThat(colcon_packages_ignore["default"], Equals([]))
self.assertThat(colcon_packages_ignore["minitems"], Equals(1))
self.assertTrue(colcon_packages_ignore["uniqueItems"])
self.assertThat(colcon_packages_ignore["items"], Contains("type"))
self.assertThat(colcon_packages_ignore["items"]["type"], Equals("string"))

def test_get_pull_properties(self):
expected_pull_properties = [
"colcon-rosdistro",
Expand All @@ -291,6 +309,7 @@ def test_get_build_properties(self):
"colcon-cmake-args",
"colcon-catkin-cmake-args",
"colcon-ament-cmake-args",
"colcon-packages-ignore",
]
actual_build_properties = colcon.ColconPlugin.get_build_properties()

Expand Down Expand Up @@ -948,6 +967,89 @@ def test_pull_pip_dependencies(self):
)


class _CheckBuildCommand:
def __init__(self, test, plugin):
self.test = test
self.plugin = plugin

def __eq__(self, args):
# Matching like this for order independence (otherwise it would be
# quite fragile)
command = " ".join(args)
if "debug" in self.test.build_attributes:
self.test.assertThat(
command, MatchesRegex(".*--cmake-args.*-DCMAKE_BUILD_TYPE=Debug")
)
else:
self.test.assertThat(
command, MatchesRegex(".*--cmake-args.*-DCMAKE_BUILD_TYPE=Release")
)

if self.test.colcon_cmake_args:
expected_args = " ".join(self.test.colcon_cmake_args)
self.test.assertThat(
command,
MatchesRegex(".*--cmake-args.*{}".format(re.escape(expected_args))),
)
if self.test.properties.disable_parallel:
self.test.assertThat(command, MatchesRegex(".*--parallel-workers=1"))
else:
self.test.assertThat(
command,
MatchesRegex(
".*--parallel-workers={}".format(self.plugin.parallel_build_count)
),
)
if self.test.colcon_catkin_cmake_args:
expected_args = " ".join(self.test.colcon_catkin_cmake_args)
self.test.assertThat(
command,
MatchesRegex(
".*--catkin-cmake-args.*{}".format(re.escape(expected_args))
),
)
if self.test.colcon_ament_cmake_args:
expected_args = " ".join(self.test.colcon_ament_cmake_args)
self.test.assertThat(
command,
MatchesRegex(
".*--ament-cmake-args.*{}".format(re.escape(expected_args))
),
)
if self.test.colcon_packages_ignore:
expected_args = " ".join(self.test.colcon_packages_ignore)
self.test.assertThat(
command,
MatchesRegex(
".*--packages-ignore.*{}".format(re.escape(expected_args))
),
)

if self.test.colcon_packages:
self.test.assertThat(
command,
Contains(
"--packages-select {}".format(" ".join(self.test.colcon_packages))
),
)
else:
self.test.assertThat(command, Not(Contains("--packages-select")))

self.test.assertThat(args[0:2], Equals(["colcon", "build"]))
self.test.assertThat(command, Contains("--merge-install"))
self.test.assertThat(
command, Contains("--build-base {}".format(self.plugin.builddir))
)
self.test.assertThat(
command, Contains("--base-paths {}".format(self.plugin._ros_package_path))
)
self.test.assertThat(
command, Contains("--install-base {}".format(self.plugin._ros_overlay))
)

return True


class BuildTestCase(ColconPluginTestBase):

package_scenarios = [
Expand Down Expand Up @@ -980,17 +1082,24 @@ class BuildTestCase(ColconPluginTestBase):
("without ament-cmake-args", {"colcon_ament_cmake_args": []}),
]

packages_ignore_scenarios = [
("with packages-ignore", {"colcon_packages_ignore": ["my_package"]}),
("without packages-ignore", {"colcon_packages_ignore": []}),
]

scenarios = multiply_scenarios(
package_scenarios,
build_type_scenarios,
cmake_args_scenarios,
catkin_args_scenarios,
ament_args_scenarios,
packages_ignore_scenarios,
)

def setUp(self):
super().setUp()
self.properties.colcon_packages = self.colcon_packages
self.properties.colcon_packages_ignore = self.colcon_packages_ignore
self.properties.build_attributes.extend(self.build_attributes)
self.properties.colcon_cmake_args = self.colcon_cmake_args
self.properties.colcon_catkin_cmake_args = self.colcon_catkin_cmake_args
Expand All @@ -1012,98 +1121,8 @@ def test_build(

prepare_build_mock.assert_called_once_with()

# Matching like this for order independence (otherwise it would be
# quite fragile)
build_attributes = self.build_attributes
colcon_cmake_args = self.colcon_cmake_args
colcon_catkin_cmake_args = self.colcon_catkin_cmake_args
colcon_ament_cmake_args = self.colcon_ament_cmake_args
disable_parallel = self.properties.disable_parallel

class _check_build_command:
def __init__(self, test):
self.test = test

def __eq__(self, args):
command = " ".join(args)
if "debug" in build_attributes:
self.test.assertThat(
command,
MatchesRegex(".*--cmake-args.*-DCMAKE_BUILD_TYPE=Debug"),
)
else:
self.test.assertThat(
command,
MatchesRegex(".*--cmake-args.*-DCMAKE_BUILD_TYPE=Release"),
)

if colcon_cmake_args:
expected_args = " ".join(colcon_cmake_args)
self.test.assertThat(
command,
MatchesRegex(
".*--cmake-args.*{}".format(re.escape(expected_args))
),
)
if disable_parallel:
self.test.assertThat(
command, MatchesRegex(".*--parallel-workers=1")
)
else:
self.test.assertThat(
command,
MatchesRegex(
".*--parallel-workers={}".format(
plugin.parallel_build_count
)
),
)
if colcon_catkin_cmake_args:
expected_args = " ".join(colcon_catkin_cmake_args)
self.test.assertThat(
command,
MatchesRegex(
".*--catkin-cmake-args.*{}".format(re.escape(expected_args))
),
)
if colcon_ament_cmake_args:
expected_args = " ".join(colcon_ament_cmake_args)
self.test.assertThat(
command,
MatchesRegex(
".*--ament-cmake-args.*{}".format(re.escape(expected_args))
),
)

if self.test.colcon_packages:
self.test.assertThat(
command,
Contains(
"--packages-select {}".format(
" ".join(self.test.colcon_packages)
)
),
)
else:
self.test.assertThat(command, Not(Contains("--packages-select")))

self.test.assertThat(args[0:2], Equals(["colcon", "build"]))
self.test.assertThat(command, Contains("--merge-install"))
self.test.assertThat(
command, Contains("--build-base {}".format(plugin.builddir))
)
self.test.assertThat(
command,
Contains("--base-paths {}".format(plugin._ros_package_path)),
)
self.test.assertThat(
command, Contains("--install-base {}".format(plugin._ros_overlay))
)

return True

if self.colcon_packages or self.colcon_packages is None:
run_mock.assert_called_with(_check_build_command(self))
run_mock.assert_called_with(_CheckBuildCommand(self, plugin))
else:
run_mock.assert_not_called()

Expand Down