Skip to content
Open
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9c696ca
Initial plan
Copilot Dec 3, 2025
2c0e4da
Add workflow and script to comment on release notes PRs
Copilot Dec 3, 2025
3804759
Add documentation for release notes PR automation
Copilot Dec 3, 2025
72ddc4e
Add manual workflow to comment on existing release notes PRs
Copilot Dec 3, 2025
e43f26b
Auto-detect version from RELEASENOTES.md instead of hardcoding
Copilot Dec 3, 2025
307c1d1
Use more flexible regex pattern for version detection
Copilot Dec 3, 2025
46506c2
Support optional patch version in regex pattern
Copilot Dec 3, 2025
52fd30e
Improve PowerShell script logic and fix syntax errors
Copilot Dec 3, 2025
2f26fb1
Error out if version cannot be detected from RELEASENOTES.md
Copilot Dec 3, 2025
3bb21cd
Refactor to use GitHub CLI and remove workflows per feedback
Copilot Dec 3, 2025
64e0e56
Fix error handling and add security notes per code review
Copilot Dec 3, 2025
10e3d2b
Add finally block for temp file cleanup and simplify jq filter
Copilot Dec 3, 2025
c762f5b
Fix regex to use multiline modifier for version detection
Copilot Dec 3, 2025
f608059
Handle null result from ConvertFrom-Json on empty arrays
Copilot Dec 3, 2025
7f92ee2
Remove support for vX.Y.Z format, only support vX.Y
Copilot Dec 3, 2025
7a54d94
Simplify array handling with @() operator
Copilot Dec 3, 2025
0cd998e
Move script to _Internal folder and remove separate documentation files
Copilot Dec 3, 2025
434f9af
Change to review comments on RELEASENOTES.md and rephrase message
Copilot Dec 3, 2025
cb95a1d
Move script to Internal/Scripts folder at repository root
Copilot Dec 4, 2025
707667d
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez Dec 4, 2025
26de992
Include current version in existing comment check
Copilot Dec 4, 2025
a063f9d
Fix trailing whitespace in script
Copilot Dec 4, 2025
0f405e7
Fix file encoding to UTF-8 with BOM for PSScriptAnalyzer
Copilot Dec 4, 2025
5807318
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez Dec 8, 2025
e26d8d6
Address PR review comments - fix API payload, error handling, and limits
Copilot Dec 8, 2025
f508d16
Remove unused response variable to fix PSScriptAnalyzer alert
Copilot Dec 9, 2025
6a3774f
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez Dec 12, 2025
64373f2
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez Dec 16, 2025
66e4c02
Merge branch 'main' into copilot/comment-release-notes-prs
mazhelez Dec 18, 2025
5c9b831
Rename script to PascalCase to match repository convention
Copilot Dec 18, 2025
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
225 changes: 225 additions & 0 deletions Internal/Scripts/CommentOnExistingReleaseNotesPrs.ps1
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) {
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
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
}
Loading