Public/Build/Read-Changelog.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
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' ) # Import the changelog 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 # 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" } } # 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 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 } } |