Status of the clutch
Status of the clutch currently in incubation
Clutch is a tool which gathers details about the projects currently in
incubation and re-generates the table below.
It aims to encourage and nurture, to provide an overview of
the state of establishment of various resources, and to provide quick
access to those resources.
See more notes below regarding purpose and
interpretation.
-
The orange items indicate where more care
and attention is needed. Anything vermilion
is an issue that should be addressed ASAP.
The bluish-green items indicate success
and the yellow items are okay.
-
A: startDate
-
B: elapsedDays
- <3
<12
<18
<24
>24 months
-
C: reportingMonthly in
w.a.o/incubator/ReportingSchedule
(current report: %(nameCurrentReport)s)
-
D: reportingGroup - in which set of months do they report:
group-1=Jan,Apr,Jul,Oct group-2=Feb,May,Aug,Nov group-3=Mar,Jun,Sep,Dec
-
E: hasReportingGroup - did podling remember to choose a group
-
F: hasStatusEntry in i.a.o/projects
(the main "Currently in incubation" table)
-
G: statusUpdateDate - the status page was last updated
-
H: statusAge - days since the SVN status page was last updated
- <2
<4
<9
>9 months
-
I: statusUpdateCounts - number of commits to status file in the
previous 2,4,9 months (cumulative)
-
J: numberCommitters - accounts have been established, total number to date
-
K: numberCommittersNew - new committers added since establishment
(gathered from each project's Status page "News" section)
-
L: hasSvn - Subversion repository is created
-
M: hasTracker - has an Issue Tracker
-
N: hasMailListDev - has dev mail list and archives
-
O: hasMailListCommits - has commits mail list and archives
-
P: hasWebSite
-
Q: hasDistributionArea - has w.a.o/dist/incubator/... area (not necessarily yet a release)
-
R: hasKeys - has a PGP KEYS file in their distribution area
-
S: hasRelease - has a release in their distribution area
""" % {'urlCurrentReport': urlCurrentReport,
'nameCurrentReport': nameCurrentReport
}
fileXml.write(headerXml)
if len(otherIssues):
otherXml = """- other issues listed below for: """
otherIssuesRE = re.compile("^([^:]+):.*$")
for issue in otherIssues:
matchOtherIssues = re.search(otherIssuesRE, issue)
otherXml += """ %s """ % matchOtherIssues.group(1)
otherXml += "
\n"
fileXml.write(otherXml)
tableColumnHeadersXml = """
| Project |
Sponsor |
A |
B |
C |
D |
E |
F |
G |
H |
I |
J |
K |
L |
M |
N |
O |
P |
Q |
R |
S |
"""
tableTopXml = """
Clutch last gathered: %(gatherDate)s UTC.
Number of podlings in incubation: %(numProjects)s
""" % {'gatherDate': gatherDateString,
'numProjects': len(projects)
}
fileXml.write(tableTopXml)
fileXml.write(tableColumnHeadersXml)
fileList.write('#identifier,name,sponsor\n')
reportList1 = ""
reportList2 = ""
reportList3 = ""
tableRowCount = 0
tableRowCountMid = int(len(projects) / 2)
for k in projectNames:
tableRowCount += 1
if tableRowCount == tableRowCountMid:
fileXml.write(tableColumnHeadersXml)
fileXml.write(' \n' % k)
fileXml.write(' | %s | \n' % projects[k]['name'])
output[k] = {}
output[k]['podlingName'] = projects[k]['name']
if projects[k]['sponsor'].find("?") >= 0:
fileXml.write(' %s | \n' % projects[k]['sponsor'])
else:
fileXml.write(' %s | \n' % projects[k]['sponsor'])
output[k]['sponsor'] = projects[k]['sponsor']
output[k]['description'] = projects[k]['description']
output[k]['mentors'] = projects[k]['mentors']
fileXml.write(' %s | \n' % projects[k]['startDate'])
output[k]['startDate'] = projects[k]['startDate']
# elapsedDays column
fileXml.write(' | \n')
if not projects[k]['reportingMonthly']:
fileXml.write(' %s | \n' % projects[k]['reportingMonthly'])
else:
fileXml.write(' %s | \n' % projects[k]['reportingMonthly'])
output[k]['reportingMonthly'] = projects[k]['reportingMonthly']
fileXml.write(' %s | \n' % projects[k]['reportingGroup'])
output[k]['reportingGroup'] = reportingGroups[projects[k]['reportingGroup']]
reportDevList = '"%s Developers"' % projects[k]['name']
if projects[k]['hasMailListDev']:
matchDevMail = re.search(mailListNameUrlRE, projects[k]['hasMailListDev'])
if matchDevMail:
mailListGroup = "%s" % matchDevMail.group(1)
mailListNameHint = "%s" % matchDevMail.group(2)
reportDevList += ' <%(a)s@%(b)s.apache.org>' % \
{'a': matchDevMail.group(2), 'b': matchDevMail.group(1)}
else:
reportDevList += ' '
else:
reportDevList += ' '
if optionVerbose:
print "DEBUG: reportDevList=%s" % reportDevList
if projects[k]['reportingMonthly']:
reportList1 += '%s\n' % reportDevList
reportList2 += '%s\n' % reportDevList
reportList3 += '%s\n' % reportDevList
else:
if (projects[k]['reportingGroup'] == "group-1"):
reportList1 += "%s\n" % reportDevList
elif (projects[k]['reportingGroup'] == "group-2"):
reportList2 += "%s\n" % reportDevList
elif (projects[k]['reportingGroup'] == "group-3"):
reportList3 += "%s\n" % reportDevList
if projects[k]['hasReportingGroup']:
fileXml.write(' %s | \n' % projects[k]['hasReportingGroup'])
else:
fileXml.write(' %s | \n' % projects[k]['hasReportingGroup'])
if projects[k]['hasStatusEntry']:
fileXml.write(' %(entry)s | \n' % \
{'name': projects[k]['statusFileName'], 'entry': projects[k]['hasStatusEntry']})
else:
fileXml.write(' %s | \n' % projects[k]['hasStatusEntry'])
fileXml.write(' %s | \n' % projects[k]['statusLastUpdated'])
# statusAge column
fileXml.write(' | \n')
fileXml.write(' %s | \n' % projects[k]['statusUpdateCounts'])
if projects[k]['numberCommitters'] > 0:
if projects[k]['numberCommitters'] > 2:
fileXml.write(' %(b)s | \n' % \
{'a': projects[k]['committersSvn'], 'b': projects[k]['numberCommitters']})
else:
fileXml.write(' %(b)s | \n' % \
{'a': projects[k]['committersSvn'], 'b': projects[k]['numberCommitters']})
else:
fileXml.write(' - | \n')
if projects[k]['numberCommittersNew'] > 0:
if projects[k]['numberCommittersNew'] > 1:
fileXml.write(' %s | \n' % \
projects[k]['numberCommittersNew'])
else:
fileXml.write(' %s | \n' % \
projects[k]['numberCommittersNew'])
else:
fileXml.write(' 0 | \n')
if projects[k]['urlSvn']:
fileXml.write(' True | \n' % projects[k]['urlSvn'])
else:
fileXml.write(' False | \n')
output[k]['urlSvn'] = projects[k]['urlSvn']
if projects[k]['urlTracker']:
fileXml.write(' True | \n' % projects[k]['urlTracker'])
else:
fileXml.write(' False | \n')
output[k]['urlTracker'] = projects[k]['urlTracker']
matchUrl = re.search(urlHttpRE, projects[k]['hasMailListDev'])
if matchUrl:
hasUrl = True
else:
hasUrl = False
if hasUrl:
fileXml.write(' True | \n' % projects[k]['hasMailListDev'])
else:
fileXml.write(' False | \n')
output[k]['hasMailListDev'] = projects[k]['hasMailListDev']
matchUrl = re.search(urlHttpRE, projects[k]['hasMailListCommits'])
if matchUrl:
hasUrl = True
else:
hasUrl = False
if hasUrl:
fileXml.write(' True | \n' % projects[k]['hasMailListCommits'])
else:
fileXml.write(' False | \n')
output[k]['hasMailListCommits'] = projects[k]['hasMailListCommits']
if projects[k]['urlWww']:
fileXml.write(' True | \n' % \
projects[k]['urlWww'])
else:
fileXml.write(' False | \n')
output[k]['urlWww'] = projects[k]['urlWww']
if projects[k]['urlDist']:
fileXml.write(' True | \n' % \
projects[k]['urlDist'])
else:
fileXml.write(' False | \n')
output[k]['urlDist'] = projects[k]['urlDist']
if projects[k]['urlKeys']:
fileXml.write(' True | \n' % \
projects[k]['urlKeys'])
else:
fileXml.write(' False | \n')
try:
releases[k]
except KeyError:
fileXml.write(' False | \n')
else:
fileXml.write(' True | \n' % \
projects[k]['urlDist'])
fileXml.write('
\n')
fileList.write('%(a)s,"%(b)s","%(c)s"\n' % \
{'a': k,
'b': projects[k]['name'],
'c': projects[k]['sponsor'],
})
# End of rows
fileXml.write(tableColumnHeadersXml)
fileXml.write("
\n \n")
# Other issues
fileXml.write("""
Other issues
Occasionally there are other issues, e.g. Not listed in
ReportingSchedule, yet listed in IncubationTable.
""")
if len(otherIssues):
otherIssues.sort()
for issue in otherIssues:
fileXml.write(" - %s
\n" % issue)
else:
fileXml.write(" - No known issues.
\n")
fileXml.write("
\n \n")
notesXml = """
Notes
Any Incubator committer can run 'clutch'. In the top-level of the
"incubator/public/trunk" SVN, do: 'python clutch.py' which will
generate a source xml file at "site-author/clutch.xml".
Do 'svn diff' to see what changed.
Then build and deploy the site as normal.
It reads the Wiki page at
ReportingSchedule
then builds a list of projects, adds some attributes, does some
validation. Then it reads the source file for the
"projects currently in incubation" table,
ensures that each new project has an entry, adds some more attributes.
Clutch then gathers some data from each project's Status page, makes
other guesses, and validates that certain facilities are established
and steps are achieved.
The clutch is
the set of eggs which have been laid. The mother hen (our Incubator PMC)
needs to continually gather them, to ensure that none have rolled from
the nest or moved to the outside, being forgotten or becoming cold.
Clutch also means to grasp eagerly.
So please interpret this table from the point-of-view of encouragement
and nurture.
"""
fileXml.write(notesXml)
stepsXml = """
Steps
Essentially Clutch is helping us all to follow the process from the
"Acceptance" phase onwards (explained in
Process Description
and
Incubation Policy
and
Mentor Guide
and
Other Guides
and summarised at
Podling Bootstrap).
Any committer on a podling can help with these steps. Don't leave it
to your mentors, although there are some steps that only they can do.
The first steps are the "Acceptance" phase. See
doc and
doc and
doc.
The orange and vermilion
items indicate where more care and attention is needed. The following
notes for each column, expand on the column definitions above and
attempt to link directly to the relevant process documentation:
- Project -
If your project is in incubation, but is missing from the Clutch table,
then you have forgotten to add it to the Wiki
ReportingSchedule.
(doc and
doc)
-
A: startDate -
This information is gathered from the list of
Projects in incubation summary table.
The "not known" is because it is missing from that table.
-
B: elapsedDays - Calculated from startDate.
-
C: reportingMonthly in
ReportingSchedule.
-
D: reportingGroup - in which set of months do they report.
-
E: hasReportingGroup - did podling remember to choose a group.
See notes for "Project" above.
-
F: hasStatusEntry in Projects in incubation table and an
associated project Status page.
(doc and
doc and
doc and
doc)
-
G: statusUpdateDate - the status page was last updated. Clutch does an 'svn log'
query for the project's Status page.
-
H: statusAge - days since the SVN status page was last updated
-
I: statusUpdateCounts - number of commits to status file in the
previous 2,4,9 months (cumulative).
Clutch does an 'svn log' query for the project's Status page, and counts the edits
for those time ranges.
-
J: numberCommitters - accounts have been established, total number to date.
Clutch parses the relevant section of the
ASF Committers by Project Modules
page and counts the total, including mentors.
-
K: numberCommittersNew - new committers added since establishment
(gathered from each project's Status page "News" section). Clutch parses the News
section and detects the string "new committer", counting each matched line.
See notes for "hasStatusEntry" above.
(doc and
doc and
doc)
-
L: hasSvn - Subversion repository is created.
(doc and
doc)
-
M: hasTracker - has an Issue Tracker
-
N: hasMailListDev -
-
O: hasMailListCommits -
-
P: hasWebSite -
-
Q: hasDistributionArea - has w.a.o/dist/incubator/... area (not necessarily yet a release)
-
R: hasKeys - has a PGP KEYS file in their distribution area
-
S: hasRelease - has a release in their distribution area. The test is
whether they have a signature file (*.asc or *.sig ) associated with
a source release artifact (*.tar.gz or *.tgz or *.bz2 or *zip) and the
filename includes the word "incubating".
(doc and
doc)
-
otherIssues - When projects graduate or become dormant, then they need to clean up.
-
Graduate - Remove from the
ReportingSchedule.
In the Projects in incubation table, move it to the
"Graduated" section. Remove entry from right-side panel.
Do various other tasks listed in the docs.
(doc
and
doc)
-
Dormant or Retired - Remove from the
ReportingSchedule.
In the Projects in incubation table, move it to the
"Dormant" or "Retired" section. Remove entry from right-side panel.
(doc)
"""
fileXml.write(stepsXml)
fileXml.write("""
Mentors projects
This list is gathered from the Projects in incubation
summary table.
""")
mentors = mentorsProjects.keys()
mentors.sort()
for mentor in mentors:
fileXml.write(" - %(a)s: %(b)s
\n" % {'a': mentor, 'b':mentorsProjects[mentor]})
fileXml.write("
\n \n")
footerXml = """
Data files
Data files are also generated so that other tools can easily re-use the
metadata for the set of projects currently in incubation:
-
clutch.txt
- list of projects, one per line. Comma-separated values (CSV).
-
clutch.pkl
- a Python "pickle" file with various attributes (it is in the top-level of SVN incubator/public/trunk).
-
Structured list of various details. Not yet happening - need to
decide which format (e.g. RDFa, etc.) and which attributes to be
stored.
"""
fileXml.write(footerXml)
fileXml.close()
fileList.close()
fileReport1 = open('site-author/report_due_1.txt', 'w')
fileReport1.write("%s" % reportList1)
fileReport1.close()
fileReport2 = open('site-author/report_due_2.txt', 'w')
fileReport2.write("%s" % reportList2)
fileReport2.close()
fileReport3 = open('site-author/report_due_3.txt', 'w')
fileReport3.write("%s" % reportList3)
fileReport3.close()
# Create the persistent data file.
outputFile = open('clutch.pkl', 'wb')
pickle.dump(output, outputFile, pickle.HIGHEST_PROTOCOL)
outputFile.close()
print "Done. Generated site-author/clutch.xml file."
print "Now you need to re-build the site, as usual."