Public/Build/Update-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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
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)" } } |