66 - opened
77 - edited
88 - reopened
9- - labeled
10- - unlabeled
119 - assigned
1210 - unassigned
1311
1412permissions :
1513 contents : read
1614 issues : read
1715
16+ # Optional: set in Settings → Variables → Repository variables
17+ # CODING_AGENT_USER = <agent-gh-handle> (leave empty to disable the assignee filter)
1818env :
19- TARGET_REPOSITORY : hyperifyio/goagent
2019 CODING_AGENT_USER : ${{ vars.CODING_AGENT_USER }}
2120
2221concurrency :
23- group : coding-agent
24- cancel-in-progress : false
22+ group : issue-${{ github.event.issue.number }}-dispatch
23+ cancel-in-progress : true
2524
2625jobs :
2726 dispatch :
28- if : ${{ github.repository == env.TARGET_REPOSITORY }}
27+ # Only members/maintainers/collaborators can trigger runs from a public repo
28+ if : ${{ contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.actor_association) }}
2929 runs-on : ubuntu-latest
30+ timeout-minutes : 5
31+
3032 steps :
31- - name : Determine issue type and assignment (GraphQL, with label fallback )
33+ - name : Determine issue type and assignment (Issue Types only )
3234 id : meta
3335 env :
34- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
36+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }} # gh uses GH_TOKEN
3537 CODING_AGENT_USER : ${{ env.CODING_AGENT_USER }}
3638 run : |
3739 set -euo pipefail
4042 REPO="${GITHUB_REPOSITORY#*/}"
4143 NUMBER="${{ github.event.issue.number }}"
4244
43- # Query metadata, including Issue Types, labels, and assignees
45+ # Query: issue type + assignees (no labels)
4446 RESP="$(gh api graphql \
4547 -H 'GraphQL-Features: issue_types' \
4648 -f owner="$OWNER" \
5355 number
5456 title
5557 issueType { name }
56- labels(first: 50) { nodes { name } }
5758 assignees(first: 100) { nodes { login } }
5859 }
5960 }
@@ -62,24 +63,12 @@ jobs:
6263
6364 TYPE="$(jq -r '.data.repository.issue.issueType.name // empty' <<< "$RESP")"
6465
65- if [[ -z "$TYPE" ]]; then
66- # Fallback to labels if Issue Types are not enabled/used
67- TYPE="$(jq -r '
68- [.data.repository.issue.labels.nodes[].name // empty
69- | ascii_downcase] as $L
70- | if ($L | index("bug")) then "Bug"
71- elif ($L | index("task")) then "Task"
72- else "" end
73- ' <<< "$RESP")"
74- fi
75-
76- # Assignment filter
66+ # Optional assignee filter
7767 RAW_AGENT="${CODING_AGENT_USER:-}"
78- # Strip leading @ and lowercase
7968 AGENT_CLEAN="$(tr -d '\n' <<< "${RAW_AGENT#@}" | tr '[:upper:]' '[:lower:]')"
8069
8170 if [[ -z "$AGENT_CLEAN" ]]; then
82- ASSIGNED_OK="true" # no filter requested
71+ ASSIGNED_OK="true"
8372 else
8473 ASSIGNED_OK="$(
8574 jq -r --arg agent "$AGENT_CLEAN" '
@@ -89,40 +78,37 @@ jobs:
8978 )"
9079 fi
9180
92- # Type filter
93- LOWER_TYPE="$(tr '[:upper:]' '[:lower:]' <<< "${TYPE}")"
94- case "$LOWER_TYPE" in
81+ # Type filter: only "Task" or "Bug"
82+ case "$(tr '[:upper:]' '[:lower:]' <<< "${TYPE}")" in
9583 bug|task) TYPE_OK="true" ;;
9684 *) TYPE_OK="false" ;;
9785 esac
9886
99- # Final decision
100- if [[ "$TYPE_OK" == "true" && "$ASSIGNED_OK" == "true" ]]; then
101- SHOULD="true"
102- else
103- SHOULD="false"
104- fi
87+ SHOULD=$([[ "$TYPE_OK" == "true" && "$ASSIGNED_OK" == "true" ]] && echo true || echo false)
10588
106- echo "issue_type=${TYPE}" >> "$GITHUB_OUTPUT"
107- echo "assigned_ok=${ASSIGNED_OK}" >> "$GITHUB_OUTPUT"
108- echo "type_ok=${TYPE_OK}" >> "$GITHUB_OUTPUT"
109- echo "should_dispatch=${SHOULD}" >> "$GITHUB_OUTPUT"
110- echo "agent_user=${AGENT_CLEAN}" >> "$GITHUB_OUTPUT"
89+ {
90+ echo "issue_type=${TYPE}"
91+ echo "assigned_ok=${ASSIGNED_OK}"
92+ echo "type_ok=${TYPE_OK}"
93+ echo "should_dispatch=${SHOULD}"
94+ echo "agent_user=${AGENT_CLEAN}"
95+ } >> "$GITHUB_OUTPUT"
11196
11297 - name : Log & skip if not eligible
11398 if : ${{ steps.meta.outputs.should_dispatch != 'true' }}
11499 run : |
115100 echo "Issue #${{ github.event.issue.number }} not eligible for dispatch."
116- echo " Detected type: '${{ steps.meta.outputs.issue_type }}' (type_ok=${{ steps.meta.outputs.type_ok }})"
117- echo " CODING_AGENT_USER='${{ steps.meta.outputs.agent_user }}' assigned_ok=${{ steps.meta.outputs.assigned_ok }}"
101+ echo " issue_type='${{ steps.meta.outputs.issue_type }}' (type_ok=${{ steps.meta.outputs.type_ok }})"
102+ echo " assigned_ok=${{ steps.meta.outputs.assigned_ok }} agent='${{ steps.meta.outputs.agent_user }}'"
103+ echo " Note: This workflow requires GitHub Issue Types ('Task' or 'Bug')."
118104
119105 - name : Build payload
120106 if : ${{ steps.meta.outputs.should_dispatch == 'true' }}
121107 id : payload
122108 env :
123- ISSUE_TYPE : ${{ steps.meta.outputs.issue_type }}
124- AGENT_USER : ${{ steps.meta.outputs.agent_user }}
125- ASSIGNED_OK : ${{ steps.meta.outputs.assigned_ok }}
109+ ISSUE_TYPE : ${{ steps.meta.outputs.issue_type }}
110+ AGENT_USER : ${{ steps.meta.outputs.agent_user }}
111+ ASSIGNED_OK : ${{ steps.meta.outputs.assigned_ok }}
126112 run : |
127113 jq -n \
128114 --arg repo "${{ github.repository }}" \
@@ -147,35 +133,43 @@ jobs:
147133 assigned_ok:$assigned_ok
148134 }}' \
149135 > payload.json
150- echo "payload=$(cat payload.json)" >> "$GITHUB_OUTPUT"
151136
152- - name : Send repository_dispatch to aibuddy (gh api )
137+ - name : Preflight (token & target repo access )
153138 if : ${{ steps.meta.outputs.should_dispatch == 'true' }}
154139 env :
155140 GH_TOKEN : ${{ secrets.AIBUDDY_DISPATCH_PAT }}
156141 run : |
157142 set -euo pipefail
143+ TARGET="hyperifyio/aibuddy"
158144
159145 if [[ -z "${GH_TOKEN:-}" ]]; then
160146 echo "::error title=Missing secret::AIBUDDY_DISPATCH_PAT is not set."
161147 exit 1
162148 fi
163149
164- echo "::error title=Missing payload::payload.json was not created or is empty."
150+ # Verify token can access the private repo
151+ if ! gh api "repos/$TARGET" >/dev/null 2>err.txt; then
152+ echo "::error title=Token cannot access target repo::$TARGET not accessible with provided token."
153+ cat err.txt || true
165154 exit 1
166155 fi
167156
168- if command -v jq >/dev/null 2>&1; then
169- jq -e . payload.json >/dev/null || {
170- echo "::error title=Invalid JSON payload::payload.json is not valid JSON"
171- cat payload.json
172- exit 1
173- }
174- fi
157+ # Validate payload JSON
158+ jq -e . payload.json >/dev/null || {
159+ echo "::error title=Invalid payload::payload.json is not valid JSON"
160+ cat payload.json
161+ exit 1
162+ }
175163
164+ - name : Send repository_dispatch to aibuddy (gh api)
165+ if : ${{ steps.meta.outputs.should_dispatch == 'true' }}
166+ env :
167+ GH_TOKEN : ${{ secrets.AIBUDDY_DISPATCH_PAT }}
168+ run : |
169+ set -euo pipefail
176170 gh api repos/hyperifyio/aibuddy/dispatches \
177171 --method POST \
178172 -H "Accept: application/vnd.github+json" \
179173 --input payload.json
180-
181174 echo "repository_dispatch sent for issue #${{ github.event.issue.number }} (type=${{ steps.meta.outputs.issue_type }}, agent='${{ steps.meta.outputs.agent_user }}')"
175+
0 commit comments