Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Font Data Updater

This directory contains scripts for automating the maintenance of the NerdFonts module.

## Update-FontsData.ps1

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.

### Features

- **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

### How It Works

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

### PR Lifecycle Management

The font data updater implements PR supersedence similar to Dependabot. When a new update PR is created:

- 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:

```text
This PR has been superseded by #[NEW_PR_NUMBER] and will be closed automatically.

The font data has been updated in the newer PR. Please refer to #[NEW_PR_NUMBER] for the most current changes.
```

- All superseded PRs are automatically closed
- Branches for closed PRs are deleted

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.

### Workflow

#### 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
74 changes: 74 additions & 0 deletions scripts/Update-FontsData.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
}
}

$repoName = $env:GITHUB_REPOSITORY

Install-PSResource -Repository PSGallery -TrustRepository -Name 'Json'

Connect-GitHubApp -Organization 'PSModule' -Default
Expand Down Expand Up @@ -125,5 +127,77 @@ LogGroup 'Process changes' {
--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."
}
}
}
}
Loading