feat(ci-bot): add a patch counter script

Add a simple script to count the number of patches in each project on
tforg from a given query. By default this will be the patches in review,
although this is configurable from an argument.

The implementation is very similar to the ci_status_bot so that they can
be used together from a script as well as standalone if necessary.

Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: I982ea6894b89b72176c8473d52e46bb5d8a9f344
diff --git a/script/status_reporting/gerrit_patch_count.py b/script/status_reporting/gerrit_patch_count.py
new file mode 100644
index 0000000..570b671
--- /dev/null
+++ b/script/status_reporting/gerrit_patch_count.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+
+import argparse
+import asyncio
+import json
+import sys
+
+import aiohttp
+
+async def get_patch_counts(session, query: str) -> str:
+    url = "https://review.trustedfirmware.org/changes/?q="
+    skip_arg = "&S={}"
+    skip_num = 0
+
+    totals = {}
+    while True:
+        async with session.get(url + query + skip_arg.format(skip_num)) as response:
+            text = (await response.text())[4:] # strip magic string ")]}'"
+            data = json.loads(text)
+
+            for entry in data:
+                name = entry["project"]
+                totals[name] = totals.get(name, 0) + 1
+
+            if len(data) and data[-1].get("_more_changes", False):
+                skip_num = len(data)
+            else:
+                break
+
+    message = "Patches in review:\n"
+    for name, count in totals.items():
+        message += f"* {name}: {count}\n"
+    return message
+
+async def run_local(query: str) -> str:
+    async with aiohttp.ClientSession() as session:
+        msg = await get_patch_counts(session, query)
+        print(msg)
+
+def add_gerrit_arg(parser):
+    parser.add_argument(
+        "-q", "--tforg-gerrit-query",
+        default=(
+            "(parentproject:TF-A OR parentproject:TF-RMM OR parentproject:TS OR "
+            "parentproject:hafnium OR project:^ci/hafnium-.%2B OR project:^ci/tf-a-.%2B) "
+            "(branch:integration OR branch:master OR branch:^topics\\/.*) -is:wip is:open"
+        ), help="the query to pass to tforg's Gerrit (as written in the query box)"
+    )
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(
+        description="Counter of patches in tforg's gerrit",
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+    )
+    add_gerrit_arg(parser)
+    args = parser.parse_args(sys.argv[1:])
+
+    asyncio.run(run_local(args.tforg_gerrit_query))