diff mbox series

[1/2] devtool: upgrade: write changelog metadata as JSON sidecar

Message ID 20260918120125.770604-1-daniel.turull@ericsson.com
State New
Headers show
Series [1/2] devtool: upgrade: write changelog metadata as JSON sidecar | expand

Commit Message

Daniel Turull Sept. 18, 2026, 12:01 p.m. UTC
From: Daniel Turull <daniel.turull@ericsson.com>

Add changelogs/<pn>.json alongside the existing changelogs/<pn>.txt,
to include metadata. This makes the upgrade/changelog metadata
machine-readable without having to parse it out of the .txt file.

The .txt file no longer has the 'Changelog for ...'/'Source: ...'
header lines, now containing just the changelog body; that
information moved to the JSON file instead. devtool reset now cleans
up both files.

AI-Generated: Uses Kiro with Claude-sonnet-5
Signed-off-by: Daniel Turull <daniel.turull@ericsson.com>
---
 .../python3-guessing-game_git.bb.changelog    |  2 --
 .../devtool-upgrade-test1_1.5.3.bb.changelog  |  3 ---
 .../devtool-upgrade-test2_git.bb.changelog    |  2 --
 .../devtool-upgrade-test3_1.5.3.bb.changelog  |  3 ---
 .../devtool-upgrade-test4_1.5.3.bb.changelog  |  3 ---
 .../devtool-upgrade-test5_git.bb.changelog    |  2 --
 meta/lib/oeqa/selftest/cases/devtool.py       | 17 +++++++++++++--
 scripts/lib/devtool/standard.py               |  9 +++++---
 scripts/lib/devtool/upgrade.py                | 21 +++++++++++++++----
 9 files changed, 38 insertions(+), 24 deletions(-)
diff mbox series

Patch

diff --git a/meta-selftest/recipes-devtools/python/python3-guessing-game_git.bb.changelog b/meta-selftest/recipes-devtools/python/python3-guessing-game_git.bb.changelog
index 571220b2a4..ef0052160b 100644
--- a/meta-selftest/recipes-devtools/python/python3-guessing-game_git.bb.changelog
+++ b/meta-selftest/recipes-devtools/python/python3-guessing-game_git.bb.changelog
@@ -1,3 +1 @@ 
-Changelog for python3-guessing-game: 0.1.0 -> 0.2.0
-
 40cf004 Sync with maturin tutorial source
diff --git a/meta-selftest/recipes-test/devtool/devtool-upgrade-test1_1.5.3.bb.changelog b/meta-selftest/recipes-test/devtool/devtool-upgrade-test1_1.5.3.bb.changelog
index a37f796a0d..15d7baeeb4 100644
--- a/meta-selftest/recipes-test/devtool/devtool-upgrade-test1_1.5.3.bb.changelog
+++ b/meta-selftest/recipes-test/devtool/devtool-upgrade-test1_1.5.3.bb.changelog
@@ -1,6 +1,3 @@ 
-Changelog for devtool-upgrade-test1: 1.5.3 -> 1.6.0
-Source: doc/NEWS
-
 1.6.0 - 15 March 2015
   - fix lstat64 support when unavailable - separate patches supplied by
     Ganael Laplanche and Peter Korsgaard
diff --git a/meta-selftest/recipes-test/devtool/devtool-upgrade-test2_git.bb.changelog b/meta-selftest/recipes-test/devtool/devtool-upgrade-test2_git.bb.changelog
index b7f0019d56..ac133c483f 100644
--- a/meta-selftest/recipes-test/devtool/devtool-upgrade-test2_git.bb.changelog
+++ b/meta-selftest/recipes-test/devtool/devtool-upgrade-test2_git.bb.changelog
@@ -1,3 +1 @@ 
-Changelog for devtool-upgrade-test2: 0.1+git -> 0.1+git
-
 6cc6077 dbus-wait.c: Fix typo
