|
4 | 4 |  |
5 | 5 | [](https://codecov.io/gh/Joschi3/package_xml_validation/) |
6 | 6 |
|
7 | | - |
8 | | - |
9 | | -Validates and formats `package.xml` files to enforce consistency and ROS 2 schema compliance. |
10 | | - |
11 | | -### ✅ What it does: |
12 | | - |
13 | | -- **XML Schema Validation & Correction** |
14 | | - - Validates against [package_format3.xsd](http://download.ros.org/schema/package_format3.xsd) |
15 | | - - Automatically fixes ordering and formatting errors |
16 | | -- **Dependency Grouping & Sorting** |
17 | | - - Groups dependencies by type (e.g., `build_depend`, `test_depend`) |
18 | | - - Sorts alphabetically within each group |
19 | | -- **Non-Destructive Edits** |
20 | | - - Leaves comments and indentation **unchanged** |
21 | | -- **Launch File Dependency Validation** |
22 | | - - Scans Python (`.py`), YAML (`.yaml/.yml`), and XML (`.xml`) launch files for package references |
23 | | - - Validates and corrects that all referenced packages are declared in `package.xml` (as `<exec_depend>` or `<depend>`) |
24 | | - - Parses the `test` folder to extract missing `<test_depend>` dependencies |
25 | | -- **Rosdep Key Checking** |
26 | | - - Verifies that all declared packages exist as valid rosdep keys (optional) |
27 | | -- **CMakeLists.txt Synchronization** |
28 | | - - Compares build and test dependencies against `CMakeLists.txt` (optional) |
29 | | - - Automatically inserts missing dependencies from CMake into `package.xml` as `<depend>` or `<build_depend>` (optional) |
30 | | -- **Export Build Type Validation** |
31 | | - - Ensures `package.xml` includes the appropriate `build_type` export (e.g., `ament_cmake`, `ament_python`) |
32 | | - - Validates `buildtool_depend` |
33 | | - |
34 | | -#### Example: Enforced Grouping of Dependencies |
| 7 | + |
| 8 | +**Automate `package.xml` consistency in your ROS 2 projects.** |
| 9 | + |
| 10 | +This tool validates your package manifests against the ROS 2 schema, checks for missing dependencies in code/launch files, and automatically formats the XML to standard conventions. **It is designed primarily to be used as a [pre-commit](https://pre-commit.com/) hook.** |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## 🚀 Quick Start: Pre-commit Hook |
| 15 | + |
| 16 | +The recommended way to use this tool is to integrate it into your `pre-commit` workflow. This ensures that every commit is automatically validated and formatted without manual intervention. |
| 17 | + |
| 18 | +### 1. Add to `.pre-commit-config.yaml` |
| 19 | + |
| 20 | +```yaml |
| 21 | +repos: |
| 22 | + - repo: git@github.com:Joschi3/package_xml_validation.git |
| 23 | + rev: v1.3.0 # Use the latest tag |
| 24 | + hooks: |
| 25 | + - id: format-package-xml |
| 26 | + name: Format package.xml |
| 27 | + |
| 28 | +``` |
| 29 | + |
| 30 | +### 2. Install the Hook |
| 31 | + |
| 32 | +If you haven't already installed pre-commit hooks in your repository: |
| 33 | + |
| 34 | +```bash |
| 35 | +pip install pre-commit |
| 36 | +pre-commit install |
| 37 | + |
| 38 | +``` |
| 39 | + |
| 40 | +Now, `package.xml` files will be checked and formatted automatically on every `git commit`. |
| 41 | + |
| 42 | +--- |
| 43 | + |
| 44 | +## 🔍 Visual Example |
| 45 | + |
| 46 | +This tool enforces the standard ROS 2 element order: |
| 47 | +`name` → `version` → `description` → `maintainer` → `license` → dependencies → `export`. |
| 48 | + |
| 49 | +**Before (Disorganized & Missing Build Type):** |
| 50 | +*Contains valid tags, but the order is random, grouping is missing, and the export tag is absent.* |
| 51 | + |
| 52 | +```xml |
| 53 | +<package format="3"> |
| 54 | + <name>my_package</name> |
| 55 | + <description>My cool package</description> |
| 56 | + <version>0.0.0</version> |
| 57 | + <license>Apache-2.0</license> |
| 58 | + <maintainer email="me@example.com">Me</maintainer> |
| 59 | + <test_depend>ament_lint_auto</test_depend> |
| 60 | + <buildtool_depend>ament_cmake</buildtool_depend> |
| 61 | + <depend>std_msgs</depend> |
| 62 | + <depend>rclcpp</depend> |
| 63 | +</package> |
| 64 | + |
| 65 | +``` |
| 66 | + |
| 67 | +**After (Standardized, Sorted & Fixed):** |
| 68 | +*Elements are reordered to match the schema, dependencies are grouped alphabetically, and missing dependencies detected in CMakeLists.txt or launch files are automatically added.* |
| 69 | + |
35 | 70 | ```xml |
36 | 71 | <package format="3"> |
37 | | - ... |
| 72 | + <name>my_package</name> |
| 73 | + <version>0.0.0</version> |
| 74 | + <description>My cool package</description> |
| 75 | + <maintainer email="me@example.com">Me</maintainer> |
| 76 | + <license>Apache-2.0</license> |
| 77 | + |
38 | 78 | <buildtool_depend>ament_cmake</buildtool_depend> |
39 | 79 |
|
40 | | - <depend>controller_manager_msgs</depend> |
41 | | - <depend>pluginlib</depend> |
| 80 | + <depend>example_from_cmake</depend> <!-- Automatically added missing dep from the CMakeLists.txt --> |
42 | 81 | <depend>rclcpp</depend> |
43 | | - <depend>rclcpp_action</depend> |
| 82 | + <depend>std_msgs</depend> |
44 | 83 |
|
45 | 84 | <test_depend>ament_lint_auto</test_depend> |
46 | | - <test_depend>ament_lint_common</test_depend> |
47 | | - ... |
| 85 | + <test_depend>test_launch_example</test_depend> <!-- Automatically added missing dep from a test launch file--> |
| 86 | + |
48 | 87 | <export> |
49 | 88 | <build_type>ament_cmake</build_type> |
50 | 89 | </export> |
51 | 90 | </package> |
| 91 | + |
52 | 92 | ``` |
53 | 93 |
|
54 | 94 | --- |
55 | 95 |
|
56 | | -## 🛠️ Usage Example |
57 | | - |
58 | | -```bash |
59 | | -package-xml-validator [-h] [--check-only] [--file FILE] [--verbose] [--skip-rosdep-key-validation] [--compare-with-cmake] [--auto-fill-missing-deps] [--missing-deps-only] [--ignore-formatting-errors] |
60 | | - [--strict-cmake-checking] |
61 | | - [src ...] |
62 | | - |
63 | | -Validate and format ROS2 package.xml files. |
64 | | - |
65 | | -positional arguments: |
66 | | - src List of files or directories to process. |
67 | | - |
68 | | -options: |
69 | | - -h, --help show this help message and exit |
70 | | - --check-only Only check for errors without correcting. |
71 | | - --file FILE Path to a single XML file to process. If provided, 'src' arguments are ignored. |
72 | | - --verbose Enable verbose output. |
73 | | - --skip-rosdep-key-validation |
74 | | - Check if rosdeps are valid. |
75 | | - --compare-with-cmake Check if all CMake dependencies are in package.xml. |
76 | | - --auto-fill-missing-deps |
77 | | - Automatically fill missing dependencies in package.xml [--compare-with-cmake must be set]. |
78 | | - --missing-deps-only Only report missing dependencies (implies --check-only). |
79 | | - --ignore-formatting-errors |
80 | | - Ignore formatting-only checks (implies --check-only). |
81 | | - --strict-cmake-checking |
82 | | - Treat unresolved CMake dependencies as errors instead of warnings. |
| 96 | +## ✨ Features |
83 | 97 |
|
| 98 | +### 1. XML Formatting & Standards |
84 | 99 |
|
85 | | -``` |
| 100 | +* **Schema Compliance:** Enforces the presence of required tags (`name`, `version`, `description`, `maintainer`, `license`). |
| 101 | +* **Strict Ordering:** Reorders elements to match the official ROS 2 standard ([package_format3.xsd](http://download.ros.org/schema/package_format3.xsd)). |
| 102 | +* **Intelligent Sorting:** Groups dependencies (e.g., `build_depend`, `exec_depend`) and sorts them alphabetically. |
| 103 | +* **Non-Destructive:** Preserves your existing comments and indentation. |
86 | 104 |
|
87 | | -**Example with verbose logging:** |
88 | | -
|
89 | | -```text |
90 | | -package-xml-validator ~/hector/src/hector_gamepad_manager/hector_gamepad_plugin_interface --check-only --compare-with-cmake --verbose |
91 | | -Processing hector_gamepad_plugin_interface... |
92 | | -✅ [1/13] Check for invalid tags passed. |
93 | | -✅ [2/13] Check for empty lines passed. |
94 | | -✅ [3/13] Check for duplicate elements passed. |
95 | | -✅ [4/13] Check element occurrences passed. |
96 | | -✅ [5/13] Check element order passed. |
97 | | -✅ [6/13] Check dependency order passed. |
98 | | -✅ [7/13] Check indentation passed. |
99 | | -✅ [8/13] Check launch dependencies passed. |
100 | | -✅ [9/13] Check build tool depend passed. |
101 | | -✅ [10/13] Check member of group passed. |
102 | | -✅ [11/13] Check build type export passed. |
103 | | -✅ [12/13] Check ROS dependencies passed. |
104 | | -✅ [13/13] Check CMake dependencies passed. |
105 | | -🎉 All `package.xml` files are valid and nicely formatted. 🚀 |
106 | | -``` |
107 | | -
|
108 | | ---- |
| 105 | +### 2. Dependency Integrity |
109 | 106 |
|
110 | | -## ✅ Pre-commit Hook Setup |
| 107 | +* **Launch File Scanning:** Scans `.py`, `.yaml`, and `.xml` launch files. If a package is used in a launch file but missing from `package.xml`, it adds it as an `<exec_depend>` or `<test_depend>`. |
| 108 | +* **CMake Synchronization:** Compares `package.xml` against `CMakeLists.txt` to ensure build dependencies match. It adds missing as `<depend>` or `<test_depend>`. |
| 109 | +* **Rosdep Validation:** Verifies that your dependency names exist as valid keys in the rosdep database. |
111 | 110 |
|
112 | | -Use [`pre-commit`](https://pre-commit.com/) to automatically validate and format `package.xml` files before every commit. |
| 111 | +### 3. Build Configuration |
113 | 112 |
|
114 | | -### 1. Install `pre-commit` |
| 113 | +* **Export Validation:** Ensures the correct `<build_type>` (e.g., `ament_cmake`) is exported. |
| 114 | +* **Test Dependencies:** Parses `test/` folders to ensure testing libraries are declared as `<test_depend>`. |
115 | 115 |
|
116 | | -```bash |
117 | | -pip install pre-commit |
118 | | -``` |
| 116 | +--- |
119 | 117 |
|
120 | | -### 2. Add to `.pre-commit-config.yaml` |
| 118 | +## 🛠️ Manual Usage (CLI) |
121 | 119 |
|
122 | | -```yaml |
123 | | -repos: |
124 | | - - repo: git@github.com:Joschi3/package_xml_validation.git |
125 | | - rev: v1.3.0 |
126 | | - hooks: |
127 | | - - id: format-package-xml |
128 | | - name: Format package.xml |
129 | | -``` |
| 120 | +If you need to run the validator manually or in a CI environment without pre-commit, you can install it via pip. |
130 | 121 |
|
131 | | -### 3. Install the hook (run once) |
| 122 | +### Installation |
132 | 123 |
|
133 | 124 | ```bash |
134 | | -pre-commit install |
135 | | -``` |
136 | | -
|
137 | | -### 4. Run manually (e.g., on first setup) |
| 125 | +pip install package-xml-validator |
| 126 | +# OR install from source |
| 127 | +pip install . |
138 | 128 |
|
139 | | -```bash |
140 | | -pre-commit run --all-files |
141 | 129 | ``` |
142 | 130 |
|
143 | | ---- |
| 131 | +### Usage Examples |
144 | 132 |
|
145 | | -## 🧪 CI Use: Check-only Mode |
146 | 133 |
|
147 | | -If you are running in CI and want to **fail on violations without modifying files**, use: |
| 134 | +**Check only (Don't modify files)** |
148 | 135 |
|
149 | 136 | ```bash |
150 | | -package-xml-validator --check-only --compare-with-cmake . |
| 137 | +package-xml-validator . --check-only |
| 138 | + |
151 | 139 | ``` |
152 | 140 |
|
153 | | -This will: |
| 141 | +**Auto-fill missing dependencies from CMake** |
154 | 142 |
|
155 | | -* Validate all `package.xml` files. |
156 | | -* Print formatting/schema issues. |
157 | | -* Check validity of rosdep keys. |
158 | | -* Compare dependencies against `CMakeLists.txt`. |
159 | | -* Exit with a non-zero code if problems are found. |
160 | | -* **Modify no files.** |
| 143 | +```bash |
| 144 | +package-xml-validator . --compare-with-cmake --auto-fill-missing-deps |
161 | 145 |
|
162 | | -*Note: If `rosdep` is not initialized in your CI environment, add `--skip-rosdep-key-validation`.* |
| 146 | +``` |
163 | 147 |
|
164 | | -### 🎯 Focused Modes |
| 148 | +### CLI Options |
165 | 149 |
|
166 | | -* `--missing-deps-only`: Skips formatting checks; only reports missing dependencies (useful for quick audits). |
167 | | -* `--ignore-formatting-errors`: Checks for logic/dependency errors but ignores indentation or sorting issues. |
| 150 | +| Option | Description | |
| 151 | +| --- | --- | |
| 152 | +| `--check-only` | Report errors/formatting issues without modifying files (Exit code 1 on failure). | |
| 153 | +| `--compare-with-cmake` | Check if dependencies used in `CMakeLists.txt` are declared in `package.xml`. | |
| 154 | +| `--auto-fill-missing-deps` | Automatically add dependencies found in CMake/Launch files to `package.xml`. | |
| 155 | +| `--strict-cmake-checking` | Treat unresolved CMake dependencies as errors instead of warnings. | |
| 156 | +| `--skip-rosdep-key-validation` | Skip verifying if dependency names exist in the `rosdep` database. | |
| 157 | +| `--missing-deps-only` | Skips formatting checks; only looks for missing dependencies. | |
168 | 158 |
|
169 | 159 | --- |
170 | 160 |
|
171 | | -## ✨ Autocompletion |
| 161 | +## 🧪 CI Integration |
172 | 162 |
|
173 | | -To enable tab autocompletion for arguments and flags: |
| 163 | +To run this in GitHub Actions or GitLab CI (outside of pre-commit), use the check-only mode. |
174 | 164 |
|
175 | | -1. **Install the package:** |
176 | 165 | ```bash |
177 | | -pip install . |
| 166 | +package-xml-validator --check-only --compare-with-cmake . |
| 167 | + |
178 | 168 | ``` |
179 | 169 |
|
| 170 | +*Note: If `rosdep` is not initialized in your CI environment, add `--skip-rosdep-key-validation` to avoid errors.* |
180 | 171 |
|
181 | | -2. **Enable temporarily:** |
182 | | -Run this in your terminal: |
183 | | -```bash |
184 | | -eval "$(register-python-argcomplete package-xml-validator)" |
185 | | -``` |
| 172 | +--- |
186 | 173 |
|
| 174 | +## ⌨️ Autocompletion |
187 | 175 |
|
188 | | -3. **Enable permanently:** |
189 | | -Add the activation command to your shell profile (`~/.bashrc` or `~/.zshrc`): |
190 | | -```bash |
191 | | -echo 'eval "$(register-python-argcomplete package-xml-validator)"' >> ~/.bashrc |
192 | | -``` |
| 176 | +To enable tab autocompletion for CLI arguments: |
| 177 | + |
| 178 | +1. **Install:** `pip install .` |
| 179 | +2. **Enable (Temporary):** `eval "$(register-python-argcomplete package-xml-validator)"` |
| 180 | +3. **Enable (Permanent):** `echo 'eval "$(register-python-argcomplete package-xml-validator)"' >> ~/.bashrc` |
0 commit comments