This repository defines a common development environment for and enforces consistency of components of OpenADS, the Open Automated Driving Systems project.
Features
- .vscode settings, recommended extensions, tasks, and debugging configurations
- .devcontainer definition for developing and debugging in container images built by docker-ros
- pre-commit hooks configuration for running linting and formatting on each commit
- README generator for generating common-style repository READMEs
- Docker Compose generator for generating OpenADS Compose files from launch metadata
- Helm Chart generator for generating OpenADS Helm charts from launch metadata
- consistency checker for enforcing conventions across repositories
- CI workflow templates for building and testing container images, building documentation, and checking repository consistency
- Add this repository as a Git submodule named
.openads-dev-environmentto the root of any other repository that you would like to use these settings for.git submodule add https://github.com/openads-project/openads-dev-environment.git .openads-dev-environment
- Create symbolic links to the relevant files and folders.
ln -s .openads-dev-environment/.vscode .vscode ln -s .openads-dev-environment/.devcontainer .devcontainer ln -s .openads-dev-environment/.pre-commit-config.yaml .pre-commit-config.yaml
- Copy the CI workflow templates into your repository.
# GitHub mkdir -p .github/workflows cp .openads-dev-environment/.github/workflow_calls/*.yml .github/workflows/ # GitLab cp .openads-dev-environment/.gitlab-ci.template.yml .gitlab-ci.yml
- Customize the copied CI workflows to fit your repository, in particular
base-imageandcommandof thedocker-rosjob. - Install the recommended VS Code extensions.
Ctrl+Shift+P / Extensions: Show Recommended Extensions / Install Workspace Recommended Extensions (Cloud Download Icon)
- (optional) Install Git pre-commit hooks.
pip install pre-commit pre-commit install
- (optional) Check consistency of your repository with OpenADS conventions.
.openads-dev-environment/scripts/check_repository_consistency.py
This repository stores common .vscode settings for developing and debugging C++ and Python applications, in particular, ROS applications in container images built by docker-ros.
- Tasks (
tasks.json) are pre-defined recurring actions (e.g, building a ROS workspace) that can easily be invoked - Debugging Configurations (
launch.json) allow to easily debug applications (e.g., ROS nodes) including breakpoints, stack traces, and more - Settings (
settings.json,c_cpp_properties.json,format/*,lint/*) store common VS Code settings (e.g., configuring code formatters) - Extensions Recommendations (
extensions.json) recommend useful VS Code extensions
Select Ctrl+Shift+P / Run Task to run a task. Tasks are defined in tasks.json.
| Name | Description |
|---|---|
| Build | Builds ROS target workspace using colcon (Ctrl+Shift+B) |
| Build with Build Type | Builds ROS target workspace using colcon with given build type |
| Test | Runs tests in ROS target workspace using colcon |
| Clean | Removes all build artifacts from ROS workspace |
| Clean CMake cache | Builds CMake's clean target |
| New ROS 2 Package | Creates a new ROS 2 package using ros2-pkg-create |
| Clone VCS repositories | Clones VCS repositories from .repos file using vcs import |
| Install dependencies | Install ROS dependencies declared in package.xml files using rosdep |
Select the Run and Debug view in the Activity Bar on the side of VS Code (Ctrl+Shift+D). Select one of the pre-defined debugging configurations to start debugging. Debugging configurations are defined in launch.json.
| Name | Description |
|---|---|
| ROS 2: Attach | Attach debugger to a running ROS executable (requires container to be started as root) |
| ROS 2: Executable | Debug a ROS executable |
| ROS 2: Launch File | Debug ROS nodes started by a launch file |
| Python: ROS 2 Launch file | Debug a ROS 2 Python launch file using the Python debugger |
| Python: Current File | Debug the currently opened Python script |
This repository stores a common .devcontainer definition for attaching VS Code to container images built by docker-ros. This allows you to develop and debug ROS applications right from within VS Code.
Select Ctrl+Shift+P / Dev Containers: Rebuild and Reopen in Container. VS Code will automatically build and launch a new development container and open your repository inside this container.
By default, the Dev Container image is derived from your repository origin, e.g., ghcr.io/<owner>/<repo>:latest-dev or latest-dev_<branch>_ci on non-default branches. If the derived image cannot be pulled, the Dev Container helper falls back to building the image locally with docker-ros.
Add an .env file to the root of your repository to create custom environment variables. The following variables are used within the build-local-dockerfile.sh:
# overwrites the automatically generated base container image name
VSCODE_DEVCONTAINER_IMAGE=""
# forces to build the base container image locally using docker-ros instead of pulling it from a registry
VSCODE_DEVCONTAINER_BUILD_LOCALLY="false"
# chooses a docker-ros git reference if building the base container image locally using docker-ros
VSCODE_DEVCONTAINER_DOCKER_ROS_REF="main"This repository stores a common pre-commit configuration for running linting and formatting checks before committing code.
Pre-commit hooks are auto-installed in the Dev Container. On the host, the pre-commit package is required.
pip install pre-commit
pre-commit installPre-commit hooks will automatically run on git commit and check all staged files. If any check fails, the commit is aborted and you can fix the issues before re-committing.
Pre-commit hooks can also be run manually.
pre-commit run --all-filesUse generate_readme.py to generate common-style top-level and package-level READMEs. These READMEs are expected to be auto-generated by the consistency checker, but expect some customization and allow some freedom.
.openads-dev-environment/scripts/generate_readme.pyThe package README generator derives ROS interface documentation from source and launch metadata. For C++ ROS nodes, parameters are extracted from declareAndLoadParameter(...) calls. Launch arguments are extracted from DeclareLaunchArgument(...) calls. Topic tables and flowcharts are generated from private ROS topic names such as ~/input and launch remapping metadata. Known transport helper APIs such as image_transport and point_cloud_transport are mapped to their underlying ROS message types.
Use generate_compose.py to generate Docker Compose deployments from the repository's ROS 2 launch files.
.openads-dev-environment/scripts/generate_compose.pyTo check whether the committed Compose file is up to date without changing it, run:
.openads-dev-environment/scripts/generate_compose.py --checkThe generator expects a ROS package subdirectory with launch files in launch/. A package-level <package>_launch.py remains the exclusive default and generates deployment/compose/docker-compose.yml. Without that default, a single launch file that directly starts the package generates the same output. Multiple directly launching files generate deployment/compose/docker-compose.<name>.yml, where <name> is the filename without _launch.py or .launch.py. Launch files that only include other launch files do not create a deployment.
Multi-launch deployments use each launch file's default node name and parameter file. The GitHub and GitLab compose-oci jobs publish them below the existing Compose image name with the launch name appended to the ref tag, for example compose:main-cam_generator. Single-launch artifact names and tags remain unchanged.
Each directly launching file must define at least one Node and DeclareLaunchArgument(...) entries. A remappable_topics list is optional and only controls which topic remaps are exposed and grouped as Compose environment variables. The generator owns docker-compose.yml and docker-compose.*.yml below deployment/compose; generation removes obsolete outputs and --check reports them.
For GitLab remotes, the generator uses the registry from an existing Compose file when available. Otherwise, override the derived registry with --gitlab-registry <host[:port]> or OPENADS_GITLAB_REGISTRY; if neither is set, it falls back to <gitlab-host>:5050.
Use generate_helm.py to generate helm/Chart.yaml and helm/values.yaml, similar to the Docker Compose Generator.
.openads-dev-environment/scripts/generate_helm.py --checkA single launch deployment keeps the existing deployment/helm/Chart.yaml and deployment/helm/values.yaml paths, chart name, and version. Multiple directly launching files generate one chart below deployment/helm/<name>/ per launch file. All charts use the same package-derived chart name and therefore share one OCI repository. Multi-launch chart versions append the launch name with underscores converted to hyphens, for example 1.0.0-first-node; branch builds append the Git ref afterwards. The Helm OCI workflows discover, package, publish, and clean up all generated charts.
Use check_repository_consistency.py to run a set of checks that enforce consistency and conventions across repositories. This is set up to be run in CI, but can also be run locally to check for issues before pushing.
.openads-dev-environment/scripts/check_repository_consistency.pySpecific checks can be skipped in CI by setting the skip-checks input in the GitHub workflow template or setting the CONSISTENCY_CHECKS_SKIP environment variable in the GitLab template.
The check_downstream_consistency.py helper is used by the consistency-downstream workflow to run the current development-environment checks against downstream OpenADS modules. When a new OpenADS module becomes available, add its repository URL to .github/workflows/consistency-downstream.yml so generator and consistency-check changes are tested against the complete module set.
| Name | Description |
|---|---|
compose_generator_is_idempotent |
Passes when running .openads-dev-environment/scripts/generate_compose.py --check reports that all single- or multi-launch Compose files below deployment/compose match the current launch metadata and no obsolete generated files remain. Re-run the generator and commit the result until the check is clean. |
cpp_code_has_doxygen_docs |
Passes when every tracked C++ function that Doxygen discovers has documentation on at least one emitted declaration or definition record. |
default_launch_remappable_topics_cover_node_pubsub |
Passes when each default ROS package launch file lists every string-literal pub/sub/service/client name used by the launched node executables in its remappable_topics launch arguments. Packages without a default launch file are skipped. |
dev_environment_at_remote_main |
Passes when .openads-dev-environment is present as a git repository and its current HEAD exactly matches origin/main. Update the submodule if it points to any other commit. |
docker_ros_ci_has_no_todo |
Passes when root docker-ros CI files, specifically .github/workflows/docker-ros.yml and .gitlab-ci.yml when present, contain no TODO placeholder text. This ensures the template command placeholder was replaced with a repository-specific command. |
generated_readmes_have_no_todo |
Passes when the repository top-level README.md and every generated package README.md contain no TODO placeholders. Replace all remaining placeholder text before committing. |
helm_generator_is_idempotent |
Passes when running .openads-dev-environment/scripts/generate_helm.py --check reports that all single- or multi-launch Helm charts below deployment/helm match the current launch metadata and no obsolete generated files remain. Re-run the generator and commit the result until the check is clean. |
no_top_level_package_xml |
Passes when the repository root does not contain a package.xml. ROS packages must live in subdirectories instead of treating the whole repository as one package. |
readme_generator_is_idempotent |
Passes when running .openads-dev-environment/scripts/generate_readme.py produces no README content changes and no additional git status changes. Re-run the generator and commit the result until a second run is clean. |
required_root_ci_workflows |
Passes when .github/workflows/ contains compose-oci.yml, consistency.yml, docker-ros.yml, docs.yml, ghcr-cleanup.yml, and helm-oci.yml. |
required_top_level_symlinks |
Passes when the repository root contains symlinks .devcontainer -> .openads-dev-environment/.devcontainer/, .vscode -> .openads-dev-environment/.vscode/, and .pre-commit-config.yaml -> .openads-dev-environment/.pre-commit-config.yaml. |
root_ci_workflows_match_templates |
Passes when the root workflow files .github/workflows/compose-oci.yml, .github/workflows/consistency.yml, .github/workflows/docs.yml, .github/workflows/ghcr-cleanup.yml, and .github/workflows/helm-oci.yml contain at least the content of the corresponding templates in .openads-dev-environment/.github/workflow_calls/. |
ros_cmake_has_required_lint_block |
Passes when every ROS package CMakeLists.txt that declares targets with add_executable(...) or add_library(...) contains the exact required ament_lint_auto block, including the configured .clang-format, .clang-tidy, and ament_flake8.ini paths. |
ros_nodes_have_parameter_loader |
Passes when each detected ROS node source file defines the required parameter helper: declareAndLoadParameter for C++ nodes or declare_and_load_parameter for Python nodes. |
ros_packagexml_has_required_metadata |
Passes when every ROS package package.xml is valid XML and contains non-placeholder <name>, non-0.0.0 <version>, <description>, at least one non-empty <license>, and at least one <maintainer email="...">...</maintainer> plus <author email="...">...</author> entry that are not left at the default TODO placeholder values. |
ros_packagexml_has_required_testdepends |
Passes when every ROS package package.xml contains the exact required <test_depend> block for ament_lint_auto, ament_cmake_clang_format, ament_cmake_clang_tidy, and ament_cmake_flake8. |
ros_pubsub_topics_private_namespace |
Passes when string-literal topic and service names passed to ROS create_publisher, create_subscription, create_service, and create_client calls use the private namespace form ~/... instead of global or relative names. |
source_files_have_copyright_notice |
Passes when every tracked .cpp, .hpp, and .py file contains a copyright notice and a non-placeholder license notice near the top of the file, for example via SPDX-License-Identifier: <license-expression>. |
top_level_license |
Passes when a top-level LICENSE file exists and contains non-placeholder license text. |
This repository stores CI workflow templates for the following use cases. CI workflows are defined for GitHub Actions in .github/workflow_calls and for GitLab CI/CD in .gitlab-ci.template.yml.
| Name | Description |
|---|---|
compose-oci |
Publishes the repository's single- or multi-launch Docker Compose files as OCI artifacts to the configured container registry. |
consistency |
Runs the consistency checker to check for repository consistency and convention adherence. |
docker-ros |
Uses docker-ros to build, test, and push a container image containing the ROS packages of the repository. |
docs |
Builds and deploys documentation using GitHub Pages or GitLab Pages. |
ghcr-cleanup |
Cleans up unused images in the GitHub Container Registry. |
helm-oci |
Publishes the repository's single- or multi-launch Helm charts as OCI artifacts to the configured container registry. |