diff --git a/meta-selftest/recipes-test/devtool/devtool-upgrade-test3_1.5.3.bb.changelog b/meta-selftest/recipes-test/devtool/devtool-upgrade-test3_1.5.3.bb.changelog
index aaab809736..15d7baeeb4 100644
--- a/meta-selftest/recipes-test/devtool/devtool-upgrade-test3_1.5.3.bb.changelog
+++ b/meta-selftest/recipes-test/devtool/devtool-upgrade-test3_1.5.3.bb.changelog
@@ -1,6 +1,3 @@ 
-Changelog for devtool-upgrade-test3: 1.5.3 -> 1.6.0
-Source: doc/NEWS
-
 1.6.0 - 15 March 2015
   - fix lstat64 support when unavailable - separate patches supplied by
     Ganael Laplanche and Peter Korsgaard
diff --git a/meta-selftest/recipes-test/devtool/devtool-upgrade-test4_1.5.3.bb.changelog b/meta-selftest/recipes-test/devtool/devtool-upgrade-test4_1.5.3.bb.changelog
index 0ce6547c77..15d7baeeb4 100644
--- a/meta-selftest/recipes-test/devtool/devtool-upgrade-test4_1.5.3.bb.changelog
+++ b/meta-selftest/recipes-test/devtool/devtool-upgrade-test4_1.5.3.bb.changelog
@@ -1,6 +1,3 @@ 
-Changelog for devtool-upgrade-test4: 1.5.3 -> 1.6.0
-Source: doc/NEWS
-
 1.6.0 - 15 March 2015
   - fix lstat64 support when unavailable - separate patches supplied by
     Ganael Laplanche and Peter Korsgaard
diff --git a/meta-selftest/recipes-test/devtool/devtool-upgrade-test5_git.bb.changelog b/meta-selftest/recipes-test/devtool/devtool-upgrade-test5_git.bb.changelog
index 7c5ecf3505..8077da3e21 100644
--- a/meta-selftest/recipes-test/devtool/devtool-upgrade-test5_git.bb.changelog
+++ b/meta-selftest/recipes-test/devtool/devtool-upgrade-test5_git.bb.changelog
@@ -1,3 +1 @@ 
-Changelog for devtool-upgrade-test5: 0.1+git -> 0.1+git
-
 0a60d6a Add dummy commit on tip for testing
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 84e020cd3d..dda59a3459 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -2337,21 +2337,33 @@  class DevtoolUpgradeTests(DevtoolBase):
         except:
             self.skip("Git user.name and user.email must be set")
 
-    def _check_changelog(self, recipe, oldrecipefile):
+    def _check_changelog(self, recipe, oldrecipefile, old_ver=None, new_ver=None):
         """Compare extracted changelog against reference data."""
         changelog_ref = oldrecipefile + '.changelog'
         self.assertExists(changelog_ref, 'Changelog reference file must exist for %s' % recipe)
         changelog_file = os.path.join(self.workspacedir, 'changelogs', '%s.txt' % recipe)
+        metadata_file = os.path.join(self.workspacedir, 'changelogs', '%s.json' % recipe)
         with open(changelog_ref, 'r') as f:
             expected = f.read()
         if not expected:
             self.assertNotExists(changelog_file,
                 'Changelog file should not exist when reference is empty')
+            self.assertNotExists(metadata_file,
+                'Changelog metadata file should not exist when reference is empty')
         else:
             self.assertExists(changelog_file, 'Changelog file should exist after upgrade')
             with open(changelog_file, 'r') as f:
                 actual = f.read()
             self.assertEqual(expected, actual)
+            self.assertExists(metadata_file, 'Changelog metadata file should exist after upgrade')
+            with open(metadata_file, 'r') as f:
+                metadata = json.load(f)
+            self.assertEqual(metadata.get('package'), recipe)
+            if old_ver:
+                self.assertEqual(metadata.get('old_version'), old_ver)
+            if new_ver:
+                self.assertEqual(metadata.get('new_version'), new_ver)
+            self.assertEqual(metadata.get('changelog_file'), '%s.txt' % recipe)
 
     def test_devtool_upgrade(self):
         # Check preconditions
