From 6b1eaf6d2402e38b58ffea5ec584a9902905eb5d Mon Sep 17 00:00:00 2001 From: Aljoscha Schmidt Date: Thu, 30 Jan 2025 15:13:52 +0100 Subject: [PATCH 1/3] Added Pkg and CI Template Creation --- scripts/create.py | 259 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100755 scripts/create.py diff --git a/scripts/create.py b/scripts/create.py new file mode 100755 index 0000000..13af75e --- /dev/null +++ b/scripts/create.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 +from tuda_workspace_scripts.workspace import get_workspace_root, PackageChoicesCompleter + +import argcomplete +import argparse +import os +from ament_index_python.packages import get_package_share_directory + +try: + import git +except ImportError: + print( + "GitPython is required! Install using 'pip3 install --user gitpython' or 'apt install python3-git'" + ) + raise + +try: + import copier +except ImportError: + print("GitPython is required! Install using 'pip3 install --user copier'") + raise + + +def parseArguments() -> argparse.Namespace: + + parser = argparse.ArgumentParser( + description="Creates a ROS 2 package from templates" + ) + + parser.add_argument( + "--template", + type=str, + default=None, + choices=["cpp_pkg", "msgs_pkg", "python_pkg", "ci"], + help="Template", + ) + parser.add_argument( + "--destination", + "-d", + type=str, + default=None, + help="Destination directory (default: /src/)", + ) + parser.add_argument( + "--defaults", action="store_true", help="Use defaults for all options" + ) + + parser.add_argument("--package-name", type=str, default=None, help="Package name") + parser.add_argument("--description", type=str, default=None, help="Description") + parser.add_argument("--maintainer", type=str, default=None, help="Maintainer") + parser.add_argument( + "--maintainer-email", type=str, default=None, help="Maintainer email" + ) + parser.add_argument("--author", type=str, default=None, help="Author") + parser.add_argument("--author-email", type=str, default=None, help="Author email") + parser.add_argument( + "--license", + type=str, + default=None, + choices=[ + "Apache-2.0", + "BSL-1.0", + "BSD-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "GPL-3.0-only", + "LGPL-2.1-only", + "LGPL-3.0-only", + "MIT", + "MIT-0", + ], + help="License", + ) + parser.add_argument("--node-name", type=str, default=None, help="Node name") + parser.add_argument( + "--node-class-name", type=str, default=None, help="Class name of node" + ) + parser.add_argument( + "--is-component", action="store_true", default=None, help="Make it a component?" + ) + parser.add_argument( + "--no-is-component", dest="is-component", default=None, action="store_false" + ) + parser.add_argument( + "--is-lifecycle", + action="store_true", + default=None, + help="Make it a lifecycle node?", + ) + parser.add_argument( + "--no-is-lifecycle", dest="is-lifecycle", default=None, action="store_false" + ) + parser.add_argument( + "--has-launch-file", + action="store_true", + default=None, + help="Add a launch file?", + ) + parser.add_argument( + "--no-has-launch-file", + dest="has-launch-file", + default=None, + action="store_false", + ) + parser.add_argument( + "--launch-file-type", + type=str, + choices=["xml", "py", "yml"], + help="Type of launch file", + ) + parser.add_argument( + "--has-params", action="store_true", default=None, help="Add parameter loading" + ) + parser.add_argument( + "--no-has-params", dest="has-params", default=None, action="store_false" + ) + parser.add_argument( + "--has-subscriber", action="store_true", default=None, help="Add a subscriber?" + ) + parser.add_argument( + "--no-has-subscriber", dest="has-subscriber", default=None, action="store_false" + ) + parser.add_argument( + "--has-publisher", action="store_true", default=None, help="Add a publisher?" + ) + parser.add_argument( + "--no-has-publisher", dest="has-publisher", default=None, action="store_false" + ) + parser.add_argument( + "--has-service-server", + action="store_true", + default=None, + help="Add a service server?", + ) + parser.add_argument( + "--no-has-service-server", + dest="has-service-server", + default=None, + action="store_false", + ) + parser.add_argument( + "--has-action-server", + action="store_true", + default=None, + help="Add an action server?", + ) + parser.add_argument( + "--no-has-action-server", + dest="has-action-server", + default=None, + action="store_false", + ) + parser.add_argument( + "--has-timer", action="store_true", default=None, help="Add a timer callback?" + ) + parser.add_argument( + "--no-has-timer", dest="has-timer", default=None, action="store_false" + ) + parser.add_argument( + "--auto-shutdown", + action="store_true", + default=None, + help="Automatically shutdown the node after launch (useful in CI/CD)?", + ) + parser.add_argument( + "--no-auto-shutdown", dest="auto-shutdown", default=None, action="store_false" + ) + parser.add_argument( + "--interface-types", + type=str, + default=None, + choices=["Message", "Service", "Action"], + help="Interfaces types", + ) + parser.add_argument("--msg-name", type=str, default=None, help="Message name") + parser.add_argument("--srv-name", type=str, default=None, help="Service name") + parser.add_argument("--action-name", type=str, default=None, help="Action name") + parser.add_argument( + "--ci-type", + type=str, + choices=["github", "gitlab"], + default=None, + help="CI type", + ) + parser.add_argument( + "--add_pre_commit", + action="store_true", + default=None, + help="Add pre-commit hook?", + ) + # parser.add_argument("--has-docker-ros", action="store_true", default=None, help="Add the docker-ros CI integration?") + + argcomplete.autocomplete(parser) + return parser.parse_args() + + +def add_git_config_info(answers): + # add author and maintainer info from git config if not yet set + git_config = git.GitConfigParser() + git_config.read() + if not answers.get("author") or not answers.get("maintainer"): + answers["user_name_git"] = git_config.get_value("user", "name") + if not answers.get("author_email") or not answers.get("maintainer_email"): + answers["user_email_git"] = git_config.get_value("user", "email") + + +def add_ros_distro(answers): + answers["ros_distro"] = os.environ.get("ROS_DISTRO", "jazzy") + + +def create(template_pkg_name: str, template_url: str): + + # pass specified arguments as data to copier + args = parseArguments() + workspace_src = os.path.join(get_workspace_root(), "src") + + # Adapt destination path + if args.destination is None: + args.destination = workspace_src + if not os.path.isabs(args.destination): + args.destination = os.path.join(workspace_src, args.destination) + print(f"Destination: {args.destination}") + + answers = {k: v for k, v in vars(args).items() if v is not None} + + # add author and maintainer info from git config if not yet set + add_git_config_info(answers) + + add_ros_distro(answers) + + # get pkg template location if installed as ros pkg + try: + template_location = get_package_share_directory(template_pkg_name) + except KeyError: + print( + f"Package '{template_pkg_name}' not found locally. Using remote template." + ) + template_location = template_url + + # run copier + try: + copier.run_copy( + template_location, + args.destination, + data=answers, + defaults=args.defaults, + unsafe=True, + vcs_ref="HEAD", + ) + + except copier.CopierAnswersInterrupt: + print("Aborted") + return + + +if __name__ == "__main__": + template_pkg_name = "ros2_pkg_create" + template_url = "https://github.com/Joschi3/ros2-pkg-create" + create(template_pkg_name, template_url) From 1694d8867b1efd01aad4a43896fde24476154508 Mon Sep 17 00:00:00 2001 From: Aljoscha Schmidt Date: Fri, 31 Jan 2025 10:13:26 +0100 Subject: [PATCH 2/3] Removed unnecessary arguments and ros distro default argument --- scripts/create.py | 51 ++++++----------------------------------------- 1 file changed, 6 insertions(+), 45 deletions(-) diff --git a/scripts/create.py b/scripts/create.py index 13af75e..afc3223 100755 --- a/scripts/create.py +++ b/scripts/create.py @@ -9,15 +9,15 @@ try: import git except ImportError: - print( - "GitPython is required! Install using 'pip3 install --user gitpython' or 'apt install python3-git'" - ) + print("GitPython is required! Install using 'apt install python3-git'") raise try: import copier except ImportError: - print("GitPython is required! Install using 'pip3 install --user copier'") + print( + "Copier is required! Install using 'pip3 install copier --break-system-packages'" + ) raise @@ -78,30 +78,18 @@ def parseArguments() -> argparse.Namespace: parser.add_argument( "--is-component", action="store_true", default=None, help="Make it a component?" ) - parser.add_argument( - "--no-is-component", dest="is-component", default=None, action="store_false" - ) parser.add_argument( "--is-lifecycle", action="store_true", default=None, help="Make it a lifecycle node?", ) - parser.add_argument( - "--no-is-lifecycle", dest="is-lifecycle", default=None, action="store_false" - ) parser.add_argument( "--has-launch-file", action="store_true", default=None, help="Add a launch file?", ) - parser.add_argument( - "--no-has-launch-file", - dest="has-launch-file", - default=None, - action="store_false", - ) parser.add_argument( "--launch-file-type", type=str, @@ -111,60 +99,33 @@ def parseArguments() -> argparse.Namespace: parser.add_argument( "--has-params", action="store_true", default=None, help="Add parameter loading" ) - parser.add_argument( - "--no-has-params", dest="has-params", default=None, action="store_false" - ) parser.add_argument( "--has-subscriber", action="store_true", default=None, help="Add a subscriber?" ) - parser.add_argument( - "--no-has-subscriber", dest="has-subscriber", default=None, action="store_false" - ) parser.add_argument( "--has-publisher", action="store_true", default=None, help="Add a publisher?" ) - parser.add_argument( - "--no-has-publisher", dest="has-publisher", default=None, action="store_false" - ) parser.add_argument( "--has-service-server", action="store_true", default=None, help="Add a service server?", ) - parser.add_argument( - "--no-has-service-server", - dest="has-service-server", - default=None, - action="store_false", - ) parser.add_argument( "--has-action-server", action="store_true", default=None, help="Add an action server?", ) - parser.add_argument( - "--no-has-action-server", - dest="has-action-server", - default=None, - action="store_false", - ) parser.add_argument( "--has-timer", action="store_true", default=None, help="Add a timer callback?" ) - parser.add_argument( - "--no-has-timer", dest="has-timer", default=None, action="store_false" - ) parser.add_argument( "--auto-shutdown", action="store_true", default=None, help="Automatically shutdown the node after launch (useful in CI/CD)?", ) - parser.add_argument( - "--no-auto-shutdown", dest="auto-shutdown", default=None, action="store_false" - ) parser.add_argument( "--interface-types", type=str, @@ -188,7 +149,6 @@ def parseArguments() -> argparse.Namespace: default=None, help="Add pre-commit hook?", ) - # parser.add_argument("--has-docker-ros", action="store_true", default=None, help="Add the docker-ros CI integration?") argcomplete.autocomplete(parser) return parser.parse_args() @@ -205,7 +165,8 @@ def add_git_config_info(answers): def add_ros_distro(answers): - answers["ros_distro"] = os.environ.get("ROS_DISTRO", "jazzy") + if os.environ.get("ROS_DISTRO"): + answers["ros_distro"] = os.environ.get("ROS_DISTRO") def create(template_pkg_name: str, template_url: str): From 51add93dcb7a6ed153c61506d40f0d4dc04009b1 Mon Sep 17 00:00:00 2001 From: Aljoscha Schmidt Date: Fri, 31 Jan 2025 11:49:04 +0100 Subject: [PATCH 3/3] Fixed pre-commit argument --- scripts/create.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/create.py b/scripts/create.py index afc3223..cc010c8 100755 --- a/scripts/create.py +++ b/scripts/create.py @@ -16,7 +16,7 @@ import copier except ImportError: print( - "Copier is required! Install using 'pip3 install copier --break-system-packages'" + "Copier is required! Install using 'pip3 install copier --user --break-system-packages'" ) raise @@ -144,7 +144,7 @@ def parseArguments() -> argparse.Namespace: help="CI type", ) parser.add_argument( - "--add_pre_commit", + "--add-pre-commit", action="store_true", default=None, help="Add pre-commit hook?",