(
repoFullName: string,
state: 'open' | 'closed' | 'all' = 'open',
perPage = 10,
page = 1,
labels?: string
)
| 285 | } |
| 286 | |
| 287 | async getRepositoryIssues( |
| 288 | repoFullName: string, |
| 289 | state: 'open' | 'closed' | 'all' = 'open', |
| 290 | perPage = 10, |
| 291 | page = 1, |
| 292 | labels?: string |
| 293 | ): Promise<GitHubIssue[]> { |
| 294 | const [owner, repo] = repoFullName.split('/'); |
| 295 | try { |
| 296 | // If labels are provided, try each label individually since GitHub treats |
| 297 | // comma-separated labels as AND (must have all) not OR (can have any) |
| 298 | if (labels) { |
| 299 | const labelVariants = labels.split(',').map(label => label.trim()); |
| 300 | const allIssues: GitHubIssue[] = []; |
| 301 | const seenIssueIds = new Set<number>(); |
| 302 | |
| 303 | // Try each label variant individually |
| 304 | for (const label of labelVariants) { |
| 305 | try { |
| 306 | const params = { |
| 307 | state, |
| 308 | per_page: Math.min(perPage * 2, 100), // Get more results to account for duplicates |
| 309 | page: 1, // Always start from page 1 for each label |
| 310 | sort: 'updated', |
| 311 | direction: 'desc', |
| 312 | labels: label |
| 313 | }; |
| 314 | |
| 315 | const response = await axios.get(`${this.baseURL}/repos/${owner}/${repo}/issues`, { |
| 316 | headers: this.getHeaders(), |
| 317 | params |
| 318 | }); |
| 319 | |
| 320 | // Add unique issues (avoid duplicates) |
| 321 | for (const issue of response.data) { |
| 322 | if (!seenIssueIds.has(issue.id)) { |
| 323 | seenIssueIds.add(issue.id); |
| 324 | allIssues.push(issue); |
| 325 | } |
| 326 | } |
| 327 | } catch (labelError) { |
| 328 | // Continue with next label if one fails |
| 329 | console.warn(`Failed to fetch issues for label "${label}" in ${repoFullName}:`, labelError); |
| 330 | continue; |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | // Sort by updated date and return requested page |
| 335 | allIssues.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()); |
| 336 | |
| 337 | // Handle pagination for the combined results |
| 338 | const startIndex = (page - 1) * perPage; |
| 339 | const endIndex = startIndex + perPage; |
| 340 | return allIssues.slice(startIndex, endIndex); |
| 341 | } |
| 342 | |
| 343 | // Fallback to original behavior for single label or no labels |
| 344 | const params: { |
no test coverage detected