diff --git a/.github/skills/issue-triage/SKILL.md b/.github/skills/issue-triage/SKILL.md index 780084b1b543..91cc5dfa4585 100644 --- a/.github/skills/issue-triage/SKILL.md +++ b/.github/skills/issue-triage/SKILL.md @@ -3,8 +3,8 @@ name: issue-triage description: Queries and triages open GitHub issues that need attention. Helps identify issues needing milestones, labels, or investigation. metadata: author: dotnet-maui - version: "2.1" -compatibility: Requires GitHub CLI (gh) authenticated with access to dotnet/maui repository. + version: "2.3" +compatibility: Requires GitHub CLI (gh) installed and authenticated. Run `gh auth login` before using. --- # Issue Triage Skill @@ -16,6 +16,27 @@ This skill helps triage open GitHub issues in the dotnet/maui repository by: 4. Suggesting milestones based on issue characteristics 5. Tracking progress through a triage session +## Prerequisites + +**GitHub CLI (gh) must be installed and authenticated:** + +```bash +# Install +# Windows: +winget install --id GitHub.cli + +# macOS: +brew install gh + +# Linux: +# See https://cli.github.com/manual/installation + +# Authenticate (required before first use) +gh auth login +``` + +The scripts will check for `gh` and exit with installation instructions if not found. + ## When to Use - "Find issues to triage" @@ -25,6 +46,10 @@ This skill helps triage open GitHub issues in the dotnet/maui repository by: ## Triage Workflow +**🚨 CRITICAL: ALWAYS use the skill scripts. NEVER use ad-hoc GitHub API queries.** + +The scripts have proper filters, exclusions, and milestone logic built-in. Don't bypass them. + ### Step 1: Initialize Session Start by initializing a session to load current milestones and labels: @@ -33,14 +58,29 @@ Start by initializing a session to load current milestones and labels: pwsh .github/skills/issue-triage/scripts/init-triage-session.ps1 ``` +**What this does:** +- Fetches current milestones (SR4, SR5, etc.) from GitHub API +- Displays servicing milestones for reference during triage +- Creates session file to track progress + ### Step 2: Load Issues Into Memory -Load a batch of issues (e.g., 20) but DO NOT display them all. Store them for one-at-a-time presentation: +**MANDATORY: Use query-issues.ps1 - it has the right filters!** ```bash -pwsh .github/skills/issue-triage/scripts/query-issues.ps1 -Limit 100 -OutputFormat triage +pwsh .github/skills/issue-triage/scripts/query-issues.ps1 -Limit 50 -OutputFormat triage ``` +**What this does:** +- Queries GitHub with exclusion filters: `-label:s/needs-info -label:s/needs-repro -label:area-blazor -label:s/try-latest-version -label:s/move-to-vs-feedback` +- Returns issues without milestones +- Stores results for one-at-a-time presentation + +**DON'T:** +- ❌ Use `github-mcp-server-list_issues` directly +- ❌ Use `github-mcp-server-search_issues` without the same filters +- ❌ Try to replicate the logic yourself - use the script! + ### Step 3: Present ONE Issue at a Time **IMPORTANT**: When user asks to triage, present only ONE issue at a time in this format: @@ -65,7 +105,7 @@ pwsh .github/skills/issue-triage/scripts/query-issues.ps1 -Limit 100 -OutputForm **Comment Summary** (if any): - [Author] Comment preview... -**My Suggestion**: `Milestone` - Reason +**My Suggestion**: `Milestone` - Reason (based on init session output) --- @@ -75,14 +115,33 @@ What would you like to do with this issue? ### Step 4: Wait for User Decision Wait for user to say: -- A milestone name (e.g., "Backlog", "current SR", "Servicing") +- A milestone name (e.g., "Backlog", ".NET 10 SR5", ".NET 10 Servicing") - "yes" to accept suggestion - "skip" or "next" to move on without changes - Specific instructions (e.g., "next SR and add regression label") -### Step 5: Apply Changes and Move to Next +### Step 5: Move to Next Issue + +After user decision, automatically present the NEXT issue. + +### Step 6: When Batch is Empty -After applying changes, automatically present the NEXT issue. +**🚨 CRITICAL: When you run out of issues, AUTOMATICALLY reload more issues.** + +```bash +# Run query again to load next batch +pwsh .github/skills/issue-triage/scripts/query-issues.ps1 -Limit 50 -Skip -OutputFormat triage +``` + +**DO NOT:** +- ❌ Stop and ask "Load more?" +- ❌ Say "No more issues found" +- ❌ Use different GitHub queries + +**DO:** +- ✅ Automatically run `query-issues.ps1` again with `-Skip` parameter +- ✅ Continue presenting issues one at a time +- ✅ Only stop when query returns zero issues ## Script Parameters @@ -100,16 +159,39 @@ After applying changes, automatically present the NEXT issue. ## Milestone Suggestion Logic -The script dynamically queries current milestones from dotnet/maui and suggests them based on issue characteristics: +**🚨 CRITICAL: ALWAYS use actual milestone names from init-triage-session.ps1 output. NEVER guess or assume milestone names.** + +The skill dynamically queries current milestones from dotnet/maui at session initialization. Milestone names change frequently (e.g., SR4, SR5, SR6), so **always reference the session output** when suggesting milestones. + +### Suggestion Guidelines | Condition | Suggested Milestone | Reason | |-----------|---------------------|--------| | Linked PR has milestone | PR's milestone | "PR already has milestone" | -| Has `i/regression` label | Current SR milestone (soonest due) | "Regression - current SR milestone" | -| Has open linked PR | Servicing milestone (or next SR) | "Has open PR" | +| Has `i/regression` label | Highest numbered SR milestone | "Regression - needs servicing" | +| Has open linked PR | Current servicing milestone | "Has open PR" | | Default | Backlog | "No PR, not a regression" | -**Note**: SR milestones are sorted by due date, so the soonest SR is suggested for regressions. Milestone names change monthly, so they are queried dynamically rather than hardcoded. +**Example Session Output:** +``` +Servicing Releases: + - .NET 9 Servicing [246 open] + - .NET 10 Servicing [213 open] + - .NET 10 SR5 [55 open] ← Use this for .NET 10 regressions + - .NET 10.0 SR4 [103 open] + +Other: + - .NET 11 Planning [167 open] + - .NET 11.0-preview1 [8 open] + +Backlog: + - Backlog [3037 open] +``` + +**How to suggest milestones:** +- ✅ "Assign to `.NET 10 SR5`" (from session output) +- ❌ "Assign to `.NET 10 SR2`" (guessing, might not exist) +- ❌ "Assign to current SR" (ambiguous, multiple active) ## Applying Triage Decisions @@ -125,17 +207,6 @@ gh issue edit ISSUE_NUMBER --repo dotnet/maui --milestone "MILESTONE_NAME" gh pr edit PR_NUMBER --repo dotnet/maui --milestone "MILESTONE_NAME" ``` -## Common Milestone Types - -| Milestone Type | Use When | -|----------------|----------| -| Current SR (e.g., SR3) | Regressions, critical bugs with PRs ready | -| Next SR (e.g., SR4) | Important bugs, regressions being investigated | -| Servicing | General fixes with PRs, non-urgent improvements | -| Backlog | No PR, not a regression, nice-to-have fixes | - -**Note**: Use `init-triage-session.ps1` to see current milestone names. - ## Label Quick Reference **Regression Labels:** @@ -151,6 +222,16 @@ gh pr edit PR_NUMBER --repo dotnet/maui --milestone "MILESTONE_NAME" **iOS 26 / macOS 26:** - `version/iOS-26` - iOS 26 specific issue +## Common Mistakes to Avoid + +| Mistake | Why It's Wrong | Correct Approach | +|---------|----------------|------------------| +| ❌ Using `github-mcp-server-list_issues` directly | Missing exclusion filters (needs-info, needs-repro, etc.) | ✅ Use `query-issues.ps1` script | +| ❌ Stopping when batch is empty | There are likely more issues available | ✅ Automatically run `query-issues.ps1 -Skip N` | +| ❌ Suggesting milestone names like "SR2" | Milestone doesn't exist, based on assumptions | ✅ Use actual milestone names from `init-triage-session.ps1` output | +| ❌ Asking "Load more?" when out of issues | Creates unnecessary interruption | ✅ Just load more automatically | +| ❌ Using ad-hoc API queries with custom filters | Likely to miss or include wrong issues | ✅ Trust the skill's scripts - they have the right logic | + ## Session Tracking (Optional) ```bash diff --git a/.github/skills/issue-triage/scripts/init-triage-session.ps1 b/.github/skills/issue-triage/scripts/init-triage-session.ps1 index ea5e065862b5..1d3461efc7b0 100644 --- a/.github/skills/issue-triage/scripts/init-triage-session.ps1 +++ b/.github/skills/issue-triage/scripts/init-triage-session.ps1 @@ -40,6 +40,39 @@ Write-Host "╔═════════════════════ Write-Host "║ Initializing Triage Session ║" -ForegroundColor Cyan Write-Host "╚═══════════════════════════════════════════════════════════╝" -ForegroundColor Cyan +# Check for GitHub CLI prerequisite +Write-Host "" +Write-Host "Checking prerequisites..." -ForegroundColor Cyan +try { + $ghPath = (Get-Command gh -ErrorAction Stop).Source + Write-Host " ✅ GitHub CLI found: $ghPath" -ForegroundColor Green +} catch { + Write-Host "" + Write-Host " ❌ GitHub CLI (gh) is not installed" -ForegroundColor Red + Write-Host "" + Write-Host " The issue-triage skill requires GitHub CLI for querying issues." -ForegroundColor Yellow + Write-Host "" + Write-Host " Installation:" -ForegroundColor Cyan + Write-Host " Windows: winget install --id GitHub.cli" -ForegroundColor White + Write-Host " macOS: brew install gh" -ForegroundColor White + Write-Host " Linux: See https://cli.github.com/manual/installation" -ForegroundColor White + Write-Host "" + Write-Host " After installation, authenticate with: gh auth login" -ForegroundColor Cyan + Write-Host "" + exit 1 +} + +# Verify GitHub CLI authentication +$authStatus = gh auth status 2>&1 +if ($LASTEXITCODE -ne 0) { + Write-Host "" + Write-Host " ❌ GitHub CLI (gh) is not authenticated" -ForegroundColor Red + Write-Host " Run: gh auth login" -ForegroundColor Cyan + Write-Host "" + exit 1 +} +Write-Host " ✅ GitHub CLI authenticated" -ForegroundColor Green + # Create output directory if (-not (Test-Path $OutputDir)) { New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null @@ -62,11 +95,9 @@ Write-Host "Fetching open milestones..." -ForegroundColor Cyan $milestones = @() try { - $msResult = gh api repos/dotnet/maui/milestones --jq '.[] | {number, title, due_on, open_issues}' 2>&1 - $msLines = $msResult -split "`n" | Where-Object { $_ -match "^\{" } + $msData = Invoke-RestMethod -Uri "https://api.github.com/repos/dotnet/maui/milestones?state=open&per_page=100" - foreach ($line in $msLines) { - $ms = $line | ConvertFrom-Json + foreach ($ms in $msData) { $milestones += [PSCustomObject]@{ Number = $ms.number Title = $ms.title diff --git a/.github/skills/issue-triage/scripts/query-issues.ps1 b/.github/skills/issue-triage/scripts/query-issues.ps1 index d9fbd90e1853..9ee0916d3fb0 100644 --- a/.github/skills/issue-triage/scripts/query-issues.ps1 +++ b/.github/skills/issue-triage/scripts/query-issues.ps1 @@ -99,6 +99,36 @@ param( $ErrorActionPreference = "Stop" +# Check for GitHub CLI prerequisite +try { + $null = Get-Command gh -ErrorAction Stop +} catch { + Write-Host "" + Write-Host "❌ GitHub CLI (gh) is not installed" -ForegroundColor Red + Write-Host "" + Write-Host "The issue-triage skill requires GitHub CLI for querying issues." -ForegroundColor Yellow + Write-Host "" + Write-Host "Installation:" -ForegroundColor Cyan + Write-Host " Windows: winget install --id GitHub.cli" -ForegroundColor White + Write-Host " macOS: brew install gh" -ForegroundColor White + Write-Host " Linux: See https://cli.github.com/manual/installation" -ForegroundColor White + Write-Host "" + Write-Host "After installation, authenticate with: gh auth login" -ForegroundColor Cyan + Write-Host "" + exit 1 +} + +# Verify GitHub CLI authentication +$authStatus = gh auth status 2>&1 +if ($LASTEXITCODE -ne 0) { + Write-Host "" + Write-Host "❌ GitHub CLI (gh) is not authenticated" -ForegroundColor Red + Write-Host "Run: gh auth login" -ForegroundColor Cyan + Write-Host "" + exit 1 +} +Write-Host "✅ GitHub CLI authenticated" -ForegroundColor Green + Write-Host "Querying GitHub issues..." -ForegroundColor Cyan # Labels to exclude from triage results