From e495fb5da225ec90b0bba813f702cf7edb660888 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:01:57 +0000 Subject: [PATCH 1/6] Initial plan From ffbcfe134d1a07ec2d06bdb8661e132b91523c1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:04:43 +0000 Subject: [PATCH 2/6] Implement PR supersedence for font data updater Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> --- scripts/Update-FontsData.ps1 | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/scripts/Update-FontsData.ps1 b/scripts/Update-FontsData.ps1 index ea748b9..8baf490 100644 --- a/scripts/Update-FontsData.ps1 +++ b/scripts/Update-FontsData.ps1 @@ -111,6 +111,45 @@ $changes } +LogGroup 'Close superseded PRs' { + Write-Output 'Checking for existing open font data update PRs...' + + # Get all open PRs with "Auto-Update" in the title + $openPRsJson = Run gh pr list --state open --json number,title,headRefName --search 'Auto-Update in:title' + + if (-not [string]::IsNullOrWhiteSpace($openPRsJson)) { + $openPRs = $openPRsJson | ConvertFrom-Json + + if ($openPRs.Count -gt 0) { + Write-Output "Found $($openPRs.Count) existing open font data update PR(s)" + + foreach ($pr in $openPRs) { + # Skip the current branch if we're updating an existing PR + if ($pr.headRefName -eq $targetBranch) { + Write-Output "Skipping PR #$($pr.number) as it's the current branch: $targetBranch" + continue + } + + Write-Output "Closing superseded PR #$($pr.number): $($pr.title)" + + $supersedenceMessage = if ($targetBranch -eq $currentBranch -and $currentBranch -ne $defaultBranch) { + "This PR has been superseded by updates to branch ``$targetBranch``." + } else { + "This PR has been superseded by a newer font data update." + } + + # Close the PR with a comment + Run gh pr close $pr.number --comment $supersedenceMessage + Write-Output "Closed PR #$($pr.number)" + } + } else { + Write-Output 'No existing open font data update PRs found.' + } + } else { + Write-Output 'No existing open font data update PRs found.' + } +} + LogGroup 'Process changes' { if ($targetBranch -eq $currentBranch -and $currentBranch -ne $defaultBranch) { Run git push origin $targetBranch From 2cc824c72b2ab28b34f6999c55abcba65c11aa2e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:05:22 +0000 Subject: [PATCH 3/6] Add documentation for font data updater and PR supersedence Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> --- scripts/README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 scripts/README.md diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..695f114 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,49 @@ +# Font Data Updater + +This directory contains the automated font data updater script that keeps the NerdFonts module synchronized with the latest fonts from the [ryanoasis/nerd-fonts](https://github.com/ryanoasis/nerd-fonts) repository. + +## Update-FontsData.ps1 + +The `Update-FontsData.ps1` script is automatically run on a daily schedule via GitHub Actions. It performs the following tasks: + +1. **Fetch Latest Fonts**: Retrieves the latest font release metadata from the NerdFonts repository +2. **Update Font Data**: Updates the `src/FontsData.json` file with the latest font information +3. **Create/Update PR**: Creates a pull request with the changes or updates an existing branch +4. **PR Supersedence**: Automatically closes older, superseded font update PRs + +## PR Supersedence Behavior + +Similar to Dependabot's PR lifecycle management, the updater implements automatic PR supersedence: + +### When Creating a New PR + +When the updater creates a new font data update PR: +- It searches for existing open PRs with "Auto-Update" in the title +- Automatically closes those older PRs with a comment: "This PR has been superseded by a newer font data update." +- Creates the new PR with the latest changes + +### When Updating an Existing Branch + +When the updater pushes changes to an existing update branch: +- It searches for other open font update PRs +- Closes them with a comment indicating which branch supersedes them +- Updates the existing branch with the latest changes + +### Benefits + +This approach: +- Keeps the repository tidy by removing outdated update PRs +- Prevents confusion about which PR should be reviewed/merged +- Streamlines the review and merge process +- Mirrors the familiar behavior of Dependabot + +## Workflow + +The updater runs via the `.github/workflows/Update-FontsData.yml` workflow: +- **Schedule**: Daily at midnight UTC +- **Manual**: Can be triggered via workflow_dispatch +- **Authentication**: Uses GitHub App credentials for enhanced permissions + +## Customization + +The supersedence message can be modified by editing the `$supersedenceMessage` variable in the script. From e9a14507c3688d241ceaa1d4433aeeb4a4787fed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:05:57 +0000 Subject: [PATCH 4/6] Fix PR number interpolation in gh pr close command Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> --- scripts/Update-FontsData.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/Update-FontsData.ps1 b/scripts/Update-FontsData.ps1 index 8baf490..5dbd5bc 100644 --- a/scripts/Update-FontsData.ps1 +++ b/scripts/Update-FontsData.ps1 @@ -139,7 +139,7 @@ LogGroup 'Close superseded PRs' { } # Close the PR with a comment - Run gh pr close $pr.number --comment $supersedenceMessage + Run gh pr close $($pr.number) --comment $supersedenceMessage Write-Output "Closed PR #$($pr.number)" } } else { From dcf60cbdc83fa8cef4e5f21a33a09b0beda54106 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:06:51 +0000 Subject: [PATCH 5/6] Use constant for PR title prefix to ensure consistency Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> --- scripts/Update-FontsData.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/Update-FontsData.ps1 b/scripts/Update-FontsData.ps1 index 5dbd5bc..5d9f79c 100644 --- a/scripts/Update-FontsData.ps1 +++ b/scripts/Update-FontsData.ps1 @@ -38,6 +38,9 @@ Install-PSResource -Repository PSGallery -TrustRepository -Name 'Json' Connect-GitHubApp -Organization 'PSModule' -Default $repo = Get-GitHubRepository -Owner 'PSModule' -Name 'NerdFonts' +# Constants for PR management +$AUTO_UPDATE_PR_PREFIX = 'Auto-Update' + LogGroup 'Checkout' { $currentBranch = (Run git rev-parse --abbrev-ref HEAD).Trim() $defaultBranch = $repo.DefaultBranch @@ -114,8 +117,8 @@ $changes LogGroup 'Close superseded PRs' { Write-Output 'Checking for existing open font data update PRs...' - # Get all open PRs with "Auto-Update" in the title - $openPRsJson = Run gh pr list --state open --json number,title,headRefName --search 'Auto-Update in:title' + # Get all open PRs with the auto-update prefix in the title + $openPRsJson = Run gh pr list --state open --json number,title,headRefName --search "$AUTO_UPDATE_PR_PREFIX in:title" if (-not [string]::IsNullOrWhiteSpace($openPRsJson)) { $openPRs = $openPRsJson | ConvertFrom-Json @@ -160,7 +163,7 @@ LogGroup 'Process changes' { Run gh pr create ` --base $defaultBranch ` --head $targetBranch ` - --title "Auto-Update $timeStamp" ` + --title "$AUTO_UPDATE_PR_PREFIX $timeStamp" ` --body 'This PR updates FontsData.json with the latest metadata.' Write-Output "Changes detected and PR opened for branch: $targetBranch" From 08dac4f41fe7cd7a8149e3f79b2b97ed9fb635ac Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sat, 14 Feb 2026 22:13:00 +0100 Subject: [PATCH 6/6] [Enhancement]: Update README and script for improved PR supersedence management --- scripts/README.md | 101 +++++++++++++++++++++--------- scripts/Update-FontsData.ps1 | 118 ++++++++++++++++++++++------------- 2 files changed, 145 insertions(+), 74 deletions(-) diff --git a/scripts/README.md b/scripts/README.md index 695f114..6911141 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,49 +1,88 @@ # Font Data Updater -This directory contains the automated font data updater script that keeps the NerdFonts module synchronized with the latest fonts from the [ryanoasis/nerd-fonts](https://github.com/ryanoasis/nerd-fonts) repository. +This directory contains scripts for automating the maintenance of the NerdFonts module. ## Update-FontsData.ps1 -The `Update-FontsData.ps1` script is automatically run on a daily schedule via GitHub Actions. It performs the following tasks: +This script automatically updates the `src/FontsData.json` file with the latest font metadata from the +[ryanoasis/nerd-fonts](https://github.com/ryanoasis/nerd-fonts) repository. -1. **Fetch Latest Fonts**: Retrieves the latest font release metadata from the NerdFonts repository -2. **Update Font Data**: Updates the `src/FontsData.json` file with the latest font information -3. **Create/Update PR**: Creates a pull request with the changes or updates an existing branch -4. **PR Supersedence**: Automatically closes older, superseded font update PRs +### Features -## PR Supersedence Behavior +- **Automatic Updates**: Runs daily via GitHub Actions to fetch the latest font data +- **PR Supersedence**: Automatically closes older update pull requests when a new update is created +- **Clean Repository**: Ensures only the most recent update PR remains open -Similar to Dependabot's PR lifecycle management, the updater implements automatic PR supersedence: +### How It Works -### When Creating a New PR +1. **Scheduled Execution**: The script runs daily at midnight UTC via the `Update-FontsData` workflow +2. **Data Fetching**: Retrieves the latest font release metadata from the NerdFonts repository +3. **Change Detection**: Compares new data with existing `FontsData.json` +4. **PR Creation**: If changes are detected: + - Creates a new branch named `auto-update-YYYYMMDD-HHmmss` + - Commits the updated `FontsData.json` + - Opens a pull request with title `Auto-Update YYYYMMDD-HHmmss` +5. **PR Supersedence**: After creating a new PR, the script: + - Searches for existing open PRs with titles matching `Auto-Update*` (excluding the newly created PR) + - Closes each superseded PR with a comment referencing the new PR number + - Deletes the branches associated with superseded PRs + - Ensures only the latest update PR remains open -When the updater creates a new font data update PR: -- It searches for existing open PRs with "Auto-Update" in the title -- Automatically closes those older PRs with a comment: "This PR has been superseded by a newer font data update." -- Creates the new PR with the latest changes +### PR Lifecycle Management -### When Updating an Existing Branch +The font data updater implements PR supersedence similar to Dependabot. When a new update PR is created: -When the updater pushes changes to an existing update branch: -- It searches for other open font update PRs -- Closes them with a comment indicating which branch supersedes them -- Updates the existing branch with the latest changes +- The script first creates the new PR +- Then checks for existing open `Auto-Update*` PRs (excluding the newly created one) +- Each existing PR receives a comment referencing the new PR number: -### Benefits + ```text + This PR has been superseded by #[NEW_PR_NUMBER] and will be closed automatically. -This approach: -- Keeps the repository tidy by removing outdated update PRs -- Prevents confusion about which PR should be reviewed/merged -- Streamlines the review and merge process -- Mirrors the familiar behavior of Dependabot + The font data has been updated in the newer PR. Please refer to #[NEW_PR_NUMBER] for the most current changes. + ``` -## Workflow +- All superseded PRs are automatically closed +- Branches for closed PRs are deleted -The updater runs via the `.github/workflows/Update-FontsData.yml` workflow: -- **Schedule**: Daily at midnight UTC -- **Manual**: Can be triggered via workflow_dispatch -- **Authentication**: Uses GitHub App credentials for enhanced permissions +This means there is no need for a separate cleanup workflow on merge — by the time a PR is merged, +it is already the only open Auto-Update PR. -## Customization +### Workflow -The supersedence message can be modified by editing the `$supersedenceMessage` variable in the script. +#### Update-FontsData.yml + +Handles the scheduled updates, PR creation, and supersedence: + +- **Trigger**: Daily at midnight UTC, or manual via `workflow_dispatch` +- **Authentication**: Uses GitHub App credentials for API access + +### Manual Execution + +You can manually trigger an update using the GitHub Actions UI: + +1. Go to the **Actions** tab in the repository +2. Select the **Update-FontsData** workflow +3. Click **Run workflow** +4. Select the branch and click **Run workflow** + +### Configuration + +The supersedence behavior is built into the script and requires no additional configuration. The message +posted when closing superseded PRs can be customized by modifying `scripts/Update-FontsData.ps1`. + +### Development + +To test changes to the update script: + +1. Create a feature branch +2. Modify `scripts/Update-FontsData.ps1` +3. Push the branch +4. Manually trigger the workflow on your feature branch +5. The script will detect it's running on a feature branch and update the existing branch instead of + creating a new PR + +### Troubleshooting + +- **No updates available**: If the NerdFonts release contains the same data, no PR will be created +- **Authentication errors**: Ensure the GitHub App credentials are correctly configured diff --git a/scripts/Update-FontsData.ps1 b/scripts/Update-FontsData.ps1 index 5d9f79c..4e113a6 100644 --- a/scripts/Update-FontsData.ps1 +++ b/scripts/Update-FontsData.ps1 @@ -33,14 +33,13 @@ } } +$repoName = $env:GITHUB_REPOSITORY + Install-PSResource -Repository PSGallery -TrustRepository -Name 'Json' Connect-GitHubApp -Organization 'PSModule' -Default $repo = Get-GitHubRepository -Owner 'PSModule' -Name 'NerdFonts' -# Constants for PR management -$AUTO_UPDATE_PR_PREFIX = 'Auto-Update' - LogGroup 'Checkout' { $currentBranch = (Run git rev-parse --abbrev-ref HEAD).Trim() $defaultBranch = $repo.DefaultBranch @@ -114,45 +113,6 @@ $changes } -LogGroup 'Close superseded PRs' { - Write-Output 'Checking for existing open font data update PRs...' - - # Get all open PRs with the auto-update prefix in the title - $openPRsJson = Run gh pr list --state open --json number,title,headRefName --search "$AUTO_UPDATE_PR_PREFIX in:title" - - if (-not [string]::IsNullOrWhiteSpace($openPRsJson)) { - $openPRs = $openPRsJson | ConvertFrom-Json - - if ($openPRs.Count -gt 0) { - Write-Output "Found $($openPRs.Count) existing open font data update PR(s)" - - foreach ($pr in $openPRs) { - # Skip the current branch if we're updating an existing PR - if ($pr.headRefName -eq $targetBranch) { - Write-Output "Skipping PR #$($pr.number) as it's the current branch: $targetBranch" - continue - } - - Write-Output "Closing superseded PR #$($pr.number): $($pr.title)" - - $supersedenceMessage = if ($targetBranch -eq $currentBranch -and $currentBranch -ne $defaultBranch) { - "This PR has been superseded by updates to branch ``$targetBranch``." - } else { - "This PR has been superseded by a newer font data update." - } - - # Close the PR with a comment - Run gh pr close $($pr.number) --comment $supersedenceMessage - Write-Output "Closed PR #$($pr.number)" - } - } else { - Write-Output 'No existing open font data update PRs found.' - } - } else { - Write-Output 'No existing open font data update PRs found.' - } -} - LogGroup 'Process changes' { if ($targetBranch -eq $currentBranch -and $currentBranch -ne $defaultBranch) { Run git push origin $targetBranch @@ -163,9 +123,81 @@ LogGroup 'Process changes' { Run gh pr create ` --base $defaultBranch ` --head $targetBranch ` - --title "$AUTO_UPDATE_PR_PREFIX $timeStamp" ` + --title "Auto-Update $timeStamp" ` --body 'This PR updates FontsData.json with the latest metadata.' Write-Output "Changes detected and PR opened for branch: $targetBranch" + + # Close any existing open Auto-Update PRs after creating the new one + LogGroup 'Close superseded PRs' { + Write-Output 'Checking for existing open Auto-Update PRs to supersede...' + + # Get the newly created PR with retry logic + $newPRJson = $null + $retryCount = 0 + $maxRetries = 3 + $retryDelays = @(1, 2, 3) # Progressive delays in seconds + while ($null -eq $newPRJson -and $retryCount -lt $maxRetries) { + if ($retryCount -gt 0) { + Start-Sleep -Seconds $retryDelays[$retryCount - 1] + } + $newPRJson = Run gh pr list --repo $repoName --head $targetBranch --state open --json 'number,title' --limit 1 + $newPR = $newPRJson | ConvertFrom-Json | Select-Object -First 1 + if ($null -eq $newPR -or $null -eq $newPR.number) { + $newPR = $null + $newPRJson = $null + } + $retryCount++ + if ($null -eq $newPR -and $retryCount -lt $maxRetries) { + Write-Output "PR not found yet, retrying in $($retryDelays[$retryCount - 1]) seconds... (attempt $retryCount/$maxRetries)" + } + } + + if ($null -ne $newPR) { + Write-Output "Found new PR #$($newPR.number): $($newPR.title)" + + # Find existing open Auto-Update PRs (excluding the one we just created) + $existingPRsJson = Run gh pr list --repo $repoName --state open --search 'Auto-Update in:title' --json 'number,title,headRefName' + $existingPRs = $existingPRsJson | ConvertFrom-Json | Where-Object { $_.number -ne $newPR.number } + + if ($existingPRs) { + Write-Output "Found $(@($existingPRs).Count) existing Auto-Update PR(s) to close." + foreach ($pr in $existingPRs) { + Write-Output "Closing PR #$($pr.number): $($pr.title)" + + # Add a comment explaining the supersedence + $comment = @" +This PR has been superseded by #$($newPR.number) and will be closed automatically. + +The font data has been updated in the newer PR. Please refer to #$($newPR.number) for the most current changes. +"@ + Run gh pr comment $pr.number --repo $repoName --body $comment + + # Close the PR + Run gh pr close $pr.number --repo $repoName + + Write-Output "Successfully closed PR #$($pr.number)" + + # Delete the branch associated with the closed PR + $branchName = $pr.headRefName + if ($branchName) { + Write-Output "Deleting branch: $branchName" + $null = Run gh api -X DELETE "repos/$repoName/git/refs/heads/$branchName" + if ($LASTEXITCODE -eq 0) { + Write-Output "Successfully deleted branch: $branchName" + } else { + Write-Warning "Failed to delete branch $branchName (exit code $LASTEXITCODE)" + } + } else { + Write-Warning "Could not determine branch name for PR #$($pr.number)" + } + } + } else { + Write-Output 'No existing open Auto-Update PRs to close.' + } + } else { + Write-Warning "Could not retrieve the newly created PR after $maxRetries attempts. Skipping supersedence logic." + } + } } }