diff options
author | Alexander Kanavin <alex@linutronix.de> | 2024-07-17 20:22:15 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2024-07-22 16:53:06 +0100 |
commit | 3d98aafc43bf6d14aac997137348fe503efed04e (patch) | |
tree | 99c4454f140b999447c3e6325bca7eca5030e346 | |
parent | bd18497110796c5d86cef202dc37798478c84cd2 (diff) | |
download | poky-3d98aafc43bf6d14aac997137348fe503efed04e.tar.gz |
recipeutils/get_recipe_upgrade_status: group recipes when they need to be upgraded together
This will allow 'lockstep upgrades' of such recipes, improving success
rates in automated version updating process.
devtool check-upgrade-status now prints:
These recipes need to be upgraded together {
glib-2.0 2.80.2 2.80.4 Anuj Mittal <anuj.mittal@intel.com>
glib-2.0-initial 2.80.2 2.80.4 Anuj Mittal <anuj.mittal@intel.com>
}
These recipes need to be upgraded together {
util-linux 2.39.3 2.40.2 Chen Qi <Qi.Chen@windriver.com>
util-linux-libuuid 2.39.3 2.40.2 Chen Qi <Qi.Chen@windriver.com>
}
These recipes need to be upgraded together {
cmake 3.29.3 3.30.0 Unassigned <unassigned@yoctoproject.org>
cmake-native 3.29.3 3.30.0 Unassigned <unassigned@yoctoproject.org>
}
etc.
(From OE-Core rev: 7874aea5c62be3e8dbd19e04fce5389c5ed7aab6)
Signed-off-by: Alexander Kanavin <alex@linutronix.de>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/lib/oe/recipeutils.py | 23 | ||||
-rw-r--r-- | meta/lib/oeqa/selftest/cases/distrodata.py | 6 | ||||
-rw-r--r-- | scripts/lib/devtool/upgrade.py | 28 |
3 files changed, 44 insertions, 13 deletions
diff --git a/meta/lib/oe/recipeutils.py b/meta/lib/oe/recipeutils.py index 7586332fe0..56be75dc9c 100644 --- a/meta/lib/oe/recipeutils.py +++ b/meta/lib/oe/recipeutils.py | |||
@@ -1154,6 +1154,7 @@ def get_recipe_upgrade_status(recipes=None): | |||
1154 | if not recipes: | 1154 | if not recipes: |
1155 | recipes = tinfoil.all_recipe_files(variants=False) | 1155 | recipes = tinfoil.all_recipe_files(variants=False) |
1156 | 1156 | ||
1157 | recipeincludes = {} | ||
1157 | for fn in recipes: | 1158 | for fn in recipes: |
1158 | try: | 1159 | try: |
1159 | if fn.startswith("/"): | 1160 | if fn.startswith("/"): |
@@ -1178,11 +1179,13 @@ def get_recipe_upgrade_status(recipes=None): | |||
1178 | 1179 | ||
1179 | data_copy_list.append(data_copy) | 1180 | data_copy_list.append(data_copy) |
1180 | 1181 | ||
1182 | recipeincludes[data.getVar('FILE')] = {'bbincluded':data.getVar('BBINCLUDED').split(),'pn':data.getVar('PN')} | ||
1183 | |||
1181 | from concurrent.futures import ProcessPoolExecutor | 1184 | from concurrent.futures import ProcessPoolExecutor |
1182 | with ProcessPoolExecutor(max_workers=utils.cpu_count()) as executor: | 1185 | with ProcessPoolExecutor(max_workers=utils.cpu_count()) as executor: |
1183 | pkgs_list = executor.map(_get_recipe_upgrade_status, data_copy_list) | 1186 | pkgs_list = executor.map(_get_recipe_upgrade_status, data_copy_list) |
1184 | 1187 | ||
1185 | return pkgs_list | 1188 | return _group_recipes(pkgs_list, _get_common_include_recipes(recipeincludes)) |
1186 | 1189 | ||
1187 | def get_common_include_recipes(): | 1190 | def get_common_include_recipes(): |
1188 | with bb.tinfoil.Tinfoil() as tinfoil: | 1191 | with bb.tinfoil.Tinfoil() as tinfoil: |
@@ -1220,3 +1223,21 @@ def _get_common_include_recipes(recipeincludes_all): | |||
1220 | recipes_with_shared_includes.append(recipeset) | 1223 | recipes_with_shared_includes.append(recipeset) |
1221 | 1224 | ||
1222 | return recipes_with_shared_includes | 1225 | return recipes_with_shared_includes |
1226 | |||
1227 | def _group_recipes(recipes, groups): | ||
1228 | recipedict = {} | ||
1229 | for r in recipes: | ||
1230 | recipedict[r['pn']] = r | ||
1231 | |||
1232 | recipegroups = [] | ||
1233 | for g in groups: | ||
1234 | recipeset = [] | ||
1235 | for r in g: | ||
1236 | if r in recipedict.keys(): | ||
1237 | recipeset.append(recipedict[r]) | ||
1238 | del recipedict[r] | ||
1239 | recipegroups.append(recipeset) | ||
1240 | |||
1241 | for r in recipedict.values(): | ||
1242 | recipegroups.append([r]) | ||
1243 | return recipegroups | ||
diff --git a/meta/lib/oeqa/selftest/cases/distrodata.py b/meta/lib/oeqa/selftest/cases/distrodata.py index bc56160522..bd37552364 100644 --- a/meta/lib/oeqa/selftest/cases/distrodata.py +++ b/meta/lib/oeqa/selftest/cases/distrodata.py | |||
@@ -20,10 +20,10 @@ class Distrodata(OESelftestTestCase): | |||
20 | feature = 'LICENSE_FLAGS_ACCEPTED += " commercial"\n' | 20 | feature = 'LICENSE_FLAGS_ACCEPTED += " commercial"\n' |
21 | self.write_config(feature) | 21 | self.write_config(feature) |
22 | 22 | ||
23 | pkgs = oe.recipeutils.get_recipe_upgrade_status() | 23 | pkggroups = oe.recipeutils.get_recipe_upgrade_status() |
24 | 24 | ||
25 | regressed_failures = [pkg['pn'] for pkg in pkgs if pkg['status'] == 'UNKNOWN_BROKEN'] | 25 | regressed_failures = [pkg['pn'] for pkgs in pkggroups for pkg in pkgs if pkg['status'] == 'UNKNOWN_BROKEN'] |
26 | regressed_successes = [pkg['pn'] for pkg in pkgs if pkg['status'] == 'KNOWN_BROKEN'] | 26 | regressed_successes = [pkg['pn'] for pkgs in pkggroups for pkg in pkgs if pkg['status'] == 'KNOWN_BROKEN'] |
27 | msg = "" | 27 | msg = "" |
28 | if len(regressed_failures) > 0: | 28 | if len(regressed_failures) > 0: |
29 | msg = msg + """ | 29 | msg = msg + """ |
diff --git a/scripts/lib/devtool/upgrade.py b/scripts/lib/devtool/upgrade.py index 10b4f8b5ee..4c268af3a7 100644 --- a/scripts/lib/devtool/upgrade.py +++ b/scripts/lib/devtool/upgrade.py | |||
@@ -654,18 +654,28 @@ def latest_version(args, config, basepath, workspace): | |||
654 | return 0 | 654 | return 0 |
655 | 655 | ||
656 | def check_upgrade_status(args, config, basepath, workspace): | 656 | def check_upgrade_status(args, config, basepath, workspace): |
657 | def _print_status(recipe): | ||
658 | print("{:25} {:15} {:15} {} {} {}".format( recipe['pn'], | ||
659 | recipe['cur_ver'], | ||
660 | recipe['status'] if recipe['status'] != 'UPDATE' else (recipe['next_ver'] if not recipe['next_ver'].endswith("new-commits-available") else "new commits"), | ||
661 | recipe['maintainer'], | ||
662 | recipe['revision'] if recipe['revision'] != 'N/A' else "", | ||
663 | "cannot be updated due to: %s" %(recipe['no_upgrade_reason']) if recipe['no_upgrade_reason'] else "")) | ||
657 | if not args.recipe: | 664 | if not args.recipe: |
658 | logger.info("Checking the upstream status for all recipes may take a few minutes") | 665 | logger.info("Checking the upstream status for all recipes may take a few minutes") |
659 | results = oe.recipeutils.get_recipe_upgrade_status(args.recipe) | 666 | results = oe.recipeutils.get_recipe_upgrade_status(args.recipe) |
660 | for result in results: | 667 | for recipegroup in results: |
661 | # pn, update_status, current, latest, maintainer, latest_commit, no_update_reason | 668 | upgrades = [r for r in recipegroup if r['status'] != 'MATCH'] |
662 | if args.all or result['status'] != 'MATCH': | 669 | currents = [r for r in recipegroup if r['status'] == 'MATCH'] |
663 | print("{:25} {:15} {:15} {} {} {}".format( result['pn'], | 670 | if len(upgrades) > 1: |
664 | result['cur_ver'], | 671 | print("These recipes need to be upgraded together {") |
665 | result['status'] if result['status'] != 'UPDATE' else (result['next_ver'] if not result['next_ver'].endswith("new-commits-available") else "new commits"), | 672 | for r in upgrades: |
666 | result['maintainer'], | 673 | _print_status(r) |
667 | result['revision'] if result['revision'] != 'N/A' else "", | 674 | if len(upgrades) > 1: |
668 | "cannot be updated due to: %s" %(result['no_upgrade_reason']) if result['no_upgrade_reason'] else "")) | 675 | print("}") |
676 | for r in currents: | ||
677 | if args.all: | ||
678 | _print_status(r) | ||
669 | 679 | ||
670 | def register_commands(subparsers, context): | 680 | def register_commands(subparsers, context): |
671 | """Register devtool subcommands from this plugin""" | 681 | """Register devtool subcommands from this plugin""" |