Skip to content

Commit d5c257b

Browse files
Copilotmazhelez
andauthored
Add PowerShell script to add review comments on PRs modifying release notes (#2058)
### ❔What, Why & How Contributors updating `RELEASENOTES.md` need to be notified when a new AL-Go version is released so they can move their changes above the new version section to maintain proper changelog structure. **Solution:** - **PowerShell Script** (`Internal/Scripts/CommentOnExistingReleaseNotesPrs.ps1`): Manual script using GitHub CLI to add review comments directly on RELEASENOTES.md file changes in open PRs - **Automatic Version Detection**: Script automatically detects the current version from `RELEASENOTES.md` using multiline regex pattern that supports vX.Y format only - **Inline Documentation**: Complete usage instructions and implementation details in the script header **Usage:** ```powershell # Recommended: Use gh auth login for secure authentication gh auth login # Or set token as environment variable (may be visible in shell history) $env:GH_TOKEN = "your-token-here" # or $env:GITHUB_TOKEN = "your-token-here" # Run the script pwsh Internal/Scripts/CommentOnExistingReleaseNotesPrs.ps1 ``` **Key Features:** - **GitHub CLI Integration**: Uses `gh` commands for better readability and maintainability - **Review Comments on File Changes**: Adds comments directly on RELEASENOTES.md file in the "Files changed" tab at line 1, not as general PR comments - **Version Release Notification**: Informs contributors that a new AL-Go version has been released and their changes need to be moved - **Automatic Version Detection**: No manual updates needed when releasing new versions (supports vX.Y format only) - **Fail-fast Error Handling**: Errors out if version cannot be detected (no fallback defaults) - **Version-Specific Comment Checking**: Verifies if review comments for the current version exist on RELEASENOTES.md before adding new ones, allowing re-commenting when version changes - **Comprehensive Reporting**: Detailed summary with success/skip/fail counts and failed PR list - **Robust Error Handling**: Handles edge cases (empty PR lists, null results, API failures) with proper array checking - **Secure Authentication**: Recommends `gh auth login` with warnings about shell history exposure - **Resource Cleanup**: Finally block ensures temporary files are always removed - **Exit Codes**: Returns 0 for success, 1 for failures - **Idiomatic PowerShell**: Uses `@()` array operator for clean, simple array handling - **Self-Documenting**: All documentation is in the script header for easy maintenance - **Code Quality**: UTF-8 with BOM encoding, passes all pre-commit checks and PSScriptAnalyzer validation with zero alerts - **Scalability**: Supports up to 1000 open PRs (maximum limit for gh CLI) - **Progress Suppression**: Includes `$ProgressPreference = "SilentlyContinue"` for cleaner output in automated scenarios - **Naming Convention**: Script follows PascalCase naming convention consistent with other PowerShell scripts in the repository **Comment Message:** ``` A new version of AL-Go (vX.Y) has been released. Please move your release notes changes to above the ## vX.Y 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. ``` **Implementation Details:** - Uses multiline regex `(?m)^##\s*v(\d+\.\d+)` for version detection (major.minor format only) - Creates review comments using GitHub API endpoint `/repos/{owner}/{repo}/pulls/{pr}/comments` with required `line: 1` field - Review comments include `path: "RELEASENOTES.md"`, `line: 1`, and the PR's head commit SHA - Checks for existing review comments on RELEASENOTES.md file with version-specific text: "A new version of AL-Go (vX.Y) has been released." - Version-specific checking prevents false positives from comments about different versions and allows re-commenting when a new version is released - Properly validates empty arrays using `@($existingReviewComments).Count -gt 0` check - Uses `Write-Host` with error indicators (✗) for consistent error reporting instead of `Write-Warning` - Tracks success, skip, and fail counts separately - Lists specific PR numbers that failed for manual review - Uses `@()` array operator for simplified null-safe array handling - Properly escapes `$searchText` to prevent issues with special characters in jq filters - Fetches up to 1000 open PRs (maximum for gh CLI) with documentation note about limitation - Suppresses progress bars with `$ProgressPreference = "SilentlyContinue"` for consistency with other scripts in the repository - Discards API response output using `Out-Null` to avoid unused variable warnings - Script is located in `Internal/Scripts/` alongside other internal utility scripts - File encoded with UTF-8 with BOM for PSScriptAnalyzer compliance - Code follows repository standards with no trailing whitespace - File name uses PascalCase (`CommentOnExistingReleaseNotesPrs.ps1`) to match repository conventions (e.g., `GetOwnerForE2ETests.ps1`, `RemoveTempRepos.ps1`) **Requirements:** - GitHub CLI (`gh`) installed: https://cli.github.com/ - GitHub authentication (via `gh auth login` or token) - PowerShell 7 or later Related to issue: # ### ✅ Checklist - [ ] Add tests (E2E, unit tests) - [ ] Update RELEASENOTES.md - [x] Update documentation (e.g. for new settings or scenarios) - [ ] Add telemetry <!-- START COPILOT CODING AGENT SUFFIX --> <details> <summary>Original prompt</summary> > Go through all open PRs that change the release notes and add a comment that it needs to be moved above the new version section. </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mazhelez <43066499+mazhelez@users.noreply.github.com>
1 parent 4847b79 commit d5c257b

1 file changed

Lines changed: 225 additions & 0 deletions

File tree

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
#!/usr/bin/env pwsh
2+
3+
<#
4+
.SYNOPSIS
5+
Adds a comment to all open PRs that modify RELEASENOTES.md
6+
.DESCRIPTION
7+
This script searches for all open PRs that have changes to RELEASENOTES.md
8+
and adds a reminder comment about placing changes above the new version section.
9+
10+
Uses GitHub CLI (gh) for better readability and maintainability.
11+
12+
The script will:
13+
1. Verify GitHub CLI is installed and authenticated
14+
2. Automatically detect the current version from RELEASENOTES.md
15+
3. Fetch all open pull requests using 'gh pr list'
16+
4. Check each PR to see if it modifies RELEASENOTES.md
17+
5. For PRs that modify the release notes:
18+
- Check if an active reminder comment already exists
19+
- If not, add a comment reminding contributors to place changes above the new version section
20+
6. Provide a detailed summary with success/skip/fail counts
21+
7. List any PRs where comment addition failed
22+
.PARAMETER Owner
23+
The repository owner (default: microsoft)
24+
.PARAMETER Repo
25+
The repository name (default: AL-Go)
26+
.EXAMPLE
27+
# Recommended: Use gh auth login (more secure)
28+
gh auth login
29+
./comment-on-existing-release-notes-prs.ps1
30+
.EXAMPLE
31+
# Alternative: Set GH_TOKEN or GITHUB_TOKEN environment variable
32+
# Note: Tokens may be visible in shell history
33+
$env:GH_TOKEN = "your-token-here"
34+
./comment-on-existing-release-notes-prs.ps1
35+
.NOTES
36+
Requirements:
37+
- GitHub CLI (gh) installed: https://cli.github.com/
38+
- GitHub authentication (via 'gh auth login' or GH_TOKEN/GITHUB_TOKEN environment variable)
39+
- PowerShell 7 or later
40+
41+
Error Handling:
42+
- Errors out if GitHub CLI is not installed
43+
- Errors out if not authenticated
44+
- Errors out if version cannot be detected from RELEASENOTES.md
45+
- Tracks and reports failed comment additions
46+
- Exit code 1 if any comments fail, 0 if all successful
47+
#>
48+
49+
param(
50+
[string]$Owner = "microsoft",
51+
[string]$Repo = "AL-Go"
52+
)
53+
54+
$ErrorActionPreference = "Stop"; $ProgressPreference = "SilentlyContinue"; Set-StrictMode -Version 2.0
55+
56+
# Check if gh CLI is available
57+
if (-not (Get-Command gh -ErrorAction SilentlyContinue)) {
58+
Write-Error "GitHub CLI (gh) is not installed. Please install it from https://cli.github.com/"
59+
exit 1
60+
}
61+
62+
# Verify authentication
63+
try {
64+
$null = gh auth status 2>&1
65+
if ($LASTEXITCODE -ne 0) {
66+
Write-Error "GitHub CLI is not authenticated. Run 'gh auth login' or set GH_TOKEN/GITHUB_TOKEN environment variable."
67+
exit 1
68+
}
69+
} catch {
70+
Write-Error "Failed to verify GitHub CLI authentication: $_"
71+
exit 1
72+
}
73+
74+
# Detect current version from RELEASENOTES.md
75+
$releaseNotesPath = Join-Path $PSScriptRoot "../../RELEASENOTES.md"
76+
if (-not (Test-Path $releaseNotesPath)) {
77+
Write-Error "RELEASENOTES.md not found at $releaseNotesPath"
78+
exit 1
79+
}
80+
81+
$releaseNotesContent = Get-Content -Path $releaseNotesPath -Raw
82+
if ($releaseNotesContent -match '(?m)^##\s*v(\d+\.\d+)') {
83+
$currentVersion = "v$($matches[1])"
84+
Write-Host "Detected current version: $currentVersion"
85+
} else {
86+
Write-Error "Could not detect version from RELEASENOTES.md. Expected to find a line matching '## vX.Y'"
87+
exit 1
88+
}
89+
90+
$comment = @"
91+
A new version of AL-Go ($currentVersion) has been released.
92+
93+
Please move your release notes changes to above the ``## $currentVersion`` section in the RELEASENOTES.md file.
94+
95+
This ensures your changes are included in the next release rather than being listed under an already-released version.
96+
"@
97+
98+
Write-Host "Fetching open pull requests for $Owner/$Repo..."
99+
100+
# Get all open PRs using gh CLI
101+
# NOTE: The maximum limit for 'gh pr list' is 1000. If the repository has more than 1000 open PRs, some may be missed.
102+
$prsJsonOutput = gh pr list --repo "$Owner/$Repo" --state open --limit 1000 --json number,title,files
103+
if ($LASTEXITCODE -ne 0) {
104+
Write-Error "Failed to fetch pull requests from GitHub"
105+
exit 1
106+
}
107+
108+
$prsJson = @($prsJsonOutput | ConvertFrom-Json)
109+
110+
Write-Host "Found $($prsJson.Count) open PRs. Checking which ones modify RELEASENOTES.md..."
111+
112+
$prsWithReleaseNotes = @()
113+
114+
foreach ($pr in $prsJson) {
115+
$prNumber = $pr.number
116+
Write-Host "Checking PR #$prNumber..."
117+
118+
# Check if RELEASENOTES.md was modified
119+
$releaseNotesModified = $pr.files | Where-Object { $_.path -eq "RELEASENOTES.md" }
120+
121+
if ($releaseNotesModified) {
122+
Write-Host " ✓ PR #$prNumber modifies RELEASENOTES.md"
123+
$prsWithReleaseNotes += $pr
124+
} else {
125+
Write-Host " - PR #$prNumber does not modify RELEASENOTES.md"
126+
}
127+
}
128+
129+
if ($prsWithReleaseNotes.Count -eq 0) {
130+
Write-Host "`nNo PRs found that modify RELEASENOTES.md. Exiting."
131+
exit 0
132+
}
133+
134+
Write-Host "`nFound $($prsWithReleaseNotes.Count) PRs that modify RELEASENOTES.md"
135+
Write-Host "`nAdding comments to PRs..."
136+
137+
$successCount = 0
138+
$skipCount = 0
139+
$failCount = 0
140+
$failedPRs = @()
141+
142+
foreach ($pr in $prsWithReleaseNotes) {
143+
$prNumber = $pr.number
144+
$prTitle = $pr.title
145+
146+
Write-Host "`nProcessing PR #${prNumber}: $prTitle"
147+
148+
# Check if we've already commented (check for review comments on RELEASENOTES.md)
149+
$searchText = "A new version of AL-Go ($currentVersion) has been released."
150+
$escapedSearchText = $searchText -replace '\\', '\\\\' -replace '"', '\"'
151+
$existingReviewCommentsOutput = gh api "/repos/$Owner/$Repo/pulls/$prNumber/comments" --jq "[.[] | select(.path == `"RELEASENOTES.md`" and (.body | contains(`"$escapedSearchText`")))]"
152+
153+
if ($LASTEXITCODE -eq 0) {
154+
$existingReviewComments = $existingReviewCommentsOutput | ConvertFrom-Json -ErrorAction SilentlyContinue
155+
156+
if ($existingReviewComments -and @($existingReviewComments).Count -gt 0) {
157+
Write-Host " ℹ️ Review comment already exists on RELEASENOTES.md in PR #$prNumber, skipping..."
158+
$skipCount++
159+
continue
160+
}
161+
}
162+
163+
# Add review comment on RELEASENOTES.md file
164+
$tempFile = $null
165+
try {
166+
# Get the commit SHA for the PR
167+
$prDetails = gh api "/repos/$Owner/$Repo/pulls/$prNumber" | ConvertFrom-Json
168+
$commitSha = $prDetails.head.sha
169+
170+
# Create review comment payload
171+
$reviewCommentBody = @{
172+
body = $comment
173+
path = "RELEASENOTES.md"
174+
commit_id = $commitSha
175+
line = 1
176+
} | ConvertTo-Json -Compress
177+
178+
# Save to temp file
179+
$tempFile = [System.IO.Path]::GetTempFileName()
180+
Set-Content -Path $tempFile -Value $reviewCommentBody -NoNewline
181+
182+
# Post the review comment
183+
gh api -X POST "/repos/$Owner/$Repo/pulls/$prNumber/comments" --input $tempFile | Out-Null
184+
185+
if ($LASTEXITCODE -eq 0) {
186+
Write-Host " ✓ Review comment added to RELEASENOTES.md in PR #$prNumber"
187+
$successCount++
188+
} else {
189+
Write-Host " ✗ Failed to add review comment to PR #${prNumber}"
190+
$failCount++
191+
$failedPRs += $prNumber
192+
}
193+
}
194+
catch {
195+
Write-Host " ✗ Failed to add review comment to PR #${prNumber}: $_"
196+
$failCount++
197+
$failedPRs += $prNumber
198+
}
199+
finally {
200+
# Always clean up temp file
201+
if ($tempFile -and (Test-Path $tempFile)) {
202+
Remove-Item -Path $tempFile -Force -ErrorAction SilentlyContinue
203+
}
204+
}
205+
}
206+
207+
# Final summary
208+
Write-Host "`n========================================="
209+
Write-Host "Summary:"
210+
Write-Host " Total PRs with RELEASENOTES.md changes: $($prsWithReleaseNotes.Count)"
211+
Write-Host " Comments added: $successCount"
212+
Write-Host " Skipped (already commented): $skipCount"
213+
Write-Host " Failed: $failCount"
214+
215+
if ($failCount -gt 0) {
216+
Write-Host "`n⚠️ Failed to add comments to the following PRs:"
217+
foreach ($prNum in $failedPRs) {
218+
Write-Host " - PR #$prNum"
219+
}
220+
Write-Host "`nPlease review these PRs manually."
221+
exit 1
222+
} else {
223+
Write-Host "`n✓ Done! All comments have been processed successfully."
224+
exit 0
225+
}

0 commit comments

Comments
 (0)