2021-12-30 01:28:49 -04:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
'''
|
|
|
|
script to build a html file showing flash free for current builds
|
|
|
|
|
|
|
|
AP_FLAKE8_CLEAN
|
|
|
|
'''
|
|
|
|
|
|
|
|
import os
|
|
|
|
import argparse
|
|
|
|
import fnmatch
|
|
|
|
import json
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(description='create builds.html for list of builds')
|
|
|
|
parser.add_argument('basedir', default=None, help='base directory (binaries directory)')
|
|
|
|
parser.add_argument('--outfile', default="builds.html", help='output file')
|
|
|
|
|
2023-05-24 18:13:26 -03:00
|
|
|
build_dirs = ['latest', 'beta', 'beta-4.3', 'stable']
|
2022-02-23 06:17:00 -04:00
|
|
|
builds = ['Plane', 'Copter', 'Rover', 'Sub', 'Blimp', 'AntennaTracker', 'AP_Periph']
|
2021-12-30 01:28:49 -04:00
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
2022-01-04 23:36:17 -04:00
|
|
|
warning_flash_free = 5000
|
|
|
|
warning_build_days = 3
|
|
|
|
|
2024-01-18 17:11:59 -04:00
|
|
|
LINUX_BINARIES = ["arduplane", "arducopter", "arducopter-heli", "ardurover", "ardusub", "antennatracker"]
|
|
|
|
|
2021-12-30 01:28:49 -04:00
|
|
|
|
|
|
|
class APJInfo:
|
|
|
|
def __init__(self, vehicle, board, githash, mtime, flash_free):
|
|
|
|
self.vehicle = vehicle
|
|
|
|
self.board = board
|
|
|
|
self.githash = githash
|
|
|
|
self.mtime = mtime
|
|
|
|
self.flash_free = flash_free
|
2022-01-04 23:36:17 -04:00
|
|
|
self.warning = 0
|
2021-12-30 01:28:49 -04:00
|
|
|
|
|
|
|
|
2024-01-18 17:11:59 -04:00
|
|
|
def firmware_list(basedir):
|
2021-12-30 01:28:49 -04:00
|
|
|
'''list of APJInfo for one directory'''
|
|
|
|
boards = []
|
|
|
|
for root, subdirs, files in os.walk(basedir):
|
|
|
|
for f in files:
|
2024-01-18 17:11:59 -04:00
|
|
|
if not fnmatch.fnmatch(f, "*.apj") and f not in LINUX_BINARIES:
|
2021-12-30 01:28:49 -04:00
|
|
|
continue
|
|
|
|
fname = os.path.join(root, f)
|
|
|
|
board = os.path.basename(root)
|
|
|
|
vehicle = fname.split('/')[-4]
|
|
|
|
mtime = os.stat(fname).st_mtime
|
2024-01-18 17:11:59 -04:00
|
|
|
if f in LINUX_BINARIES:
|
|
|
|
git_version = os.path.join(root, "git-version.txt")
|
|
|
|
try:
|
|
|
|
line = open(git_version, 'r').readline()
|
|
|
|
githash = line.split()[1][:8]
|
|
|
|
except OSError:
|
|
|
|
githash = "unknown"
|
|
|
|
flash_free = 999999
|
|
|
|
else:
|
|
|
|
fw_json = json.load(open(fname, "r"))
|
|
|
|
githash = fw_json['git_identity']
|
|
|
|
flash_free = fw_json.get('flash_free', -1)
|
2021-12-30 01:28:49 -04:00
|
|
|
apjinfo = APJInfo(vehicle, board, githash, mtime, flash_free)
|
|
|
|
boards.append(apjinfo)
|
|
|
|
return boards
|
|
|
|
|
|
|
|
|
|
|
|
def write_headers(h):
|
|
|
|
'''write html headers'''
|
|
|
|
h.write('''
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<script src="sorttable.js"></script>
|
2022-01-04 23:36:17 -04:00
|
|
|
<script src="filtertable.js"></script>
|
|
|
|
<link href="../../css/main.css" rel="stylesheet" type="text/css" />
|
2021-12-30 01:28:49 -04:00
|
|
|
<style>
|
|
|
|
td {
|
|
|
|
border-left:1px solid black;
|
|
|
|
border-top:1px solid black;
|
|
|
|
}
|
|
|
|
th {
|
|
|
|
text-align: left;
|
|
|
|
border-left:1px solid black;
|
|
|
|
border-top:1px solid black;
|
|
|
|
}
|
|
|
|
table {
|
|
|
|
border-right:1px solid black;
|
|
|
|
border-bottom:1px solid black;
|
|
|
|
}
|
2022-01-04 23:36:17 -04:00
|
|
|
a {
|
|
|
|
color: inherit;
|
|
|
|
}
|
2021-12-30 01:28:49 -04:00
|
|
|
</style>
|
|
|
|
<title>Build List</title>
|
|
|
|
</head>
|
|
|
|
<body>
|
2022-01-04 23:36:17 -04:00
|
|
|
<div id="main">
|
|
|
|
<a href="https://firmware.ardupilot.org/">
|
|
|
|
<div id="logo" style="text-align:center;">
|
|
|
|
</div>
|
|
|
|
</a>
|
|
|
|
<h2 id='top'>Build List</h2>
|
|
|
|
<p>This is an auto-generated list of current builds
|
2022-01-20 05:05:19 -04:00
|
|
|
allowing us to quickly see how close we are to running out of flash space.
|
|
|
|
<br>This page was most recently regenerated on %s UTC.</p>
|
2022-01-04 23:36:17 -04:00
|
|
|
<p>Builds that are coloured red haven't built recently. Builds that are coloured yellow have low flash space remaining.</p>
|
|
|
|
<p>Click on any column header to sort by that column, or filter by entering a search term in the box above each table.</p>
|
2021-12-30 01:28:49 -04:00
|
|
|
<ul>
|
|
|
|
<li>Jump to <a href='#latest'>latest</a></li>
|
|
|
|
<li>Jump to <a href='#beta'>beta</a></li>
|
2023-05-24 18:13:26 -03:00
|
|
|
<li>Jump to <a href='#beta-4.3'>beta-4.3</a></li>
|
2021-12-30 01:28:49 -04:00
|
|
|
<li>Jump to <a href='#stable'>stable</a></li>
|
|
|
|
</ul>
|
2022-01-20 05:05:19 -04:00
|
|
|
''' % datetime.now().strftime("%F %k:%M"))
|
2021-12-30 01:28:49 -04:00
|
|
|
|
|
|
|
|
|
|
|
def write_footer(h):
|
|
|
|
'''write html footer'''
|
|
|
|
h.write('''
|
2022-01-04 23:36:17 -04:00
|
|
|
</div>
|
2021-12-30 01:28:49 -04:00
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
''')
|
|
|
|
|
|
|
|
|
|
|
|
def write_table(h, build_type):
|
|
|
|
'''write table for one build type'''
|
|
|
|
boards = []
|
|
|
|
|
|
|
|
for build in builds:
|
2024-01-18 17:11:59 -04:00
|
|
|
boards.extend(firmware_list(os.path.join(args.basedir, build, build_type)))
|
2021-12-30 01:28:49 -04:00
|
|
|
|
2022-01-04 23:36:17 -04:00
|
|
|
max_mtime = 0
|
|
|
|
for apjinfo in boards:
|
|
|
|
if apjinfo.mtime > max_mtime:
|
|
|
|
max_mtime = apjinfo.mtime
|
|
|
|
|
|
|
|
for apjinfo in boards:
|
2022-01-20 05:05:19 -04:00
|
|
|
if apjinfo.flash_free < warning_flash_free and not apjinfo.flash_free == -1:
|
2022-01-04 23:36:17 -04:00
|
|
|
apjinfo.warning = 1
|
2022-01-07 00:27:19 -04:00
|
|
|
if int(apjinfo.mtime) < int(max_mtime)-warning_build_days*86400 and build_type == "latest":
|
2022-01-04 23:36:17 -04:00
|
|
|
apjinfo.warning = 2
|
|
|
|
|
|
|
|
boards.sort(key=lambda board: board.warning, reverse=True)
|
|
|
|
|
|
|
|
try:
|
|
|
|
idxs1 = [i for (i, e) in enumerate(boards) if e.warning == 1]
|
|
|
|
boards[min(idxs1):max(idxs1)] = sorted(boards[min(idxs1):max(idxs1)], key=lambda board: board.flash_free)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
try:
|
|
|
|
idxs2 = [i for (i, e) in enumerate(boards) if e.warning == 2]
|
|
|
|
boards[min(idxs2):max(idxs2)] = sorted(boards[min(idxs2):max(idxs2)], key=lambda board: board.mtime)
|
|
|
|
except ValueError:
|
|
|
|
pass
|
|
|
|
|
2021-12-30 01:28:49 -04:00
|
|
|
h.write('''
|
2022-01-04 23:36:17 -04:00
|
|
|
<h3 id='%s'>%s builds</h3>
|
|
|
|
<p><input type="text" id="search_%s" onkeyup="searchFunc('%s')" placeholder="Filter..."></p>
|
|
|
|
<table class="sortable" id="table_%s">
|
2022-01-20 05:05:19 -04:00
|
|
|
<tr><th style="width:90px">Vehicle</th><th style="width:250px">Board</th><th style="width:140px">Build Date</th>
|
2022-01-04 23:36:17 -04:00
|
|
|
<th style="width:100px">git hash</th><th style="width:100px">Flash Free</th></tr>
|
|
|
|
''' % (build_type, build_type.capitalize(), build_type, build_type, build_type))
|
2021-12-30 01:28:49 -04:00
|
|
|
|
|
|
|
for apjinfo in boards:
|
2022-01-04 23:36:17 -04:00
|
|
|
if apjinfo.warning == 1:
|
|
|
|
h.write('<tr style="color:#E6B800;">')
|
|
|
|
elif apjinfo.warning == 2:
|
|
|
|
h.write('<tr style="color:#FF0000;">')
|
|
|
|
else:
|
|
|
|
h.write('<tr>')
|
2022-01-07 00:27:19 -04:00
|
|
|
h.write('''<td>%s</td>
|
|
|
|
<td><a href="https://firmware.ardupilot.org/%s/%s/%s">%s</a></td>
|
|
|
|
<td>%s</td>
|
|
|
|
<td><a href="https://github.com/ArduPilot/ardupilot/commit/%s">%s</a></td>
|
|
|
|
<td>%u</td></tr>\n''' % (
|
|
|
|
apjinfo.vehicle, apjinfo.vehicle, build_type, apjinfo.board, apjinfo.board,
|
|
|
|
datetime.fromtimestamp(apjinfo.mtime).strftime("%F %k:%M"),
|
2021-12-30 01:28:49 -04:00
|
|
|
apjinfo.githash, apjinfo.githash, apjinfo.flash_free))
|
|
|
|
|
|
|
|
h.write('''
|
|
|
|
</table>
|
2022-01-04 23:36:17 -04:00
|
|
|
<p>Return to <a href='#top'>top</a></p>
|
2021-12-30 01:28:49 -04:00
|
|
|
''')
|
|
|
|
|
|
|
|
|
|
|
|
h = open(args.outfile, "w")
|
|
|
|
write_headers(h)
|
|
|
|
for t in build_dirs:
|
|
|
|
write_table(h, t)
|
|
|
|
write_footer(h)
|