From 0c4173a552ad9f93660950542d3263c82228d8ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20H=C3=B6ppner?= <jonas.hoeppner@garz-fricke.com>
Date: Thu, 19 Sep 2024 09:30:40 +0200
Subject: [PATCH] Changelog-generator: Add parameter to include all integrated
 projects

Before this, the changelog was generated on a given list of projects,
all using the same branch.
The new parameter now goes the the specified projects from the
parameters, and detects all integrated projects into this.
So normally you would specify one or two manifest projects, everything
else is automatically added to the list.

This also handles different branch names. As for example the kernel
branches are different, the integration branch is used instead of the
branch from the command line.
---
 scripts/changelog_generator.py | 81 ++++++++++++++++++++++++++++++----
 1 file changed, 72 insertions(+), 9 deletions(-)

diff --git a/scripts/changelog_generator.py b/scripts/changelog_generator.py
index 2e85e5fa..1a80e522 100755
--- a/scripts/changelog_generator.py
+++ b/scripts/changelog_generator.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python3
-""" 
+"""
 
 Simple changelog generator for Garz&Fricke gitlab projects.
 
@@ -22,6 +22,7 @@ import sys
 import gitlab as gl
 
 import common
+from get_integration_sources import get_integration_sources
 
 __author__ = "Jonas Höppner"
 __email__ = "jonas.hoeppner@garz-fricke.com"
@@ -58,7 +59,7 @@ class Tag:
         self.message = tag.message
         self.commit = tag.commit
         """
-        The tags timestamp is a little more complicated it normally points 
+        The tags timestamp is a little more complicated it normally points
         to the tagged commit's timestamps. But the merge happens later.
         To handle this, the relelated mergerequest is found by comparing the
         sha's and also take the merged_at timestamp.
@@ -182,7 +183,6 @@ class MergeRequest:
 
 
 def main(args):
-
     parser = argparse.ArgumentParser(description=__doc__, usage="%(prog)s [OPTIONS]")
 
     parser.add_argument(
@@ -213,6 +213,25 @@ def main(args):
         required=True,
     )
 
+    parser.add_argument(
+        "-a",
+        "--all-projects",
+        help="""Parse all projects integrated into the listed ones""",
+        action="store_true",
+        default=False,
+        required=False,
+    )
+    parser.add_argument(
+        "-s",
+        "--skip-project",
+        help="""Projects to not include into the change log.
+                (can be passed multiple times)""",
+        dest="skip_project",
+        action="append",
+        default=[],
+        required=False,
+    )
+
     parser.add_argument(
         "-v",
         "--verbose",
@@ -229,10 +248,54 @@ def main(args):
     logging.debug(options)
     gitlab = gl.Gitlab(options.gitlab_url, private_token=options.token)
 
-    projects = [Project(gitlab.projects.get(project)) for project in options.project]
+    project_list = {}
+    manifest_project = options.project[0]
+    if not options.all_projects:
+        # Old behaviour: Just a list of all projects from the commandline,
+        # only one branch name
+        for project in options.project:
+            if project in options.skip_project:
+                continue
+            project_list[project] = {"branch": options.branch}
+    else:
+        # New behaviour: Go through the project list from the parameters
+        # and check for all integrated projects
+        groupname = options.project[0].split("/")[0]
+        group = gitlab.groups.get(groupname, retry_transient_errors=True)
+        for project in options.project:
+            if project in options.skip_project:
+                continue
+            project_list[project] = {"branch": options.branch}
+
+            integration_sources = get_integration_sources(
+                project, options.branch, group
+            )
+            for source in integration_sources:
+                if source["project"] in options.skip_project:
+                    continue
+                if (
+                    source["project"] in project_list.keys()
+                ):  # Only add the first included branch
+                    continue
+                project_list[source["project"]] = {"branch": source["branch"]}
+
+    if options.verbose:
+        print("Projects included in the report:")
+        for p, b in project_list.items():
+            print(f"{p}- {b['branch']}")
+        print("Skip list:")
+        for p in options.skip_project:
+            print(f"{p}")
+
+    for p in project_list.keys():
+        gl_project = Project(gitlab.projects.get(p))
+        project_list[p]["gitlab"] = gl_project
+
     releases = [
         Release(Tag(t))
-        for t in projects[0].project.tags.list(search=options.branch, as_list=False)
+        for t in project_list[manifest_project]["gitlab"].project.tags.list(
+            search=project_list[manifest_project]["branch"], as_list=False
+        )
     ]
     # Add dummy release with date today for new unstaged commits
     releases.append(
@@ -247,11 +310,11 @@ def main(args):
     # Sort by date, oldest first
     releases = sorted(releases, key=lambda d: d.tag.timestamp, reverse=False)
 
-    for p in projects:
-        for mr in p.project.mergerequests.list(
-            scope="all", state="merged", target_branch=options.branch, as_list=False
+    for p in project_list.values():
+        for mr in p["gitlab"].project.mergerequests.list(
+            scope="all", state="merged", target_branch=p["branch"], as_list=False
         ):
-            m = MergeRequest(mr, p)
+            m = MergeRequest(mr, p["gitlab"])
             for r in releases:
                 if r.add_mergerequest(m):
                     break
-- 
GitLab