Skip to content

Commit 9775288

Browse files
visigothclaude
andcommitted
feat: add --limit flag to control max issues imported
Adds a --limit <n> flag to ralph-enable and ralph-enable-ci that controls the maximum number of issues fetched from any source. Default is 0 (all issues), which fixes the previous behavior where bd list silently capped at 50 items and gh issue list at 50. The limit is threaded through fetch_beads_tasks, fetch_github_tasks, get_beads_count, and import_tasks_from_sources. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e13a3cb commit 9775288

4 files changed

Lines changed: 204 additions & 31 deletions

File tree

lib/task_sources.sh

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ check_beads_available() {
3131
#
3232
# Parameters:
3333
# $1 (filterStatus) - Status filter (optional, default: "open")
34+
# $2 (limit) - Max issues to fetch (optional, default: "0" = all)
3435
#
3536
# Outputs:
3637
# Tasks in markdown checkbox format, one per line
@@ -42,6 +43,7 @@ check_beads_available() {
4243
#
4344
fetch_beads_tasks() {
4445
local filterStatus="${1:-open}"
46+
local limit="${2:-0}"
4547
local tasks=""
4648

4749
# Check if beads is available
@@ -50,7 +52,7 @@ fetch_beads_tasks() {
5052
fi
5153

5254
# Build bd list command arguments
53-
local bdArgs=("list" "--json")
55+
local bdArgs=("list" "--json" "--limit" "$limit")
5456
if [[ "$filterStatus" == "open" ]]; then
5557
bdArgs+=("--status" "open")
5658
elif [[ "$filterStatus" == "in_progress" ]]; then
@@ -78,7 +80,7 @@ fetch_beads_tasks() {
7880
# Fallback: try plain text output if JSON failed or produced no results
7981
if [[ -z "$tasks" ]]; then
8082
# Build fallback args (reuse status logic, but without --json)
81-
local fallbackArgs=("list")
83+
local fallbackArgs=("list" "--limit" "$limit")
8284
if [[ "$filterStatus" == "open" ]]; then
8385
fallbackArgs+=("--status" "open")
8486
elif [[ "$filterStatus" == "in_progress" ]]; then
@@ -109,11 +111,16 @@ fetch_beads_tasks() {
109111
110112
# get_beads_count - Get count of open beads issues
111113
#
114+
# Parameters:
115+
# $1 (limit) - Max issues to fetch (optional, default: "0" = all)
116+
#
112117
# Returns:
113118
# 0 and echoes the count
114119
# 1 if beads unavailable
115120
#
116121
get_beads_count() {
122+
local limit="${1:-0}"
123+
117124
if ! check_beads_available; then
118125
echo "0"
119126
return 1
@@ -122,9 +129,9 @@ get_beads_count() {
122129
local count
123130
if command -v jq &>/dev/null; then
124131
# Note: Use 'select(.status == "closed" | not)' to avoid bash escaping issues with '!='
125-
count=$(bd list --json 2>/dev/null | jq '[.[] | select(.status == "closed" | not)] | length' 2>/dev/null || echo "0")
132+
count=$(bd list --json --limit "$limit" 2>/dev/null | jq '[.[] | select(.status == "closed" | not)] | length' 2>/dev/null || echo "0")
126133
else
127-
count=$(bd list 2>/dev/null | wc -l | tr -d ' ')
134+
count=$(bd list --limit "$limit" 2>/dev/null | wc -l | tr -d ' ')
128135
fi
129136
130137
echo "${count:-0}"
@@ -163,8 +170,8 @@ check_github_available() {
163170
# fetch_github_tasks - Fetch issues from GitHub
164171
#
165172
# Parameters:
166-
# $1 (label) - Label to filter by (optional, default: "ralph-task")
167-
# $2 (limit) - Maximum number of issues (optional, default: 50)
173+
# $1 (label) - Label to filter by (optional)
174+
# $2 (limit) - Maximum number of issues (optional, default: "0" = all)
168175
#
169176
# Outputs:
170177
# Tasks in markdown checkbox format
@@ -174,34 +181,58 @@ check_github_available() {
174181
# 0 - Success
175182
# 1 - Error
176183
#
184+
# Note:
185+
# `gh issue list --limit` enforces a hard cap of 1000 regardless of the
186+
# value supplied. When limit=0 ("all"), we fall back to `gh api --paginate`
187+
# against the issues endpoint so large repos are not silently truncated.
188+
# The issues endpoint returns pull requests as well, so those are filtered
189+
# out via `.pull_request | not`.
190+
#
177191
fetch_github_tasks() {
178192
local label="${1:-}"
179-
local limit="${2:-50}"
193+
local limit="${2:-0}"
180194
local tasks=""
195+
local json_output
181196
182197
# Check if GitHub is available
183198
if ! check_github_available; then
184199
return 1
185200
fi
186201
187-
# Build gh command
188-
local gh_args=("issue" "list" "--state" "open" "--limit" "$limit" "--json" "number,title,labels")
189-
if [[ -n "$label" ]]; then
190-
gh_args+=("--label" "$label")
191-
fi
192-
193-
# Fetch issues
194-
local json_output
195-
if ! json_output=$(gh "${gh_args[@]}" 2>/dev/null); then
196-
return 1
197-
fi
198-
199-
# Parse JSON and format as markdown tasks
200-
if command -v jq &>/dev/null; then
201-
tasks=$(echo "$json_output" | jq -r '
202-
.[] |
203-
"- [ ] [#\(.number)] \(.title)"
204-
' 2>/dev/null)
202+
if [[ "$limit" == "0" ]]; then
203+
# Fetch all open issues via the REST API with automatic pagination.
204+
# `-f` passes URL-encoded string fields so labels with spaces or
205+
# special characters are handled correctly.
206+
local api_args=("api" "--method" "GET" "repos/{owner}/{repo}/issues"
207+
"-f" "state=open" "-f" "per_page=100" "--paginate")
208+
if [[ -n "$label" ]]; then
209+
api_args+=("-f" "labels=$label")
210+
fi
211+
if ! json_output=$(gh "${api_args[@]}" 2>/dev/null); then
212+
return 1
213+
fi
214+
# Parse and format, filtering out pull requests
215+
if command -v jq &>/dev/null; then
216+
tasks=$(echo "$json_output" | jq -r '
217+
.[] | select(.pull_request | not) |
218+
"- [ ] [#\(.number)] \(.title)"
219+
' 2>/dev/null)
220+
fi
221+
else
222+
# Bounded fetch via `gh issue list` which already excludes PRs
223+
local gh_args=("issue" "list" "--state" "open" "--limit" "$limit" "--json" "number,title,labels")
224+
if [[ -n "$label" ]]; then
225+
gh_args+=("--label" "$label")
226+
fi
227+
if ! json_output=$(gh "${gh_args[@]}" 2>/dev/null); then
228+
return 1
229+
fi
230+
if command -v jq &>/dev/null; then
231+
tasks=$(echo "$json_output" | jq -r '
232+
.[] |
233+
"- [ ] [#\(.number)] \(.title)"
234+
' 2>/dev/null)
235+
fi
205236
fi
206237
207238
if [[ -n "$tasks" ]]; then
@@ -490,6 +521,7 @@ prioritize_tasks() {
490521
# $1 (sources) - Space-separated list of sources: beads, github, prd
491522
# $2 (prd_file) - Path to PRD file (required if prd in sources)
492523
# $3 (github_label) - GitHub label filter (optional)
524+
# $4 (limit) - Max issues to fetch per source (optional, default: "0" = all)
493525
#
494526
# Outputs:
495527
# Combined tasks in markdown format
@@ -502,14 +534,15 @@ import_tasks_from_sources() {
502534
local sources=$1
503535
local prd_file="${2:-}"
504536
local github_label="${3:-}"
537+
local limit="${4:-0}"
505538
506539
local all_tasks=""
507540
local source_count=0
508541
509542
# Import from beads
510543
if echo "$sources" | grep -qw "beads"; then
511544
local beads_tasks
512-
if beads_tasks=$(fetch_beads_tasks); then
545+
if beads_tasks=$(fetch_beads_tasks "open" "$limit"); then
513546
if [[ -n "$beads_tasks" ]]; then
514547
all_tasks="${all_tasks}
515548
# Tasks from beads
@@ -523,7 +556,7 @@ ${beads_tasks}
523556
# Import from GitHub
524557
if echo "$sources" | grep -qw "github"; then
525558
local github_tasks
526-
if github_tasks=$(fetch_github_tasks "$github_label"); then
559+
if github_tasks=$(fetch_github_tasks "$github_label" "$limit"); then
527560
if [[ -n "$github_tasks" ]]; then
528561
all_tasks="${all_tasks}
529562
# Tasks from GitHub

ralph_enable.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ SKIP_TASKS=false
4343
TASK_SOURCE=""
4444
PRD_FILE=""
4545
GITHUB_LABEL=""
46+
IMPORT_LIMIT="0"
4647
NON_INTERACTIVE=false
4748
SHOW_HELP=false
4849

@@ -63,6 +64,7 @@ Options:
6364
--from <source> Import tasks from: beads, github, prd
6465
--prd <file> PRD file to convert (when --from prd)
6566
--label <label> GitHub label filter (when --from github)
67+
--limit <n> Max issues to import (default: 0 = all)
6668
--force Overwrite existing .ralph/ configuration
6769
--skip-tasks Skip task import, use default templates
6870
--non-interactive Run with defaults (no prompts)
@@ -142,6 +144,15 @@ parse_arguments() {
142144
exit $ENABLE_INVALID_ARGS
143145
fi
144146
;;
147+
--limit)
148+
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then
149+
IMPORT_LIMIT="$2"
150+
shift 2
151+
else
152+
echo "Error: --limit requires a non-negative integer" >&2
153+
exit $ENABLE_INVALID_ARGS
154+
fi
155+
;;
145156
--force)
146157
FORCE_OVERWRITE=true
147158
shift
@@ -403,7 +414,7 @@ phase_file_generation() {
403414

404415
if echo "$SELECTED_SOURCES" | grep -qw "beads"; then
405416
local beads_tasks
406-
if beads_tasks=$(fetch_beads_tasks); then
417+
if beads_tasks=$(fetch_beads_tasks "open" "$IMPORT_LIMIT"); then
407418
imported_tasks="${imported_tasks}${beads_tasks}
408419
"
409420
print_success "Imported tasks from beads"
@@ -412,7 +423,7 @@ phase_file_generation() {
412423

413424
if echo "$SELECTED_SOURCES" | grep -qw "github"; then
414425
local github_tasks
415-
if github_tasks=$(fetch_github_tasks "$CONFIG_GITHUB_LABEL"); then
426+
if github_tasks=$(fetch_github_tasks "$CONFIG_GITHUB_LABEL" "$IMPORT_LIMIT"); then
416427
imported_tasks="${imported_tasks}${github_tasks}
417428
"
418429
print_success "Imported tasks from GitHub"

ralph_enable_ci.sh

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ FORCE_OVERWRITE=false
5050
TASK_SOURCE=""
5151
PRD_FILE=""
5252
GITHUB_LABEL="ralph-task"
53+
IMPORT_LIMIT="0"
5354
PROJECT_NAME=""
5455
PROJECT_TYPE=""
5556
OUTPUT_JSON=false
@@ -73,6 +74,7 @@ Options:
7374
--from <source> Import tasks from: beads, github, prd, none
7475
--prd <file> PRD file to convert (when --from prd)
7576
--label <label> GitHub label filter (default: ralph-task)
77+
--limit <n> Max issues to import (default: 0 = all)
7678
--project-name <name> Override detected project name
7779
--project-type <type> Override detected type (typescript, python, etc.)
7880
--force Overwrite existing .ralph/ configuration
@@ -155,6 +157,15 @@ parse_arguments() {
155157
exit $ENABLE_INVALID_ARGS
156158
fi
157159
;;
160+
--limit)
161+
if [[ -n "$2" && "$2" =~ ^[0-9]+$ ]]; then
162+
IMPORT_LIMIT="$2"
163+
shift 2
164+
else
165+
output_error "--limit requires a non-negative integer"
166+
exit $ENABLE_INVALID_ARGS
167+
fi
168+
;;
158169
--project-name)
159170
if [[ -n "$2" && ! "$2" =~ ^-- ]]; then
160171
PROJECT_NAME="$2"
@@ -322,16 +333,19 @@ main() {
322333

323334
# Import tasks
324335
local imported_tasks=""
336+
local beads_tasks=""
337+
local github_tasks=""
338+
local prd_tasks=""
325339
case "$TASK_SOURCE" in
326340
beads)
327-
if beads_tasks=$(fetch_beads_tasks 2>/dev/null); then
341+
if beads_tasks=$(fetch_beads_tasks "open" "$IMPORT_LIMIT" 2>/dev/null); then
328342
imported_tasks="$beads_tasks"
329343
TASKS_IMPORTED=$(echo "$imported_tasks" | grep -c '^\- \[' || echo "0")
330344
output_message "Imported $TASKS_IMPORTED tasks from beads"
331345
fi
332346
;;
333347
github)
334-
if github_tasks=$(fetch_github_tasks "$GITHUB_LABEL" 2>/dev/null); then
348+
if github_tasks=$(fetch_github_tasks "$GITHUB_LABEL" "$IMPORT_LIMIT" 2>/dev/null); then
335349
imported_tasks="$github_tasks"
336350
TASKS_IMPORTED=$(echo "$imported_tasks" | grep -c '^\- \[' || echo "0")
337351
output_message "Imported $TASKS_IMPORTED tasks from GitHub"

0 commit comments

Comments
 (0)