Update-Package.ps1
# Author: Miodrag Milic <miodrag.milic@gmail.com> # Last Change: 17-Jul-2016. <# .SYNOPSIS Update automatic package .DESCRIPTION This function is used to perform necessary updates to the specified files in the package. It shouldn't be used on its own but must be part of the script which defines two functions: - au_SearchReplace The function should return HashTable where keys are file paths and value is another HashTable where keys and values are standard search and replace strings - au_GetLatest Returns the HashTable where the script specifies information about new Version, new URLs and any other data. You can refer to this variable as the $Latest in the script. While Version is used to determine if updates to the package are needed, other arguments can be used in search and replace patterns or for whatever purpose. With those 2 functions defined, calling Update-Package will: - Update the nuspec with the latest version - Do the necessary file replacements - Check the returned URLs and Versions for validity (unless NoCheckXXX variables are specified) - Pack the files into the nuget package You can also define au_BeforeUpdate and au_AfterUpdate functions to integrate your code into the update pipeline. .EXAMPLE PS> notepad update.ps1 # The following script is used to update the package from the github releases page. # Once it defines the 2 functions, it calls the Update-Package. import-module au function global:au_SearchReplace { @{".\tools\chocolateyInstall.ps1" = @{ "(^[$]url\s*=\s*)('.*')" = "`$1'$($Latest.URL)'" }} } function global:au_GetLatest { $download_page = Invoke-WebRequest -Uri https://github.com/hluk/CopyQ/releases $re = "copyq-.*-setup.exe" $url = $download_page.links | ? href -match $re | select -First 1 -expand href $version = $url -split '-|.exe' | select -Last 1 -Skip 2 return $Latest = @{ URL = $url; Version = $version } } Update-Package #> function Update-Package { [CmdletBinding()] param( #Do not check URL and version for validity. [switch] $NoCheckUrl, #Do not check if latest returned version already exists in the Chocolatey repository. [switch] $NoCheckChocoVersion, #Timeout for all web operations. The default can be specified in global variable $global:au_timeout #If not specified at all it defaults to 100 seconds. [int] $Timeout ) function Load-NuspecFile() { $nu = New-Object xml $nu.psbase.PreserveWhitespace = $true $nu.Load($nuspecFile) $nu } function check_url() { $Latest.Keys | ? {$_ -like 'url*' } | % { $url = $Latest[ $_ ] try { $response = request $url if ($response.ContentType -like '*text/html*') { $res = $false; $err="Latest $packageName URL content type is text/html" } else { $res = $true } } catch { $res = $false $err = $_ } if (!$res) { throw "Can't validate latest $packageName URL '$url'`n$err" } } } function request( $url ) { if ([string]::IsNullOrWhiteSpace($url)) {throw 'The URL is empty'} $request = [System.Net.HttpWebRequest]::Create($url) if ($Timeout) { $request.Timeout = $Timeout*1000 } $request.GetResponse() } function check_version() { $re = '^(\d+)(\.\d+){0,3}$' if ($Latest.Version -notmatch $re) { throw "Latest $packageName version doesn't match the pattern '$re': '$($Latest.Version)'" } } function updated() { #Updated only if nuspec version is lower then online version. That will allow to update package revision manually on package errors. [version]($latest_version) -gt [version]($nuspec_version) } if (!$Timeout) { $Timeout = $global:au_timeout } if ($PSBoundParameters.Keys -notcontains 'NoCheckChocoVersion') { if ($global:NoCheckChocoVersion) { $NoCheckChocoVersion = $global:NoCheckChocoVersion } } if ($PSBoundParameters.Keys -notcontains 'NoCheckUrl') { if ($global:NoCheckUrl) { $NoCheckUrl = $global:NoCheckUrl } } $packageName = Split-Path $pwd -Leaf $nuspecFile = gi "$packageName.nuspec" -ea ig if (!$nuspecFile) {throw 'No nuspec file' } $nu = Load-NuspecFile $global:nuspec_version = $nu.package.metadata.version "$packageName - checking updates" try { $global:Latest = au_GetLatest } catch { throw "au_GetLatest failed`n$_" } $latest_version = $Latest.version if (!$NoCheckUrl) { check_url } check_version "nuspec version: $nuspec_version" "remote version: $latest_version" if (!(updated)) { 'No new version found'; return } if (!$NoCheckChocoVersion) { $choco_url = "https://chocolatey.org/packages/{0}/{1}" -f $packageName, $latest_version try { request $choco_url | out-null "New version is available but it already exists in chocolatey:`n $choco_url" return } catch { } } 'New version is available' $sr = au_SearchReplace if (Test-Path Function:\au_BeforeUpdate) { 'Running au_BeforeUpdate' au_BeforeUpdate } 'Updating files' " $(Split-Path $nuspecFile -Leaf)" " updating version: $nuspec_version -> $latest_version" $nu.package.metadata.version = "$latest_version" $nu.Save($nuspecFile) $sr.Keys | % { $fileName = $_ " $fileName" $fileContent = gc $fileName $sr[ $fileName ].GetEnumerator() | % { (' {0} = {1} ' -f $_.name, $_.value) $fileContent = $fileContent -replace $_.name, $_.value } $fileContent | Out-File -Encoding UTF8 $fileName } cpack if (Test-Path Function:\au_AfterUpdate) { 'Running au_AfterUpdate' au_AfterUpdate } return 'Package updated' } Set-Alias update Update-Package |