1- #! /bin/bash
1+ #! /usr/bin/env bash
2+ # chmod +x .github/scripts/bot-advanced-check.sh
3+ # REPO=hiero-ledger/hiero-sdk-python \
4+ # DRY_RUN=true \
5+ # DRY_RUN_USER=abc \
6+ # .github/scripts/bot-advanced-check.sh
7+
28set -euo pipefail
39
4- # 1. Define Helper Functions First
10+ # ######################################
11+ # Logging helper
12+ # ######################################
513log () {
614 echo " [advanced-check] $1 "
715}
816
9- # 2. Validate required environment variables
10- if [[ -z " ${REPO:- } " ]] || [[ -z " ${ISSUE_NUMBER:- } " ]] || [[ -z " ${GH_TOKEN:- } " ]]; then
11- log " ERROR: Required environment variables (REPO, ISSUE_NUMBER, GH_TOKEN) must be set"
17+ # ######################################
18+ # Validate required environment variables
19+ # ######################################
20+ if [[ -z " ${REPO:- } " ]]; then
21+ log " ERROR: REPO must be set (e.g. owner/name)"
22+ exit 1
23+ fi
24+
25+ OWNER=" ${REPO%%/* } "
26+ NAME=" ${REPO##*/ } "
27+
28+ # ######################################
29+ # GraphQL count helper (INTERMEDIATE ONLY)
30+ # ######################################
31+ get_intermediate_count () {
32+ local user=$1
33+
34+ gh api graphql -f query="
35+ {
36+ repository(owner: \" $OWNER \" , name: \" $NAME \" ) {
37+ intermediate: issues(
38+ first: 1
39+ states: CLOSED
40+ filterBy: {
41+ assignee: \" $user \"
42+ labels: [\" intermediate\" ]
43+ }
44+ ) {
45+ totalCount
46+ }
47+ }
48+ }"
49+ }
50+
51+ # ######################################
52+ # DRY RUN MODE
53+ # ######################################
54+ if [[ " ${DRY_RUN:- false} " == " true" ]]; then
55+ if [[ -z " ${DRY_RUN_USER:- } " ]]; then
56+ log " ERROR: DRY_RUN_USER must be set when DRY_RUN=true"
57+ exit 1
58+ fi
59+
60+ USER=" $DRY_RUN_USER "
61+ log " DRY RUN MODE ENABLED"
62+ log " Repository: $REPO "
63+ log " User: @$USER "
64+
65+ COUNTS=$( get_intermediate_count " $USER " )
66+ INT_COUNT=$( jq ' .data.repository.intermediate.totalCount' <<< " $COUNTS" )
67+
68+ echo
69+ log " Intermediate Issues (closed): $INT_COUNT "
70+
71+ if (( INT_COUNT >= 1 )) ; then
72+ log " Result: USER QUALIFIED"
73+ else
74+ log " Result: USER NOT QUALIFIED"
75+ fi
76+
77+ exit 0
78+ fi
79+
80+ # ######################################
81+ # NORMAL MODE (ENFORCEMENT)
82+ # ######################################
83+ if [[ -z " ${ISSUE_NUMBER:- } " ]]; then
84+ log " ERROR: ISSUE_NUMBER must be set in normal mode"
1285 exit 1
1386fi
1487
15- # 3. Function to check a single user
88+ # ######################################
89+ # Check a single user
90+ # ######################################
1691check_user () {
1792 local user=$1
1893 log " Checking qualification for @$user ..."
1994
2095 # Permission exemption
21- PERM_JSON=$( gh api " repos/$REPO /collaborators/$user /permission" 2> /dev/null || echo ' {"permission":"none"}' )
22- PERMISSION=$( echo " $PERM_JSON " | jq -r ' .permission // "none"' )
96+ PERMISSION=$(
97+ gh api " repos/$REPO /collaborators/$user /permission" \
98+ --jq ' .permission // "none"' 2> /dev/null || echo " none"
99+ )
23100
24101 if [[ " $PERMISSION " =~ ^(admin| write| triage)$ ]]; then
25- log " User @$user is core member ($PERMISSION ). Qualification check skipped ."
102+ log " User @$user is core member ($PERMISSION ). Skipping ."
26103 return 0
27104 fi
28105
29- # 2. Get counts
30- # Using exact repository label names ("Good First Issue" and "intermediate")
31- GFI_QUERY=" repo:$REPO is:issue is:closed assignee:$user -reason:\" not planned\" label:\" Good First Issue\" "
32- INT_QUERY=" repo:$REPO is:issue is:closed assignee:$user -reason:\" not planned\" label:\" intermediate\" "
33-
34- GFI_COUNT=$( gh api " search/issues" -f q=" $GFI_QUERY " --jq ' .total_count' || echo " 0" )
35- INT_COUNT=$( gh api " search/issues" -f q=" $INT_QUERY " --jq ' .total_count' || echo " 0" )
106+ COUNTS=$( get_intermediate_count " $user " )
107+ INT_COUNT=$( jq ' .data.repository.intermediate.totalCount' <<< " $COUNTS" )
36108
37- # Numeric validation
38- if ! [[ " $GFI_COUNT " =~ ^[0-9]+$ ]]; then GFI_COUNT=0; fi
39- if ! [[ " $INT_COUNT " =~ ^[0-9]+$ ]]; then INT_COUNT=0; fi
109+ log " Counts → Intermediate: $INT_COUNT "
40110
41- # Validation Logic
42- if (( GFI_COUNT >= 1 )) && (( INT_COUNT >= 1 )) ; then
111+ if (( INT_COUNT >= 1 )) ; then
43112 log " User @$user qualified."
44113 return 0
45- else
46- log " User @$user failed. Unassigning..."
114+ fi
115+
116+ # ##################################
117+ # Failure path
118+ # ##################################
119+ log " User @$user NOT qualified. Unassigning."
47120
48- # Tailor the suggestion based on what is missing
49- # Links and names now match exact repository labels
50- if (( GFI_COUNT == 0 )) ; then
51- SUGGESTION=" [Good First Issue](https://github.com/$REPO /labels/Good%20First%20Issue)"
52- else
53- SUGGESTION=" [intermediate issue](https://github.com/$REPO /labels/intermediate)"
54- fi
121+ SUGGESTION=" [intermediate issues](https://github.com/$REPO /labels/intermediate)"
55122
56- # Post the message FIRST, then unassign.
57- MSG=" Hi @$user , I cannot assign you to this issue yet.
123+ MSG=" Hi @$user , I cannot assign you to this issue yet.
58124
59125**Why?**
60- Advanced issues involve high-risk changes to the core codebase. They require significant testing and can impact automation and CI behavior .
126+ Advanced issues involve high-risk changes to the core codebase and require prior experience in this repository .
61127
62128**Requirement:**
63- - Complete at least **1** 'Good First Issue' (You have: **$GFI_COUNT **)
64129- Complete at least **1** 'intermediate' issue (You have: **$INT_COUNT **)
65130
66- Please check out our **$SUGGESTION ** tasks to build your experience first!"
131+ Please check out our **$SUGGESTION ** to build your experience first!"
67132
68- gh issue comment " $ISSUE_NUMBER " --repo " $REPO " --body " $MSG "
69- gh issue edit " $ISSUE_NUMBER " --repo " $REPO " --remove-assignee " $user "
70- fi
133+ gh issue comment " $ISSUE_NUMBER " --repo " $REPO " --body " $MSG "
134+ gh issue edit " $ISSUE_NUMBER " --repo " $REPO " --remove-assignee " $user "
71135}
72136
73- # --- Main Logic ---
137+ # ######################################
138+ # Main execution
139+ # ######################################
140+ log " Normal enforcement mode enabled"
141+ log " Repository: $REPO "
142+ log " Issue: #$ISSUE_NUMBER "
74143
75144if [[ -n " ${TRIGGER_ASSIGNEE:- } " ]]; then
76145 check_user " $TRIGGER_ASSIGNEE "
77146else
78- log " Checking all current assignees..."
79-
80- # Fetch assignees into a variable first.
81- ASSIGNEE_LIST=$( gh issue view " $ISSUE_NUMBER " --repo " $REPO " --json assignees --jq ' .assignees[].login' )
147+ log " Checking all assignees..."
82148
83- if [[ -z " $ASSIGNEE_LIST " ]]; then
84- log " No assignees found to check."
85- else
86- # Use a here-string (<<<) to iterate over the variable safely.
87- while read -r user; do
88- if [[ -n " $user " ]]; then
89- check_user " $user "
90- fi
91- done <<< " $ASSIGNEE_LIST"
149+ ASSIGNEES=$(
150+ gh issue view " $ISSUE_NUMBER " --repo " $REPO " \
151+ --json assignees --jq ' .assignees[].login'
152+ )
153+
154+ if [[ -z " $ASSIGNEES " ]]; then
155+ log " No assignees found."
156+ exit 0
92157 fi
93- fi
158+
159+ while read -r user; do
160+ [[ -n " $user " ]] && check_user " $user "
161+ done <<< " $ASSIGNEES"
162+ fi
0 commit comments