From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-1637967-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits))
	(No client certificate requested)
	by finch.gentoo.org (Postfix) with ESMTPS id 58A7A15849D
	for <garchives@archives.gentoo.org>; Sun,  2 Jun 2024 00:13:51 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id 06FA5E2A90;
	Sun,  2 Jun 2024 00:13:50 +0000 (UTC)
Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256)
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id E238AE2A90
	for <gentoo-commits@lists.gentoo.org>; Sun,  2 Jun 2024 00:13:49 +0000 (UTC)
Received: from oystercatcher.gentoo.org (oystercatcher.gentoo.org [148.251.78.52])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256)
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id 72F7433FECD
	for <gentoo-commits@lists.gentoo.org>; Sun,  2 Jun 2024 00:13:48 +0000 (UTC)
Received: from localhost.localdomain (localhost [IPv6:::1])
	by oystercatcher.gentoo.org (Postfix) with ESMTP id DAA12119
	for <gentoo-commits@lists.gentoo.org>; Sun,  2 Jun 2024 00:13:46 +0000 (UTC)
From: "Robin H. Johnson" <robbat2@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Robin H. Johnson" <robbat2@gentoo.org>
Message-ID: <1717287101.41002dc5a2d784967053a34de70c3ebe9578c3b4.robbat2@gentoo>
Subject: [gentoo-commits] proj/elections:master commit in: /
X-VCS-Repository: proj/elections
X-VCS-Files: README.md Votify.pm election-details.template populate-election.sh
X-VCS-Directories: /
X-VCS-Committer: robbat2
X-VCS-Committer-Name: Robin H. Johnson
X-VCS-Revision: 41002dc5a2d784967053a34de70c3ebe9578c3b4
X-VCS-Branch: master
Date: Sun,  2 Jun 2024 00:13:46 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply
X-Archives-Salt: 625600d8-0fe9-40bb-90c8-d2c02efb9116
X-Archives-Hash: fdf246fb72cc5937a2e0bbb6d8d83827

commit:     41002dc5a2d784967053a34de70c3ebe9578c3b4
Author:     Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
AuthorDate: Sun Jun  2 00:09:11 2024 +0000
Commit:     Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
CommitDate: Sun Jun  2 00:11:41 2024 +0000
URL:        https://gitweb.gentoo.org/proj/elections.git/commit/?id=41002dc5

build: make it easier to start a new election

Signed-off-by: Robin H. Johnson <robbat2 <AT> gentoo.org>

 README.md                 | 37 +++++++++++++++---------
 Votify.pm                 |  5 ++--
 election-details.template |  8 +++++
 populate-election.sh      | 74 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 108 insertions(+), 16 deletions(-)

