Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
update_readme_table.py
1 #!/usr/bin/python3
2 # Copyright (c) 2024 Open Navigation LLC
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 # This tool populates the README table of build status for each package
17 
18 import time
19 
20 import requests
21 
22 # Global information about current distributions, shouldn't need to update
23 OSs = {'humble': 'jammy', 'jazzy': 'noble', 'lyrical': 'resolute'}
24 Prefixs = {'humble': 'H', 'jazzy': 'J', 'lyrical': 'L'}
25 
26 # Set your packages here
27 Packages = [
28  'navigation2',
29  'nav2_amcl',
30  'nav2_behavior_tree',
31  'nav2_behaviors',
32  'nav2_bringup',
33  'nav2_bt_navigator',
34  'nav2_collision_monitor',
35  'nav2_common',
36  'nav2_constrained_smoother',
37  'nav2_controller',
38  'nav2_core',
39  'nav2_costmap_2d',
40  'opennav_docking',
41  'opennav_docking_bt',
42  'opennav_docking_core',
43  'nav2_dwb_controller', # Controller plugin for DWB packages
44  'opennav_following',
45  'nav2_graceful_controller',
46  'nav2_lifecycle_manager',
47  'nav2_loopback_sim',
48  'nav2_map_server',
49  'nav2_mppi_controller',
50  'nav2_msgs',
51  'nav2_navfn_planner',
52  'nav2_planner',
53  'nav2_regulated_pure_pursuit_controller',
54  'nav2_rotation_shim_controller',
55  'nav2_ros_common',
56  'nav2_route',
57  'nav2_rviz_plugins',
58  'nav2_simple_commander',
59  'nav2_smac_planner',
60  'nav2_smoother',
61  'nav2_system_tests',
62  'nav2_theta_star_planner',
63  'nav2_util',
64  'nav2_velocity_smoother',
65  'nav2_voxel_grid',
66  'nav2_waypoint_follower',
67 ]
68 
69 # Set which distributions you care about
70 Distros = ['humble', 'jazzy', 'lyrical']
71 
72 
73 def getSrcPath(package: str, prefix: str, OS: str) -> str:
74  return f'https://build.ros2.org/job/{prefix}src_u{OS[0]}__{package}__ubuntu_{OS}__source/'
75 
76 
77 def getBinPath(package: str, prefix: str, OS: str) -> str:
78  return (
79  f'https://build.ros2.org/job/{prefix}bin_u{OS[0]}64__{package}__ubuntu_{OS}_'
80  'amd64__binary/'
81  )
82 
83 
84 def createPreamble(Distros: list[str]) -> str:
85  table = '| Package | '
86  for distro in Distros:
87  table += distro + ' Source | ' + distro + ' Debian | '
88  table = table[:-1] # Remove the last space
89  table += '\n'
90  table += '| :---: |'
91  for distro in Distros:
92  table += ' :---: | :---: |'
93  return table
94 
95 
96 def main() -> None:
97  header = createPreamble(Distros)
98 
99  body = ''
100  for package in Packages:
101  entry = f'| {package} | '
102  for distro in Distros:
103  # TODO check if website exists with requests
104  prefix = Prefixs[distro]
105  OS = OSs[distro]
106  srcURL = getSrcPath(package, prefix, OS)
107  binURL = getBinPath(package, prefix, OS)
108  # Check if package exists in this distribution with retries
109  status = None
110  for attempt in range(3):
111  try:
112  response = requests.get(srcURL, timeout=10)
113  status = response.status_code
114  if status == 200:
115  break
116  time.sleep(1)
117  except requests.exceptions.RequestException:
118  time.sleep(1)
119  if status != 200:
120  entry += 'N/A | N/A | '
121  else:
122  entry += f'[![Build Status]({srcURL}badge/icon)]({srcURL}) | '
123  entry += f'[![Build Status]({binURL}badge/icon)]({binURL}) | '
124  entry = entry[:-1]
125  entry += '\n'
126  body += entry
127 
128  # Special case for Opennav Docking for directory structure of Nav2
129  body = body.replace('| opennav_docking |', '| nav2_docking |')
130  body = body.replace('| opennav_docking_bt |', '| nav2_docking_bt |')
131  body = body.replace('| opennav_docking_core |', '| nav2_docking_core |')
132  # Special case for Opennav Following for directory structure of Nav2
133  body = body.replace('| opennav_following |', '| nav2_following |')
134  # Special case for reducing the label length
135  body = body.replace('| nav2_regulated_pure_pursuit_controller |',
136  '| nav2_regulated_pure_pursuit |')
137 
138  print(header + '\n' + body)
139 
140 
141 if __name__ == '__main__':
142  main()