blob: ded18489ebc5d8e355cd8bba294903f4381a5ee7 [file] [log] [blame]
#
# Secretary post-meeting todo list
#
TLPREQ = '/srv/secretary/tlpreq'
date = params[:date].gsub('-', '_')
date.untaint if date =~ /^\d+_\d+_\d+$/
agenda = "board_agenda_#{date}.txt"
`svn up #{TLPREQ}`
victims = Dir["#{TLPREQ}/victims-#{date}.*.txt"].
map {|name| File.read(name.untaint).lines().map(&:chomp)}.flatten
# fetch minutes
@minutes = agenda.sub('_agenda_', '_minutes_')
minutes_file = "#{AGENDA_WORK}/#{@minutes.sub('.txt', '.yml')}"
minutes_file.untaint if @minutes =~ /^board_minutes_\d+_\d+_\d+\.txt$/
if File.exist? minutes_file
minutes = YAML.load_file(minutes_file) || {}
else
minutes = {}
end
minutes[:todos] ||= {}
todos = minutes[:todos].dup
# iterate over the agenda, finding items where there is either comments or
# minutes that can be forwarded to the PMC
feedback = []
Agenda.parse(agenda, :full).each do |item|
# select exec officer, additional officer, and committee reports
next unless item[:attach] =~ /^(4[A-Z]|\d|[A-Z]+)$/
next unless item['chair_email']
next unless minutes[item['title']] or
(item['comments'] and not item['comments'].empty?)
unless todos[:feedback_sent] and todos[:feedback_sent].include? item['title']
feedback << item['title']
end
end
########################################################################
# Actions #
########################################################################
if @remove and env.password
chairs = ASF::Service.find('pmc-chairs')
people = @remove.select {|id, checked| checked}.
map {|id, checked| ASF::Person.find(id)}
ASF::LDAP.bind(env.user, env.password) do
chairs.remove people
end
minutes[:todos][:removed] ||= []
minutes[:todos][:removed] += people.map {|person| person.id}
end
if @add and env.password
chairs = ASF::Service.find('pmc-chairs')
people = @add.select {|id, checked| checked}.
map {|id, checked| ASF::Person.find(id)}
ASF::LDAP.bind(env.user, env.password) do
chairs.add people
end
# send out congratulations email
ASF::Mail.configure
sender = ASF::Person.new(env.user)
mail = Mail.new do
from "#{sender.public_name.inspect} <#{sender.id}@apache.org>".untaint
to people.map do |person|
"#{person.public_name.inspect} <#{person.id}@apache.org>".untaint
end
cc 'Apache Board <board@apache.org>'
subject "Congratulations on your new role at Apache"
body "Dear new PMC chairs,\n\nCongratulations on your new role at " +
"Apache. I've changed your LDAP privileges to reflect your new " +
"status.\n\nPlease read this and update the foundation records:\n" +
"https://svn.apache.org/repos/private/foundation/officers/advice-for-new-pmc-chairs.txt" +
"\n\nWarm regards,\n\n#{sender.public_name}"
end
mail.deliver!
minutes[:todos][:added] ||= []
minutes[:todos][:added] += people.map {|person| person.id}
end
if @establish and env.password
establish = @establish.select {|title, checked| checked}.map(&:first)
# common to all establish resolutions
chairs = ASF::Service.find('pmc-chairs')
cinfo = "#{ASF::SVN['private/committers/board']}/committee-info.txt"
established = Date.parse(date.gsub('_', '-'))
# update LDAP, committee-info.txt
establish.each do |pmc|
resolution = Agenda.parse(agenda, :full).find do |item|
item['title'] == "Establish #{pmc}"
end
chair = ASF::Person.find(resolution['chair'])
members = resolution['people'].map {|id, hash| ASF::Person.find(id)}
people = resolution['people'].map {|id, hash| [id, hash[:name]]}
ASF::SVN.update cinfo, resolution['title'], env, _ do |tmpdir, contents|
ASF::Committee.establish(contents, pmc, established, people)
end
ASF::LDAP.bind(env.user, env.password) do
chairs.add [chair] unless chairs.members.include? chair
guineapig = ASF::Committee::GUINEAPIGS.include?(pmc.downcase)
# old style definitions
unless guineapig
if ASF::Group.find(pmc.downcase).members.empty?
ASF::Group.add(pmc.downcase, members)
end
if ASF::Committee.find(pmc.downcase).members.empty?
ASF::Committee.add(pmc.downcase, members)
end
end
# new style definitions
project = ASF::Project[pmc.downcase]
if not project
project.create(members, members)
elsif not guineapig
# sync project owners with new PMC list
project.add_owners(members)
project.remove_owners(project.owners - members)
project.add_members(members)
end
end
end
# create 'victims' file for tlpreq tool
count = Dir["#{TLPREQ}/victims-#{date}.*.txt"].length
message = "record #{date} approved TLP resolutions"
ASF::SVN.update TLPREQ, message, env, _ do |tmpdir|
filename = "victims-#{date}.#{count}.txt"
contents = establish.join("\n") + "\n"
File.write "#{tmpdir}/#{filename}", contents
_.system "svn add #{tmpdir}/#{filename}"
end
victims += establish
minutes[:todos][:established] ||= []
minutes[:todos][:established] += establish
end
unless todos == minutes[:todos]
File.write minutes_file, YAML.dump(minutes)
end
########################################################################
# Response #
########################################################################
transitioning = {}
establish = {}
terminate = {}
Agenda.parse(agenda, :full).each do |item|
next unless item[:attach] =~ /^7\w$/
if item['title'] =~ /^Change .*? Chair$/ and item['people']
item['people'].keys.each do |person|
transitioning[ASF::Person.find(person)] = item['title']
end
elsif item['title'] =~ /^Establish\s*(.*?)\s*$/ and item['chair']
establish[$1] = item['title']
transitioning[ASF::Person.find(item['chair'])] = item['title']
elsif item['title'] =~ /^Terminate\s*(.*?)\s*$/
terminate[$1] = item['title']
end
end
add = transitioning.keys - ASF.pmc_chairs
remove = ASF.pmc_chairs - ASF::Committee.pmcs.map(&:chair) - transitioning.keys
victims.each {|victim| establish.delete victim}
_add add.map {|person| {id: person.id, name: person.public_name,
email: person.mail.first, resolution: transitioning[person]}}.
sort_by {|person| person[:id]}
_remove remove.map {|person| {id: person.id, name: person.public_name}}.
sort_by {|person| person[:id]}
_establish establish.
map {|name, resolution| {name: name, resolution: resolution}}
_terminate terminate.
map {|name, resolution| {name: name, resolution: resolution}}
_minutes minutes
_feedback feedback