blob: 8f8571d02d30c94e867282c230bd1533285b0c6f [file] [log] [blame]
#!/usr/bin/env ruby
PAGETITLE = "Incubator Mentor Signoffs" # Wvisible:incubator
# quick and dirty script to tally up which mentors have been providing
# signoffs and which have not.
$LOAD_PATH.unshift '/srv/whimsy/lib'
require 'nokogiri'
require 'wunderbar'
require 'wunderbar/bootstrap'
require 'whimsy/asf'
# Authenticate - must be first!
user = ASF::Person.find($USER)
incubator = ASF::Committee.find('incubator').owners
unless user.asf_member? or incubator.include? user
print "Status: 401 Unauthorized\r\n"
print "WWW-Authenticate: Basic realm=\"Incubator PMC and Members\"\r\n\r\n"
exit
end
BOARD = ASF::SVN['foundation_board']
# Gather data from board agendas about podlings and actual mentors listed
def get_mentor_signoffs()
ASF::Person.preload('cn')
ASF::ICLA.preload()
people = Hash[ASF::Person.list.map {|person| [person.public_name, person.id]}]
agendas = Dir[File.join(BOARD, 'board_agenda_*.txt'),
File.join(BOARD, 'archived_agendas', 'board_agenda_*.txt')]
agendas = agendas.sort_by {|file| File.basename(file)}[-13..-1]
if File.read(agendas.last).include? 'The Apache Incubator is the entry path'
agendas.shift
else
agendas.pop
end
# projects = URI.parse('http://incubator.apache.org/projects/')
# table = Nokogiri::HTML(Net::HTTP.get(projects)).at('table')
# # extract a list of [podling names, table row]
# podlings = table.search('tr').map do |tr|
# tds = tr.search('td')
# next if tds.empty?
# [tds.last.text, tr]
# end
mentors = {}
podlings = {}
agendas.each do |file|
date = file[/\d+_\d+_\d+/].gsub('_', '-')
agenda = File.read(file)
signoffs = agenda.scan(/^#* ?Signed-off-by:\s+.*?\n\n/m).join
signoffs.scan(/\[(.+?)\]\((.*?)\) (.*)/).each do |check, podling, name|
name.strip!
podling.strip!
# allow for reports where comments have been joined to the previous line
name.sub! %r{ Comments:.*}, ''
name.sub! /\s+\(.*?\)/, ''
mentors[name] = [] unless mentors[name]
mentors[name] << {
date: date,
checked: !check.strip.empty?,
podling: podling
}
podlings[podling] = Hash.new{|h,k| h[k] = [] } unless podlings[podling]
podlings[podling][date] << [name, !check.strip.empty?]
end
end
return mentors, podlings, people
end
mentor_signoffs, podling_signoffs, people = get_mentor_signoffs()
ROSTER_URL = '/roster/committer/'
_html do
# http://bconnelly.net/2013/10/creating-colorblind-friendly-figures/
_style %{
.check {color: rgb(0,114,178)}
.blank {color: rgb(230,159,0); font-style: italic; font-weight: bold}
}
_whimsy_body(
title: PAGETITLE,
related: {
'https://incubator.apache.org/images/incubator_feather_egg_logo_sm.png' => 'Apache Incubator Egg Logo',
'https://incubator.apache.org/projects/' => 'Incubator Podling List',
'/incubator/moderators' => 'Incubator Mailing List Moderators',
'#bypodling' => 'Signoffs By Podling'
},
helpblock: -> {
_p do
_ 'This script checks recent Incubator podling reports as submitted to the board agenda for mentor signoffs. '
_span.check 'Blue'
_ ' means signoff is present in that report, '
_span.blank 'orange'
_ ' means signoff is absent.'
_br
_a_ 'Signoffs By Mentor', href: '#bymentor'
_ ' | '
_a_ 'Signoffs By Podling', href: '#bypodling'
end
}
) do
_whimsy_panel_table(
title: "Podling Signoffs By Mentor",
helpblock: -> {
_p "This table shows all mentors and the podlings they signed off on. Hover over podling name to see date of report."
}
) do
_table.table.table_hover.table_striped id: 'bymentor' do
_thead_ do
_tr do
_th 'Mentor Name'
_th 'Podling Monthly Reports'
end
end
_tbody do
mentor_signoffs.sort.each do |name, entries|
_tr_ do
_td do
if people[name]
if ASF::Person.find(people[name]).asf_member?
_b! {_a name, href: ROSTER_URL + people[name]}
else
_a name, href: ROSTER_URL + people[name]
end
else
_a name, href: ROSTER_URL + '?q=' + URI.encode(name)
end
end
_td do
entries.each do |entry|
if entry[:checked]
_span.check entry[:podling], title: entry[:date]
else
_span.blank entry[:podling], title: entry[:date]
end
end
end
end
end
end
end
end
_whimsy_panel_table(
title: "Podling Signoffs By Podling",
helpblock: -> {
_p "This table shows all podlings and how many mentors signed off on reports, by date. Reminder: only checks recent monthly reports."
}
) do
_table.table.table_hover.table_striped id: 'bypodling' do
_thead_ do
_tr do
_th 'Podling Name (signoff %)'
_th 'Date: (Mentor signoffs/Number of mentors) ...'
end
end
_tbody do
podling_signoffs.sort.each do |podling, signoffs|
m = 0
s = 0
signoffs.each do |month, mentors|
m += mentors.length
s += mentors.count { |x| x[1] }
end
_tr_ do
_td do
_a_ podling, href: "https://incubator.apache.org/projects/#{podling}"
_ " (#{((s/m.to_f)*100).round()}%)"
end
_td do
signoffs.each do |month, mentors|
_ " #{month} (#{mentors.count { |x| x[1] }} / #{mentors.length}) "
end
end
end
end
end
end
end
end
end