Skip to content

Commit 9f71c8a

Browse files
authored
Merge pull request #33 from NixOS/improved-new-committer-tracking
Track committer additions with git history
2 parents 0ddf4a2 + db0c92b commit 9f71c8a

File tree

10 files changed

+70
-30
lines changed

10 files changed

+70
-30
lines changed

.github/workflows/retire.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ jobs:
3434
uses: actions/checkout@v4
3535
with:
3636
token: ${{ steps.app-token.outputs.token }}
37+
# Fetch full history to determine when committers were added
38+
fetch-depth: 0
3739
- name: Run script
3840
# One month plus a bit of leeway
3941
run: scripts/retire.sh NixOS nixpkgs nixpkgs-committers members "yesterday 1 month ago"

members/Enzime

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
2025-08-20

members/LordGrimmauld

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
2025-08-20

members/MattSturgeon

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
2025-08-20

members/SigmaSquadron

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
2025-08-20

members/jmbaur

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
2025-08-20

members/m1cr0man

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
2025-08-20

scripts/README.md

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,27 +36,32 @@ Once you have the above setup (or got @infinisil to add yourself to his), you ha
3636
This script has no external effects and as such can be easily tested by running:
3737

3838
```bash
39-
scripts/sync.sh infinisil-test-org actors members
39+
scripts/sync.sh infinisil-test-org actors members-test
4040
```
4141

42-
Check that it synchronises the files in the `members` directory with the team members of the `actors` team.
42+
Check that it synchronises the files in the `members-test` directory with the team members of the `actors` team.
4343

4444
## `retire.sh`
4545

4646
This script has external effects and as such needs a bit more care when testing.
4747

4848
### Setup (important!)
4949

50-
To avoid other users getting pings, ensure that the `members` directory contains only a simulated new user and your own user (simulated to have been added over a year ago), then commit and push it for testing:
50+
To avoid other users getting pings, ensure that the `members-test` directory contains only simulated new users and your own user (simulated to have been added over a year ago), then commit and push it for testing:
5151

5252
```bash
5353
me=$(gh api /user --jq .login)
5454
git switch -C "test-$me"
55-
rm -rf members
56-
mkdir members
57-
date +%F > "members/github"
58-
date --date="1 year ago 1 day ago" +%F > "members/$me"
59-
git add members
55+
rm -rf members-test
56+
mkdir -p members-test
57+
58+
touch members-test/"$me"
59+
date +%F > "members-test/new-committer-1"
60+
git add members-test
61+
GIT_COMMITTER_DATE=$(date --date @0) git commit -m testing
62+
63+
touch "members-test/new-committer-2"
64+
git add members-test
6065
git commit -m testing
6166
git push -f -u origin HEAD
6267
```
@@ -67,40 +72,40 @@ The following sequence tests all code paths:
6772

6873
1. Run the script with the `active` repo argument to simulate CI running without inactive users:
6974
```bash
70-
scripts/retire.sh infinisil-test-org active nixpkgs-committers members 'yesterday 1 month ago'
75+
scripts/retire.sh infinisil-test-org active nixpkgs-committers members-test 'yesterday 1 month ago'
7176
```
7277

7378
Check that no PR would be opened.
7479
2. Run the script with the `empty` repo argument to simulate CI running with inactive users:
7580

7681
```bash
77-
scripts/retire.sh infinisil-test-org empty nixpkgs-committers members 'yesterday 1 month ago'
82+
scripts/retire.sh infinisil-test-org empty nixpkgs-committers members-test 'yesterday 1 month ago'
7883
```
7984

80-
Check that it would only create a PR for your own user and not the "github" user before running it again with `PROD=1` to actually do it:
85+
Check that it would only create a PR for your own user and not the "new-committer-1" or "new-committer-2" user before running it again with `PROD=1` to actually do it:
8186

8287
```bash
83-
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members 'yesterday 1 month ago'
88+
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members-test 'yesterday 1 month ago'
8489
```
8590

