-
Notifications
You must be signed in to change notification settings - Fork 176
Add PowerShell script to add review comments on PRs modifying release notes #2058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Copilot
wants to merge
30
commits into
main
Choose a base branch
from
copilot/comment-release-notes-prs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
9c696ca
Initial plan
Copilot 2c0e4da
Add workflow and script to comment on release notes PRs
Copilot 3804759
Add documentation for release notes PR automation
Copilot 72ddc4e
Add manual workflow to comment on existing release notes PRs
Copilot e43f26b
Auto-detect version from RELEASENOTES.md instead of hardcoding
Copilot 307c1d1
Use more flexible regex pattern for version detection
Copilot 46506c2
Support optional patch version in regex pattern
Copilot 52fd30e
Improve PowerShell script logic and fix syntax errors
Copilot 2f26fb1
Error out if version cannot be detected from RELEASENOTES.md
Copilot 3bb21cd
Refactor to use GitHub CLI and remove workflows per feedback
Copilot 64e0e56
Fix error handling and add security notes per code review
Copilot 10e3d2b
Add finally block for temp file cleanup and simplify jq filter
Copilot c762f5b
Fix regex to use multiline modifier for version detection
Copilot f608059
Handle null result from ConvertFrom-Json on empty arrays
Copilot 7f92ee2
Remove support for vX.Y.Z format, only support vX.Y
Copilot 7a54d94
Simplify array handling with @() operator
Copilot 0cd998e
Move script to _Internal folder and remove separate documentation files
Copilot 434f9af
Change to review comments on RELEASENOTES.md and rephrase message
Copilot cb95a1d
Move script to Internal/Scripts folder at repository root
Copilot 707667d
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez 26de992
Include current version in existing comment check
Copilot a063f9d
Fix trailing whitespace in script
Copilot 0f405e7
Fix file encoding to UTF-8 with BOM for PSScriptAnalyzer
Copilot 5807318
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez e26d8d6
Address PR review comments - fix API payload, error handling, and limits
Copilot f508d16
Remove unused response variable to fix PSScriptAnalyzer alert
Copilot 6a3774f
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez 64373f2
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez 66e4c02
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez 5c9b831
Rename script to PascalCase to match repository convention
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,225 @@ | ||
| #!/usr/bin/env pwsh | ||
|
|
||
| <# | ||
| .SYNOPSIS | ||
| Adds a comment to all open PRs that modify RELEASENOTES.md | ||
| .DESCRIPTION | ||
| This script searches for all open PRs that have changes to RELEASENOTES.md | ||
| and adds a reminder comment about placing changes above the new version section. | ||
|
|
||
| Uses GitHub CLI (gh) for better readability and maintainability. | ||
|
|
||
| The script will: | ||
| 1. Verify GitHub CLI is installed and authenticated | ||
| 2. Automatically detect the current version from RELEASENOTES.md | ||
| 3. Fetch all open pull requests using 'gh pr list' | ||
| 4. Check each PR to see if it modifies RELEASENOTES.md | ||
| 5. For PRs that modify the release notes: | ||
| - Check if an active reminder comment already exists | ||
| - If not, add a comment reminding contributors to place changes above the new version section | ||
| 6. Provide a detailed summary with success/skip/fail counts | ||
| 7. List any PRs where comment addition failed | ||
| .PARAMETER Owner | ||
| The repository owner (default: microsoft) | ||
| .PARAMETER Repo | ||
| The repository name (default: AL-Go) | ||
| .EXAMPLE | ||
| # Recommended: Use gh auth login (more secure) | ||
| gh auth login | ||
| ./comment-on-existing-release-notes-prs.ps1 | ||
| .EXAMPLE | ||
| # Alternative: Set GH_TOKEN or GITHUB_TOKEN environment variable | ||
| # Note: Tokens may be visible in shell history | ||
| $env:GH_TOKEN = "your-token-here" | ||
| ./comment-on-existing-release-notes-prs.ps1 | ||
| .NOTES | ||
| Requirements: | ||
| - GitHub CLI (gh) installed: https://cli.github.com/ | ||
| - GitHub authentication (via 'gh auth login' or GH_TOKEN/GITHUB_TOKEN environment variable) | ||
| - PowerShell 7 or later | ||
|
|
||
| Error Handling: | ||
| - Errors out if GitHub CLI is not installed | ||
| - Errors out if not authenticated | ||
| - Errors out if version cannot be detected from RELEASENOTES.md | ||
| - Tracks and reports failed comment additions | ||
| - Exit code 1 if any comments fail, 0 if all successful | ||
| #> | ||
|
|
||
| param( | ||
| [string]$Owner = "microsoft", | ||
| [string]$Repo = "AL-Go" | ||
| ) | ||
|
|
||
| $ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0 | ||
|
|
||
| # Check if gh CLI is available | ||
| if (-not (Get-Command gh -ErrorAction SilentlyContinue)) { | ||
| Write-Error "GitHub CLI (gh) is not installed. Please install it from https://cli.github.com/" | ||
| exit 1 | ||
| } | ||
|
|
||
| # Verify authentication | ||
| try { | ||
| $null = gh auth status 2>&1 | ||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-Error "GitHub CLI is not authenticated. Run 'gh auth login' or set GH_TOKEN/GITHUB_TOKEN environment variable." | ||
| exit 1 | ||
| } | ||
| } catch { | ||
| Write-Error "Failed to verify GitHub CLI authentication: $_" | ||
| exit 1 | ||
| } | ||
|
|
||
| # Detect current version from RELEASENOTES.md | ||
| $releaseNotesPath = Join-Path $PSScriptRoot "../../RELEASENOTES.md" | ||
| if (-not (Test-Path $releaseNotesPath)) { | ||
| Write-Error "RELEASENOTES.md not found at $releaseNotesPath" | ||
| exit 1 | ||
| } | ||
|
|
||
| $releaseNotesContent = Get-Content -Path $releaseNotesPath -Raw | ||
| if ($releaseNotesContent -match '(?m)^##\s*v(\d+\.\d+)') { | ||
| $currentVersion = "v$($matches[1])" | ||
| Write-Host "Detected current version: $currentVersion" | ||
| } else { | ||
| Write-Error "Could not detect version from RELEASENOTES.md. Expected to find a line matching '## vX.Y'" | ||
| exit 1 | ||
| } | ||
|
|
||
| $comment = @" | ||
| A new version of AL-Go ($currentVersion) has been released. | ||
|
|
||
| Please move your release notes changes to above the ``## $currentVersion`` section in the RELEASENOTES.md file. | ||
|
|
||
| This ensures your changes are included in the next release rather than being listed under an already-released version. | ||
| "@ | ||
|
|
||
| Write-Host "Fetching open pull requests for $Owner/$Repo..." | ||
|
|
||
| # Get all open PRs using gh CLI | ||
| # NOTE: The maximum limit for 'gh pr list' is 1000. If the repository has more than 1000 open PRs, some may be missed. | ||
| $prsJsonOutput = gh pr list --repo "$Owner/$Repo" --state open --limit 1000 --json number,title,files | ||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-Error "Failed to fetch pull requests from GitHub" | ||
| exit 1 | ||
| } | ||
|
|
||
| $prsJson = @($prsJsonOutput | ConvertFrom-Json) | ||
|
|
||
| Write-Host "Found $($prsJson.Count) open PRs. Checking which ones modify RELEASENOTES.md..." | ||
|
|
||
| $prsWithReleaseNotes = @() | ||
|
|
||
| foreach ($pr in $prsJson) { | ||
| $prNumber = $pr.number | ||
| Write-Host "Checking PR #$prNumber..." | ||
|
|
||
| # Check if RELEASENOTES.md was modified | ||
| $releaseNotesModified = $pr.files | Where-Object { $_.path -eq "RELEASENOTES.md" } | ||
|
|
||
| if ($releaseNotesModified) { | ||
| Write-Host " ✓ PR #$prNumber modifies RELEASENOTES.md" | ||
| $prsWithReleaseNotes += $pr | ||
| } else { | ||
| Write-Host " - PR #$prNumber does not modify RELEASENOTES.md" | ||
| } | ||
| } | ||
|
|
||
| if ($prsWithReleaseNotes.Count -eq 0) { | ||
mazhelez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Write-Host "`nNo PRs found that modify RELEASENOTES.md. Exiting." | ||
| exit 0 | ||
| } | ||
|
|
||
| Write-Host "`nFound $($prsWithReleaseNotes.Count) PRs that modify RELEASENOTES.md" | ||
| Write-Host "`nAdding comments to PRs..." | ||
|
|
||
| $successCount = 0 | ||
| $skipCount = 0 | ||
| $failCount = 0 | ||
| $failedPRs = @() | ||
|
|
||
| foreach ($pr in $prsWithReleaseNotes) { | ||
| $prNumber = $pr.number | ||
| $prTitle = $pr.title | ||
|
|
||
| Write-Host "`nProcessing PR #${prNumber}: $prTitle" | ||
|
|
||
| # Check if we've already commented (check for review comments on RELEASENOTES.md) | ||
| $searchText = "A new version of AL-Go ($currentVersion) has been released." | ||
| $escapedSearchText = $searchText -replace '\\', '\\\\' -replace '"', '\"' | ||
| $existingReviewCommentsOutput = gh api "/repos/$Owner/$Repo/pulls/$prNumber/comments" --jq "[.[] | select(.path == `"RELEASENOTES.md`" and (.body | contains(`"$escapedSearchText`")))]" | ||
|
|
||
| if ($LASTEXITCODE -eq 0) { | ||
| $existingReviewComments = $existingReviewCommentsOutput | ConvertFrom-Json -ErrorAction SilentlyContinue | ||
|
|
||
| if ($existingReviewComments -and @($existingReviewComments).Count -gt 0) { | ||
| Write-Host " ℹ️ Review comment already exists on RELEASENOTES.md in PR #$prNumber, skipping..." | ||
| $skipCount++ | ||
| continue | ||
| } | ||
| } | ||
|
|
||
| # Add review comment on RELEASENOTES.md file | ||
| $tempFile = $null | ||
| try { | ||
| # Get the commit SHA for the PR | ||
| $prDetails = gh api "/repos/$Owner/$Repo/pulls/$prNumber" | ConvertFrom-Json | ||
| $commitSha = $prDetails.head.sha | ||
|
|
||
| # Create review comment payload | ||
| $reviewCommentBody = @{ | ||
| body = $comment | ||
| path = "RELEASENOTES.md" | ||
| commit_id = $commitSha | ||
mazhelez marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| line = 1 | ||
| } | ConvertTo-Json -Compress | ||
|
|
||
| # Save to temp file | ||
| $tempFile = [System.IO.Path]::GetTempFileName() | ||
| Set-Content -Path $tempFile -Value $reviewCommentBody -NoNewline | ||
|
|
||
| # Post the review comment | ||
| gh api -X POST "/repos/$Owner/$Repo/pulls/$prNumber/comments" --input $tempFile | Out-Null | ||
|
|
||
| if ($LASTEXITCODE -eq 0) { | ||
| Write-Host " ✓ Review comment added to RELEASENOTES.md in PR #$prNumber" | ||
| $successCount++ | ||
| } else { | ||
| Write-Host " ✗ Failed to add review comment to PR #${prNumber}" | ||
| $failCount++ | ||
| $failedPRs += $prNumber | ||
| } | ||
| } | ||
| catch { | ||
| Write-Host " ✗ Failed to add review comment to PR #${prNumber}: $_" | ||
| $failCount++ | ||
| $failedPRs += $prNumber | ||
| } | ||
| finally { | ||
| # Always clean up temp file | ||
| if ($tempFile -and (Test-Path $tempFile)) { | ||
| Remove-Item -Path $tempFile -Force -ErrorAction SilentlyContinue | ||
| } | ||
| } | ||
| } | ||
|
|
||
| # Final summary | ||
| Write-Host "`n=========================================" | ||
| Write-Host "Summary:" | ||
| Write-Host " Total PRs with RELEASENOTES.md changes: $($prsWithReleaseNotes.Count)" | ||
| Write-Host " Comments added: $successCount" | ||
| Write-Host " Skipped (already commented): $skipCount" | ||
| Write-Host " Failed: $failCount" | ||
|
|
||
| if ($failCount -gt 0) { | ||
| Write-Host "`n⚠️ Failed to add comments to the following PRs:" | ||
| foreach ($prNum in $failedPRs) { | ||
| Write-Host " - PR #$prNum" | ||
| } | ||
| Write-Host "`nPlease review these PRs manually." | ||
| exit 1 | ||
| } else { | ||
| Write-Host "`n✓ Done! All comments have been processed successfully." | ||
| exit 0 | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.