-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
scripts: add machine summary report tool
machine-summary.py is a tool to generate a report of what recipes and versions are used for what machines, and what the latest upstream release is. Change-Id: Iecf21a14057df0fd1cb05be9b54c621dfbaddd94 Signed-off-by: Ross Burton <[email protected]> Signed-off-by: Jon Mason <[email protected]>
- Loading branch information
1 parent
8f204c2
commit b1d667c
Showing
4 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Machine Overview | ||
Generated at {{ timestamp }}. | ||
{% for machine, data in data|dictsort %} | ||
|
||
MACHINE: {{ machine }} | ||
{% for recipe in recipes|sort %} | ||
{% if recipe in data %} | ||
{% set details = data[recipe] %} | ||
{{ details.recipe }}: {{ details.version }} | ||
{% endif %} | ||
{% endfor %} | ||
{% endfor %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Pending Machine Upgrades Report</title> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css"> | ||
</head> | ||
<body> | ||
<section class="section"> | ||
<div class="content"> | ||
<h1 class="title">Pending Machine Upgrades Report</h1> | ||
<p>Generated at {{ timestamp }}.</p> | ||
</div> | ||
|
||
<table class="table is-striped"> | ||
<thead> | ||
<tr> | ||
<th>Machine</th> | ||
{% for recipe in recipes|sort %} | ||
<th>{{ recipe }} ({{releases[recipe]|default("?")}})</th> | ||
{% endfor %} | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{% for machine, data in data|dictsort %} | ||
<tr> | ||
<th>{{ machine }}</th> | ||
{% for recipe in recipes|sort %} | ||
{% if recipe in data %} | ||
{% set details = data[recipe] %} | ||
{% set is_old = details.version is old(details.upstream) %} | ||
<td class="{% if is_old %}has-text-weight-bold{% endif %}"> | ||
{{ details.recipe if details.recipe != recipe}} | ||
{{ details.version }} | ||
{{ "(patched)" if details.patched }} | ||
</td> | ||
{% else %} | ||
<td>-</td> | ||
{% endif %} | ||
{% endfor %} | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</table> | ||
</section> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
#! /usr/bin/env python3 | ||
|
||
import os | ||
import sys | ||
import argparse | ||
import datetime | ||
|
||
import jinja2 | ||
|
||
def get_template(name): | ||
template_dir = os.path.dirname(os.path.abspath(__file__)) | ||
env = jinja2.Environment( | ||
loader=jinja2.FileSystemLoader(template_dir), | ||
autoescape=jinja2.select_autoescape(), | ||
trim_blocks=True, | ||
lstrip_blocks=True | ||
) | ||
def is_old(version, upstream): | ||
if "+git" in version: | ||
# strip +git and see if this is a post-release snapshot | ||
version = version.replace("+git", "") | ||
return version != upstream | ||
env.tests["old"] = is_old | ||
|
||
return env.get_template(f"machine-summary-{name}.jinja") | ||
|
||
def trim_pv(pv): | ||
""" | ||
Strip anything after +git from the PV | ||
""" | ||
return "".join(pv.partition("+git")[:2]) | ||
|
||
def layer_path(layername, d): | ||
""" | ||
Return the path to the specified layer, or None if the layer isn't present. | ||
""" | ||
import re | ||
bbpath = d.getVar("BBPATH").split(":") | ||
pattern = d.getVar('BBFILE_PATTERN_' + layername) | ||
for path in reversed(sorted(bbpath)): | ||
if re.match(pattern, path + "/"): | ||
return path | ||
return None | ||
|
||
def harvest_data(machines, recipes): | ||
import bb.tinfoil, bb.utils | ||
with bb.tinfoil.Tinfoil() as tinfoil: | ||
tinfoil.prepare(config_only=True) | ||
corepath = layer_path("core", tinfoil.config_data) | ||
sys.path.append(os.path.join(corepath, "lib")) | ||
import oe.recipeutils | ||
import oe.patch | ||
|
||
# Queue of recipes that we're still looking for upstream releases for | ||
to_check = list(recipes) | ||
|
||
# Upstream releases | ||
upstreams = {} | ||
# Machines to recipes to versions | ||
versions = {} | ||
|
||
for machine in machines: | ||
print(f"Gathering data for {machine}...") | ||
os.environ["MACHINE"] = machine | ||
with bb.tinfoil.Tinfoil() as tinfoil: | ||
versions[machine] = {} | ||
|
||
tinfoil.prepare(quiet=2) | ||
for recipe in recipes: | ||
try: | ||
d = tinfoil.parse_recipe(recipe) | ||
except bb.providers.NoProvider: | ||
continue | ||
|
||
if recipe in to_check: | ||
try: | ||
info = oe.recipeutils.get_recipe_upstream_version(d) | ||
upstreams[recipe] = info["version"] | ||
to_check.remove(recipe) | ||
except (bb.providers.NoProvider, KeyError): | ||
pass | ||
|
||
details = versions[machine][recipe] = {} | ||
details["recipe"] = d.getVar("PN") | ||
details["version"] = trim_pv(d.getVar("PV")) | ||
details["patched"] = bool(oe.patch.src_patches(d)) | ||
|
||
# Now backfill the upstream versions | ||
for machine in versions: | ||
for recipe in versions[machine]: | ||
versions[machine][recipe]["upstream"] = upstreams[recipe] | ||
|
||
return upstreams, versions | ||
|
||
# TODO can this be inferred from the list of recipes in the layer | ||
recipes = ("virtual/kernel", | ||
"scp-firmware", | ||
"trusted-firmware-a", | ||
"trusted-firmware-m", | ||
"edk2-firmware", | ||
"u-boot", | ||
"optee-os", | ||
"armcompiler-native", | ||
"gcc-aarch64-none-elf-native", | ||
"gcc-arm-none-eabi-native") | ||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser(description="machine-summary") | ||
parser.add_argument("machines", nargs="+", help="machine names", metavar="MACHINE") | ||
parser.add_argument("-t", "--template", required=True) | ||
parser.add_argument("-o", "--output", required=True, type=argparse.FileType('w', encoding='UTF-8')) | ||
args = parser.parse_args() | ||
|
||
template = get_template(args.template) | ||
|
||
context = {} | ||
# TODO: include git describe for meta-arm | ||
context["timestamp"] = str(datetime.datetime.now().strftime("%c")) | ||
context["recipes"] = sorted(recipes) | ||
context["releases"], context["data"] = harvest_data(args.machines, recipes) | ||
|
||
args.output.write(template.render(context)) |