8691
Check that it created the PR appropriately.
8792
You can undo this step by closing the PR.
8893
3. Run it again to simulate CI running again later:
8994
```bash
90-
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members 'yesterday 1 month ago'
95+
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members-test 'yesterday 1 month ago'
9196
```
9297
Check that no other PR is opened.
9398
4. Run it again with `now` as the date to simulate the time interval passing:
9499
```bash
95-
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members now
100+
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members-test now
96101
```
97102
Check that it undrafted the previous PR and posted an appropriate comment.
98103
5. Run it again to simulate CI running again later:
99104
```bash
100-
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members now
105+
PROD=1 scripts/retire.sh infinisil-test-org empty nixpkgs-committers members-test now
101106
```
102107
6. Reset by marking the PR as a draft again.
103108
7. Run it again with the `active` repo argument to simulate activity during the time interval:
104109
```bash
105-
PROD=1 scripts/retire.sh infinisil-test-org active nixpkgs-committers members now
110+
PROD=1 scripts/retire.sh infinisil-test-org active nixpkgs-committers members-test now
106111
```

scripts/retire.sh

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,31 @@ DIR=${4:-$(usage)}
3737
NOTICE_CUTOFF=${5:-$(usage)}
3838

3939
mainBranch=$(git branch --show-current)
40-
newCutoff=$(date --date="1 year ago" +%s)
4140
noticeCutoff=$(date --date="$NOTICE_CUTOFF" +%s)
4241

42+
# People that received the commit bit after this date won't be retired
43+
newCutoff=$(date --date="1 year ago" +%s)
44+
45+
# We need to know when people received their commit bit to avoid retiring them within the first year.
46+
# For now this is done either with the git creation date of the file, or its contents:
47+
#
48+
# | commit bit reception date | file creation date | file contents |
49+
# | -------------------------- | ------------------ | -------------- |
50+
# | A) -∞ - 2024-10-06 | 2025-07-08 | empty |
51+
# | B) 2024-10-07 - 2025-04-22 | 2025-07-08 | reception date |
52+
# | C) 2025-08-13 - ∞ | reception date | empty |
53+
#
54+
# After 2026-04-23 (one year after C started), the file creation date
55+
# for all first-year committers will match the reception date,
56+
# while everybody else will have been a committer for more than one year.
57+
# This means the code can then be simplified to just
58+
# check if the file creation date is in the last year.
59+
#
60+
# For now however, the code needs to check if the file creation date
61+
# is before 2025-07-09 to distinguish between periods A and C,
62+
# so we hardcode that date for the code to use.
63+
createdOnReceptionEpoch=$(date --date=2025-07-09 +%s)
64+
4365
if [[ -z "${PROD:-}" ]]; then
4466
tmp=$(git rev-parse --show-toplevel)/.tmp
4567
rm -rf "$tmp"
@@ -54,12 +76,30 @@ mkdir -p "$DIR"
5476
cd "$DIR"
5577
for login in *; do
5678

57-
# Don't remove people that have been added recently
58-
if [[ -s "$login" ]]; then
59-
epochAdded=$(date --date="$(<"$login")" +%s)
60-
if (( newCutoff < epochAdded )); then
61-
continue
79+
# Figure out when this person received the commit bit
80+
# Get the unix epoch of the first commit that touched this file
81+
# --first-parent is important to get the time of when the main branch was changed
82+
fileCommitEpoch=$(git log --reverse --first-parent --format=%cd --date=unix -- "$login" | head -1)
83+
if (( fileCommitEpoch < createdOnReceptionEpoch )); then
84+
# If it was created before creation actually matched the reception date
85+
# This branch can be removed after 2026-04-23
86+
87+
if [[ -s "$login" ]]; then
88+
# If the file is non-empty it indicates an explicit reception date
89+
receptionEpoch=$(date --date="$(<"$login")" +%s)
90+
else
91+
# Otherwise they received the commit bit more than a year ago (start of unix epoch, 1970)
92+
receptionEpoch=0
6293
fi
94+
else
95+
# Otherwise creation matches reception
96+
receptionEpoch=$fileCommitEpoch
97+
fi
98+
99+
# If the commit bit was received after the cutoff date, don't retire in any case
100+
if (( newCutoff < receptionEpoch )); then
101+
log "$login became a committer less than 1 year ago, skipping retirement check"
102+
continue
63103
fi
64104

65105
trace gh api -X GET /repos/"$ORG"/"$ACTIVITY_REPO"/activity \

scripts/sync.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ gh api /orgs/"$ORG"/teams/"$TEAM"/members --paginate --jq '.[].login' |
1717
if [[ -f "$DIR/$login" ]]; then
1818
mv "$DIR/$login" "$DIR.new"
1919
else
20-
# Keep track of when the user was added
21-
date +%F > "$DIR.new/$login"
20+
touch "$DIR.new/$login"
2221
fi
2322
done
2423

0 commit comments

Comments
 (0)