| #!/usr/bin/env python3 |
| |
| """ |
| |
| Find project resources for retired projects and generate JIRA issue text for INFRA: |
| - 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 sys |
| import subprocess |
| from urlutils import loadjson, urlexists |
| |
| 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'] |
| |
| |
| # ===================================== |
| |
| retired = loadjson(EMAIL)['retired'] |
| gitbox = loadjson(GITBOX)['projects'] |
| |
| def check_wiki(pid): |
| url = CWIKI + pid.upper() |
| if urlexists(url): |
| print("Make CWIKI readonly: %s" % url) |
| print("Flag CWIKI as retired: create file '%s.txt' under puppet:modules/cwiki_asf/files/attic/" % pid) |
| |
| def check_mail(pid): |
| try: |
| mlists = retired[pid]['mlists'] |
| if len(mlists) > 0: |
| print("Mailing lists https://lists.apache.org/list.html?%s.apache.org :" % pid) |
| 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: |
| if dev > 0: |
| print("Remove the distribution SVN developer directory:") |
| print('- ' + DEV + pid) |
| if rel > 0: |
| print("Remove the distribution SVN release directory contents, and") |
| print("set up redirection to https://attic.apache.org/projects/%s.html" % pid) |
| print('- ' + REL + 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 = loadjson(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 https://issues.apache.org/jira/projects/%s read-only and flag as retired" % key) |
| elif catname.lower() == pid: |
| print("Make the JIRA project https://issues.apache.org/jira/projects/%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 https://gitbox.apache.org/repos/asf#%s :" % pid) |
| for repo in gitbox[pid]['repositories']: |
| print("- %s" % repo) |
| print("Please do NOT rename the repos.") |
| |
| 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") |