Skip to content

Commit e750645

Browse files
authored
Add gh.sh wrapper for gh CLI commands in workflows (#975)
1 parent cd4b150 commit e750645

File tree

3 files changed

+106
-13
lines changed

3 files changed

+106
-13
lines changed

.claude/commands/label-issue.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
allowed-tools: Bash(gh label list:*),Bash(gh issue view:*),Bash(./scripts/edit-issue-labels.sh:*),Bash(gh search issues:*)
2+
allowed-tools: Bash(./scripts/gh.sh:*),Bash(./scripts/edit-issue-labels.sh:*)
33
description: Apply labels to GitHub issues
44
---
55

@@ -14,17 +14,18 @@ Issue Information:
1414

1515
TASK OVERVIEW:
1616

17-
1. First, fetch the list of labels available in this repository by running: `gh label list`. Run exactly this command with nothing else.
17+
1. First, fetch the list of labels available in this repository by running: `./scripts/gh.sh label list`. Run exactly this command with nothing else.
1818

19-
2. Next, use gh commands to get context about the issue:
19+
2. Next, use gh wrapper commands to get context about the issue:
2020

21-
- Use `gh issue view ${{ github.event.issue.number }}` to retrieve the current issue's details
22-
- Use `gh search issues` to find similar issues that might provide context for proper categorization
23-
- You have access to these Bash commands:
24-
- Bash(gh label list:\*) - to get available labels
25-
- Bash(gh issue view:\*) - to view issue details
26-
- Bash(./scripts/edit-issue-labels.sh:\*) - to apply labels to the issue
27-
- Bash(gh search issues:\*) - to search for similar issues
21+
- Use `./scripts/gh.sh issue view ${{ github.event.issue.number }}` to retrieve the current issue's details
22+
- Use `./scripts/gh.sh search issues` to find similar issues that might provide context for proper categorization
23+
- `./scripts/gh.sh` is a wrapper for `gh` CLI. Example commands:
24+
- `./scripts/gh.sh label list` — fetch all available labels
25+
- `./scripts/gh.sh issue view 123` — view issue details
26+
- `./scripts/gh.sh issue view 123 --comments` — view with comments
27+
- `./scripts/gh.sh search issues "query" --limit 10` — search for issues
28+
- `./scripts/edit-issue-labels.sh` — apply labels to the issue
2829

2930
3. Analyze the issue content, considering:
3031

@@ -39,9 +40,9 @@ TASK OVERVIEW:
3940

4041
- Choose labels that accurately reflect the issue's nature
4142
- Be specific but comprehensive
42-
- IMPORTANT: Add a priority label (P1, P2, or P3) based on the label descriptions from gh label list
43+
- IMPORTANT: Add a priority label (P1, P2, or P3) based on the label descriptions from ./scripts/gh.sh label list
4344
- Consider platform labels (android, ios) if applicable
44-
- If you find similar issues using gh search, consider using a "duplicate" label if appropriate. Only do so if the issue is a duplicate of another OPEN issue.
45+
- If you find similar issues using ./scripts/gh.sh search, consider using a "duplicate" label if appropriate. Only do so if the issue is a duplicate of another OPEN issue.
4546

4647
5. Apply the selected labels:
4748
- Use `./scripts/edit-issue-labels.sh --issue NUMBER --add-label LABEL1 --add-label LABEL2` to apply your selected labels

docs/solutions.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ jobs:
398398
issues: write
399399
id-token: write
400400
steps:
401+
- uses: actions/checkout@v4
401402
- uses: anthropics/claude-code-action@v1
402403
with:
403404
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
@@ -414,20 +415,26 @@ jobs:
414415
3. Suggest appropriate labels
415416
4. Check if it duplicates existing issues
416417
418+
Use ./scripts/gh.sh to interact with GitHub:
419+
- `./scripts/gh.sh issue view [number]` to view the issue
420+
- `./scripts/gh.sh search issues "query"` to find similar issues
421+
- `./scripts/gh.sh label list` to see available labels
422+
417423
Based on your analysis, add the appropriate labels using:
418424
`./scripts/edit-issue-labels.sh --issue [number] --add-label "label1" --add-label "label2"`
419425

420426
If it appears to be a duplicate, post a comment mentioning the original issue.
421427

422428
claude_args: |
423-
--allowedTools "Bash(gh issue view:*),Bash(gh search issues:*),Bash(./scripts/edit-issue-labels.sh:*)"
429+
--allowedTools "Bash(./scripts/gh.sh:*),Bash(./scripts/edit-issue-labels.sh:*)"
424430
```
425431
426432
**Key Configuration:**
427433
428434
- Triggered on new issues
429435
- Issue context in prompt
430436
- Label management capabilities
437+
- Requires `scripts/gh.sh` and `scripts/edit-issue-labels.sh` in your repo (see this repo's `scripts/` directory for examples)
431438

432439
**Expected Output:** Automatically labeled and categorized issues.
433440

scripts/gh.sh

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Wrapper around gh CLI that only allows specific subcommands and flags.
5+
# All commands are scoped to the current repository via GH_REPO or GITHUB_REPOSITORY.
6+
#
7+
# Usage:
8+
# ./scripts/gh.sh issue view 123
9+
# ./scripts/gh.sh issue view 123 --comments
10+
# ./scripts/gh.sh issue list --state open --limit 20
11+
# ./scripts/gh.sh search issues "search query" --limit 10
12+
# ./scripts/gh.sh label list --limit 100
13+
14+
ALLOWED_FLAGS=(--comments --state --limit --label)
15+
FLAGS_WITH_VALUES=(--state --limit --label)
16+
17+
SUB1="${1:-}"
18+
SUB2="${2:-}"
19+
CMD="$SUB1 $SUB2"
20+
case "$CMD" in
21+
"issue view"|"issue list"|"search issues"|"label list")
22+
;;
23+
*)
24+
exit 1
25+
;;
26+
esac
27+
28+
shift 2
29+
30+
# Separate flags from positional arguments
31+
POSITIONAL=()
32+
FLAGS=()
33+
skip_next=false
34+
for arg in "$@"; do
35+
if [[ "$skip_next" == true ]]; then
36+
FLAGS+=("$arg")
37+
skip_next=false
38+
elif [[ "$arg" == -* ]]; then
39+
flag="${arg%%=*}"
40+
matched=false
41+
for allowed in "${ALLOWED_FLAGS[@]}"; do
42+
if [[ "$flag" == "$allowed" ]]; then
43+
matched=true
44+
break
45+
fi
46+
done
47+
if [[ "$matched" == false ]]; then
48+
exit 1
49+
fi
50+
FLAGS+=("$arg")
51+
# If flag expects a value and isn't using = syntax, skip next arg
52+
if [[ "$arg" != *=* ]]; then
53+
for vflag in "${FLAGS_WITH_VALUES[@]}"; do
54+
if [[ "$flag" == "$vflag" ]]; then
55+
skip_next=true
56+
break
57+
fi
58+
done
59+
fi
60+
else
61+
POSITIONAL+=("$arg")
62+
fi
63+
done
64+
65+
REPO="${GH_REPO:-${GITHUB_REPOSITORY:-}}"
66+
67+
if [[ "$CMD" == "search issues" ]]; then
68+
if [[ -z "$REPO" ]]; then
69+
exit 1
70+
fi
71+
QUERY="${POSITIONAL[0]:-}"
72+
QUERY_LOWER=$(echo "$QUERY" | tr '[:upper:]' '[:lower:]')
73+
if [[ "$QUERY_LOWER" == *"repo:"* || "$QUERY_LOWER" == *"org:"* || "$QUERY_LOWER" == *"user:"* ]]; then
74+
exit 1
75+
fi
76+
gh "$SUB1" "$SUB2" "$QUERY" --repo "$REPO" "${FLAGS[@]}"
77+
else
78+
# Reject URLs in positional args to prevent cross-repo access
79+
for pos in "${POSITIONAL[@]}"; do
80+
if [[ "$pos" == http://* || "$pos" == https://* ]]; then
81+
exit 1
82+
fi
83+
done
84+
gh "$SUB1" "$SUB2" "${POSITIONAL[@]}" "${FLAGS[@]}"
85+
fi

0 commit comments

Comments
 (0)