Skip to content
This repository has been archived by the owner on Oct 25, 2022. It is now read-only.

Streams enhancements #109

Merged
merged 7 commits into from
Nov 9, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 6 additions & 17 deletions AU/Plugins/GitReleases.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ param(
# The text that should be used in the description of the release.
[string]$releaseDescription = $null,

# The text that should be used in the description when a release is created for a stream (by default it uses the latest commit message).
[string]$streamReleaseDescription = '',

# The formatting to use when replacing <date> in release header/description and on date based releases.
[string]$dateFormat = '{0:yyyy-MM-dd}',

Expand Down Expand Up @@ -70,14 +67,12 @@ $packagesToRelease = New-Object 'System.Collections.Generic.List[hashtable]'

$packages | % {
if ($_.Streams) {
$pkg = $_
$data = ConvertFrom-Json ($pkg.Streams -replace '@', '' -replace '\s*=\s*', '":"' -replace '{\s*', '{"' -replace '\s*}', '"}' -replace '\s*;\s*', '","')
($data | Get-Member -MemberType NoteProperty).Name | % {
$value = $data.$_
$_.StreamsDetails.Values | ? { $_.Updated } | % {
$packagesToRelease.Add(@{
Name = $pkg.Name
RemoteVersion = $value
NuFile = Resolve-Path ("$($pkg.Path)/*.$($value).nupkg")
Name = $_.Name
NuspecVersion = $_.NuspecVersion
RemoteVersion = $_.RemoteVersion
NuFile = Resolve-Path ("$($_.Path)/$($_.Name).$($_.RemoteVersion).nupkg")
})
}
}
Expand Down Expand Up @@ -143,13 +138,7 @@ $packagesToRelease | % {

if ($releaseType -eq 'package') {
$releaseName = $releaseHeader -replace '<PackageName>', $_.Name -replace '<RemoteVersion>', $_.RemoteVersion -replace '<NuspecVersion>', $_.NuspecVersion -replace '<date>', $date
if ($_.NuspecVersion) {
$packageDesc = $releaseDescription
}
else {
$packageDesc = $streamReleaseDescription
}
$packageDesc = $packageDesc -replace '<PackageName>', $_.Name -replace '<RemoteVersion>', $_.RemoteVersion -replace '<NuspecVersion>', $_.NuspecVersion -replace '<date>', $date
$packageDesc = $releaseDescription -replace '<PackageName>', $_.Name -replace '<RemoteVersion>', $_.RemoteVersion -replace '<NuspecVersion>', $_.NuspecVersion -replace '<date>', $date

$release = GetOrCreateRelease `
-tagName "$($_.Name)-$($_.RemoteVersion)" `
Expand Down
26 changes: 26 additions & 0 deletions AU/Private/AUPackage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class AUPackage {

[string] $StreamsPath
[pscustomobject] $Streams
[hashtable] $StreamsDetails
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't it more intuitive that $Streams actually contains [AUPackage] for each stream instead of StreamsDetails. I don't like you need to use 2 different mechanisms for streams vs non streams where the later should be just a special case having 1 package in stream.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just sayin', not that I can't live with it, given that streams are rare.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, I've merged both properties.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, feel free to merge when you are done with this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! I'm doing a final test and then I merge. Thanks!


AUPackage([string] $Path ){
if ([String]::IsNullOrWhiteSpace( $Path )) { throw 'Package path can not be empty' }
Expand All @@ -31,6 +32,16 @@ class AUPackage {
$this.Streams = [AUPackage]::LoadStreams( $this.StreamsPath )
}

[PSCustomObject] GetStreamDetails() {
return [PSCustomObject] @{
Path = $this.Path
Name = $this.Name
Updated = $this.Updated
RemoteVersion = $this.RemoteVersion
NuspecVersion = $this.NuspecVersion
}
}

static [xml] LoadNuspecFile( $NuspecPath ) {
$nu = New-Object xml
$nu.PSBase.PreserveWhitespace = $true
Expand Down Expand Up @@ -77,4 +88,19 @@ class AUPackage {
return "$d\_output"
}

AUPackage( [hashtable] $obj ) {
if (!$obj) { throw 'Obj can not be empty' }
$obj.Keys | % {
$this.$_ = $obj[$_]
}
}

[hashtable] Serialize() {
$res = @{}
$this | Get-Member -Type Properties | % {
$property = $_.Name
$res.Add($property, $this.$property)
}
return $res
}
}
2 changes: 2 additions & 0 deletions AU/Private/AUVersion.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class AUVersion : System.IComparable {
}
}

[AUVersion] WithVersion([version] $version) { return [AUVersion]::new($version, $this.Prerelease, $this.BuildMetadata) }

[int] CompareTo($obj) {
if ($obj -eq $null) { return 1 }
if ($obj -isnot [AUVersion]) { throw "AUVersion expected: $($obj.GetType())" }
Expand Down
4 changes: 3 additions & 1 deletion AU/Public/Update-AUPackages.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ function Update-AUPackages {
} else {
$pkg.Error = 'Job returned no object, Vector smash ?'
}
} else {
$pkg = [AUPackage]::new($pkg)
}


Expand Down Expand Up @@ -228,7 +230,7 @@ function Update-AUPackages {
. $s $using:package_name $Options
}

$pkg
$pkg.Serialize()
} | Out-Null
}
$result = $result | sort Name
Expand Down
44 changes: 30 additions & 14 deletions AU/Public/Update-Package.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ function Update-Package {
}

function process_stream() {
$package.Updated = $false

if (!(is_version $package.NuspecVersion)) {
Write-Warning "Invalid nuspec file Version '$($package.NuspecVersion)' - using 0.0"
$global:Latest.NuspecVersion = $package.NuspecVersion = '0.0'
Expand Down Expand Up @@ -284,7 +286,7 @@ function Update-Package {

$build = if ($v.Build -eq -1) {0} else {$v.Build}
$v = [version] ('{0}.{1}.{2}.{3}' -f $v.Major, $v.Minor, $build, $d)
$package.RemoteVersion = [AUVersion]::new($v, $nuspecVersion.Prerelease, $nuspecVersion.BuildMetadata).ToString()
$package.RemoteVersion = $nuspecVersion.WithVersion($v).ToString()
$Latest.Version = $package.RemoteVersion -as $Latest.Version.GetType()
}

Expand Down Expand Up @@ -401,30 +403,41 @@ function Update-Package {

if ($res.ContainsKey('Streams')) {
if (!$res.Streams) { throw "au_GetLatest's streams returned nothing" }
if ($res.Streams -isnot [HashTable]) { throw "au_GetLatest's streams don't return a HashTable result but $($res.Streams.GetType())" }
if ($res.Streams -isnot [System.Collections.Specialized.OrderedDictionary] -and $res.Streams -isnot [HashTable]) {
throw "au_GetLatest doesn't return an OrderedDictionary or HashTable result for streams but $($res.Streams.GetType())"
}

# Streams are expected to be sorted starting with the most recent one
$streams = @($res.Streams.Keys)
# In case of HashTable (i.e. not sorted), let's sort streams alphabetically descending
if ($res.Streams -is [HashTable]) { $streams = $streams | sort -Descending }

if ($Include) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include should be renamed to IncludeStream

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if ($Include -isnot [string] -and $Include -isnot [double] -and $Include -isnot [Array]) {
throw "`$Include must be either a String, a Double or an Array but is $($Include.GetType())"
}
if ($Include -is [double]) { $Include = $Include -as [string] }
if ($Include -is [string]) { [Array] $Include = $Include -split ',' | foreach { ,$_.Trim() } }
if ($Include -is [string]) {
# Forcing type in order to handle case when only one version is included
[Array] $Include = $Include -split ',' | % { $_.Trim() }
}
} elseif ($Force) {
$Include = @($res.Streams.Keys | sort { [AUVersion] $_ } -Descending | select -First 1)
# When forcing update, a single stream is expected
# By default, we take the first one (i.e. the most recent one)
$Include = @($streams | select -First 1)
}
if ($Force -and (!$Include -or $Include.Length -ne 1)) { throw 'A single stream must be included when forcing package update' }

if ($Include) {
$streams = @{}
$res.Streams.Keys | ? { $_ -in $Include } | % {
$streams.Add($_, $res.Streams[$_])
}
} else {
$streams = $res.Streams
}
if ($Include) { $streams = $streams | ? { $_ -in $Include } }
# Let's reverse the order in order to process streams starting with the oldest one
[Array]::Reverse($streams)

$streams.Keys | ? { !$Include -or $_ -in $Include } | sort { [AUVersion] $_ } | % {
$stream = $streams[$_]
$res.Keys | ? { $_ -ne 'Streams' } | % { $global:au_Latest.Remove($_) }
$global:au_Latest += $res

$package.StreamsDetails = @{}
$streams | % {
$stream = $res.Streams[$_]

'' | result
"*** Stream: $_ ***" | result
Expand All @@ -440,7 +453,10 @@ function Update-Package {

set_latest $stream $package.Streams.$_ $_
process_stream

$package.StreamsDetails.Add($_, $package.GetStreamDetails())
}
$package.StreamsDetails.Values | ? { $_.updated } | % { $package.Updated = $true }
} else {
'' | result
set_latest $res $package.NuspecVersion
Expand Down
10 changes: 8 additions & 2 deletions test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ param(
[switch]$Chocolatey,

[switch]$Pester,
[string]$Tag
[string]$Tag,
[switch]$CodeCoverage
)

if (!$Chocolatey -and !$Pester) { $Chocolatey = $Pester = $true }
Expand All @@ -20,5 +21,10 @@ if ($Pester) {
Write-Host "`n==| Running Pester tests"

$testResultsFile = "$build_dir/TestResults.xml"
Invoke-Pester -Tag $Tag -OutputFormat NUnitXml -OutputFile $testResultsFile -PassThru
if ($CodeCoverage) {
$files = @(ls $PSScriptRoot/AU/* -Filter *.ps1 -Recurse | % FullName)
Invoke-Pester -Tag $Tag -OutputFormat NUnitXml -OutputFile $testResultsFile -PassThru -CodeCoverage $files
} else {
Invoke-Pester -Tag $Tag -OutputFormat NUnitXml -OutputFile $testResultsFile -PassThru
}
}
80 changes: 24 additions & 56 deletions tests/Update-AUPackages.Streams.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -33,65 +33,33 @@ Describe 'Update-AUPackages using streams' -Tag updateallstreams {

Context 'Plugins' {

It 'should ignore the package that returns "ignore"' {
It 'should execute GitReleases plugin when there are updates' {
gc $global:au_Root\test_package_with_streams_1\update.ps1 | set content
$content -replace 'update', "Write-Host 'test ignore'; 'ignore'" | set content
$content -replace '@\{.+1\.3.+\}', "@{ Version = '1.3.2' }" | set content
$content -replace '@\{.+1\.2.+\}', "@{ Version = '1.2.4' }" | set content
$content | sc $global:au_Root\test_package_with_streams_1\update.ps1

$res = updateall -Options $Options -NoPlugins:$false 6>$null

$res[0].Ignored | Should Be $true
$res[0].IgnoreMessage | Should Be 'test ignore'
}

It 'should repeat and ignore on specific error' {
gc $global:au_Root\test_package_with_streams_1\update.ps1 | set content
$content -replace 'update', "1|Out-File -Append $TestDrive\tmp_test; throw 'test ignore'; update" | set content
$content | sc $global:au_Root\test_package_with_streams_1\update.ps1

$Options.RepeatOn = @('test ignore')
$Options.RepeatCount = 2
$Options.IgnoreOn = @('test ignore')

$res = updateall -Options $Options -NoPlugins:$false 6>$null

$res[0].Ignored | Should Be $true
$res[0].IgnoreMessage | Should BeLike 'AU ignored on*test ignore'

(gc $TestDrive\tmp_test).Count | Should be 3
}

It 'should execute Report plugin' {
$Options.Report = @{
Type = 'markdown'
Path = "$global:au_Root\report.md"
Params = @{ Github_UserRepo = 'majkinetor/chocolatey' }
}

updateall -NoPlugins:$false -Options $Options 6> $null

Test-Path $Options.Report.Path | Should Be $true

$report = gc $Options.Report.Path
($report -match "test_package_with_streams_[1-$pkg_no]").Count | Should Be (3 * $pkg_no)
}

It 'should execute RunInfo plugin' {
$Options.RunInfo = @{
Path = "$global:au_Root\update_info.xml"
Exclude = 'password'

$Options.GitReleases = @{
ApiToken = 'apiToken'
ReleaseType = 'package'
Force = $true
}
$Options.Test = @{
MyPassword = 'password'
Parameter2 = 'p2'`
}

$res = updateall -NoPlugins:$false -Options $Options 6> $null

Test-Path $Options.RunInfo.Path | Should Be $true
$info = Import-Clixml $Options.RunInfo.Path
$info.plugin_results.RunInfo -match 'Test.MyPassword' | Should Be $true
$info.Options.Test.MyPassword | Should Be '*****'
Mock Invoke-RestMethod {
return @{
tag_name = 'test_package_with_streams_1-1.2.4'
assets = @(
@{
url = 'https://api.github.com/test_package_with_streams_1.1.2.4.nupkg'
name = 'test_package_with_streams_1.1.2.4.nupkg'
}
)
}
} -ModuleName AU

updateall -NoPlugins:$false -Options $Options 6> $null

Assert-MockCalled Invoke-RestMethod -Exactly 6 -ModuleName AU
}
}

Expand All @@ -100,7 +68,7 @@ Describe 'Update-AUPackages using streams' -Tag updateallstreams {
$choco_path = gcm choco.exe | % Source
$choco_hash = Get-FileHash $choco_path -Algorithm SHA256 | % Hash
gc $global:au_Root\test_package_with_streams_1\update.ps1 | set content
$content -replace '@\{.+\}', "@{ Version = '1.3'; ChecksumType32 = 'sha256'; Checksum32 = '$choco_hash'}" | set content
$content -replace '@\{.+1\.3.+\}', "@{ Version = '1.3.2'; ChecksumType32 = 'sha256'; Checksum32 = '$choco_hash'}" | set content
$content -replace 'update', "update -ChecksumFor 32" | set content
$content | sc $global:au_Root\test_package_with_streams_1\update.ps1

Expand Down
62 changes: 62 additions & 0 deletions tests/Update-AUPackages.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,68 @@ Describe 'Update-AUPackages' -Tag updateall {
$info.plugin_results.RunInfo -match 'Test.MyPassword' | Should Be $true
$info.Options.Test.MyPassword | Should Be '*****'
}

It 'should execute GitReleases plugin when there are no updates' {
$Options.GitReleases = @{
ApiToken = 'apiToken'
ReleaseType = 'package'
Force = $true
}

Mock Invoke-RestMethod {} -ModuleName AU

updateall -NoPlugins:$false -Options $Options 6> $null

Assert-MockCalled Invoke-RestMethod -Exactly 0 -ModuleName AU
}

It 'should execute GitReleases plugin per package when there are updates' {
gc $global:au_Root\test_package_1\update.ps1 | set content
$content -replace '@\{.+\}', "@{ Version = '1.3' }" | set content
$content | sc $global:au_Root\test_package_1\update.ps1

$Options.GitReleases = @{
ApiToken = 'apiToken'
ReleaseType = 'package'
Force = $true
}

Mock Invoke-RestMethod {
return @{
tag_name = 'test_package_1-1.3'
assets = @(
@{
url = 'https://api.github.com/test_package_1.1.3.nupkg'
name = 'test_package_1.1.3.nupkg'
}
)
}
} -ModuleName AU

updateall -NoPlugins:$false -Options $Options 6> $null

Assert-MockCalled Invoke-RestMethod -Exactly 3 -ModuleName AU
}

It 'should execute GitReleases plugin per date when there are updates' {
gc $global:au_Root\test_package_1\update.ps1 | set content
$content -replace '@\{.+\}', "@{ Version = '1.3' }" | set content
$content | sc $global:au_Root\test_package_1\update.ps1

$Options.GitReleases = @{
ApiToken = 'apiToken'
ReleaseType = 'date'
Force = $true
}

Mock Get-Date { return '2017-11-05' } -ParameterFilter { $UFormat -eq '{0:yyyy-MM-dd}' } -ModuleName AU
Mock Invoke-RestMethod { return @{ tag_name = '2017-11-05' } } -ModuleName AU

updateall -NoPlugins:$false -Options $Options 6> $null

Assert-MockCalled Get-Date -Exactly 1 -ModuleName AU
Assert-MockCalled Invoke-RestMethod -Exactly 2 -ModuleName AU
}
}

It 'should update package with checksum verification mode' {
Expand Down
Loading