diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..1d8ab7a --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,85 @@ +# Font Data Updater + +This directory contains scripts for automating the maintenance of the GoogleFonts module. + +## Update-FontsData.ps1 + +This script automatically updates the `src/FontsData.json` file with the latest font metadata from Google Fonts API. + +### 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 metadata from Google Fonts API +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 + - 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 + +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 +- **Permissions**: Requires secrets: + - `GOOGLE_DEVELOPER_API_KEY`: For accessing Google Fonts API + - `GOOGLEFONTS_UPDATER_BOT_CLIENT_ID`: GitHub App client ID + - `GOOGLEFONTS_UPDATER_BOT_PRIVATE_KEY`: GitHub App private key + +### 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 Google Fonts API returns the same data, no PR will be created +- **Authentication errors**: Ensure the GitHub App credentials are correctly configured +- **API rate limits**: The Google Fonts API key must have sufficient quota for daily requests diff --git a/scripts/Update-FontsData.ps1 b/scripts/Update-FontsData.ps1 index 6cf884d..784761c 100644 --- a/scripts/Update-FontsData.ps1 +++ b/scripts/Update-FontsData.ps1 @@ -129,5 +129,63 @@ 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 'PSModule/GoogleFonts' --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 'PSModule/GoogleFonts' --state open --search 'Auto-Update in:title' --json number, title + $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 'PSModule/GoogleFonts' --body $comment + + # Close the PR + Run h pr close $pr.number --repo 'PSModule/GoogleFonts' + + Write-Output "Successfully closed 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." + } + } } }