public inbox for cygwin-apps-cvs@sourceware.org
help / color / mirror / Atom feed
* [calm - Cygwin server-side packaging maintenance script] branch master, updated. 20230209-111-gb586495
@ 2024-05-29 15:12 Jon Turney
  0 siblings, 0 replies; only message in thread
From: Jon Turney @ 2024-05-29 15:12 UTC (permalink / raw)
  To: cygwin-apps-cvs




https://sourceware.org/git/gitweb.cgi?p=cygwin-apps/calm.git;h=b5864958558c98ed95f831a9276f3cd33eb8998f

commit b5864958558c98ed95f831a9276f3cd33eb8998f
Author: Jon Turney <jon.turney@dronecode.org.uk>
Date:   Mon May 27 15:19:00 2024 +0100

    Produce a report to help identify long-inactive maintainers


Diff:
---
 calm/maintainers.py                        |  9 ++++
 calm/pkg2html.py                           |  5 ++-
 calm/reports.py                            | 70 +++++++++++++++++++++++++++++-
 test/testdata/process_arch/htdocs.expected |  7 ++-
 4 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/calm/maintainers.py b/calm/maintainers.py
index e2c60c7..2a02dc0 100644
--- a/calm/maintainers.py
+++ b/calm/maintainers.py
@@ -33,6 +33,7 @@
 # - an email address (in HOME/!email (or !mail), as we don't want to publish
 #   it, and want to allow the maintainer to change it)
 # - the timestamp when 'ignoring' warnings were last emitted
+# - the timestamp of their last ssh connection
 #
 
 import logging
@@ -84,6 +85,7 @@ class Maintainer(object):
         self.email = email
         self.pkgs = pkgs
         self.quiet = False
+        self.has_homedir = os.path.isdir(self.homedir())
 
         # the mtime of this file records the timestamp
         reminder_file = os.path.join(self.homedir(), '!reminder-timestamp')
@@ -94,6 +96,13 @@ class Maintainer(object):
         self.reminders_issued = False
         self.reminders_timestamp_checked = False
 
+        # the mtime of this file records the last ssh session
+        last_seen_file = os.path.join(self.homedir(), '.last-seen')
+        if os.path.isfile(last_seen_file):
+            self.last_seen = os.path.getmtime(last_seen_file)
+        else:
+            self.last_seen = 0  # meaning 'unknown'
+
     def __repr__(self):
         return "maintainers.Maintainer('%s', %s, %s)" % (self.name, self.email, self.pkgs)
 
diff --git a/calm/pkg2html.py b/calm/pkg2html.py
index 979914b..ab7591a 100755
--- a/calm/pkg2html.py
+++ b/calm/pkg2html.py
@@ -136,7 +136,10 @@ def ensure_dir_exists(args, path):
 # format a unix epoch time (UTC)
 #
 def tsformat(ts):
-    return time.strftime('%Y-%m-%d %H:%M', time.gmtime(ts))
+    if ts == 0:
+        return 'Unknown'
+    else:
+        return time.strftime('%Y-%m-%d %H:%M', time.gmtime(ts))
 
 
 #
diff --git a/calm/reports.py b/calm/reports.py
index 02e9082..240b5d9 100644
--- a/calm/reports.py
+++ b/calm/reports.py
@@ -69,7 +69,7 @@ def write_report(args, title, body, fn, reportlist, not_empty=True):
 
 
 def linkify(pn, po):
-    return '<a href="/packages/summary/{0}.html">{1}</a>'.format(pn, po.orig_name)
+    return '<a href="/packages/summary/{0}.html">{1}</a>'.format(po.name, po.orig_name)
 
 
 #
@@ -281,6 +281,72 @@ def unstable(args, packages, reportlist):
     write_report(args, 'Packages marked as unstable', body, 'unstable.html', reportlist)
 
 
+# produce a report on maintainer (in)activity
+#
+def maintainer_activity(args, packages, reportlist):
+    activity_list = []
+
+    arch = 'x86_64'
+    # XXX: look into how we can make this 'src', after x86 is dropped
+
+    ml = maintainers.maintainer_list(args)
+    for m in ml.values():
+        if m.name == 'ORPHANED':
+            continue
+
+        a = types.SimpleNamespace()
+        a.name = m.name
+        a.last_seen = m.last_seen
+
+        count = 0
+        mtime = 0
+        pkgs = []
+        for p in m.pkgs:
+            if not p.is_orphaned():
+                count += 1
+
+            pn = p.data + '-src'
+            # do something reasonable for sourceless packages
+            if pn not in packages[arch]:
+                pn = p.data
+
+            po = packages[arch].get(pn, None)
+            if po:
+                pkgs.append(pn)
+
+                for v in po.versions():
+                    if po.tar(v).mtime > mtime:
+                        mtime = po.tar(v).mtime
+
+        # ignore if all their packages are orphaned
+        # (key should be already disabled in this case)
+        if count == 0:
+            continue
+
+        a.count = count
+        a.pkgs = pkgs
+        a.last_package = mtime
+
+        activity_list.append(a)
+
+    body = io.StringIO()
+    print('<p>Maintainer activity.</p>', file=body)
+
+    print('<table class="grid sortable">', file=body)
+    print('<tr><th>Maintainer</th><th># packages</th><th>Last ssh</th><th>Latest package</th></tr>', file=body)
+
+    for a in sorted(activity_list, key=lambda i: (i.last_seen, i.last_package)):
+        def pkg_details(pkgs):
+            return '<details><summary>%d</summary>%s</details>' % (len(pkgs), ', '.join(linkify(p, packages[arch][p]) for p in pkgs))
+
+        print('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>' %
+              (a.name, pkg_details(a.pkgs), pkg2html.tsformat(a.last_seen), pkg2html.tsformat(a.last_package)), file=body)
+
+    print('</table>', file=body)
+
+    write_report(args, 'Maintainer activity', body, 'maintainer_activity.html', reportlist, not_empty=False)
+
+
 # produce a report of packages which need rebuilding for the latest major
 # version version provides
 #
@@ -463,6 +529,8 @@ def do_reports(args, packages):
     provides_rebuild(args, packages, 'ruby_rebuilds.html', 'ruby', reportlist)
     python_rebuild(args, packages, 'python_rebuilds.html', reportlist)
 
+    maintainer_activity(args, packages, reportlist)
+
     fn = os.path.join(args.htdocs, 'reports_list.inc')
     with utils.open_amifc(fn) as f:
         print('<ul>', file=f)
diff --git a/test/testdata/process_arch/htdocs.expected b/test/testdata/process_arch/htdocs.expected
index 80e2fdf..cb93982 100644
--- a/test/testdata/process_arch/htdocs.expected
+++ b/test/testdata/process_arch/htdocs.expected
@@ -1,5 +1,10 @@
 {'.': ['calm.db', 'packages.inc', 'reports_list.inc', 'src_packages.inc'],
- 'reports': ['deprecated_so.html', 'perl_rebuilds.html', 'ruby_rebuilds.html', 'unmaintained.html', 'unstable.html'],
+ 'reports': ['deprecated_so.html',
+             'maintainer_activity.html',
+             'perl_rebuilds.html',
+             'ruby_rebuilds.html',
+             'unmaintained.html',
+             'unstable.html'],
  'summary': ['arc-src.html',
              'arc.html',
              'base-cygwin.html',


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-05-29 15:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-29 15:12 [calm - Cygwin server-side packaging maintenance script] branch master, updated. 20230209-111-gb586495 Jon Turney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).