From 86bfeed510d8a86b2543188ccde593c0cfa9a928 Mon Sep 17 00:00:00 2001 From: Emily Date: Sun, 7 Dec 2025 19:28:36 +0000 Subject: [PATCH 1/3] scripts/common.sh: set time zone to UTC --- scripts/common.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/common.sh b/scripts/common.sh index 1cd2c42..0d91611 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -1,5 +1,7 @@ set -euo pipefail +export TZ=UTC + log() { echo "$@" >&2 } From 2a14cf5e7e26ebc4643908b54228017c2a04089e Mon Sep 17 00:00:00 2001 From: Emily Date: Sun, 7 Dec 2025 19:28:36 +0000 Subject: [PATCH 2/3] scripts/retire.sh: find the latest commit that added a committer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise, a committer that is removed and then added again may be proposed for retirement within the first year of their new tenure. This also fixes an interaction between `-o pipefail` and `SIGPIPE` that seems to reproduce in local tests on both Darwin and Linux for me, but somehow hasn’t been affecting CI. --- scripts/retire.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/retire.sh b/scripts/retire.sh index 88b3f01..2d50bc0 100755 --- a/scripts/retire.sh +++ b/scripts/retire.sh @@ -59,9 +59,16 @@ cd "$DIR" for login in *; do # Figure out when this person received the commit bit - # Get the unix epoch of the first commit that touched this file + # Get the unix epoch of the last commit that added this file # --first-parent is important to get the time of when the main branch was changed - fileCommitEpoch=$(git log --reverse --first-parent --format=%cd --date=unix -- "$login" | head -1) + fileCommitEpoch=$(git log \ + --first-parent \ + --no-follow \ + --diff-filter=A \ + --max-count=1 \ + --format=%cd \ + --date=unix \ + -- "$login") if (( fileCommitEpoch < createdOnReceptionEpoch )); then # If it was created before creation actually matched the reception date # This branch can be removed after 2026-04-23 From 9c08aaf59aec3fc3330cc6b1c0a4fc803c4f960b Mon Sep 17 00:00:00 2001 From: Emily Date: Sun, 7 Dec 2025 02:53:31 +0000 Subject: [PATCH 3/3] scripts/retire.sh: use commits endpoint rather than activity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The activity endpoint does not work with the merge queue, and counts things like branch creations that we don’t really want to include. This finds two‐parent merge commits with the correct author committed and signed by the GitHub key that are reachable from the main branch; I believe that PR merges are the only such commits, but any exceptions should be very marginal. Closes: #69 --- scripts/README.md | 4 ++-- scripts/retire.sh | 30 ++++++++++++++---------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/scripts/README.md b/scripts/README.md index c476b32..6e3b118 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -10,7 +10,7 @@ whose identifiers will be used here. - [infinisil-test-org](https://github.com/infinisil-test-org): A GitHub organisation you're part of - Repositories: - - [infinisil-test-org/empty](https://github.com/infinisil-test-org/empty): An empty one with no activity on it + - [infinisil-test-org/empty](https://github.com/infinisil-test-org/empty): A repository with only one commit, not attributed to your GitHub user - [infinisil-test-org/active](https://github.com/infinisil-test-org/active): One where you have some activity - [infinisil-test-org/nixpkgs-committers](https://github.com/infinisil-test-org/nixpkgs-committers): A fork of the upstream repo @@ -22,7 +22,7 @@ whose identifiers will be used here. Once you have the above setup (or got @infinisil to add yourself to his), you have to prepare the following: - Add some activity of yours to the `active` repo. - To cover all code branches it's recommended to create, push to and delete a branch. + To match Nixpkgs, it’s recommended to do this by setting the “Default commit message” for merge commits to “Pull request title”, then creating and merging a PR. You can do this from the web interface. - Get the GitHub CLI available (`pkgs.github-cli`) and authenticate it using `gh auth login` - A local Git clone of this repository with the `origin` remote set to the test repository: diff --git a/scripts/retire.sh b/scripts/retire.sh index 2d50bc0..cf144b5 100755 --- a/scripts/retire.sh +++ b/scripts/retire.sh @@ -108,22 +108,20 @@ for login in *; do continue fi - trace gh api -X GET /repos/"$ORG"/"$ACTIVITY_REPO"/activity \ - -f time_period=year \ - -f actor="$login" \ + PR_PREFIX="$ORG/$ACTIVITY_REPO" \ + trace gh api -X GET /repos/"$ORG"/"$ACTIVITY_REPO"/commits \ + -f since="$(date --date='1 year ago' --iso-8601=seconds)" \ + -f author="$login" \ + -f committer=web-flow \ -f per_page=100 \ --jq '.[] | - "- \(.timestamp) [\(.activity_type) on \(.ref | ltrimstr("refs/heads/"))](https://github.com/'"$ORG/$ACTIVITY_REPO"'/\( - if .activity_type == "branch_creation" then - "commit/\(.after)" - elif .activity_type == "branch_deletion" then - "commit/\(.before)" - else - "compare/\(.before)...\(.after)" - end - ))"' \ + # PR merge commits have two parents. We also check it’s an + # authentic GitHub commit, because… why not? + select((.parents | length) == 2 and .commit.verification.verified) | + (.commit.message | capture(" \\((?#[0-9]+)\\)$").pr) as $pr | + "- `\(.commit.committer.date)` – \(env.PR_PREFIX)\($pr)"' \ > "$tmp/$login" - activityCount=$(wc -l <"$tmp/$login") + mergeCount=$(wc -l <"$tmp/$login") if [[ "$prState" == open ]]; then # If there is an open PR already @@ -133,7 +131,7 @@ for login in *; do log "$login has a retirement PR due, unmarking PR as draft and commenting with next steps" effect gh pr ready --repo "$ORG/$MEMBER_REPO" "$prNumber" { - if (( activityCount > 0 )); then + if (( mergeCount > 0 )); then echo "One month has passed, and @$login has been active again:" cat "$tmp/$login" echo "" @@ -158,7 +156,7 @@ for login in *; do else log "$login has a retirement PR pending" fi - elif (( activityCount <= 0 )); then + elif (( mergeCount <= 0 )); then log "$login has become inactive, opening a PR" # If there is no PR yet, but they have become inactive ( @@ -192,7 +190,7 @@ for login in *; do -f "labels[]=retirement" >/dev/null ) else - log "$login is active with $activityCount activities" + log "$login is active with $mergeCount merges" fi log "" done