Skip to content

Commit edd860c

Browse files
committed
Make retire.sh more easily testable
- By default runs in dry mode now while showing what external effects would be run in production mode - Doesn't delete the temporary directory in dry mode - Makes sure to rerunnable by resetting the local state to what it was before - Traces commands that could fail - Make the waiting time period configurable with an argument
1 parent 81a8973 commit edd860c

File tree

3 files changed

+68
-32
lines changed

3 files changed

+68
-32
lines changed

.github/workflows/retire.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ jobs:
3535
with:
3636
token: ${{ steps.app-token.outputs.token }}
3737
- name: Run script
38-
run: scripts/retire.sh NixOS nixpkgs nixpkgs-committers members
38+
# One month plus a bit of leeway
39+
run: scripts/retire.sh NixOS nixpkgs nixpkgs-committers members "yesterday 1 month ago"
3940
env:
4041
GH_TOKEN: ${{ steps.app-token.outputs.token }}
42+
PROD: "1"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.tmp

scripts/retire.sh

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,70 @@
11
#!/usr/bin/env bash
22
set -euo pipefail
3+
shopt -s nullglob
4+
5+
log() {
6+
echo "$@" >&2
7+
}
8+
9+
trace() {
10+
log "Running:" "${@@Q}"
11+
"$@"
12+
}
13+
14+
effect() {
15+
log -en "\e[33m"
16+
if [[ -z "${PROD:-}" ]]; then
17+
log "Skipping effect:" "${@@Q}"
18+
# If there's stdin, show it
19+
if read -t 0 _; then
20+
sed "s/^/[stdin] /" >&2
21+
fi
22+
else
23+
trace "$@"
24+
fi
25+
log -en "\e[0m"
26+
}
327

428
usage() {
5-
echo >&2 "Usage: $0 ORG ACTIVITY_REPO MEMBER_REPO DIR"
29+
log "Usage: $0 ORG ACTIVITY_REPO MEMBER_REPO DIR PR_CUTOFF_DATE"
630
exit 1
731
}
832

933
ORG=${1:-$(usage)}
1034
ACTIVITY_REPO=${2:-$(usage)}
1135
MEMBER_REPO=${3:-$(usage)}
1236
DIR=${4:-$(usage)}
37+
CUTOFF_DATE=${5:-$(usage)}
1338

14-
tmp=$(mktemp -d)
15-
16-
shopt -s nullglob
17-
18-
# One month plus a bit of leeway
19-
epochOneMonthAgo=$(( $(date --date='1 month ago' +%s) - 60 * 60 * 12 ))
2039
mainBranch=$(git branch --show-current)
40+
cutoffEpoch=$(date --date="$CUTOFF_DATE" +%s)
41+
42+
if [[ -z "${PROD:-}" ]]; then
43+
tmp=$(git rev-parse --show-toplevel)/.tmp
44+
rm -rf "$tmp"
45+
mkdir "$tmp"
46+
log -e "\e[33mPROD=1 is not set, skipping effects and keeping temporary files in $tmp until the next run\e[0m"
47+
else
48+
tmp=$(mktemp -d)
49+
trap 'rm -rf "$tmp"' exit
50+
fi
2151

2252
mkdir -p "$DIR"
2353
cd "$DIR"
2454
for login in *; do
25-
gh api -X GET /repos/"$ORG"/"$ACTIVITY_REPO"/activity -f time_period=year -f actor="$login" -f per_page=100 \
55+
trace gh api -X GET /repos/"$ORG"/"$ACTIVITY_REPO"/activity -f time_period=year -f actor="$login" -f per_page=100 \
2656
--jq ".[] | \"- \(.timestamp) [\(.activity_type) on \(.ref | ltrimstr(\"refs/heads/\"))](https://github.com/$ORG/$ACTIVITY_REPO/compare/\(.before)...\(.after))\"" \
2757
> "$tmp/$login"
2858
activityCount=$(wc -l <"$tmp/$login")
2959

3060
branchName=retire-$login
31-
prInfo=$(gh api -X GET /repos/"$ORG"/"$MEMBER_REPO"/pulls -f head="$ORG":"$branchName" --jq '.[0]')
61+
prInfo=$(trace gh api -X GET /repos/"$ORG"/"$MEMBER_REPO"/pulls -f head="$ORG":"$branchName" --jq '.[0]')
3262
if [[ -n "$prInfo" ]]; then
3363
# If there is a PR already
3464
prNumber=$(jq .number <<< "$prInfo")
3565
epochCreatedAt=$(date --date="$(jq -r .created_at <<< "$prInfo")" +%s)
36-
if (( epochCreatedAt < epochOneMonthAgo )); then
37-
echo "$login has a retirement PR due, comment with a reminder to merge"
66+
if (( epochCreatedAt < cutoffEpoch )); then
67+
log "$login has a retirement PR due, commenting with next steps"
3868
{
3969
if (( activityCount > 0 )); then
4070
echo "One month has passed, @$login has been active again:"
@@ -57,30 +87,33 @@ for login in *; do
5787
echo ' --method DELETE \'
5888
echo " '/orgs/NixOS/teams/nixpkgs-committers/memberships/$login'"
5989
echo ' ```'
60-
} | gh api --method POST /repos/"$ORG"/"$MEMBER_REPO"/issues/"$prNumber"/comments -F "body=@-" >/dev/null
90+
} | effect gh api --method POST /repos/"$ORG"/"$MEMBER_REPO"/issues/"$prNumber"/comments -F "body=@-" >/dev/null
6191
else
62-
echo "$login has a retirement PR pending"
92+
log "$login has a retirement PR pending"
6393
fi
6494
elif (( activityCount <= 0 )); then
65-
echo "$login has become inactive, opening a PR"
95+
log "$login has become inactive, opening a PR"
6696
# If there is no PR yet, but they have become inactive
67-
git switch -C "$branchName"
68-
git rm "$login"
69-
git commit -m "Automatic retirement of @$login"
70-
git push -f origin "$branchName"
71-
{
72-
echo "This is an automated PR to retire @$login as a Nixpkgs committers due to not using their commit access for 1 year."
73-
echo ""
74-
echo "Make a comment with your motivation to keep commit access, otherwise this PR will be merged and implemented in 1 month."
75-
} | gh api \
76-
--method POST \
77-
/repos/"$ORG"/"$MEMBER_REPO"/pulls \
78-
-f "title=Automatic retirement of @$login" \
79-
-F "body=@-" \
80-
-f "head=$ORG:$branchName" \
81-
-f "base=$mainBranch" >/dev/null
82-
git checkout "$mainBranch"
97+
(
98+
trace git switch -C "$branchName"
99+
trap 'trace git checkout "$mainBranch" && trace git branch -D "$branchName"' exit
100+
trace git rm "$login"
101+
trace git commit -m "Automatic retirement of @$login"
102+
effect git push -f -u [email protected]:"$ORG"/"$MEMBER_REPO" "$branchName"
103+
{
104+
echo "This is an automated PR to retire @$login as a Nixpkgs committers due to not using their commit access for 1 year."
105+
echo ""
106+
echo "Make a comment with your motivation to keep commit access, otherwise this PR will be merged and implemented in 1 month."
107+
} | effect gh api \
108+
--method POST \
109+
/repos/"$ORG"/"$MEMBER_REPO"/pulls \
110+
-f "title=Automatic retirement of @$login" \
111+
-F "body=@-" \
112+
-f "head=$ORG:$branchName" \
113+
-f "base=$mainBranch" >/dev/null
114+
)
83115
else
84-
echo "$login is active with $activityCount activities"
116+
log "$login is active with $activityCount activities"
85117
fi
118+
log ""
86119
done

0 commit comments

Comments
 (0)