aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2024-06-01 17:09:11 -0700
committerRobin H. Johnson <robbat2@gentoo.org>2024-06-01 17:11:41 -0700
commit41002dc5a2d784967053a34de70c3ebe9578c3b4 (patch)
tree6b552ebd577f1c0c98e702ccbde029e2e2f009a4
parentREADME: improve details about infra steps (diff)
downloadelections-41002dc5a2d784967053a34de70c3ebe9578c3b4.tar.gz
elections-41002dc5a2d784967053a34de70c3ebe9578c3b4.tar.bz2
elections-41002dc5a2d784967053a34de70c3ebe9578c3b4.zip
build: make it easier to start a new election
Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
-rw-r--r--README.md37
-rw-r--r--Votify.pm5
-rw-r--r--election-details.template8
-rwxr-xr-xpopulate-election.sh74
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}/"