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

Commit

Permalink
Merge pull request #109 from Thilas/streams-enhancements
Browse files Browse the repository at this point in the history
Streams enhancements:
- Support alphabetical streams (not version-like streams)
- Add support for common properties shared between all streams
- Add more information on streams for plugins (+ adapt GitReleases)
- Rename Include argument into IncludeStream on Update-Package
- Add more pester tests (+ enable code coverage)
  • Loading branch information
Thilas authored Nov 9, 2017
2 parents 972cc01 + daf04b5 commit dfff548
Show file tree
Hide file tree
Showing 13 changed files with 310 additions and 146 deletions.
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.$_
$_.Streams.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
63 changes: 51 additions & 12 deletions AU/Private/AUPackage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ class AUPackage {
[xml] $NuspecXml
[bool] $Ignored
[string] $IgnoreMessage

[string] $StreamsPath
[pscustomobject] $Streams
[string] $StreamsPath
[System.Collections.Specialized.OrderedDictionary] $Streams

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

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

static [xml] LoadNuspecFile( $NuspecPath ) {
$nu = New-Object xml
$nu.PSBase.PreserveWhitespace = $true
Expand All @@ -43,21 +51,28 @@ class AUPackage {
[System.IO.File]::WriteAllText($this.NuspecPath, $this.NuspecXml.InnerXml, $Utf8NoBomEncoding)
}

static [pscustomobject] LoadStreams( $StreamsPath ) {
if (!(Test-Path $StreamsPath)) { return $null }
return Get-Content $StreamsPath | ConvertFrom-Json
static [System.Collections.Specialized.OrderedDictionary] LoadStreams( $streamsPath ) {
if (!(Test-Path $streamsPath)) { return $null }
$res = [ordered] @{}
$versions = Get-Content $streamsPath | ConvertFrom-Json
$versions.psobject.Properties | % {
$stream = $_.Name
$res.Add($stream, @{ NuspecVersion = $versions.$stream })
}
return $res
}

UpdateStream( $stream, $version ){
if (!$this.Streams) { $this.Streams = [pscustomobject] @{} }
$s = $stream.ToString()
$v = $version.ToString()
if ($this.Streams | Get-Member $s) {
if ($this.Streams.$s -ne 'ignore') { $this.Streams.$s = $v }
} else {
$this.Streams | Add-Member $s $v
if (!$this.Streams) { $this.Streams = [ordered] @{} }
if (!$this.Streams.Contains($s)) { $this.Streams.$s = @{} }
if ($this.Streams.$s -ne 'ignore') { $this.Streams.$s.NuspecVersion = $v }
$versions = [ordered] @{}
$this.Streams.Keys | % {
$versions.Add($_, $this.Streams.$_.NuspecVersion)
}
$this.Streams | ConvertTo-Json | Set-Content $this.StreamsPath -Encoding UTF8
$versions | ConvertTo-Json | Set-Content $this.StreamsPath -Encoding UTF8
}

Backup() {
Expand All @@ -77,4 +92,28 @@ class AUPackage {
return "$d\_output"
}

AUPackage( [hashtable] $obj ) {
if (!$obj) { throw 'Obj can not be empty' }
$obj.Keys | ? { $_ -ne 'Streams' } | % {
$this.$_ = $obj.$_
}
if ($obj.Streams) {
$this.Streams = [ordered] @{}
$obj.Streams.psobject.Properties | % {
$this.Streams.Add($_.Name, $_.Value)
}
}
}

[hashtable] Serialize() {
$res = @{}
$this | Get-Member -Type Properties | ? { $_.Name -ne 'Streams' } | % {
$property = $_.Name
$res.Add($property, $this.$property)
}
if ($this.Streams) {
$res.Add('Streams', [PSCustomObject] $this.Streams)
}
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
66 changes: 40 additions & 26 deletions AU/Public/Update-Package.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function Update-Package {

#Streams to process, either a string or an array. If ommitted, all streams are processed.
#Single stream required when Force is specified.
$Include,
$IncludeStream,

#Force package update even if no new version is found.
#For multi streams packages, most recent stream is checked by default when Force is specified.
Expand Down 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 @@ -391,40 +393,48 @@ function Update-Package {
$res_type = $res.GetType()
if ($res_type -ne [HashTable]) { throw "au_GetLatest doesn't return a HashTable result but $res_type" }

if ($global:au_Force) {
$Force = $true
if ($global:au_Include) { $Include = $global:au_Include }
}
if ($global:au_Force) { $Force = $true }
if ($global:au_IncludeStream) { $IncludeStream = $global:au_IncludeStream }
} catch {
throw "au_GetLatest failed`n$_"
}

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())"
}

if ($Include) {
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())"
# 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 ($IncludeStream) {
if ($IncludeStream -isnot [string] -and $IncludeStream -isnot [double] -and $IncludeStream -isnot [Array]) {
throw "`$IncludeStream must be either a String, a Double or an Array but is $($IncludeStream.GetType())"
}
if ($IncludeStream -is [double]) { $IncludeStream = $IncludeStream -as [string] }
if ($IncludeStream -is [string]) {
# Forcing type in order to handle case when only one version is included
[Array] $IncludeStream = $IncludeStream -split ',' | % { $_.Trim() }
}
if ($Include -is [double]) { $Include = $Include -as [string] }
if ($Include -is [string]) { [Array] $Include = $Include -split ',' | foreach { ,$_.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)
$IncludeStream = @($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 ($Force -and (!$IncludeStream -or $IncludeStream.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 ($IncludeStream) { $streams = @($streams | ? { $_ -in $IncludeStream }) }
# 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

$streams | % {
$stream = $res.Streams[$_]

'' | result
"*** Stream: $_ ***" | result
Expand All @@ -433,14 +443,18 @@ function Update-Package {
if ($stream -eq 'ignore') { return }
if ($stream -isnot [HashTable]) { throw "au_GetLatest's $_ stream doesn't return a HashTable result but $($stream.GetType())" }

if ($package.Streams.$_ -eq 'ignore') {
if ($package.Streams.$_.NuspecVersion -eq 'ignore') {
'Ignored' | result
return
}

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

$package.Streams.$_ += $package.GetStreamDetails()
}
$package.Updated = $false
$package.Streams.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
}
}
57 changes: 57 additions & 0 deletions tests/AUPackage.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
remove-module AU -ea ignore
import-module $PSScriptRoot\..\AU

Describe 'AUPackage' -Tag aupackage {
InModuleScope AU {
It 'throws an error when intanciating without a path' {
{ [AUPackage]::new('') } | Should Throw 'empty'
}

It 'throws an error when intanciating without a hashtable' {
{ [AUPackage]::new([hashtable] $null) } | Should Throw 'empty'
}

It 'can serialize and deserialize' {
$expected = @{
Path = 'path'
Name = 'name'
Updated = $true
Pushed = $true
RemoteVersion = '1.2.3'
NuspecVersion = '0.1.2'
Result = 'result1,result2,result3' -split ','
Error = 'error'
NuspecPath = 'nuspecPath'
Ignored = $true
IgnoreMessage = 'ignoreMessage'
StreamsPath = 'streamsPath'
Streams = [PSCustomObject] @{
'0.1' = @{
NuspecVersion = '0.1.2'
Path = 'path'
Name = 'name'
Updated = $true
RemoteVersion = '1.2.3'
}
'0.2' = @{
NuspecVersion = '0.2.2'
Path = 'path'
Name = 'name'
Updated = $true
RemoteVersion = '1.2.3'
}
}
}

$package = [AUPackage]::new($expected)
$actual = $package.Serialize()

$expected.Keys | ? { $_ -ne 'Streams' } | % {
$actual.$_ | Should Be $expected.$_
}
$expected.Streams.psobject.Properties | % {
$actual.Streams.$_ | Should Be $expected.Streams.$_
}
}
}
}
12 changes: 0 additions & 12 deletions tests/Get-Version.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,7 @@ remove-module AU -ea ignore
import-module $PSScriptRoot\..\AU

Describe 'Get-Version' -Tag getversion {
$saved_pwd = $pwd

BeforeEach {
cd TestDrive:\
rm -Recurse -Force TestDrive:\test_package -ea ignore
cp -Recurse -Force $PSScriptRoot\test_package TestDrive:\test_package
}

InModuleScope AU {

It 'should convert a strict version' {
$expectedVersionStart = '1.2'
$expectedVersion = "$expectedVersionStart.3.4"
Expand Down Expand Up @@ -116,8 +107,5 @@ Describe 'Get-Version' -Tag getversion {
$version = [AUVersion] $Value
$version | Should Not BeNullOrEmpty
}

}

cd $saved_pwd
}
Loading

0 comments on commit dfff548

Please sign in to comment.