You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whimsical.apache.org by ru...@apache.org on 2017/09/26 16:15:52 UTC
[whimsy] branch master updated: update code to process PMC
resolutions
This is an automated email from the ASF dual-hosted git repository.
rubys pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/whimsy.git
The following commit(s) were added to refs/heads/master by this push:
new bd43869 update code to process PMC resolutions
bd43869 is described below
commit bd43869beac935626dba9cee5cf3b912dd1c191a
Author: Sam Ruby <ru...@intertwingly.net>
AuthorDate: Tue Sep 26 12:15:34 2017 -0400
update code to process PMC resolutions
---
lib/whimsy/asf/agenda/special.rb | 8 +-
lib/whimsy/asf/committee.rb | 36 +++--
www/board/agenda/views/actions/todos.json.rb | 186 ++++++++++++++++---------
www/board/agenda/views/pages/adjournment.js.rb | 107 ++++++++------
4 files changed, 210 insertions(+), 127 deletions(-)
diff --git a/lib/whimsy/asf/agenda/special.rb b/lib/whimsy/asf/agenda/special.rb
index 31a4064..858e48e 100644
--- a/lib/whimsy/asf/agenda/special.rb
+++ b/lib/whimsy/asf/agenda/special.rb
@@ -25,7 +25,13 @@ class ASF::Board::Agenda
title.sub! /\sCommittee\s/, ' '
title.sub! /\sProject(\s|$)/i, '\1'
title.sub! /\sPMC(\s|$)/, '\1'
- title.sub! /\s\(.*\)$/, ''
+
+ if title =~ /^Establish .* \((.*)\)$/
+ title.sub! /\s.*?\(/, ' '
+ title.sub! /\)$/, ''
+ else
+ title.sub! /\s\(.*\)$/, ''
+ end
attrs['fulltitle'] = fulltitle if title != fulltitle
diff --git a/lib/whimsy/asf/committee.rb b/lib/whimsy/asf/committee.rb
index 9aa728c..25a179b 100644
--- a/lib/whimsy/asf/committee.rb
+++ b/lib/whimsy/asf/committee.rb
@@ -120,23 +120,23 @@ module ASF
# update/remove existing 'missing' entries
block.gsub! /(.*?)# missing in .*\n/ do |line|
- if missing.include? $1.strip
- missing.delete $1.strip
- "#{line.chomp}, #{month}\n"
- else
- ''
- end
+ if missing.include? $1.strip
+ missing.delete $1.strip
+ "#{line.chomp}, #{month}\n"
+ else
+ ''
+ end
end
# add new 'missing' entries
missing.each do |pmc|
- block += " #{pmc.ljust(22)} # missing in #{month}\n"
+ block += " #{pmc.ljust(22)} # missing in #{month}\n"
end
# add new 'established' entries
month = (date+91).strftime('%B')
establish.each do |pmc|
- block += " #{pmc.ljust(22)} # new, monthly through #{month}\n"
+ block += " #{pmc.ljust(22)} # new, monthly through #{month}\n"
end
# replace/append block
@@ -154,27 +154,25 @@ module ASF
end
# update chairs
- def self.update_chairs(contents, establish, change, terminate)
+ def self.update_chairs(contents, establish_or_change, terminate)
# extract committee section; and then extract the lines containing
# committee names and chairs
section = contents[/^1\..*?\n=+/m]
committees = section[/-\n(.*?)\n\n/m, 1].scan(/^ +(.*?) +(.*)/).to_h
# update/add chairs based on establish and change resolutions
- (establish.merge(change)).each do |name, chair|
- person = ASF::Person.find(chair)
- committees[name] = "#{person.public_name} <#{...@apache.org>"
+ establish_or_change.each do |name, chair|
+ person = ASF::Person.find(chair)
+ committees[name] = "#{person.public_name} <#{...@apache.org>"
end
# remove committees based on terminate resolutions
- terminate.each do |name|
- committees.delete(name)
- end
+ terminate.each {|name| committees.delete(name)} if terminate
# sort and concatenate committees
committees = committees.sort_by {|name, chair| name.downcase}.
- map {|name, chair| " #{name.ljust(23)} #{chair}"}.
- join("\n")
+ map {|name, chair| " #{name.ljust(23)} #{chair}"}.
+ join("\n")
# replace committee info in the section, and then replace the
# section in the committee-info contents
@@ -198,8 +196,8 @@ module ASF
# build new section
section = ["#{pmc} (est. #{date.strftime('%m/%Y')})"]
- people.sort.each do |id, name|
- name = "#{name.ljust(26)} <#{...@apache.org>"
+ people.sort.each do |id, person|
+ name = "#{person[:name].ljust(26)} <#{...@apache.org>"
section << " #{(name).ljust(59)} [#{date.strftime('%Y-%m-%d')}]"
end
diff --git a/www/board/agenda/views/actions/todos.json.rb b/www/board/agenda/views/actions/todos.json.rb
index 760001d..29b6bb6 100644
--- a/www/board/agenda/views/actions/todos.json.rb
+++ b/www/board/agenda/views/actions/todos.json.rb
@@ -7,9 +7,6 @@ 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_')
@@ -25,10 +22,12 @@ end
minutes[:todos] ||= {}
todos = minutes[:todos].dup
+parsed_agenda = Agenda.parse(agenda, :full)
+
# 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|
+parsed_agenda.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']
@@ -48,8 +47,7 @@ end
if @remove and env.password
chairs = ASF::Service.find('pmc-chairs')
- people = @remove.select {|id, checked| checked}.
- map {|id, checked| ASF::Person.find(id)}
+ people = @remove.map {|id| ASF::Person.find(id)}
ASF::LDAP.bind(env.user, env.password) do
chairs.remove people
@@ -59,67 +57,64 @@ if @remove and env.password
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)}
+# update committee-info.txt
+if (@change || @establish || @terminate) and env.password
+ cinfo = "#{ASF::SVN['private/committers/board']}/committee-info.txt"
- ASF::LDAP.bind(env.user, env.password) do
- chairs.add people
+ todos = Array(@change) + Array(@establish) + Array(@terminate)
+ if todos.length == 1
+ title = todos.first['title']
+ else
+ title = 'board resolutions: ' + todos.map {|todo| todo['name']}.join(', ')
end
- # send out congratulations email
- ASF::Mail.configure
- sender = ASF::Person.new(env.user)
- mail = Mail.new do
- from "#{sender.public_name.inspect} <#{...@apache.org>".untaint
-
- to people.map do |person|
- "#{person.public_name.inspect} <#{...@apache.org>".untaint
+ ASF::SVN.update cinfo, title, env, _ do |tmpdir, contents|
+ unless minutes[:todos][:next_month]
+ # update list of reports expected next month
+ missing = parsed_agenda.
+ select {|item| item[:attach] =~ /^[A-Z]+$/ and item['missing']}.
+ map {|item| item['title']}
+ contents = ASF::Committee.update_next_month(contents,
+ Date.parse(date.gsub('_', '-')), missing,
+ Array(@establish).map {|resolution| resolution['name']})
end
- cc 'Apache Board <bo...@apache.org>'
+ # update chairs from establish, change, and terminate resolutions
+ chairs = todos.
+ map {|resolution| [resolution['name'], resolution['chair']]}.to_h
+ contents = ASF::Committee.update_chairs(contents, chairs, @terminate)
- subject "Congratulations on your new role at Apache"
+ # add people from establish resolutions
+ established = Date.parse(date.gsub('_', '-'))
+ Array(@establish).each do |resolution|
+ item = parsed_agenda.find do |item|
+ item['title'] == resolution['title']
+ end
- 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
+ contents = ASF::Committee.establish(contents, resolution['name'],
+ established, item['people'])
+ end
- mail.deliver!
+ contents
+ end
- minutes[:todos][:added] ||= []
- minutes[:todos][:added] += people.map {|person| person.id}
+ minutes[:todos][:next_month] = true
+ File.write minutes_file, YAML.dump(minutes)
end
+# update LDAP, create victims.txt
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('_', '-'))
+ @establish.each do |resolution|
+ pmc = resolution['name']
- # update LDAP, committee-info.txt
- establish.each do |pmc|
- resolution = Agenda.parse(agenda, :full).find do |item|
- item['title'] == "Establish #{pmc}"
+ item = parsed_agenda.find do |item|
+ item['title'] == resolution['title']
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
+ members = item['people'].map {|id, hash| ASF::Person.find(id)}
+ people = item['people'].map {|id, hash| [id, hash[:name]]}
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
@@ -136,7 +131,11 @@ if @establish and env.password
# new style definitions
project = ASF::Project[pmc.downcase]
if not project
- project.create(members, members)
+ unless ASF::Committee[pmc.downcase]
+ ASF::Committee.add(pmc.downcase, members)
+ end
+
+ ASF::Project.find(pmc.downcase).create(members, members)
elsif not guineapig
# sync project owners with new PMC list
project.add_owners(members)
@@ -146,19 +145,80 @@ if @establish and env.password
end
end
+ establish = @establish.map {|resolution| resolution['name']}
+
# 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}"
+ `svn up #{TLPREQ}`
+ establish -= Dir["#{TLPREQ}/victims-#{date}.*.txt"].
+ map {|name| File.read(name.untaint).lines().map(&:chomp)}.flatten
+ unless establish.empty?
+ 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
+ end
+end
+
+# update LDAP and send out congratulatory email
+if (@change || @establish) and env.password
+ chairs = ASF::Service.find('pmc-chairs')
+
+ todos = Array(@change) + Array(@establish)
+ people = todos.map {|todo| ASF::Person.find(todo['chair'])}.uniq
+
+ # add new chairs to pmc-chairs
+ unless (people-chairs.members).empty?
+ ASF::LDAP.bind(env.user, env.password) do
+ chairs.add people-chairs.members
+ end
+ end
+
+ # send out congratulations email
+ ASF::Mail.configure
+ sender = ASF::Person.new(env.user)
+ mail = Mail.new do
+ from "#{sender.public_name.inspect} <#{...@apache.org>".untaint
+
+ to people.map {|person|
+ "#{person.public_name.inspect} <#{...@apache.org>".untaint
+ }.to_a
+
+ cc 'Apache Board <bo...@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
- victims += establish
+ mail.deliver!
+end
+
+########################################################################
+# Update list of completed todos #
+########################################################################
+
+if @change
+ minutes[:todos][:changed] ||= []
+ minutes[:todos][:changed] += @change.map {|resolution| resolution['name']}
+end
+
+if @establish
minutes[:todos][:established] ||= []
- minutes[:todos][:established] += establish
+ minutes[:todos][:established] +=
+ @establish.map {|resolution| resolution['name']}
+end
+
+if @terminate
+ minutes[:todos][:terminated] ||= []
+ minutes[:todos][:terminated] += @terminate
end
unless todos == minutes[:todos]
@@ -174,18 +234,20 @@ establish = []
terminate = {}
change = []
-Agenda.parse(agenda, :full).each do |item|
+parsed_agenda.each do |item|
next unless item[:attach] =~ /^7\w$/
if item['title'] =~ /^Change (.*?) Chair$/ and item['people']
+ next if Array(minutes[:todos][:changed]).include? $1
change << {name: $1, resolution: item['title'], chair: item['chair']}
item['people'].keys.each do |person|
transitioning[ASF::Person.find(person)] = item['title']
end
elsif item['title'] =~ /^Establish\s*(.*?)\s*$/ and item['chair']
- next if victims.include? $1
+ next if Array(minutes[:todos][:established]).include? $1
establish << {name: $1, resolution: item['title'], chair: item['chair']}
transitioning[ASF::Person.find(item['chair'])] = item['title']
elsif item['title'] =~ /^Terminate\s*(.*?)\s*$/
+ next if Array(minutes[:todos][:terminated]).include? $1
terminate[$1] = item['title']
end
end
diff --git a/www/board/agenda/views/pages/adjournment.js.rb b/www/board/agenda/views/pages/adjournment.js.rb
index 10cbf40..5677cde 100644
--- a/www/board/agenda/views/pages/adjournment.js.rb
+++ b/www/board/agenda/views/pages/adjournment.js.rb
@@ -67,7 +67,7 @@ class Adjournment < Vue
end
unless Todos.remove.empty?
- _TodoActions action: 'remove'
+ _TodoRemove
end
unless Todos.feedback.empty?
@@ -150,15 +150,15 @@ class PMCActions < Vue
_ul.checklist @resolutions do |item|
_li do
- _input type: 'checkbox', checked: item.checked,
- onChange:-> { item.checked = !item.checked; self.refresh() }
+ _input type: 'checkbox', checked: item.checked,
+ onChange:-> { item.checked = !item.checked; self.refresh() }
- _Link text: item.title, href: Todos.link(item.title)
+ _Link text: item.title, href: Todos.link(item.title)
- if item.minutes
- _ ' - '
- _Link text: item.minutes, href: Todos.link(item.title)
- end
+ if item.minutes
+ _ ' - '
+ _Link text: item.minutes, href: Todos.link(item.title)
+ end
end
end
@@ -166,28 +166,33 @@ class PMCActions < Vue
onClick: self.submit
end
- # update check marks based on current Todo list
+ # gather a list of resolutions
def created()
@resolutions = []
+
Agenda.index.each do |item|
- if Todos.change.any? {|todo| todo.resolution == item.title}
- action = :change
- elsif Todos.establish.any? {|todo| todo.resolution == item.title}
- action = :establish
- elsif Todos.terminate.any? {|todo| todo.resolution == item.title}
- action = :terminate
- else
- next
- end
-
- minutes = Minutes.get(item.title)
+ action = name = nil
+
+ %w(change establish terminate).each do |todo_type|
+ Todos[todo_type].each do |todo|
+ if todo.resolution == item.title
+ minutes = Minutes.get(item.title)
- @resolutions << {
- action: action,
- title: item.title,
- minutes: minutes,
- checked: (minutes != 'tabled')
- }
+ resolution = {
+ action: todo_type,
+ name: todo.name,
+ title: item.title,
+ minutes: minutes,
+ checked: (minutes != 'tabled')
+ }
+
+ resolution.chair = todo.chair if todo.chair
+ resolution.people = todo.people if todo.people
+
+ @resolutions << resolution
+ end
+ end
+ end
end
self.refresh()
@@ -196,13 +201,35 @@ class PMCActions < Vue
def refresh()
@disabled = @resolutions.all? {|item| not item.checked}
end
+
+ def submit()
+ data = {
+ change: [],
+ establish: [],
+ terminate: []
+ }
+
+ @resolutions.each do |resolution|
+ data[resolution.action] << resolution if resolution.checked
+ end
+
+ data.change = nil if data.change.empty?
+ data.establish = nil if data.establish.empty?
+ data.terminate = nil if data.terminate.empty?
+
+ @disabled = true
+ post "secretary-todos/#{Agenda.title}", data do |todos|
+ @disabled = false
+ Todos.set todos
+ end
+ end
end
########################################################################
-# Add, Remove chairs #
+# Remove chairs #
########################################################################
-class TodoActions < Vue
+class TodoRemove < Vue
def initialize
@checked = {}
@disabled = true
@@ -211,7 +238,7 @@ class TodoActions < Vue
# update check marks based on current Todo list
def created()
- @people = Todos[@@action]
+ @people = Todos.remove
# uncheck people who were removed
for id in @checked
@@ -244,11 +271,7 @@ class TodoActions < Vue
end
def render
- if @@action == 'add'
- _p 'Add to pmc-chairs and email welcome message:'
- else
- _p 'Remove from pmc-chairs:'
- end
+ _p 'Remove from pmc-chairs:'
_ul.checklist @people do |person|
_li do
@@ -261,14 +284,6 @@ class TodoActions < Vue
_a person.id,
href: "/roster/committer/#{person.id}"
_ " (#{person.name})"
-
- if @@action == 'add' and person.resolution
- resolution = Minutes.get(person.resolution)
- if resolution
- _ ' - '
- _Link text: resolution, href: Todos.link(person.resolution)
- end
- end
end
end
@@ -279,10 +294,12 @@ class TodoActions < Vue
def submit()
@disabled = true
- data = {}
- data[@@action] = @checked
+ remove = []
+ for id in @checked
+ remove << id if @checked[id]
+ end
- post "secretary-todos/#{Agenda.title}", data do |todos|
+ post "secretary-todos/#{Agenda.title}", remove: remove do |todos|
@disabled = false
Todos.set todos
end
--
To stop receiving notification emails like this one, please contact
['"commits@whimsical.apache.org" <co...@whimsical.apache.org>'].