Examples/ReleaseNotes.ps1
|
# Require the modern PowerShell runtime used by these runnable examples. #requires -Version 7.0 # Select the repository and number of recent commit subjects to review. [CmdletBinding()] param( # Read commits from this local repository path. [string] $RepositoryPath = (Get-Location).Path, # Bound the commit list size before it is sent as repeated API requests. [ValidateRange(1, 100)] [int] $Count = 20 ) # Import the Cloudflare Clef module from this repository. Import-Module (Join-Path $PSScriptRoot '..' 'PSAICloudflareClef.psd1') -Force # Read abbreviated commit hashes and subjects without changing the repository. $commitLines = @(git -C $RepositoryPath log -n $Count --format='%h%x09%s') if ($LASTEXITCODE -ne 0) { throw "Could not read Git history from '$RepositoryPath'. Check that it is a Git repository." } $commits = foreach ($line in $commitLines) { $parts = $line -split "`t", 2 if ($parts.Count -eq 2) { [pscustomobject]@{ Commit = $parts[0]; Subject = $parts[1] } } } # Classify each subject into one of four release-note groups. $question = New-CloudflareClefQuestion -Name category -Type Choice ` -Instructions 'Classify this Git commit using only its subject. Choose breaking for an incompatible public change that likely requires users to change scripts or configuration; feature for a user-visible capability; fix for a user-visible defect correction; internal for tests, documentation, refactoring, or maintenance without user-visible behavior change.' ` -Criteria ([ordered]@{ breaking = 'An incompatible public change that may require existing users to update scripts or configuration.' feature = 'A new user-visible capability or meaningful improvement.' fix = 'A correction to a user-visible defect.' internal = 'Tests, documentation, refactoring, or maintenance without user-visible behavior change.' }) # Evaluate each commit independently and retain the returned confidence and probabilities. $results = foreach ($commit in $commits) { $answer = (Invoke-CloudflareClefDecision -State @{ Commit = $commit.Commit; Subject = $commit.Subject } -Question $question).answers.category [pscustomobject]@{ Category = $answer.choice; Confidence = [math]::Round([double]$answer.confidence, 2); Probabilities = $answer.probabilities; Commit = $commit.Commit; Subject = $commit.Subject } } # Show every category so internal work stays visible during review. foreach ($category in 'breaking', 'feature', 'fix', 'internal') { $items = @($results | Where-Object Category -eq $category) if ($items.Count -eq 0) { continue } $heading = if ($category -eq 'internal') { 'Internal changes (left out of draft)' } else { $category.ToUpperInvariant() } Write-Host "`n$heading" -ForegroundColor Cyan $items | Sort-Object Confidence -Descending | Format-Table Confidence, Commit, Subject -Wrap } # Produce a draft list from behavior changes for a human to edit before publishing. Write-Host "`nDraft release notes (review before publishing):" -ForegroundColor Cyan $results | Where-Object Category -in @('breaking', 'feature', 'fix') | Sort-Object @{ Expression = { @('breaking', 'feature', 'fix').IndexOf($_.Category) } }, @{ Expression = 'Confidence'; Descending = $true } | ForEach-Object { "- [$($_.Category)] $($_.Subject)" } |