diff --git a/BuildTasks/BuildManifest.Task.ps1 b/BuildTasks/BuildManifest.Task.ps1 index ef5f460..343e0e3 100644 --- a/BuildTasks/BuildManifest.Task.ps1 +++ b/BuildTasks/BuildManifest.Task.ps1 @@ -14,93 +14,5 @@ taskx BuildManifest @{ 'Setting FunctionsToExport...' Set-ModuleFunctions -Name $ManifestPath -FunctionsToExport $functions.BaseName } - - 'Detecting semantic versioning...' - "Importing Module [$ManifestPath]..." - Import-Module -FullyQualifiedName $ManifestPath - - "Get-Command -Module [$ModuleName]..." - $commands = Get-Command -Module $ModuleName - - "Removing Module [$ModuleName]..." - Remove-Module -Name $ModuleName -Force - - 'Calculating fingerprint...' - $fingerprint = foreach ($command in $commands) - { - foreach ($parameter in $command.Parameters.Keys) - { - if($false -eq $command.Parameters[$parameter].IsDynamic) - { - '{0}:{1}' -f $command.Name, $command.Parameters[$parameter].Name - foreach ($alias in $command.Parameters[$parameter].Aliases) - { - '{0}:{1}' -f $command.Name, $alias - } - } - } - } - - $fingerprint = $fingerprint | Sort-Object - - if (Test-Path -Path '.\fingerprint') - { - $oldFingerprint = Get-Content -Path '.\fingerprint' - } - - $bumpVersionType = 'Patch' - - 'Detecting new features...' - $features = $fingerprint | - Where-Object { $_ -notin $oldFingerprint } - - foreach ($feature in $features) - { - $feature - $bumpVersionType = 'Minor' - } - - 'Detecting breaking changes...' - $breakingChanges = $oldFingerprint | - Where-Object { $_ -notin $fingerprint } - - foreach ($breakingChange in $breakingChanges) - { - $breakingChange - $bumpVersionType = 'Major' - } - - Set-Content -Path '.\fingerprint' -Value $fingerprint - - # Bump the module version - $version = [version] (Get-Metadata -Path $manifestPath -PropertyName 'ModuleVersion') - - if ($version -lt ([version] '1.0.0')) - { - "Module is still in beta; don't bump major version." - if ($bumpVersionType -eq 'Major') - { - $bumpVersionType = 'Minor' - } - else - { - $bumpVersionType = 'Patch' - } - } - - "Stepping [$bumpVersionType] version [$version]..." - $version = [version] (Step-Version -Version $version -Type $bumpVersionType) - - $build = 1 - if ($null -ne $env:Build_BuildID) - { - $build = $env:Build_BuildID - } - - $version = [version]::new($version.Major, $version.Minor, $version.Build, $build) - "Using version [$version]..." - "##vso[build.updatebuildnumber]$version" - - Update-Metadata -Path $ManifestPath -PropertyName 'ModuleVersion' -Value $version } } diff --git a/BuildTasks/ImportDevModule.Task.ps1 b/BuildTasks/ImportDevModule.Task.ps1 index c852471..ea36fcc 100644 --- a/BuildTasks/ImportDevModule.Task.ps1 +++ b/BuildTasks/ImportDevModule.Task.ps1 @@ -1,21 +1,4 @@ task ImportDevModule { - - if (-not(Test-Path -Path "$Source\$ModuleName.psd1")) - { - "Module [$ModuleName] is not built; cannot find [$Source\$ModuleName.psd1]." - Write-Error -Message "Could not find module manifest [$Source\$ModuleName.psd1]." - } - else - { - $loaded = Get-Module -Name $ModuleName -All - if ($loaded) - { - "Unloading Module [$ModuleName] from a previous import..." - $loaded | Remove-Module -Force - } - - "Importing Module [$ModuleName] from [$Source\$ModuleName.psd1]..." - Import-Module -FullyQualifiedName "$Source\$ModuleName.psd1" -Force - } + ImportModule -Path "$Source\$ModuleName.psd1" } diff --git a/BuildTasks/ImportModule.Task.ps1 b/BuildTasks/ImportModule.Task.ps1 index dfe72c6..a903b45 100644 --- a/BuildTasks/ImportModule.Task.ps1 +++ b/BuildTasks/ImportModule.Task.ps1 @@ -1,20 +1,33 @@ +function ImportModule +{ + param( + [string]$path, + [switch]$PassThru + ) -task ImportModule { - if (-not(Test-Path -Path $ManifestPath)) + + if (-not(Test-Path -Path $path)) { - "Module [$ModuleName] is not built; cannot find [$ManifestPath]." - Write-Error -Message "Could not find module manifest [$ManifestPath]. You may need to build the module first." + "Cannot find [$path]." + Write-Error -Message "Could not find module manifest [$path]" } else { - $loaded = Get-Module -Name $ModuleName -All + $file = Get-Item $path + $name = $file.BaseName + + $loaded = Get-Module -Name $name -All -ErrorAction Ignore if ($loaded) { - "Unloading Module [$ModuleName] from a previous import..." + "Unloading Module [$name] from a previous import..." $loaded | Remove-Module -Force } - "Importing Module [$ModuleName] from [$ManifestPath]..." - Import-Module -FullyQualifiedName $ManifestPath -Force + "Importing Module [$name] from [$($file.fullname)]..." + Import-Module -Name $file.fullname -Force -PassThru:$PassThru } } + +task ImportModule { + ImportModule -Path $ManifestPath +} diff --git a/BuildTasks/FullTests.Task.ps1 b/BuildTasks/Pester.Task.ps1 similarity index 80% rename from BuildTasks/FullTests.Task.ps1 rename to BuildTasks/Pester.Task.ps1 index 28f9e7a..528a343 100644 --- a/BuildTasks/FullTests.Task.ps1 +++ b/BuildTasks/Pester.Task.ps1 @@ -1,7 +1,7 @@ -task FullTests { +task Pester { + $requiredPercent = $Script:CodeCoveragePercent + $params = @{ - CodeCoverage = 'Output\*\*.psm1' - CodeCoverageOutputFile = 'Output\codecoverage.xml' OutputFile = $testFile OutputFormat = 'NUnitXml' PassThru = $true @@ -10,13 +10,18 @@ task FullTests { Tag = 'Build' } + if($requiredPercent -gt 0.00) + { + $params['CodeCoverage'] = 'Output\*\*.psm1' + $params['CodeCoverageOutputFile'] = 'Output\codecoverage.xml' + } + $results = Invoke-Pester @params if ($results.FailedCount -gt 0) { Write-Error -Message "Failed [$($results.FailedCount)] Pester tests." } - $requiredPercent = $Script:CodeCoveragePercent $codeCoverage = $results.codecoverage.NumberOfCommandsExecuted / $results.codecoverage.NumberOfCommandsAnalyzed if($codeCoverage -lt $requiredPercent) { diff --git a/BuildTasks/PublishVersion.Task.ps1 b/BuildTasks/PublishVersion.Task.ps1 new file mode 100644 index 0000000..79c9eba --- /dev/null +++ b/BuildTasks/PublishVersion.Task.ps1 @@ -0,0 +1,7 @@ +task PublishVersion { + [version] $sourceVersion = (Get-Metadata -Path $manifestPath -PropertyName 'ModuleVersion') + "##vso[build.updatebuildnumber]$sourceVersion" + + # Do the same for appveyor + # https://www.appveyor.com/docs/build-worker-api/#update-build-details +} diff --git a/BuildTasks/SetVersion.Task.ps1 b/BuildTasks/SetVersion.Task.ps1 new file mode 100644 index 0000000..715af54 --- /dev/null +++ b/BuildTasks/SetVersion.Task.ps1 @@ -0,0 +1,121 @@ +function GetModulePublicInterfaceMap +{ + param($Path) + $module = ImportModule -Path $Path -PassThru + $exportedCommands = @( + $module.ExportedFunctions.values + $module.ExportedCmdlets.values + $module.ExportedAliases.values + ) + + foreach($command in $exportedCommands) + { + foreach ($parameter in $command.Parameters.Keys) + { + if($false -eq $command.Parameters[$parameter].IsDynamic) + { + '{0}:{1}' -f $command.Name, $command.Parameters[$parameter].Name + foreach ($alias in $command.Parameters[$parameter].Aliases) + { + '{0}:{1}' -f $command.Name, $alias + } + } + } + } +} + +task SetVersion { + $version = $null + + $versionStamp = (git rev-parse origin/master) + (git rev-parse head) + + "Load current version" + [version] $sourceVersion = (Get-Metadata -Path $manifestPath -PropertyName 'ModuleVersion') + " Source version [$sourceVersion]" + + $downloadFolder = Join-Path -Path $output downloads + $null = New-Item -ItemType Directory -Path $downloadFolder -Force -ErrorAction Ignore + + $versionFile = Join-Path $downloadFolder versionfile + if(Test-Path $versionFile) + { + $versionFileData = Get-Content $versionFile -raw + if($versionFileData -eq $versionStamp) + { + continue + } + } + + "Checking for published version" + $publishedModule = Find-Module -Name $ModuleName | + Sort-Object -Property {[version]$_.Version} -Descending | + Select -First 1 + + [version] $publishedVersion = $publishedModule.Version + " Published version [$publishedVersion]" + + $version = $publishedVersion + + "Downloading published module to check for breaking changes" + $publishedModule | Save-Module -Path $downloadFolder + + [System.Collections.Generic.HashSet[string]] $publishedInterface = GetModulePublicInterfaceMap -Path (Join-Path $downloadFolder $ModuleName) + [System.Collections.Generic.HashSet[string]] $buildInterface = GetModulePublicInterfaceMap -Path $ManifestPath + + $bumpVersionType = 'Patch' + if( -not $publishedInterface.IsSubsetOf($buildInterface)) + { + $bumpVersionType = 'Major' + } + elseif ($publishedInterface.count -ne $buildInterface.count) + { + $bumpVersionType = 'Minor' + } + + if ($version -lt ([version] '1.0.0')) + { + "Module is still in beta; don't bump major version." + if ($bumpVersionType -eq 'Major') + { + $bumpVersionType = 'Minor' + } + else + { + $bumpVersionType = 'Patch' + } + } + + " Steping version [$bumpVersionType]" + $version = [version] (Step-Version -Version $version -Type $bumpVersionType) + + if ($null -ne $env:Build_BuildID) + { + $build = $env:Build_BuildID + $version = [version]::new($version.Major, $version.Minor, $version.Build, $build) + } + elseif ($null -ne $env:APPVEYOR_BUILD_ID) + { + $build = $env:APPVEYOR_BUILD_ID + $version = [version]::new($version.Major, $version.Minor, $version.Build, $build) + } + + " Comparing to source version [$sourceVersion]" + if($sourceVersion -gt $version) + { + " Using existing version" + $version = $sourceVersion + } + " Setting version [$version]" + Update-Metadata -Path $ManifestPath -PropertyName 'ModuleVersion' -Value $version + + (Get-Content -Path $ManifestPath -Raw -Encoding UTF8) | + % trimend | + Set-Content -Path $ManifestPath -Encoding UTF8 + + Set-Content -Path $versionFile -Value $versionStamp -NoNewline -Encoding UTF8 + + if(Test-Path $BuildRoot\fingerprint) + { + Remove-Item $BuildRoot\fingerprint + } +} diff --git a/Module.build.ps1 b/Module.build.ps1 index 3eeb453..f549433 100644 --- a/Module.build.ps1 +++ b/Module.build.ps1 @@ -2,11 +2,13 @@ $Script:ModuleName = Get-ChildItem .\*\*.psm1 | Select-object -ExpandProperty Ba $Script:CodeCoveragePercent = 0.0 # 0 to 1 . $psscriptroot\BuildTasks\InvokeBuildInit.ps1 -task Default Build, Test, UpdateSource -task Build Copy, Compile, BuildModule, BuildManifest, Helpify +task Default Build, Helpify, Test, UpdateSource +task Build Copy, Compile, BuildModule, BuildManifest, SetVersion task Helpify GenerateMarkdown, GenerateHelp -task Test Build, ImportModule, FullTests -task Publish Build, Test, PublishModule +task Test Build, ImportModule, Pester +task Publish Build, PublishVersion, Helpify, Test, PublishModule +task TFS Clean, Build, PublishVersion, Helpify, Test +task DevTest ImportDevModule, Pester Write-Host 'Import common tasks' Get-ChildItem -Path $buildroot\BuildTasks\*.Task.ps1 |