blob: e5268f75b0d9c144fa4aee24eeaf3227ef7b0002 [file] [log] [blame]
Paul Sokolovsky2e361a12023-10-31 21:38:32 +03001#!/usr/bin/env python3
2import argparse
3import sys
4import os
5import re
6import subprocess
7
8
Paul Sokolovsky910fd552024-02-20 00:26:10 +07009DEFAULT_URL = "https://review.trustedfirmware.org/TF-A/trusted-firmware-a"
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030010WORKDIR = "trusted-firmware-a"
11
Paul Sokolovsky006f9232024-01-29 17:57:01 +070012SKIP_PATTERNS = [
13 r"docs\(changelog\): ",
14 r"Merge changes from topic ",
15 r"Merge \".+\" into ",
16 r"Merge changes .+ into ",
17]
18
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030019
20def run(cmd):
21 return subprocess.check_call(cmd, shell=True)
22
23
24def maybe_int(s):
25 if s.isdigit():
26 return int(s)
27 return s
28
29
Paul Sokolovsky6386ce62024-06-05 15:11:03 +030030def is_sandbox_run():
31 return os.environ.get("SANDBOX_RUN") != "false"
32
33
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030034def main():
35 argp = argparse.ArgumentParser(description="Prepare TF-A LTS release email content")
Paul Sokolovsky910fd552024-02-20 00:26:10 +070036 argp.add_argument("-u", "--url", default=DEFAULT_URL, help="repository URL (default: %(default)s)")
37 argp.add_argument("-b", "--branch", default="", help="repository branch for --latest option")
38 argp.add_argument("--latest", action="store_true", help="use latest release tag on --branch")
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030039 argp.add_argument("release_tag", nargs="?", help="release tag")
40 args = argp.parse_args()
41 if not args.release_tag and not args.latest:
42 argp.error("Either release_tag or --latest is required")
43
44 with open(os.path.dirname(__file__) + "/lts-release-mail.txt") as f:
45 mail_template = f.read()
46
47 if not os.path.exists(WORKDIR):
Paul Sokolovsky910fd552024-02-20 00:26:10 +070048 run("git clone %s %s" % (args.url, WORKDIR))
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030049 os.chdir(WORKDIR)
50 else:
51 os.chdir(WORKDIR)
52 run("git pull --quiet")
53
54 if args.latest:
55 latest = []
56 for l in os.popen("git tag"):
57 if not re.match(r"lts-v\d+\.\d+\.\d+", l):
58 continue
Paul Sokolovsky910fd552024-02-20 00:26:10 +070059 if not l.startswith(args.branch):
60 continue
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030061 l = l.rstrip()
62 comps = [maybe_int(x) for x in l.split(".")]
63 comps.append(l)
64 if comps > latest:
65 latest = comps
66 if not latest:
67 argp.error("Could not find latest LTS tag")
68 args.release_tag = latest[-1]
69
Paul Sokolovskyc1197812024-02-20 14:50:10 +070070 base_release = args.release_tag
71 # If it's "sandbox" tag, convert it to the corresponding release tag for
72 # rendering the template.
73 if base_release.startswith("sandbox/"):
74 m = re.match(r"sandbox/(.+)-\d+", base_release)
75 base_release = m.group(1)
76 comps = base_release.split(".")
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030077 prev_comps = comps[:-1] + [str(int(comps[-1]) - 1)]
78 prev_release = ".".join(prev_comps)
79
80 subjects = []
81 for l in os.popen("git log --oneline --reverse %s..%s" % (prev_release, args.release_tag)):
Paul Sokolovsky006f9232024-01-29 17:57:01 +070082 skip = False
83 for pat in SKIP_PATTERNS:
84 if re.match(pat, l.split(" ", 1)[1]):
85 skip = True
86 if not skip:
87 subjects.append(l.rstrip())
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030088
89 urls = []
90 for s in subjects:
91 commit_id, _ = s.split(" ", 1)
Paul Sokolovskyca973ae2024-11-27 16:28:26 +070092 change_id = None
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030093 for l in os.popen("git show %s" % commit_id):
Paul Sokolovskyca973ae2024-11-27 16:28:26 +070094 # There can be multiple Change-Id lines in some commits, and
95 # we're interested in the last in that case.
Paul Sokolovsky2e361a12023-10-31 21:38:32 +030096 if "Change-Id:" in l:
97 _, change_id = l.strip().split(None, 1)
Paul Sokolovskyca973ae2024-11-27 16:28:26 +070098 if change_id:
99 urls.append("https://review.trustedfirmware.org/q/" + change_id)
Paul Sokolovsky2e361a12023-10-31 21:38:32 +0300100
101 assert len(subjects) == len(urls)
102
103 commits = ""
104 for i, s in enumerate(subjects, 1):
105 commits += "%s [%d]\n" % (s, i)
106
107 references = ""
108 for i, s in enumerate(urls, 1):
109 references += "[%d] %s\n" % (i, s)
110
111 # Strip trailing newline, as it's encoded in template.
112 commits = commits.rstrip()
113 references = references.rstrip()
114
Paul Sokolovsky6386ce62024-06-05 15:11:03 +0300115 if is_sandbox_run():
Paul Sokolovskyff2f4d02024-06-06 17:57:35 +0300116 rtd_url = "https://trustedfirmware-a-sandbox.readthedocs.io/en/"
Paul Sokolovsky6386ce62024-06-05 15:11:03 +0300117 else:
118 rtd_url = "https://trustedfirmware-a.readthedocs.io/en/"
119 rtd_slug = args.release_tag.lower().replace("/", "-")
120 rtd_url += rtd_slug
121
Paul Sokolovskyc1197812024-02-20 14:50:10 +0700122 version = base_release[len("lts-v"):]
Paul Sokolovsky2e361a12023-10-31 21:38:32 +0300123 sys.stdout.write(
124 mail_template.format(
125 version=version,
126 commits=commits,
127 references=references,
Paul Sokolovsky6386ce62024-06-05 15:11:03 +0300128 rtd_url=rtd_url,
Paul Sokolovsky2e361a12023-10-31 21:38:32 +0300129 )
130 )
131
132
133if __name__ == "__main__":
134 main()