@@ -2364,6 +2376,7 @@  class DevtoolUpgradeTests(DevtoolBase):
             self.assertIn(param, result.output)
         # For the moment, we are using a real recipe.
         recipe = 'devtool-upgrade-test1'
+        old_version = '1.5.3'
         version = '1.6.0'
         oldrecipefile = get_bb_var('FILE', recipe)
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
@@ -2392,7 +2405,7 @@  class DevtoolUpgradeTests(DevtoolBase):
             newlines = f.readlines()
         self.assertEqual(desiredlines, newlines)
         # Check changelog
-        self._check_changelog(recipe, oldrecipefile)
+        self._check_changelog(recipe, oldrecipefile, old_version, version)
         # Check devtool reset recipe
         result = runCmd('devtool reset %s -n' % recipe)
         result = runCmd('devtool status')
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index ac9e7cd61a..0d933e68b1 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -2074,11 +2074,14 @@  def _reset(recipes, no_clean, remove_work, config, basepath, workspace):
 
         # Clean up changelog if present
         changelog_file = os.path.join(config.workspace_path, 'changelogs', '%s.txt' % pn)
+        metadata_file = os.path.join(config.workspace_path, 'changelogs', '%s.json' % pn)
         if os.path.exists(changelog_file):
             os.remove(changelog_file)
-            changelog_dir = os.path.dirname(changelog_file)
-            if not os.listdir(changelog_dir):
-                os.rmdir(changelog_dir)
+        if os.path.exists(metadata_file):
+            os.remove(metadata_file)
+        changelog_dir = os.path.join(config.workspace_path, 'changelogs')
+        if os.path.exists(changelog_dir) and not os.listdir(changelog_dir):
+            os.rmdir(changelog_dir)
 
 def reset(args, config, basepath, workspace):
     """Entry point for the devtool 'reset' subcommand"""
diff --git a/scripts/lib/devtool/upgrade.py b/scripts/lib/devtool/upgrade.py
index 58165541f6..cdc85fe7ae 100644
--- a/scripts/lib/devtool/upgrade.py
+++ b/scripts/lib/devtool/upgrade.py
@@ -9,6 +9,7 @@ 
 import os
 import sys
 import re
+import json
 import shlex
 import shutil
 import subprocess
@@ -730,13 +731,23 @@  def _extract_changelog(srctree, pn, old_ver, new_ver, old_tag, new_tag, workspac
     bb.utils.mkdirhier(changelog_dir)
     changelog_path = os.path.join(changelog_dir, '%s.txt' % pn)
     with open(changelog_path, 'w') as f:
-        f.write('Changelog for %s: %s -> %s\n' % (pn, old_ver, new_ver))
-        if changelog_fname:
-            f.write('Source: %s\n' % changelog_fname)
-        f.write('\n')
         f.write(changelog_content)
         f.write('\n')
 
+    # Metadata sidecar file: keeps upgrade/changelog details machine-readable
+    # while the changelog text itself stays in the .txt file.
+    metadata = {
+        'package': pn,
+        'old_version': old_ver,
+        'new_version': new_ver,
+        'changelog_file': os.path.basename(changelog_path),
+        'changelog_source': changelog_fname.split(', ') if changelog_fname else None,
+    }
+    metadata_path = os.path.join(changelog_dir, '%s.json' % pn)
+    with open(metadata_path, 'w') as f:
+        json.dump(metadata, f, indent=4)
+        f.write('\n')
+
     return changelog_path
 
 def upgrade(args, config, basepath, workspace):
@@ -831,6 +842,8 @@  def upgrade(args, config, basepath, workspace):
                                             config.workspace_path, is_git)
         if changelog_file:
             logger.info('Changelog extracted to %s' % changelog_file)
+            metadata_file = os.path.join(os.path.dirname(changelog_file), '%s.json' % pn)
+            logger.info('Changelog metadata written to %s' % metadata_file)
 
         if license_diff:
             logger.info('License checksums have been updated in the new recipe; please refer to it for the difference between the old and the new license texts.')