From 7d366ed989beb6397381759489cd8fe84c114fba Mon Sep 17 00:00:00 2001 From: Jaakko Heusala Date: Sun, 24 Aug 2025 16:25:46 +0300 Subject: [PATCH 1/2] Removed redudant repository check --- .github/workflows/pr.yml | 4 --- .github/workflows/task-or-bug.yml | 50 ++++++++++++++----------------- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 15b25d5..57c8d35 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -8,16 +8,12 @@ permissions: contents: read pull-requests: read -env: - TARGET_REPOSITORY: hyperifyio/goagent - concurrency: group: pr-${{ github.event.pull_request.number }}-dispatch cancel-in-progress: true jobs: dispatch: - if: ${{ !github.event.pull_request.head.repo.fork && github.repository == env.TARGET_REPOSITORY }} runs-on: ubuntu-latest steps: - name: Build payload diff --git a/.github/workflows/task-or-bug.yml b/.github/workflows/task-or-bug.yml index 5d450f8..38c7f07 100644 --- a/.github/workflows/task-or-bug.yml +++ b/.github/workflows/task-or-bug.yml @@ -15,23 +15,23 @@ permissions: contents: read issues: read +# Optional: set in Settings → Variables → Repository variables +# CODING_AGENT_USER = (leave empty to disable the assignee filter) env: - TARGET_REPOSITORY: hyperifyio/goagent CODING_AGENT_USER: ${{ vars.CODING_AGENT_USER }} concurrency: - group: coding-agent - cancel-in-progress: false + group: issue-${{ github.event.issue.number }}-dispatch + cancel-in-progress: true jobs: dispatch: - if: ${{ github.repository == env.TARGET_REPOSITORY }} runs-on: ubuntu-latest steps: - name: Determine issue type and assignment (GraphQL, with label fallback) id: meta env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # gh uses GH_TOKEN CODING_AGENT_USER: ${{ env.CODING_AGENT_USER }} run: | set -euo pipefail @@ -40,7 +40,7 @@ jobs: REPO="${GITHUB_REPOSITORY#*/}" NUMBER="${{ github.event.issue.number }}" - # Query metadata, including Issue Types, labels, and assignees + # Query: issue type, labels, assignees RESP="$(gh api graphql \ -H 'GraphQL-Features: issue_types' \ -f owner="$OWNER" \ @@ -63,7 +63,7 @@ jobs: TYPE="$(jq -r '.data.repository.issue.issueType.name // empty' <<< "$RESP")" if [[ -z "$TYPE" ]]; then - # Fallback to labels if Issue Types are not enabled/used + # Fallback: infer from labels if Issue Types are not enabled TYPE="$(jq -r ' [.data.repository.issue.labels.nodes[].name // empty | ascii_downcase] as $L @@ -73,13 +73,12 @@ jobs: ' <<< "$RESP")" fi - # Assignment filter + # Optional assignee filter RAW_AGENT="${CODING_AGENT_USER:-}" - # Strip leading @ and lowercase AGENT_CLEAN="$(tr -d '\n' <<< "${RAW_AGENT#@}" | tr '[:upper:]' '[:lower:]')" if [[ -z "$AGENT_CLEAN" ]]; then - ASSIGNED_OK="true" # no filter requested + ASSIGNED_OK="true" else ASSIGNED_OK="$( jq -r --arg agent "$AGENT_CLEAN" ' @@ -90,24 +89,20 @@ jobs: fi # Type filter - LOWER_TYPE="$(tr '[:upper:]' '[:lower:]' <<< "${TYPE}")" - case "$LOWER_TYPE" in + case "$(tr '[:upper:]' '[:lower:]' <<< "${TYPE}")" in bug|task) TYPE_OK="true" ;; *) TYPE_OK="false" ;; esac - # Final decision - if [[ "$TYPE_OK" == "true" && "$ASSIGNED_OK" == "true" ]]; then - SHOULD="true" - else - SHOULD="false" - fi + SHOULD=$([[ "$TYPE_OK" == "true" && "$ASSIGNED_OK" == "true" ]] && echo true || echo false) - echo "issue_type=${TYPE}" >> "$GITHUB_OUTPUT" - echo "assigned_ok=${ASSIGNED_OK}" >> "$GITHUB_OUTPUT" - echo "type_ok=${TYPE_OK}" >> "$GITHUB_OUTPUT" - echo "should_dispatch=${SHOULD}" >> "$GITHUB_OUTPUT" - echo "agent_user=${AGENT_CLEAN}" >> "$GITHUB_OUTPUT" + { + echo "issue_type=${TYPE}" + echo "assigned_ok=${ASSIGNED_OK}" + echo "type_ok=${TYPE_OK}" + echo "should_dispatch=${SHOULD}" + echo "agent_user=${AGENT_CLEAN}" + } >> "$GITHUB_OUTPUT" - name: Log & skip if not eligible if: ${{ steps.meta.outputs.should_dispatch != 'true' }} @@ -120,9 +115,9 @@ jobs: if: ${{ steps.meta.outputs.should_dispatch == 'true' }} id: payload env: - ISSUE_TYPE: ${{ steps.meta.outputs.issue_type }} - AGENT_USER: ${{ steps.meta.outputs.agent_user }} - ASSIGNED_OK: ${{ steps.meta.outputs.assigned_ok }} + ISSUE_TYPE: ${{ steps.meta.outputs.issue_type }} + AGENT_USER: ${{ steps.meta.outputs.agent_user }} + ASSIGNED_OK: ${{ steps.meta.outputs.assigned_ok }} run: | jq -n \ --arg repo "${{ github.repository }}" \ @@ -161,7 +156,8 @@ jobs: exit 1 fi - echo "::error title=Missing payload::payload.json was not created or is empty." + if [[ ! -s payload.json ]]; then + echo "::error title=Missing payload::payload.json was not created." exit 1 fi From 4e92038e0883e31d3e06310caa4c74b7c62a15d2 Mon Sep 17 00:00:00 2001 From: Jaakko Heusala Date: Sun, 24 Aug 2025 17:10:53 +0300 Subject: [PATCH 2/2] Fixed workflows --- .github/workflows/pr.yml | 37 +++++++++++------- .github/workflows/task-or-bug.yml | 62 +++++++++++++++---------------- 2 files changed, 53 insertions(+), 46 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 57c8d35..f2b203f 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,7 +14,13 @@ concurrency: jobs: dispatch: + # Require: internal actor, not a fork, and PR targets main (tweak branch if needed) + if: ${{ !github.event.pull_request.head.repo.fork + && contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.actor_association) + && github.event.pull_request.base.ref == 'main' }} runs-on: ubuntu-latest + timeout-minutes: 5 + steps: - name: Build payload id: payload @@ -32,37 +38,40 @@ jobs: head_repo:$head_repo,head_ref:$head_ref,base_ref:$base_ref}}' \ > payload.json - - name: Send repository_dispatch to aibuddy + - name: Preflight (token & target repo access) env: GH_TOKEN: ${{ secrets.AIBUDDY_DISPATCH_PAT }} run: | set -euo pipefail - # Secret present? + TARGET="hyperifyio/aibuddy" + if [[ -z "${GH_TOKEN:-}" ]]; then echo "::error title=Missing secret::AIBUDDY_DISPATCH_PAT is not set." exit 1 fi - # Payload present? - if [[ ! -s payload.json ]]; then - echo "::error title=Missing payload::payload.json was not created." + # Verify token can see the private repo; prints a helpful error otherwise + if ! gh api "repos/$TARGET" >/dev/null 2>err.txt; then + echo "::error title=Token cannot access target repo::$TARGET not accessible with provided token." + cat err.txt || true exit 1 fi - # Validate JSON if jq exists - if command -v jq >/dev/null 2>&1; then - jq -e . payload.json >/dev/null || { - echo "::error title=Invalid JSON payload::payload.json is not valid JSON" - cat payload.json - exit 1 - } + # Validate payload JSON + if [[ ! -s payload.json ]] || ! jq -e . payload.json >/dev/null; then + echo "::error title=Invalid payload::payload.json missing or not valid JSON" + [[ -f payload.json ]] && cat payload.json || true + exit 1 fi - # Dispatch (GitHub returns 204 No Content on success) + - name: Send repository_dispatch to aibuddy (gh api) + env: + GH_TOKEN: ${{ secrets.AIBUDDY_DISPATCH_PAT }} + run: | + set -euo pipefail gh api repos/hyperifyio/aibuddy/dispatches \ --method POST \ -H "Accept: application/vnd.github+json" \ --input payload.json - echo "repository_dispatch sent successfully." diff --git a/.github/workflows/task-or-bug.yml b/.github/workflows/task-or-bug.yml index 38c7f07..f41a24d 100644 --- a/.github/workflows/task-or-bug.yml +++ b/.github/workflows/task-or-bug.yml @@ -6,8 +6,6 @@ on: - opened - edited - reopened - - labeled - - unlabeled - assigned - unassigned @@ -26,12 +24,16 @@ concurrency: jobs: dispatch: + # Only members/maintainers/collaborators can trigger runs from a public repo + if: ${{ contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.actor_association) }} runs-on: ubuntu-latest + timeout-minutes: 5 + steps: - - name: Determine issue type and assignment (GraphQL, with label fallback) + - name: Determine issue type and assignment (Issue Types only) id: meta env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # gh uses GH_TOKEN + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # gh uses GH_TOKEN CODING_AGENT_USER: ${{ env.CODING_AGENT_USER }} run: | set -euo pipefail @@ -40,7 +42,7 @@ jobs: REPO="${GITHUB_REPOSITORY#*/}" NUMBER="${{ github.event.issue.number }}" - # Query: issue type, labels, assignees + # Query: issue type + assignees (no labels) RESP="$(gh api graphql \ -H 'GraphQL-Features: issue_types' \ -f owner="$OWNER" \ @@ -53,7 +55,6 @@ jobs: number title issueType { name } - labels(first: 50) { nodes { name } } assignees(first: 100) { nodes { login } } } } @@ -62,17 +63,6 @@ jobs: TYPE="$(jq -r '.data.repository.issue.issueType.name // empty' <<< "$RESP")" - if [[ -z "$TYPE" ]]; then - # Fallback: infer from labels if Issue Types are not enabled - TYPE="$(jq -r ' - [.data.repository.issue.labels.nodes[].name // empty - | ascii_downcase] as $L - | if ($L | index("bug")) then "Bug" - elif ($L | index("task")) then "Task" - else "" end - ' <<< "$RESP")" - fi - # Optional assignee filter RAW_AGENT="${CODING_AGENT_USER:-}" AGENT_CLEAN="$(tr -d '\n' <<< "${RAW_AGENT#@}" | tr '[:upper:]' '[:lower:]')" @@ -88,7 +78,7 @@ jobs: )" fi - # Type filter + # Type filter: only "Task" or "Bug" case "$(tr '[:upper:]' '[:lower:]' <<< "${TYPE}")" in bug|task) TYPE_OK="true" ;; *) TYPE_OK="false" ;; @@ -108,8 +98,9 @@ jobs: if: ${{ steps.meta.outputs.should_dispatch != 'true' }} run: | echo "Issue #${{ github.event.issue.number }} not eligible for dispatch." - echo " Detected type: '${{ steps.meta.outputs.issue_type }}' (type_ok=${{ steps.meta.outputs.type_ok }})" - echo " CODING_AGENT_USER='${{ steps.meta.outputs.agent_user }}' assigned_ok=${{ steps.meta.outputs.assigned_ok }}" + echo " issue_type='${{ steps.meta.outputs.issue_type }}' (type_ok=${{ steps.meta.outputs.type_ok }})" + echo " assigned_ok=${{ steps.meta.outputs.assigned_ok }} agent='${{ steps.meta.outputs.agent_user }}'" + echo " Note: This workflow requires GitHub Issue Types ('Task' or 'Bug')." - name: Build payload if: ${{ steps.meta.outputs.should_dispatch == 'true' }} @@ -142,36 +133,43 @@ jobs: assigned_ok:$assigned_ok }}' \ > payload.json - echo "payload=$(cat payload.json)" >> "$GITHUB_OUTPUT" - - name: Send repository_dispatch to aibuddy (gh api) + - name: Preflight (token & target repo access) if: ${{ steps.meta.outputs.should_dispatch == 'true' }} env: GH_TOKEN: ${{ secrets.AIBUDDY_DISPATCH_PAT }} run: | set -euo pipefail + TARGET="hyperifyio/aibuddy" if [[ -z "${GH_TOKEN:-}" ]]; then echo "::error title=Missing secret::AIBUDDY_DISPATCH_PAT is not set." exit 1 fi - if [[ ! -s payload.json ]]; then - echo "::error title=Missing payload::payload.json was not created." + # Verify token can access the private repo + if ! gh api "repos/$TARGET" >/dev/null 2>err.txt; then + echo "::error title=Token cannot access target repo::$TARGET not accessible with provided token." + cat err.txt || true exit 1 fi - if command -v jq >/dev/null 2>&1; then - jq -e . payload.json >/dev/null || { - echo "::error title=Invalid JSON payload::payload.json is not valid JSON" - cat payload.json - exit 1 - } - fi + # Validate payload JSON + jq -e . payload.json >/dev/null || { + echo "::error title=Invalid payload::payload.json is not valid JSON" + cat payload.json + exit 1 + } + - name: Send repository_dispatch to aibuddy (gh api) + if: ${{ steps.meta.outputs.should_dispatch == 'true' }} + env: + GH_TOKEN: ${{ secrets.AIBUDDY_DISPATCH_PAT }} + run: | + set -euo pipefail gh api repos/hyperifyio/aibuddy/dispatches \ --method POST \ -H "Accept: application/vnd.github+json" \ --input payload.json - echo "repository_dispatch sent for issue #${{ github.event.issue.number }} (type=${{ steps.meta.outputs.issue_type }}, agent='${{ steps.meta.outputs.agent_user }}')" +