You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@attic.apache.org by se...@apache.org on 2021/03/10 16:08:21 UTC
svn commit: r1887434 - /attic/site/jiratext.py
Author: sebb
Date: Wed Mar 10 16:08:21 2021
New Revision: 1887434
URL: http://svn.apache.org/viewvc?rev=1887434&view=rev
Log:
Initial code
Added:
attic/site/jiratext.py (with props)
Added: attic/site/jiratext.py
URL: http://svn.apache.org/viewvc/attic/site/jiratext.py?rev=1887434&view=auto
==============================================================================
--- attic/site/jiratext.py (added)
+++ attic/site/jiratext.py Wed Mar 10 16:08:21 2021
@@ -0,0 +1,181 @@
+#!/usr/bin/env python3
+
+"""
+
+Find project resources for retired projects and generate JIRA issue text:
+- source control system (SVN or Git)
+- dist.apache.org releases and dev
+- mailing lists (Whimsy)
+- JIRA https://issues.apache.org/jira/rest/api/2/project.json - detect if present
+- LDAP project
+- https://cwiki.apache.org/confluence/display/VXQUERY (e.g.)
+
+"""
+
+import re
+import sys
+import json
+import subprocess
+import errno
+import time
+
+# from contextlib import redirect_stdout
+from os.path import getmtime, basename, join
+from os import environ
+
+from urllib.request import urlopen, Request
+from urllib.error import HTTPError
+
+DEV="https://dist.apache.org/repos/dist/dev/"
+REL="https://dist.apache.org/repos/dist/release/"
+JIRA='https://issues.apache.org/jira/rest/api/2/project'
+CWIKI='https://cwiki.apache.org/confluence/display/'
+EMAIL='https://whimsy.apache.org/public/committee-retired.json'
+GITBOX='https://gitbox.apache.org/repositories.json' # ['projects']
+
+CACHE=environ.get('CACHE')
+
+def isFileStale(filename):
+ try:
+ t = getmtime(filename)
+ except OSError as e:
+ if not e.errno == errno.ENOENT:
+ raise e
+ return True
+ diff = time.time() - t
+ return diff > 600 # 5 min in seconds
+
+def urlcache(url):
+ if CACHE:
+ # basename seems to work OK with URLs
+ cache = join(CACHE,basename(url)+".tmp")
+ if isFileStale(cache):
+# print("Caching %s" % url, file=sys.stderr)
+ req = Request(url)
+ resp = urlopen(req)
+ with open(cache,'wb') as w:
+ w.write(resp.read())
+ else:
+# print("Using cache for %s" % url, file=sys.stderr)
+ pass
+ with open(cache,'r') as r:
+ return r.read()
+ else:
+# print("Fetching %s" % url, file=sys.stderr)
+ req = Request(url)
+ resp = urlopen(req)
+ return resp.read()
+
+def loadjson(url):
+# req = Request(url)
+# resp = urlopen(req)
+ return json.loads(urlcache(url))
+
+# =====================================
+
+retired = loadjson(EMAIL)['retired']
+gitbox = loadjson(GITBOX)['projects']
+
+def check_wiki(pid):
+ url = CWIKI + pid.upper()
+ req = Request(url)
+ try:
+ urlopen(req)
+ print("Make CWIKI readonly: %s" % url)
+ except HTTPError:
+ pass
+
+def check_mail(pid):
+ try:
+ mlists = retired[pid]['mlists']
+ if len(mlists) > 0:
+ print("Mailing lists:")
+ for mlist in mlists:
+ print("- %s@%s.apache.org" % (mlist,pid))
+ print()
+ except KeyError:
+ pass
+
+def svnfiles(path):
+ res = subprocess.run(["svn", "ls", path], capture_output=True)
+ if res.returncode == 0:
+ stdout = res.stdout
+ if len(stdout) == 0:
+ return 0
+ if stdout == b'.htaccess\n': # just the htaccess file is OK
+ return 0
+ return 1
+ else:
+ stderr = res.stderr
+ if b"W160013" in stderr: # no such item
+ return -1
+ print(stderr)
+ return -1
+
+def check_dist(pid):
+ dev = svnfiles(DEV + pid)
+ rel = svnfiles(REL + pid)
+ if dev > 0 or rel > 0:
+ print("Remove the distribution SVN directories:")
+ if dev > 0:
+ print('- ' + DEV + pid)
+ if rel > 0:
+ print('- ' + REL + pid)
+# print("Set up redirection to https://attic.apache.org/projects/%s.html" % pid)
+ print()
+
+# Whimsy json may be stale, so use ldapsearch for now
+def check_ldap(pid):
+ BASE='ou=project,ou=groups,dc=apache,dc=org'
+ res = subprocess.run(["ldapsearch", "-x", "-LLL", "-b", BASE, "cn=%s" % pid, "dn"], capture_output=True)
+ if res.returncode == 0:
+ if res.stdout != b'':
+ print("Remove the LDAP project group: %s" % res.stdout.rstrip().decode())
+ else:
+ print(res.stderr)
+
+def check_jira(pid):
+ jira = json.loads(urlcache(JIRA))
+ for project in jira:
+ key = project['key']
+ catname = ''
+ if 'projectCategory' in project:
+ catname = project['projectCategory']['name']
+ if pid.upper() == key:
+ if '(Retired)' in project['name'] or catname == 'Retired':
+ pass
+ else:
+ print("Make the JIRA project %s read-only and flag as retired" % key)
+ elif catname.lower() == pid:
+ print("Make the JIRA project %s read-only and flag as retired" % key)
+
+# check for SVN and Git
+def check_scs(pid):
+ svn = "https://svn.apache.org/repos/asf/%s" % pid
+ if svnfiles(svn) > 0:
+ print("Make SVN readonly: %s" % svn) # TODO what if this is the site SVN?
+# print("Update config file so commits go to attic ???")
+ if pid in gitbox:
+ print("Make the following git repos read-only:")
+ for repo in gitbox[pid]['repositories']:
+ print("- %s" % repo)
+
+if len(sys.argv) == 1:
+ print("Please provide a list of project ids")
+ sys.exit(1)
+
+for arg in sys.argv[1:]:
+ if not arg in retired:
+ print("%s is not listed as a retired TLP" % arg)
+ continue
+# with open('jira_%s.tmp' % arg, 'w') as f:
+# with redirect_stdout(f):
+ print("%s project has retired." % retired[arg]['display_name'])
+ print("The following resources were detected for archive/removal please:\n")
+ check_dist(arg)
+ check_mail(arg)
+ check_jira(arg)
+ check_scs(arg)
+ check_wiki(arg)
+ check_ldap(arg)
+ print("Turn off any automated builds")
Propchange: attic/site/jiratext.py
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: attic/site/jiratext.py
------------------------------------------------------------------------------
svn:executable = *