diff file was written using pkg_ctx['workdir'], which is never set,
causing a KeyError whenever a license change was detected. Now uses
the workdir parameter consistently.

This patch depends on "devtool: upgrade: extract changelog between versions"
Otherwise the output does not change

AI-Generated: kiro with claude-opus-4.6 model
Signed-off-by: Daniel Turull <daniel.turull@ericsson.com>
---
 modules/steps.py    | 41 ++++++++++++++++++++++++++++++++++++++---
 upgrade-helper.conf |  5 +++++
 upgrade-helper.py   |  1 +
 3 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/modules/steps.py b/modules/steps.py
index b3ec61c..a8856c2 100644
--- a/modules/steps.py
+++ b/modules/steps.py
@@ -79,10 +79,43 @@ def _make_commit_msg(group):
     pn = group['name']
     return "{}: upgrade {}".format(pn, ",".join([_get_version(p) for p in group['pkgs']]))
 
-def _devtool_upgrade(devtool, bb, git, opts, pkg_ctx):
+def _get_changelog(pn, workdir):
+    """Read the changelog generated by devtool upgrade and copy it to workdir.
+    Returns the changelog text or None."""
+    changelog_path = os.path.join(os.environ.get('BUILDDIR', ''),
+                                  'workspace', 'changelogs', '{}.txt'.format(pn))
+    if os.path.isfile(changelog_path):
+        try:
+            with open(changelog_path, 'r', encoding='utf-8', errors='replace') as f:
+                text = f.read()
+            shutil.copy2(changelog_path, os.path.join(workdir, '{}-changelog.txt'.format(pn)))
+            return text
+        except OSError as e:
+            W('Failed to copy changelog for {}: {}'.format(pn, e))
+    return None
+
+
+def _append_changelog_to_commit_msg(group, opts):
+    max_len = int(opts['changelog_max_len'])
+    for p in group['pkgs']:
+        if 'changelog_text' not in p:
+            continue
+        text = p['changelog_text'].strip()
+        if text.startswith('Changelog for '):
+            text = text[text.index('\n') + 1:].strip()
+        if len(text) > max_len:
+            text = text[:max_len] + "\n\n[... changelog truncated ...]"
+        group['commit_msg'] += "\n\n" + text
+
+
+def _devtool_upgrade(devtool, bb, git, opts, pkg_ctx, workdir):
     try:
         devtool_output = devtool.upgrade(pkg_ctx['PN'], pkg_ctx['NPV'], pkg_ctx['NSRCREV'])
         D(" 'devtool upgrade' printed:\n%s" %(devtool_output))
+        # Copy changelog before checking for conflicts — it's useful even on failure
+        changelog_text = _get_changelog(pkg_ctx['PN'], workdir)
+        if changelog_text:
+            pkg_ctx['changelog_text'] = changelog_text
         # If devtool failed to rebase patches, it does not fail, but we should
         if 'conflict' in devtool_output:
             raise DevtoolError("Running 'devtool upgrade' for recipe %s failed." %(pkg_ctx['PN']), devtool_output)
@@ -96,13 +129,15 @@ def _devtool_upgrade(devtool, bb, git, opts, pkg_ctx):
     license_diff_info = _extract_license_diff(devtool_output)
     if len(license_diff_info) > 0:
         pkg_ctx['license_diff_fn'] = "license-diff-{}.txt".format(pkg_ctx['PV'])
-        with open(os.path.join(pkg_ctx['workdir'], pkg_ctx['license_diff_fn']), 'wb') as f:
+        with open(os.path.join(workdir, pkg_ctx['license_diff_fn']), 'wb') as f:
             f.write(b"".join(license_diff_info))
 
 
 def devtool_upgrade(devtool, bb, git, opts, group):
     for p in group['pkgs']:
-        _devtool_upgrade(devtool, bb, git, opts, p)
+        _devtool_upgrade(devtool, bb, git, opts, p, group['workdir'])
+    _append_changelog_to_commit_msg(group, opts)
+
 
 def _compile(bb, pkg, machine, workdir):
         try:
diff --git a/upgrade-helper.conf b/upgrade-helper.conf
index 269bde3..d363c50 100644
--- a/upgrade-helper.conf
+++ b/upgrade-helper.conf
@@ -121,3 +121,8 @@
 #layer_mode=no
 #layer_name=meta-intel
 #layer_dir=DIR/meta-intel
+
+# Maximum number of characters from the changelog to include in the
+# commit message. Longer changelogs are truncated. The full changelog
+# is always available as an attachment.
+#changelog_max_len=3000
diff --git a/upgrade-helper.py b/upgrade-helper.py
index 40f31c4..f7a63c0 100755
--- a/upgrade-helper.py
+++ b/upgrade-helper.py
@@ -195,6 +195,7 @@ class Updater(object):
         self.opts['skip_compilation'] = self.args.skip_compilation
         self.opts['buildhistory'] = self._buildhistory_is_enabled()
         self.opts['testimage'] = self._testimage_is_enabled()
+        self.opts['changelog_max_len'] = settings.get('changelog_max_len', '3000')
 
     def _make_dirs(self, build_dir):
         self.uh_dir = os.path.join(build_dir, "upgrade-helper")
