| Message ID | 20260424114603.2444938-7-daniel.turull@ericsson.com |
|---|---|
| State | New |
| Headers | show |
| Series | upgrade_helper: scarthgap compatibility, stable updates and changelog extraction | expand |
On Fri, 24 Apr 2026 at 13:46, <daniel.turull@ericsson.com> wrote: > help="extract changelog between old and new versions, highlighting CVEs") > parser.add_argument("--stable", action="store_true", default=False, > help="only upgrade to the next patch version within the stable branch (e.g. 1.2.3 -> 1.2.4)") > + parser.add_argument("--minor", action="store_true", default=False, > + help="allow upgrades within the same major version (e.g. 3.5.2 -> 3.6.0, 3.99.0)") I'm somewhat confused. When and how one would be using either of these options? What's the workflow for them? I still think it's better to place stable maintenance information directly into recipes. Alex
Hi Alex, The workflow is: when running AUH against a stable branch (e.g. scarthgap), you typically don't want to pull in major version bumps. --stable restricts upgrades to patch-only (1.2.3 → 1.2.4), and --minor relaxes that to same-major (1.2.3 → 1.3.0). In practice, the right policy depends on the component. From our test runs on scarthgap with --prebuild and ABI checking (meta-binaryaudit [1]), even patch-level upgrades can break ABI. For example, libnotify 0.8.3 → 0.8.8 is a patch bump, but abidiff reports INCOMPATIBLE_CHANGE: 2 removed functions, 4 added (a breaking ABI change hidden behind a patch version bump) On the other hand, many minor-level upgrades like curl, libxml2, and e2fsprogs succeed without any ABI issues. So ideally you'd use --minor for some recipes and --stable for others. Right now the CLI flags apply globally, which means you either run --stable for all, or list specific recipes with --minor. That works but isn't ideal. I agree that putting this information in the recipe is the better long-term approach. Something like: AUH_UPGRADE_POLICY = "patch" # or "minor" or "none" defaulting to "patch" for conservative behavior. That way maintainers can set "minor" on recipes where it's safe, without needing to modify AUH's command line. That said, adding recipe variables to already-released branches (scarthgap) means backporting metadata changes. The CLI flags work today without touching any recipes, which is why I started there. Would you prefer I rework this as a recipe variable for the next version, or keep the CLI flags as a first step? I mean only one option (--stable) that can read AUH_UPGRADE_POLICY if present otherwise default to patch? [1] https://github.com/Nordix/meta-binaryaudit (https://github.com/Nordix/meta-binaryaudit) Daniel > -----Original Message----- > From: Alexander Kanavin <alex.kanavin@gmail.com> > Sent: Monday, 27 April 2026 12:22 > To: Daniel Turull <daniel.turull@ericsson.com> > Cc: yocto-patches@lists.yoctoproject.org; paul@pbarker.dev; > ross.burton@arm.com; yoann.congal@smile.fr > Subject: Re: [AUH][PATCH v2 6/9] upgrade-helper.py: Add minor option for > minor version upgrades > > On Fri, 24 Apr 2026 at 13:46, <daniel.turull@ericsson.com> wrote: > > help="extract changelog between old and new versions, > highlighting CVEs") > > parser.add_argument("--stable", action="store_true", default=False, > > help="only upgrade to the next patch version > > within the stable branch (e.g. 1.2.3 -> 1.2.4)") > > + parser.add_argument("--minor", action="store_true", default=False, > > + help="allow upgrades within the same major > > + version (e.g. 3.5.2 -> 3.6.0, 3.99.0)") > > I'm somewhat confused. When and how one would be using either of these > options? What's the workflow for them? > > I still think it's better to place stable maintenance information directly into > recipes. > > Alex
diff --git a/modules/utils/version.py b/modules/utils/version.py index b40eb1c..71e0a1e 100644 --- a/modules/utils/version.py +++ b/modules/utils/version.py @@ -44,6 +44,17 @@ def is_patch_update(current_ver, candidate_ver): return bb.utils.vercmp_string(candidate_ver, current_ver) > 0 +def is_minor_update(current_ver, candidate_ver): + """Check if candidate is a newer release within the same major version.""" + cur = _split_version(current_ver) + cand = _split_version(candidate_ver) + if len(cur) < 2 or len(cand) < 2: + return False + if cur[0] != cand[0]: + return False + return bb.utils.vercmp_string(candidate_ver, current_ver) > 0 + + def _find_best_version(current_ver, all_versions, filter_fn): candidates = [v for v in all_versions if filter_fn(current_ver, v)] if not candidates: @@ -58,6 +69,10 @@ def find_patch_version(current_ver, all_versions): return _find_best_version(current_ver, all_versions, is_patch_update) +def find_minor_version(current_ver, all_versions): + return _find_best_version(current_ver, all_versions, is_minor_update) + + def get_all_upstream_versions(rd): """Get all upstream versions using the fetcher infrastructure. diff --git a/upgrade-helper.py b/upgrade-helper.py index b7b8ddf..ffa7449 100755 --- a/upgrade-helper.py +++ b/upgrade-helper.py @@ -59,7 +59,8 @@ from utils.emailhandler import Email from statistics import Statistics from steps import upgrade_steps from testimage import TestImage -from utils.version import is_patch_update, find_patch_version, get_all_upstream_versions +from utils.version import is_patch_update, find_patch_version, get_all_upstream_versions, \ + is_minor_update, find_minor_version if not os.getenv('BUILDDIR', False): E(" You must source oe-init-build-env before running this script!\n") @@ -101,6 +102,8 @@ def parse_cmdline(): help="extract changelog between old and new versions, highlighting CVEs") parser.add_argument("--stable", action="store_true", default=False, help="only upgrade to the next patch version within the stable branch (e.g. 1.2.3 -> 1.2.4)") + parser.add_argument("--minor", action="store_true", default=False, + help="allow upgrades within the same major version (e.g. 3.5.2 -> 3.6.0, 3.99.0)") parser.add_argument("-d", "--debug-level", type=int, default=4, choices=range(1, 6), help="set the debug level: CRITICAL=1, ERROR=2, WARNING=3, INFO=4, DEBUG=5") @@ -702,20 +705,22 @@ class UniverseUpdater(Updater): def _get_packagegroups_to_upgrade(self, packages=None): - def _resolve_stable_version(pn, cur_ver, next_ver, tinfoil): - """Find the latest patch version within the current stable branch.""" - if is_patch_update(cur_ver, next_ver): + def _resolve_stable_version(pn, cur_ver, next_ver, tinfoil, minor=False): + """Find the latest patch (or minor) version within the allowed range.""" + check_fn = is_minor_update if minor else is_patch_update + find_fn = find_minor_version if minor else find_patch_version + if check_fn(cur_ver, next_ver): return next_ver, None - I(" %s: latest version %s is not a patch update from %s," + I(" %s: latest version %s is not a %s update from %s," " searching for versions..." % - (pn, next_ver, cur_ver)) + (pn, next_ver, "minor" if minor else "patch", cur_ver)) try: rd = tinfoil.parse_recipe(pn) if not rd: I(" %s: could not parse recipe, skipping" % pn) return None, None all_versions = get_all_upstream_versions(rd) - ver = find_patch_version(cur_ver, all_versions) + ver = find_fn(cur_ver, all_versions) if ver: I(" %s: found version %s" % (pn, ver)) return ver, "N/A" @@ -792,7 +797,7 @@ class UniverseUpdater(Updater): if upgrade_group: upgrade_pkggroups.append(upgrade_group) - if self.args.stable and upgrade_pkggroups: + if (self.args.stable or self.args.minor) and upgrade_pkggroups: stable_tinfoil = bb.tinfoil.Tinfoil() stable_tinfoil.prepare(config_only=False) try: @@ -802,7 +807,7 @@ class UniverseUpdater(Updater): for pkg in group: stable_ver, stable_rev = _resolve_stable_version( pkg['pn'], pkg['cur_ver'], pkg['next_ver'], - stable_tinfoil) + stable_tinfoil, minor=self.args.minor) if stable_ver is not None: pkg['next_ver'] = stable_ver if stable_rev is not None: