-
Notifications
You must be signed in to change notification settings - Fork 107
feat(github-actions): add inactivity bot phase 2 (stale PR detection) #989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Akshat Kumar <akshat230405@gmail.com>
Signed-off-by: Akshat8510 <akshat230405@gmail.com>
Signed-off-by: Akshat8510 <akshat230405@gmail.com>
Signed-off-by: Akshat Kumar <akshat230405@gmail.com>
|
Hi, this is MergeConflictBot. Please resolve these conflicts locally and push the changes. To assist you, please read: Thank you for contributing! From the Hiero Python SDK Team |
Signed-off-by: Akshat8510 <akshat230405@gmail.com>
Signed-off-by: Akshat8510 <akshat230405@gmail.com>
|
Hi @exploreriii , I verified the entire workflow on my fork, including stale-PR detection, commenting and closing Please take your time reviewing — happy to adjust anything if needed! |
|
I am reviewing this currently but we have 4 concurrent bot PRs to review. |
|
Do the bot have the privilege to close a pull request?? @exploreriii @Akshat8510 ? I mean we can't. |
|
Hi @MonaaEid! Great question , and yes, the bot does have the required permissions to close pull requests in the main repository. The workflow explicitly grants pull-requests: write, which is the permission level GitHub Actions needs to comment on and close PRs. This is the same permission model used by the other automation bots in this repo, so it stays fully consistent. I also verified the entire Phase 2 flow on my fork and everything worked exactly as intended: https://github.com/Akshat8510/hiero-sdk-python/pull/3 |
just a small doubt like what if this gets merged, then will the bot unassign the people who were inactive earlier? |
It will work in your forked repo for sure, but for example I can comment on other's pull requests, but I can't close it |
|
Based on how the workflow is currently designed , and to be fully transparent, I’m not completely sure, but this is how it should behave. The bot only checks PRs that are currently open. If an open PR hasn’t received any new commits for more than 21 days, the bot will post the inactivity message, close the PR, and unassign the contributor from the linked issue. Closed PRs are completely ignored and won’t be affected. So, if there are already stale open PRs in the main repository, the bot should automatically detect and handle them during its next scheduled run. |
|
Hi @MonaaEid! Thanks for raising this , and that’s a very valid point. You’re right that as contributors we can comment on others’ PRs but can’t close them manually. The key difference here is that GitHub Actions doesn’t operate using our personal contributor permissions; instead, it uses the permissions defined directly in the workflow. Since the workflow grants pull-requests: write, it effectively gives the bot elevated access beyond what a regular contributor has, which is why it can close PRs even though we personally cannot. And just to be transparent, I’m not entirely certain how GitHub handles every edge case, but based on testing and GitHub’s documentation, the bot should behave in the main repository exactly as it did in the fork. |
exploreriii
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if a user has multiple pull requests tied to an issue they are assigned to?
For example, try 1 failed, open up try 2, but you leave try 1 open.
This is not relevant right now, so not that important, but it could be.
In this case, it will only close one PR, keep the other open, but unassign the user.
Shouldn't it also close the second PR?
That makes sense, I didn't think of this. Thank you for this explanation. |
This comment was marked as spam.
This comment was marked as spam.
|
You’re right , in the current setup, the bot would only close one stale PR and still unassign the user even if another active PR exists. It’s not ideal, and the logic could definitely be improved later to either close all stale PRs for the issue or only unassign once all related PRs are handled. For now, the workflow keeps things simple, but this is a good edge case to refine in a future update. |
|
Why is this PR being judged as inactive for 39 days? #362 |
|
Hi @exploreriii , great question! The reason this PR is currently being flagged as “inactive for 39 days” is based purely on commit activity, not comments, reviews, merges from How the inactivity counter worksOur Phase 2 bot (and GitHub’s API) looks only at: → The timestamp of the most recent commit authored on the PR’s branch itself. So even if the PR is actively discussed, reviewed, or repeatedly updated by merging
Merges like “Merge branch 'main' into AddSetNodeAccountIdMethod” do not count as development work , they only pull upstream updates and don’t modify the contributor’s changes. Why this metric was chosenI’m not fully sure if GitHub provides a more detailed or reliable activity metric (like tracking “meaningful pushes”), but the last commit timestamp is:
If a better activity signal exists, I’m happy to explore it but for now, this is the most consistent measure available. |
|
Could you try to run a debug script on that PR, as some of the recent commits are not merge commits, I think: eg #!/usr/bin/env bash
set -euo pipefail
REPO="${REPO:-}"
PR="${PR:-}"
if [[ -z "$REPO" || -z "$PR" ]]; then
echo "USAGE:"
echo " REPO=owner/repo PR=362 ./debug-last-commit.sh"
exit 1
fi
echo "============================================================"
echo " DEBUG: Last Commit Detection"
echo " Repo: $REPO"
echo " PR: #$PR"
echo "============================================================"
echo
echo "[INFO] Fetching PR commits..."
COMMITS=$(gh api "repos/$REPO/pulls/$PR/commits" --paginate)
COUNT=$(echo "$COMMITS" | jq length)
echo "[INFO] Number of commits returned: $COUNT"
echo
NOW_TS=$(date +%s)
parse_ts() {
if date --version >/dev/null 2>&1; then
date -d "$1" +%s
else
date -j -f "%Y-%m-%dT%H:%M:%SZ" "$1" +"%s"
fi
}
echo "------------------------------------------------------------"
echo " COMMITS (in the order GitHub API returned them)"
echo "------------------------------------------------------------"
INDEX=0
echo "$COMMITS" | jq -c '.[] | {sha: .sha, author_date: .commit.author.date, committer_date: .commit.committer.date}' \
| while read -r line; do
SHA=$(echo "$line" | jq -r '.sha')
ADATE=$(echo "$line" | jq -r '.author_date')
CDATE=$(echo "$line" | jq -r '.committer_date')
echo "[$INDEX]"
echo " sha: $SHA"
echo " author.date: $ADATE"
echo " committer.date: $CDATE"
echo
INDEX=$((INDEX+1))
done
echo
echo "============================================================"
echo " DEBUG COMPLETE"
echo "============================================================" |
exploreriii
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you improve the precision of the lastest commit identification, I think you can sort the commits by timestamp to be sure
This is because you do a fetch the last commit approach - but i think this is not always accurate as the last in time commit
I don't want to unassign users that have been active in the last 21 days as that can be demotivating
|
Hi @exploreriii — I ran the debug script on PR #362 exactly as you suggested: REPO=hiero-ledger/hiero-sdk-python PR=362 ./debug-last-commit.shHere’s what the script reports:
From the API’s perspective, the latest commit on this PR is only a few days old , not 39 days. is correctly identifying the newest commit for #362. If a stale-age value showed “39 days,” it likely came from either:
I can review the workflow run if needed. I can also extend the debug script to explicitly sort commits by date to make its output clearer. |
|
Hi @exploreriii , absolutely, that makes sense and I agree with your concern. gh api /pulls//commits But as you said, the API's array order is not guaranteed to represent true chronological order, especially when PRs involve merges, rebases, or rewritten history. I can improve the precisionI’ll update the logic so the bot:
This ensures that even if the API returns commits out of order, the bot still evaluates the correct most recent activity. BenefitThis makes inactivity detection much more reliable and prevents accidental unassignments for contributors who have committed within the 21-day window. If you prefer sorting only by Happy to refine this further! |
|
Hi @Akshat8510 I’ll update the logic so the bot: Fetches all commit timestamps for the PR thanks! |
… bot Signed-off-by: Akshat Kumar <akshat230405@gmail.com>
|
Hi @exploreriii , thank you for the clarification! That helps me understand exactly what part was confusing in my previous explanation. To put it simply, the core issue you were highlighting is: The last commit in the GitHub API array is not guaranteed to be the actual latest commit in time. So if we rely on
I completely understand why that’s a risk we shouldn’t take. Update implementedI’ve updated Phase 2 so it now:
This guarantees the bot always uses the correct most recent activity — even in PRs with merges, rebases, or rewritten history. The ambiguity you mentioned in my earlier message ("benefit section") makes sense, and thanks for pointing it out. The important thing is: the logic is now fully deterministic and safe. If there’s any specific edge case you’d like me to test or validate, I’m happy to run more checks! |
Signed-off-by: Akshat Kumar <akshat230405@gmail.com>
Signed-off-by: Akshat8510 <akshat230405@gmail.com>
Signed-off-by: Akshat8510 <akshat230405@gmail.com>
Updated the CHANGELOG to reflect recent additions and changes, including improvements to the inactivity-unassign bot and updates to the CustomFixedFee class. Signed-off-by: Akshat8510 <akshat230405@gmail.com>
|
Hi @exploreriii I ran the updated Phase 2 dry-run script directly against the main repo with: export REPO=hiero-ledger/hiero-sdk-python
export DAYS=21
.github/scripts/dry_run_inactivity_unassign_phase2.shThe output matches exactly what you described earlier. In the final summary, the bot reports:
And for So Phase 2 is now:
This gives me confidence that the current logic behaves as intended, but I’m happy to adjust anything further if you’d like. 🙂 |
exploreriii
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!! Nearly there, you have two workflows submtited
https://github.com/hiero-ledger/hiero-sdk-python/pull/989/files#r2597621938
dc49bef to
b39caf4
Compare
Signed-off-by: Akshat Kumar <akshat230405@gmail.com>
b39caf4 to
cbc5691
Compare
|
Request second review @nadineloepfe @manishdait as this bot will unassign users and close PRs that are stale |
|
Absolutely LOVE this! Brilliant work, let's merge it! |
|
Thank you! Merged |
…hiero-ledger#989) Signed-off-by: Akshat Kumar <akshat230405@gmail.com> Signed-off-by: Akshat8510 <akshat230405@gmail.com>
Description
Adds Phase 2 of the inactivity-unassign bot.
This phase handles contributors who do have an open PR, but the PR has had no commit activity for 21+ days.
What this PR adds
New script:
inactivity_unassign_phase2.shNew dry-run script for safe local testing:
dry_run_inactivity_unassign_phase2.shUpdates to Phase 1 workflow:
pull-requests: writeNew standalone workflow:
.github/workflows/bot-inactivity-unassign-phase2.ymlCHANGELOG entry updated.
Related issue
Fixes #969