diff --git a/README.md b/README.md
index 9cd9ec1..a61f1a0 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ This handles all elections per the [Gentoo Elections](https://wiki.gentoo.org/wi
 
 The Condercet system is used, and most of this repository exists just to house
 the actual data needed to run each election, such as the start/stop time,
-eligable voters, blank ballot etc.
+eligible voters, blank ballot etc.
 
 Completed elections are available in the `completed/` directory.
 
@@ -28,32 +28,43 @@ Instructions
 1. Setup an election:
 ---------------------
 To create a new election, make a top-level directory with the exact name of
-the election. Usually in the format of `{council,trustees}-YYYYMM`.
+the election. Usually in the format of `{council,trustees}-YYYYMM`. All of the
+following files should be in that directory.
 
 Let `${election_name}` be the name of the election. Any member of the elections
 project or infra may set this up.
 
-- `Votify.pm`: symlink to `../Votify.pm` for tooling
-- `ballot-${election_name}`
-  One entry per line, in alphabetical order.
-  The special candidate `_reopen_nominations` is valid in some elections.
-  The ballot order will be randomized per candidate, at voting time.
 - `election-details`:
-  key-value file with details about the election.
+  key-value file with details about the election, see `election-details.template`
   `name`: exact election name
   `startDate`, `endDate`: start & end time in UTC
-  `officials`: election officials, including the infra contact, (prohibited from being candidates)
+  `officials`: election officials, including the infra contact (prohibited from being candidates)
   `voters`: URL to list of members who may cast a ballot
   `ballot`: URL to sample ballot
+  `url`: URL to the Elections page for this specific election (optional, newer)
+
+Using the above file, and the `populate-election.sh` script, the remaining
+files are created (pulling from URLs as needed.)
+
+- `Votify.pm`: symlink to `../Votify.pm` for tooling
+- `ballot-${election_name}`
+  One entry per line, in alphabetical order.
+  The special candidate `_reopen_nominations` is valid in some elections.
+  The ballot order will be randomized per candidate, at voting time.
 - `officials-${election_name}`: list of election officials, including the infra contact
 - `start-${election_name}`: election start time, as epoch seconds.
 - `stop-${election_name}`: election end time, as epoch seconds.
 - `voters-${election_name}`: list of members who may cast a ballot
 
-For developers, the one liner, worked example below, run on woodpecker, works.
-ldapsearch -ZZ -x -D uid=neddyseagoon,ou=devs,dc=gentoo,dc=org -W '(&(gentooStatus=active)(!(gentooAccess=infra-system.group)))' uid gentoojoin -LLL | grep "^uid" | sed -e "s/^uid: //" | sort -n > voters-council-202306.txt
-Some fine tuning to remove developers added to roll call after the cut off 
-may be required. 
+For developers, the one liner, worked example below, run on woodpecker, can create the `voters` file.
+```
+ldapsearch -ZZ -x  -w '' -S uid -LLL \
+  '(&(gentooStatus=active)(!(gentooAccess=infra-system.group)))' \
+  uid gentoojoin \
+  |awk -F ': ' '/uid:/ {print $2}' > voters-council-202406
+```
+Some fine tuning to remove developers added to roll call after the cut off
+may be required.
 
 Populate the files, commit & push to Git. At the start time, an official
 should verify that the ballot works. Ideally a non-infra official, who then

diff --git a/Votify.pm b/Votify.pm
index 49f21da..284dad2 100644
--- a/Votify.pm
+++ b/Votify.pm
@@ -1,6 +1,5 @@
-# $Id: Votify.pm,v 1.5 2005/05/16 23:58:09 agriffis Exp $
-#
-# Copyright 2005-2016 Gentoo Foundation
+#!/usr/bin/perl
+# Copyright 1999-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 #
 # votify.pm: common classes for votify and countify

diff --git a/election-details.template b/election-details.template
new file mode 100644
index 0000000..0df3612
--- /dev/null
+++ b/election-details.template
@@ -0,0 +1,8 @@
+name: __TYPE__-__YYYYMM__
+startDate: __YYYY__-MM-DD 00:00:00 UTC
+endDate: __YYYY__-MM-DD 23:59:59 UTC
+officials: __OFFICIALS__
+voters: https://projects.gentoo.org/elections/__TYPE__/__YYYY__/voters-__TYPE__-__YYYYMM__.txt
+ballot: https://projects.gentoo.org/elections/__TYPE__/__YYYY__/ballot-__TYPE__-__YYYYMM__.txt
+url: https://wiki.gentoo.org/wiki/Project:Elections/__TYPE__/__YYYYMM__
+

diff --git a/populate-election.sh b/populate-election.sh
new file mode 100755
index 0000000..bbfbc60
--- /dev/null
+++ b/populate-election.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+# Copyright 2024-2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+#
+# populate-election.sh: Create election files based on the election-details file.
+#
+
+ELECTION=${1%/}
+fullpath=$(readlink -f "./${ELECTION}")
+
+warn() {
+	echo "$@" 1>&2
+}
+
+die() {
+	echo "$@" 1>&2
+	exit 1
+}
+
+if [[ -z "${ELECTION}" ]]; then
+	die "usage: $(basename "$0") ELECTION-NAME"
+fi
+
+details="${fullpath}"/election-details
+
+if ! test -f "${details}" ; then
+	warn "Could not find $ELECTION at ${details}: missing file - generating from template"
+	mkdir -p "${ELECTION}"/
+	cat election-details.template >"${ELECTION}"/election-details
+	_type=${ELECTION//*-}
+	_yyyymm=${ELECTION//-*}
+	sed -i \
+		-e "s/__TYPE__/${_type}/g" \
+		-e "s/__YYYYMM__/${_yyyymm}/g" \
+		-e "s/__YYYY__/${_yyyymm:0:4}/g" \
+		"${ELECTION}"/election-details
+fi
+
+if ! grep -sq -x -e "name: ${ELECTION}" "${details}" ; then
+	die "Could not find $ELECTION at ${details}: bad content"
+fi
+
+for f in name startDate endDate officials voters ballot url ; do
+	awk -v f=$f -F ': ' '($1==f){print $2}' "${details}" |grep -E -e '.{6,}' -sq || die "$ELECTION: missing field $f in $details"
+done
+
+for f in voters ballot officials ; do
+	k1=${f/:*}
+	k2=${f/*:}
+	d=$ELECTION/${k1}-$ELECTION
+	v=$(awk -v f="$k2" -F ': ' '($1==f){print $2}' "${details}")
+	if [[ "$v" =~ "https://" ]]; then
+		curl --fail -Lsq -o "${d}" "$v" || warn "Could not fetch ${f} from $v"
+	else
+		tr -s ', ' '\n' <<<"$v" |fmt -1 |sort >"$d"
+	fi
+done
+
+for f in start:startDate stop:endDate ; do
+	k1=${f/:*}
+	k2=${f/*:}
+	d=$ELECTION/${k1}-$ELECTION
+	v=$(awk -v f="$k2" -F ': ' '($1==f){print $2}' "${details}")
+	date +%s -d "$v" >"${d}"
+done
+
+if [ -f "${ELECTION}/ballot-${ELECTION}" ]; then
+	overlap_candidate_official=$(grep -x -f "${ELECTION}/officials-${ELECTION}"  "${ELECTION}/ballot-${ELECTION}" -o)
+	if [[ -n "${overlap_candidate_official}" ]]; then
+		die "ERROR: One or more candidates are also election officials: ${overlap_candidate_official}"
+	fi
+fi
+
+ln -sf "../Votify.pm" "${ELECTION}/"