From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 ; 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 ; 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 ; 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 ; Sun, 2 Jun 2024 00:13:46 +0000 (UTC) From: "Robin H. Johnson" 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" 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: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail 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 gentoo org> AuthorDate: Sun Jun 2 00:09:11 2024 +0000 Commit: Robin H. Johnson gentoo 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 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}/"