Public/Build/Read-Changelog.ps1
function Read-Changelog { [CmdletBinding()] param( # The path of the changelog file to read from, wildcards are permitted. [Parameter( Mandatory = $true, Position = 0, ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [SupportsWildcards()] [string] $ChangelogPath, # The regex to use for version matching. # It should always contain a capture group named "version" as this is what the regex matcher will use to extract the version number [Parameter( Mandatory = $false, Position = 1 )] [string] $VersionPattern = '^#*\s\[v(?<version>[0-9]+\.[0-9]+\.[0-9]+)\]\((?:.*)\)\s\([0-9]+\-[0-9]+\-[0-9]+\)$', # The regex pattern for matching the repo URL. # It should always contain a capture group named "url" and this what the regex searched will use to extract your url [Parameter( Mandatory = $false, Position = 2 )] [string] $RepoURLPattern = '(?<url>http(?:.*))\/tree', # The regex pattern for matching the date of the last release. # It should always contain a capture group named "date" and this what the regex searched will use to extract your date [Parameter( Mandatory = $false, Position = 3 )] [string] $LastReleaseDatePattern = '\((?<date>[\d|-]*)\)' ) Write-Warning 'This cmdlet is deprecated and will be removed in a future release, please use Read-BrownserveChangelog instead.' # Import the changelog, we don't use the -Raw switch as we want to read the file line by line try { $Changelog = Get-Content $ChangelogPath } catch { throw "Failed to get changelog content.$($_.Exception.Message)" } # We'll store all the lines after the headers in this array so we can get the ChangelogText if we want it $ChangelogText = @() # We'll look for our current version and previous version so we can get the text in-between which _should_ be our new release notes $CurrentVersion = $null $PreviousVersion = $null # We'll read through each line of this text file so we can work out where our current release notes are $LineCount = 0 $ReleaseNotesStartOn = $null $ReleaseNotesEndOn = $null # We'll also look for the line that we can insert a new entry into (if we want) $NewChangelogLine = $null # We'll also look for the date of the last release $LastReleaseDate = $null # Go through each line until we find what we need $Changelog | ForEach-Object { $Line = $_.Trim() # Return the URL of the repo if we can find it if (-not $RepoUrl) { $RepoUrlMatch = [regex]::Match($Line, $RepoUrlPattern) if ($RepoUrlMatch.Success) { $RepoUrl = $RepoUrlMatch.Groups['url'].Value Write-Verbose "Repo URL determined to be $RepoURL" } } # If we don't already have our current version then see if this line contains it... if (-not $CurrentVersion) { $RegexMatch = [regex]::Match($Line, $VersionPattern) if ($RegexMatch.Success) { # This line matches our version regex! # This has to be the first line we've come across that matches it so it must be the current version. # Extract the version number from our capture group $CurrentVersion = [version] $RegexMatch.Groups['version'].Value # The current release notes will start on the _next_ line after the version number $ReleaseNotesStartOn = $LineCount + 1 # If we want to insert any new changelog entries then we'll need to known where we can do that # It will be the line _before_ our line with the version number on $NewChangelogLine = $LineCount - 1 Write-Verbose "Current version determined to be $CurrentVersion" # Now we've got our current version we can also extract the date of the last release $LastReleaseDateMatch = [regex]::Match($Line, $LastReleaseDatePattern) if ($LastReleaseDateMatch.Success) { $LastReleaseDate = Get-Date $LastReleaseDateMatch.Groups['date'].Value -ErrorAction 'Stop' Write-Verbose "Last release date determined to be $LastReleaseDate" } } } # If we've found our current version number then from here on out the rest of the document will be our changelog, start capturing it! if ($CurrentVersion) { $ChangelogText += $Line } # If we don't already have the previous version number see if this line contains it... if (-not $PreviousVersion) { $RegexMatch = [regex]::Match($Line, $VersionPattern) if ($RegexMatch.Success) { # We've found a potential match! $PreviousVersion = [version] $RegexMatch.Groups['version'].Value # The release notes will end on the line _before_ the previous version number $ReleaseNotesEndOn = $LineCount - 1 # If we've hit the current version then we haven't gone far enough back! # Clear our variables and continue looking if ($PreviousVersion -eq $CurrentVersion) { $PreviousVersion = $null $ReleaseNotesEndOn = $null } } } # Finally increase the line count for the next loop $LineCount++ } # If we haven't got our release notes ending line _and_ a previous version it likely means that we don't have one! (i.e. we are still on the first release!) # So just read until the end of the file if ((-not $ReleaseNotesEndOn) -and (-not $PreviousVersion)) { Write-Verbose "It looks like there is only one release.`nRelease notes will be read from line $ReleaseNotesStartOn until the end of the file" $ReleaseNotesEndOn = $Changelog.Length } else { Write-Verbose "Previous version was: $PreviousVersion, the current versions release notes end on line $ReleaseNotesEndOn" } # Extract the lines that equate to our current release notes try { $ReleaseNotes = $Changelog[$ReleaseNotesStartOn..$ReleaseNotesEndOn] } catch { # Ignore errors, we'll throw below } # If we haven't found a version or the release notes, raise an error if (-not $CurrentVersion) { throw "Failed to find version in changelog file: $ChangelogPath" } if (!$ReleaseNotes) { throw 'Unable to work out current release notes.' } return [pscustomobject]@{ ChangeLogPath = $ChangelogPath # The path to the changelog - useful when piping into other cmdlets RepoURL = $RepoURL # The URL of the repo, useful in other cmdlets Content = $Changelog # Return the whole changelog in all it's gory detail VersionHistory = $ChangelogText # The version history of the changelog CurrentVersion = $CurrentVersion # The latest version according to the changelog ReleasedOn = $LastReleaseDate # The date of the last release ReleaseNotes = $ReleaseNotes -join [System.Environment]::NewLine # The release notes for the latest version only InsertLine = $NewChangelogLine # This will be the line that we can start inserting new entries into } } |