Public/Build/Update-Changelog.ps1
function Update-Changelog { [CmdletBinding()] param ( # The path to the changelog file [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [SupportsWildcards()] [string] $ChangelogPath, # The type of release (major, minor, patch) [Parameter( Mandatory = $false )] [ValidateSet('major', 'minor', 'patch')] [string] $ReleaseType, # The feature list for this release [Parameter( Mandatory = $false )] [array] $Features, # Any bugfixes in this release [Parameter( Mandatory = $false )] [array] $Bugfixes, # Any known issues in this release [Parameter( Mandatory = $false )] [array] $KnownIssues, # The URL of the repo that the changelog belongs to # If none is provided the cmdlet will attempt to work it out from the current changelog and prompt if needed [Parameter( Mandatory = $false )] [string] $RepoUrl, # If set will attempt to auto-generate features from the commit history (ignored if $Features are passed into the cmdlet) [Parameter( Mandatory = $false )] [switch] $AutoGenerateFeatures, # Skip optional prompts [Parameter( Mandatory = $false )] [switch] $SkipOptionalPrompts ) Write-Verbose 'Checking changelog path is valid' if (!(Test-Path $ChangelogPath)) { throw "$ChangelogPath does not appear to be a valid path to a changelog" } # Read current changelog information try { $CurrentChangelogInfo = Read-Changelog -ChangelogPath $ChangelogPath } catch { throw "Failed to get current changelog information.`n$($_.Exception.Message)" } # If we don't have a URL already then try to extract it from the changelog if (!$RepoUrl) { $RepoURL = $CurrentChangelogInfo.RepoURL } # Start by getting mandatory information Write-Verbose 'Checking all required information is present' # Find out what type of release we are doing # We re-cast ReleaseType to a new variable as PowerShell does something special with cmdlet parameters when they are set-up # Meaning we can get some weird errors if we try to re-use them $ReleaseTypeCheck = $ReleaseType $ValidReleaseTypes = @('major', 'minor', 'patch') while ($ReleaseTypeCheck -notin $ValidReleaseTypes) { $ReleaseTypeCheck = Get-Response ` -Prompt "What kind of release is this? (major/minor/patch)`n Major (Breaking changes from previous version)`n Minor (Backwards compatible changes from previous version)`n Patch (Minor backwards compatible bug fixes from previous version)" ` -ResponseType 'string' ` -Mandatory } # Increment our version number based on what kind of release we're doing switch ($ReleaseTypeCheck) { 'major' { $Version = [version]::New("$($CurrentChangelogInfo.CurrentVersion.Major + 1).0.0") } 'minor' { $Version = [version]::New("$($CurrentChangelogInfo.CurrentVersion.Major).$($CurrentChangelogInfo.CurrentVersion.Minor + 1).0") } 'patch' { $Version = [version]::New("$($CurrentChangelogInfo.CurrentVersion.Major).$($CurrentChangelogInfo.CurrentVersion.Minor).$($CurrentChangelogInfo.CurrentVersion.Build + 1)") } } Write-Verbose "Version is now $($Version.ToString())" if (!$Features) { Write-Verbose 'Prompting for features' # Offer to auto generate a list of release features from the git commit history for this branch (if we haven't already specified it in the params above) if (!$AutoGenerateFeatures) { $AutoGenerateFeatures = Get-Response ` -Prompt 'Would you like to generate a list of new features for this release from this branches commit history?' ` -ResponseType 'bool' } if ($AutoGenerateFeatures) { Write-Verbose 'Auto-generating a list of features based off of commit history' try { # First get the current branch $CurrentBranch = Invoke-NativeCommand ` -FilePath 'git' ` -Arguments 'rev-parse --abbrev-ref HEAD' ` -PassThru ` -SuppressOutput | Select-Object -ExpandProperty OutputContent Write-Verbose "CurrentBranch detected as $CurrentBranch" # Create a git log search filter that will list all commits between the previous tag and the current HEAD $CommitSearcher = "v$($CurrentChangelogInfo.CurrentVersion.ToString())..HEAD" # Query the git log for all merge changes since the previous tag # Output only the body string (%b) and dump the result into an array # We use merges to try and cut down on the number of false positives, if this proves to be not verbose enough # we can switch back to messages (%s) $Features = (Invoke-NativeCommand ` -FilePath 'git' ` -Arguments "log --merges $CommitSearcher --pretty=`"%b`"" ` -PassThru ` -SuppressOutput | Select-Object -ExpandProperty OutputContent) -split "`n" if (!$Features) { Write-Error 'Failed to automatically get a list of commits' } } catch { throw $_.Exception.Message } } else { $Features = Get-Response ` -Prompt 'What are the new features that this release brings?' ` -ResponseType 'array' ` -Mandatory } } # If we haven't got the URL by now then prompt for it if (!$RepoUrl) { $RepoUrl = Get-Response ` -Prompt 'What is the URL of the repo that the changelog belongs to?' ` -ResponseType 'string' ` -Mandatory } # Get any optional params if (-not $SkipOptionalPrompts) { Write-Verbose 'Prompting for optional information' # We use '-notin $PSBoundParameters.Keys' instead of '-not' or '!' as this ensures we get the correct result each time...trust me if ('BugFixes' -notin $PSBoundParameters.Keys) { $Bugfixes = Get-Response ` -Prompt 'What Bugfixes does this release bring?' ` -ResponseType 'array' } if ('KnownIssues' -notin $PSBoundParameters.Keys) { $KnownIssues = Get-Response ` -Prompt 'What known issues are present in this release?' ` -ResponseType 'array' } } # Generate the new changelog block $ChangelogBlockParams = @{ Version = $Version RepoUrl = $RepoUrl Features = $Features } if ($Bugfixes) { $ChangelogBlockParams.Add('Bugfixes', $Bugfixes) } if ($KnownIssues) { $ChangelogBlockParams.Add('KnownIssues', $KnownIssues) } Write-Verbose 'Generating new changelog block' try { $ChangelogBlock = New-ChangelogBlock @ChangelogBlockParams } catch { throw $_.Exception.Message } Write-Debug $ChangelogBlock # All being good lets update our changelog! try { $CurrentChangelogInfo | Add-ChangelogEntry -NewContent $ChangelogBlock } catch { Write-Error "Failed to update changelog.$($_.Exception.Message)" } } |