mirror of
https://github.com/zitadel/zitadel.git
synced 2026-08-17 16:35:14 -05:00
chore: move commented To-be-closed issues to to-be-reviewed (#12515)
# Which Problems Are Solved Adds a workflow that moves an issue from `To-be-closed` to `to-be-reviewed` once it gets a genuine reply (not counting our own auto-generated cleanup comments or bot comments). Runs two ways: - Instantly, when a comment is posted on an issue. - Daily, as a safety-net sweep of all `To-be-closed` issues, in case the instant check ever misses one. This is just the label-swap automation. The 30-day auto-close workflow is separate and not part of this PR. --------- Co-authored-by: Elina Sokolovska <elinasokolovska@Elinas-MacBook-Air.local> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Livio Spring <9405495+livio-a@users.noreply.github.com>
This commit is contained in:
co-authored by
Elina Sokolovska
Copilot Autofix powered by AI
Livio Spring
parent
dc1c8620bc
commit
8bbf0ad4e0
@@ -0,0 +1,102 @@
|
||||
name: Move commented To-be-closed issues to review
|
||||
|
||||
# Two triggers doing the same job:
|
||||
# - issue_comment: reacts instantly to a new comment on a single issue.
|
||||
# - schedule (daily): full sweep of every To-be-closed issue, as a safety
|
||||
# net in case the instant trigger ever misses one.
|
||||
#
|
||||
# Handles labels being removed and re-applied: uses the FIRST "labeled"
|
||||
# event as the reference point (not the most recent), so a comment from any
|
||||
# earlier labeling cycle still counts even after a manual removal and
|
||||
# re-application. Re-application isn't reliably a deliberate "still close
|
||||
# this" decision -- accidental re-labeling has happened before -- so this
|
||||
# errs toward flagging for human review rather than risking a missed reply.
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
schedule:
|
||||
- cron: "0 7 * * *" # daily at 07:00 UTC
|
||||
workflow_dispatch: {}
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
move-to-review:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'issue_comment' || github.event.issue.pull_request == null
|
||||
steps:
|
||||
- name: Swap labels for commented-on issues
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
COMMENT_AUTHOR: ${{ github.event.comment.user.login }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
CLOSE_LABEL="To-be-closed"
|
||||
REVIEW_LABEL="to-be-reviewed"
|
||||
|
||||
gh label create "$REVIEW_LABEL" --repo "$REPO" \
|
||||
--description "Pulled out of the to-be-closed queue after a reply; needs a maintainer to review." \
|
||||
--color "FBCA04" 2>/dev/null || true
|
||||
|
||||
check_and_swap() {
|
||||
local NUM="$1"
|
||||
|
||||
LABEL_EVENT=$(CLOSE_LABEL="$CLOSE_LABEL" gh api "repos/$REPO/issues/$NUM/events" --paginate \
|
||||
--jq '[.[] | select(.event=="labeled" and ((.label.name // "") | ascii_downcase) == (env.CLOSE_LABEL | ascii_downcase))] | sort_by(.created_at) | first | .created_at')
|
||||
|
||||
if [[ -z "$LABEL_EVENT" || "$LABEL_EVENT" == "null" ]]; then
|
||||
echo "#$NUM: couldn't find a labeling event, skipping"
|
||||
return
|
||||
fi
|
||||
|
||||
# Exclude our own auto-generated round comments (shared opening
|
||||
# line, or the invisible marker) so only genuine replies count.
|
||||
HUMAN_COMMENTS=$(LABEL_EVENT="$LABEL_EVENT" gh api "repos/$REPO/issues/$NUM/comments" --paginate \
|
||||
--jq '[.[] | select(
|
||||
.created_at > env.LABEL_EVENT
|
||||
and (.user.login | test("\\[bot\\]$") | not)
|
||||
and (.body | startswith("Thanks for filing this issue. As part of an ongoing backlog cleanup, we'"'"'re closing") | not)
|
||||
and (.body | contains("<!-- zitadel-backlog-cleanup-auto-comment -->") | not)
|
||||
)] | length')
|
||||
|
||||
if [[ "$HUMAN_COMMENTS" -gt 0 ]]; then
|
||||
echo "#$NUM: got a reply since $LABEL_EVENT -- moving to '$REVIEW_LABEL'"
|
||||
gh issue edit "$NUM" --repo "$REPO" --remove-label "$CLOSE_LABEL" --add-label "$REVIEW_LABEL"
|
||||
else
|
||||
echo "#$NUM: no reply since $LABEL_EVENT"
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ "$EVENT_NAME" == "issue_comment" ]]; then
|
||||
if [[ "$COMMENT_AUTHOR" == *"[bot]" ]]; then
|
||||
echo "Comment from a bot ($COMMENT_AUTHOR) -- ignoring."
|
||||
exit 0
|
||||
fi
|
||||
LABELS=$(gh issue view "$ISSUE_NUMBER" --repo "$REPO" --json labels --jq '.labels[].name')
|
||||
if ! echo "$LABELS" | grep -qxi "$CLOSE_LABEL"; then
|
||||
echo "Issue #$ISSUE_NUMBER doesn't have '$CLOSE_LABEL' -- nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
check_and_swap "$ISSUE_NUMBER"
|
||||
else
|
||||
echo "Full daily sweep of all '$CLOSE_LABEL' issues..."
|
||||
ISSUES=$(gh issue list --repo "$REPO" --search "is:open label:\"$CLOSE_LABEL\"" --limit 1000 --json number --jq '.[].number')
|
||||
ISSUE_COUNT=$(echo "$ISSUES" | wc -w | tr -d ' ')
|
||||
if [[ "$ISSUE_COUNT" -ge 1000 ]]; then
|
||||
echo "Warning: reached the 1000 issue cap for label '$CLOSE_LABEL'; there may be additional issues not processed."
|
||||
fi
|
||||
if [[ -z "$ISSUES" ]]; then
|
||||
echo "No $CLOSE_LABEL issues found."
|
||||
exit 0
|
||||
fi
|
||||
for NUM in $ISSUES; do
|
||||
echo "--- Checking #$NUM ---"
|
||||
check_and_swap "$NUM"
|
||||
done
|
||||
fi
|
||||
Reference in New Issue
Block a user