From 417cf1dc955caa4a472acf20c0261188fd144764 Mon Sep 17 00:00:00 2001 From: Kris Turner Date: Mon, 23 Mar 2026 11:03:56 -0700 Subject: [PATCH] chore: remove project management scripts --- scripts/backfill-id-field.ps1 | 77 -------- scripts/commit-id-field-workflows.ps1 | 26 --- scripts/sync-issues-to-project.ps1 | 273 -------------------------- 3 files changed, 376 deletions(-) delete mode 100644 scripts/backfill-id-field.ps1 delete mode 100644 scripts/commit-id-field-workflows.ps1 delete mode 100644 scripts/sync-issues-to-project.ps1 diff --git a/scripts/backfill-id-field.ps1 b/scripts/backfill-id-field.ps1 deleted file mode 100644 index 5ec56ad..0000000 --- a/scripts/backfill-id-field.ps1 +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env pwsh -# Backfill the ID field (e.g., SOFS-8, AVD-42) for all project items missing it. - -$ID_FIELD = "PVTF_lADOCxeiOM4BR2KZzhADImQ" -$projectId = "PVT_kwDOCxeiOM4BR2KZ" - -function Get-Prefix($url) { - if ($url -match "azurelocal-sofs") { return "SOFS" } - if ($url -match "azurelocal-avd") { return "AVD" } - if ($url -match "azurelocal-loadtools") { return "LOAD" } - if ($url -match "azurelocal-vm-conv") { return "VMCT" } - if ($url -match "azurelocal\.github\.io|azurelocalcloud") { return "DOCS" } - if ($url -match "azurelocal-toolkit") { return "TKT" } - return $null -} - -$gqlQuery = 'query($projectId: ID!, $after: String) { - node(id: $projectId) { - ... on ProjectV2 { - items(first: 100, after: $after) { - pageInfo { hasNextPage endCursor } - nodes { - id - content { - ... on Issue { url number } - ... on PullRequest { url number } - } - fieldValues(first: 20) { - nodes { - ... on ProjectV2ItemFieldTextValue { - field { ... on ProjectV2Field { id } } - text - } - } - } - } - } - } - } -}' - -$allItems = [System.Collections.Generic.List[object]]::new() -$afterCursor = $null -do { - if ($afterCursor) { - $result = (gh api graphql -f query="$gqlQuery" -F projectId="$projectId" -F after="$afterCursor" | ConvertFrom-Json) - } else { - $result = (gh api graphql -f query="$gqlQuery" -F projectId="$projectId" | ConvertFrom-Json) - } - $page = $result.data.node.items - foreach ($n in $page.nodes) { $allItems.Add($n) } - $hasNext = $page.pageInfo.hasNextPage - $afterCursor = $page.pageInfo.endCursor -} while ($hasNext) - -Write-Host "Total items: $($allItems.Count)" -$updated = 0 - -foreach ($item in $allItems) { - if (-not $item.content -or -not $item.content.url) { continue } - - # Skip if ID already set - $hasId = $item.fieldValues.nodes | Where-Object { $_.field.id -eq $ID_FIELD -and $_.text } - if ($hasId) { continue } - - $url = $item.content.url - $number = $item.content.number - $prefix = Get-Prefix $url - if (-not $prefix) { Write-Host "SKIP (unknown repo): $url"; continue } - - $idValue = "$prefix-$number" - gh project item-edit --project-id $projectId --id $item.id --field-id $ID_FIELD --text $idValue | Out-Null - Write-Host "Set $idValue <- $url" - $updated++ -} - -Write-Host "`nDone. $updated item(s) updated." diff --git a/scripts/commit-id-field-workflows.ps1 b/scripts/commit-id-field-workflows.ps1 deleted file mode 100644 index 651192d..0000000 --- a/scripts/commit-id-field-workflows.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env pwsh -$repos = @( - @{ path = "C:\git\azurelocal-sofs-fslogix"; prefix = "SOFS" }, - @{ path = "C:\git\azurelocal-avd"; prefix = "AVD" }, - @{ path = "C:\git\azurelocal-loadtools"; prefix = "LOAD" }, - @{ path = "C:\git\azurelocal-vm-conversion-toolkit"; prefix = "VMCT" }, - @{ path = "C:\git\azurelocal-toolkit"; prefix = "TKT" }, - @{ path = "C:\git\azurelocalcloud-azurelocal.github.io"; prefix = "DOCS" } -) - -foreach ($repo in $repos) { - Set-Location $repo.path - $status = git status --porcelain .github/workflows/add-to-project.yml - if ($status) { - git add .github/workflows/add-to-project.yml - if ($repo.prefix -eq "TKT") { - git add scripts/backfill-id-field.ps1 - } - git commit -m "feat: add unique project ID field automation ($($repo.prefix)-N prefix)" - git push - Write-Host "DONE: $($repo.prefix)" - } else { - Write-Host "SKIP (already committed): $($repo.prefix)" - } -} -Write-Host "`nAll repos processed." diff --git a/scripts/sync-issues-to-project.ps1 b/scripts/sync-issues-to-project.ps1 deleted file mode 100644 index 9635cad..0000000 --- a/scripts/sync-issues-to-project.ps1 +++ /dev/null @@ -1,273 +0,0 @@ -# sync-issues-to-project.ps1 -# Ensures every open issue (and PR, if desired) from all repos is in the GitHub Project. -# Then backfills Solution, Priority, Category, and ID fields for any newly added items. - -$ErrorActionPreference = "Stop" - -$projectId = "PVT_kwDOCxeiOM4BR2KZ" -$projectNum = 3 -$org = "AzureLocal" - -# Field IDs -$ID_FIELD = "PVTF_lADOCxeiOM4BR2KZzhADImQ" -$SOLUTION_FIELD = "PVTSSF_lADOCxeiOM4BR2KZzg_jXuY" -$PRIORITY_FIELD = "PVTSSF_lADOCxeiOM4BR2KZzg_jXvs" -$CATEGORY_FIELD = "PVTSSF_lADOCxeiOM4BR2KZzg_jXxA" - -# Solution option IDs (must match option IDs in the project) -$SOLUTION_OPTIONS = @{ - "azurelocal-sofs-fslogix" = "441d7b73" # SOFS / FSLogix - "azurelocal-avd" = "88c2cad1" # AVD - "azurelocal-loadtools" = "e681af20" # Load Tools - "azurelocal-vm-conversion-toolkit" = "24cfc8b7" # VM Conversion - "azurelocal-toolkit" = "5a5921eb" # Toolkit - "azurelocal.github.io" = "409662e1" # Docs -} - -# Prefix map -$PREFIX_MAP = @{ - "azurelocal-sofs-fslogix" = "SOFS" - "azurelocal-avd" = "AVD" - "azurelocal-loadtools" = "LOAD" - "azurelocal-vm-conversion-toolkit" = "VMCT" - "azurelocal-toolkit" = "TKT" - "azurelocal.github.io" = "DOCS" -} - -$repos = @( - "azurelocal-sofs-fslogix", - "azurelocal-avd", - "azurelocal-loadtools", - "azurelocal-vm-conversion-toolkit", - "azurelocal-toolkit", - "azurelocal.github.io" -) - -# ── Step 1: Collect all open issues from all repos ─────────────────────────── -Write-Host "`n=== Step 1: Fetching all open issues from all repos ===" -ForegroundColor Cyan - -$allIssues = @{} # key = content URL, value = {repo, number, title, labels} - -foreach ($repo in $repos) { - Write-Host " Fetching: $org/$repo" -NoNewline - $page = 1 - $repoIssues = @() - do { - $batch = gh issue list --repo "$org/$repo" --state open --limit 200 --json number,title,url,labels 2>$null | ConvertFrom-Json - if ($null -eq $batch -or $batch.Count -eq 0) { break } - $repoIssues += $batch - $page++ - } while ($batch.Count -eq 200) - - Write-Host " → $($repoIssues.Count) open issues" - foreach ($issue in $repoIssues) { - $allIssues[$issue.url] = @{ - repo = $repo - number = $issue.number - title = $issue.title - labels = $issue.labels | ForEach-Object { $_.name } - url = $issue.url - } - } -} - -Write-Host "Total open issues across all repos: $($allIssues.Count)" -ForegroundColor Yellow - -# ── Step 2: Collect all items currently in the project ─────────────────────── -Write-Host "`n=== Step 2: Fetching all current project items ===" -ForegroundColor Cyan - -$projectUrls = @{} -$afterCursor = $null -$gqlQuery = 'query($projectId: ID!, $after: String) { - node(id: $projectId) { - ... on ProjectV2 { - items(first: 100, after: $after) { - pageInfo { hasNextPage endCursor } - nodes { - id - content { - ... on Issue { url } - ... on PullRequest { url } - } - fieldValues(first: 20) { - nodes { - ... on ProjectV2ItemFieldTextValue { - field { ... on ProjectV2Field { id } } - text - } - ... on ProjectV2ItemFieldSingleSelectValue { - field { ... on ProjectV2SingleSelectField { id } } - optionId - } - } - } - } - } - } - } -}' - -do { - if ($afterCursor) { - $result = gh api graphql -f query=$gqlQuery -F projectId=$projectId -F after="$afterCursor" | ConvertFrom-Json - } else { - $result = gh api graphql -f query=$gqlQuery -F projectId=$projectId | ConvertFrom-Json - } - - $page = $result.data.node.items - foreach ($item in $page.nodes) { - $url = $item.content.url - if ($url) { - # Track which fields are already set - $hasId = $false - $hasSolution = $false - $hasPriority = $false - $hasCategory = $false - foreach ($fv in $item.fieldValues.nodes) { - if ($fv.field.id -eq $ID_FIELD -and $fv.text) { $hasId = $true } - if ($fv.field.id -eq $SOLUTION_FIELD -and $fv.optionId) { $hasSolution = $true } - if ($fv.field.id -eq $PRIORITY_FIELD -and $fv.optionId) { $hasPriority = $true } - if ($fv.field.id -eq $CATEGORY_FIELD -and $fv.optionId) { $hasCategory = $true } - } - $projectUrls[$url] = @{ - itemId = $item.id - hasId = $hasId - hasSolution = $hasSolution - hasPriority = $hasPriority - hasCategory = $hasCategory - } - } - } - - $afterCursor = if ($page.pageInfo.hasNextPage) { $page.pageInfo.endCursor } else { $null } -} while ($afterCursor) - -Write-Host "Total items currently in project: $($projectUrls.Count)" -ForegroundColor Yellow - -# ── Step 3: Find missing issues ─────────────────────────────────────────────── -Write-Host "`n=== Step 3: Finding issues not in the project ===" -ForegroundColor Cyan - -$missing = @() -foreach ($url in $allIssues.Keys) { - if (-not $projectUrls.ContainsKey($url)) { - $missing += $allIssues[$url] - } -} - -Write-Host "Issues missing from project: $($missing.Count)" -ForegroundColor $(if ($missing.Count -gt 0) { "Red" } else { "Green" }) - -if ($missing.Count -eq 0) { - Write-Host "`nAll issues are already in the project. Nothing to do." -ForegroundColor Green - exit 0 -} - -# ── Step 4: Add missing issues to the project ──────────────────────────────── -Write-Host "`n=== Step 4: Adding missing issues to project ===" -ForegroundColor Cyan - -$addMutation = 'mutation($projectId: ID!, $contentId: ID!) { - addProjectV2ItemById(input: { projectId: $projectId, contentId: $contentId }) { - item { id } - } -}' - -# We need the node ID for each issue (gh issue view gives us that) -$newItems = @() -foreach ($issue in $missing) { - $repoFull = "$org/$($issue.repo)" - Write-Host " Adding $($issue.repo)#$($issue.number): $($issue.title.Substring(0, [Math]::Min(60, $issue.title.Length)))" -NoNewline - - # Get the node ID for the issue - $nodeId = gh issue view $issue.number --repo $repoFull --json id --jq '.id' 2>$null - if (-not $nodeId) { - Write-Host " [ERROR: could not get node ID]" -ForegroundColor Red - continue - } - - # Add to project - $addResult = gh api graphql -f query=$addMutation -F projectId=$projectId -F contentId=$nodeId 2>$null | ConvertFrom-Json - $itemId = $addResult.data.addProjectV2ItemById.item.id - if (-not $itemId) { - Write-Host " [ERROR: add failed]" -ForegroundColor Red - continue - } - - Write-Host " [added: $itemId]" -ForegroundColor Green - $newItems += @{ - itemId = $itemId - repo = $issue.repo - number = $issue.number - title = $issue.title - labels = $issue.labels - url = $issue.url - } -} - -Write-Host "`nSuccessfully added: $($newItems.Count) items" -ForegroundColor Yellow - -# ── Step 5: Backfill fields on newly added items ────────────────────────────── -Write-Host "`n=== Step 5: Backfilling fields on new items ===" -ForegroundColor Cyan - -function Get-PriorityOptionId($labels) { - foreach ($l in $labels) { - if ($l -match "critical") { return "74334e8d" } - if ($l -match "high") { return "2e3ede9d" } - if ($l -match "medium") { return "7709e85d" } - if ($l -match "low") { return "2182b5f9" } - } - return "7709e85d" # default: medium -} - -function Get-CategoryOptionId($labels, $title) { - # First try label-based detection - foreach ($l in $labels) { - if ($l -match "type/bug|^bug$") { return "206e624a" } - if ($l -match "type/feature|enhancement") { return "7a4fa8ea" } - if ($l -match "type/epic|^epic$") { return "7a4fa8ea" } - if ($l -match "type/docs|^doc") { return "355ce6c1" } - if ($l -match "type/infra|chore|cleanup") { return "05996f93" } - if ($l -match "type/refactor|refactor") { return "7f5509ab" } - if ($l -match "type/security|security") { return "d2af4749" } - } - # Fall back to title conventional commit prefix - if ($title -match '^docs[(:]') { return "355ce6c1" } - if ($title -match '^feat[(:]') { return "7a4fa8ea" } - if ($title -match '^fix[(:]') { return "206e624a" } - if ($title -match '^chore[(:]') { return "05996f93" } - if ($title -match '^ci[(:]') { return "05996f93" } - if ($title -match '^test[(:]') { return "05996f93" } - if ($title -match '^refactor[(:]') { return "7f5509ab" } - return "7a4fa8ea" # default: feature -} - -foreach ($item in $newItems) { - $prefix = $PREFIX_MAP[$item.repo] - $solOptId = $SOLUTION_OPTIONS[$item.repo] - $priOptId = Get-PriorityOptionId($item.labels) - $catOptId = Get-CategoryOptionId $item.labels $item.title - $idText = "$prefix-$($item.number)" - - Write-Host " $idText" -NoNewline - - # Set ID field - gh project item-edit --project-id $projectId --id $item.itemId ` - --field-id $ID_FIELD --text $idText 2>$null | Out-Null - - # Set Solution field - if ($solOptId) { - gh project item-edit --project-id $projectId --id $item.itemId ` - --field-id $SOLUTION_FIELD --single-select-option-id $solOptId 2>$null | Out-Null - } - - # Set Priority field - gh project item-edit --project-id $projectId --id $item.itemId ` - --field-id $PRIORITY_FIELD --single-select-option-id $priOptId 2>$null | Out-Null - - # Set Category field - gh project item-edit --project-id $projectId --id $item.itemId ` - --field-id $CATEGORY_FIELD --single-select-option-id $catOptId 2>$null | Out-Null - - Write-Host " [fields set]" -ForegroundColor Green -} - -Write-Host "`n=== Done ===" -ForegroundColor Cyan -Write-Host "Added $($newItems.Count) missing issue(s) to the project and backfilled all fields." -ForegroundColor Green