66
77# This variable specifies what modules to bootstrap for the build
88# It is recommended to only bootstrap BuildHelpers and PSDepend, and use PSDepend for remaining prereqs
9- $BuildHelperModules = " BuildHelpers" , " PSDepend" , " Pester" , " powershell-yaml" , " Microsoft.Powershell.Archive"
9+ $BuildHelperModules = " BuildHelpers" , " PSDepend" , " Pester" , " powershell-yaml" , " Microsoft.Powershell.Archive" , " PSScriptAnalyzer "
1010
1111# Initialize Build Environment
1212Enter-Build {
@@ -20,24 +20,34 @@ Enter-Build {
2020 }
2121
2222 # Detect if we are in a continuous integration environment (Appveyor, etc.) or otherwise running noninteractively
23- if ($ENV: CI -or ([Environment ]::GetCommandLineArgs() -like ' ^ -noni*' )) {
23+ if ($ENV: CI -or ([Environment ]::GetCommandLineArgs() -like ' -noni*' )) {
2424 write-build Green ' Detected a Noninteractive or CI environment, disabling prompt confirmations'
2525 $SCRIPT :CI = $true
2626 $ConfirmPreference = ' None'
27+ $ProgressPreference = " SilentlyContinue"
2728 }
2829
2930 # Fetch Build Helper Modules using Install-ModuleBootstrap script (works in PSv3/4)
3031 # The comma in ArgumentList a weird idiosyncracy to make sure a nested array is created to ensure Argumentlist
3132 # doesn't unwrap the buildhelpermodules as individual arguments
33+ # We suppress verbose output for master builds (because they should have already been built once cleanly)
34+
3235 foreach ($BuildHelperModuleItem in $BuildHelperModules ) {
3336 if (-not (Get-module $BuildHelperModuleItem - listavailable)) {
3437 write-verbose " Installing $BuildHelperModuleItem from Powershell Gallery to your currentuser module directory"
35- install-module - scope currentuser - Name $BuildHelperModuleItem - ErrorAction stop
3638 if ($PSVersionTable.PSVersion.Major -lt 5 ) {
3739 write-verboseheader " Bootstrapping Powershell Module: $BuildHelperModuleItem "
3840 Invoke-Command - ArgumentList @ (, $BuildHelperModules ) - ScriptBlock ([scriptblock ]::Create((new-object net.webclient).DownloadString(' https://git.io/PSModBootstrap' )))
3941 } else {
40-
42+ $installModuleParams = @ {
43+ Scope = " CurrentUser"
44+ Name = $BuildHelperModuleItem
45+ ErrorAction = " Stop"
46+ }
47+ if ($SCRIPT :CI ) {
48+ $installModuleParams.Force = $true
49+ }
50+ install-module @installModuleParams
4151 }
4252 }
4353 }
@@ -46,8 +56,14 @@ Enter-Build {
4656 $Timestamp = Get-date - uformat " %Y%m%d-%H%M%S"
4757 $PSVersion = $PSVersionTable.PSVersion.Major
4858 Set-BuildEnvironment - force
59+ write-build Green " Current Branch Name: $BranchName "
4960
5061 $PassThruParams = @ {}
62+ if ( ($VerbosePreference -ne ' SilentlyContinue' ) -or ($CI -and ($BranchName -ne ' master' )) ) {
63+ write-build Green " Verbose Build Logging Enabled"
64+ $SCRIPT :VerbosePreference = " Continue"
65+ $PassThruParams.Verbose = $true
66+ }
5167
5268 # If the branch name is master-test, run the build like we are in "master"
5369 if ($env: BHBranchName -eq ' master-test' ) {
@@ -57,13 +73,6 @@ Enter-Build {
5773 $SCRIPT :BranchName = $env: BHBranchName
5874 }
5975
60- # We suppress verbose output for master builds (because they should have already been built once cleanly)
61- if ( ($VerbosePreference -ne ' SilentlyContinue' ) -or ($CI -and ($BranchName -ne ' master' )) ) {
62- write-build Green " Verbose Build Logging Enabled"
63- $SCRIPT :VerbosePreference = " Continue"
64- $PassThruParams.Verbose = $true
65- }
66-
6776 write-verboseheader " Build Environment Prepared! Environment Information:"
6877 Get-BuildEnvironment | format-list | out-string | write-verbose
6978
@@ -86,22 +95,28 @@ Enter-Build {
8695 Get-PackageProvider Nuget @PassThruParams | format-list | out-string | write-verbose
8796 }
8897
98+ # Fix a bug with the Appveyor 2017 image having a broken nuget (points to v3 URL but installed packagemanagement doesn't query v3 correctly)
99+ # Next command will add this back
100+ if ($ENV: APPVEYOR -and ($ENV: APPVEYOR_BUILD_WORKER_IMAGE -eq ' Visual Studio 2017' )) {
101+ write-verbose " Detected Appveyor VS2017 Image, using v2 Nuget API"
102+ UnRegister-PackageSource - Name nuget.org
103+ }
104+
89105 # Add the nuget repository so we can download things like GitVersion
90106 if (! (Get-PackageSource " nuget.org" - erroraction silentlycontinue)) {
91107 write-verbose " Registering nuget.org as package source"
92- Register-PackageSource - provider NuGet - name nuget.org - location http:// www.nuget.org/ api/ v2 - Trusted @PassThruParams | out-string | out -verbose
108+ Register-PackageSource - provider NuGet - name nuget.org - location http:// www.nuget.org/ api/ v2 - Trusted @PassThruParams | out-string | write -verbose
93109 }
94110 else {
95111 $nugetOrgPackageSource = Set-PackageSource - name ' nuget.org' - Trusted @PassThruParams
96112 if ($PassThruParams.Verbose ) {
97113 write-verboseheader " Nuget.Org Package Source Info "
98114 $nugetOrgPackageSource | format-table | out-string | write-verbose
99115 }
100-
101116 }
102117
103118 # Move to the Project Directory if we aren't there already
104- Set-Location $ENV: BHProjectPath
119+ Set-Location $buildRoot
105120
106121 # Define the Project Build Path
107122 $SCRIPT :ProjectBuildPath = $ENV: BHBuildOutput + " \" + $ENV: BHProjectName
@@ -111,29 +126,28 @@ Enter-Build {
111126task Clean {
112127 # Reset the BuildOutput Directory
113128 if (test-path $env: BHBuildOutput ) {
114- write-verbose " Removing and resetting $ ( $ENV: BHBuildOutput ) "
129+ Write-Verbose " Removing and resetting Build Output Path: $ ( $ENV: BHBuildOutput ) "
115130 remove-item $env: BHBuildOutput - Recurse - Force @PassThruParams
116131 }
117- New-Item - ItemType Directory $ProjectBuildPath - force | % FullName | out-string | write-verbose
118-
132+ New-Item - ItemType Directory $ProjectBuildPath - force | ForEach-Object FullName | out-string | write-verbose
119133 # Unmount any modules named the same as our module
120134
121135}
122136
123137task Version {
124138 # This task determines what version number to assign this build
125- $GitVersionConfig = " $env: BHProjectPath /GitVersion.yml"
139+ $GitVersionConfig = " $buildRoot /GitVersion.yml"
126140
127141 # Fetch GitVersion
128142 # TODO: Use Nuget.exe to fetch to make this v3/v4 compatible
129143 $GitVersionCMDPackageName = " gitversion.commandline"
130144 if (! (Get-Package $GitVersionCMDPackageName - erroraction SilentlyContinue)) {
131145 write-verbose " Package $GitVersionCMDPackageName Not Found Locally, Installing..."
132146 write-verboseheader " Nuget.Org Package Source Info for fetching Gitversion"
133- Get-PackageSource | ft | out-string | write-verbose
147+ Get-PackageSource | Format-Table | out-string | write-verbose
134148
135149 # Fetch GitVersion
136- Install-Package $GitVersionCMDPackageName - scope currentuser - source ' nuget.org' - force @PassThruParams
150+ Install-Package $GitVersionCMDPackageName - scope currentuser - source ' nuget.org' - force @PassThruParams | Out-Null
137151 }
138152 $GitVersionEXE = ((get-package $GitVersionCMDPackageName ).source | split-path - Parent) + " \tools\GitVersion.exe"
139153
@@ -142,7 +156,7 @@ task Version {
142156 if (Test-Path $env: BHPSModuleManifest ) {
143157 write-verbose " Fetching Version from Powershell Module Manifest (if present)"
144158 $ModuleManifestVersion = [Version ](Get-Metadata $env: BHPSModuleManifest )
145- if (Test-Path $env: BHProjectPath / GitVersion.yml) {
159+ if (Test-Path $buildRoot / GitVersion.yml) {
146160 $GitVersionConfigYAML = [ordered ]@ {}
147161 # ConvertFrom-YAML returns as individual key-value hashtables, we need to combine them into a single hashtable
148162 (Get-Content $GitVersionConfig | ConvertFrom-Yaml ) | foreach-object {$GitVersionConfigYAML += $PSItem }
@@ -156,14 +170,14 @@ task Version {
156170
157171 # Calcuate the GitVersion
158172 write-verbose " Executing GitVersion to determine version info"
159- $GitVersionOutput = & $GitVersionEXE $env: BHProjectPath
173+ $GitVersionOutput = & $GitVersionEXE $buildRoot
160174
161175 # Since GitVersion doesn't return error exit codes, we look for error text in the output in the output
162- if ($GitVersionOutput -match ' ^[ERROR|INFO] \[' ) {throw " An error occured when running GitVersion.exe $env: BHProjectPath " }
176+ if ($GitVersionOutput -match ' ^[ERROR|INFO] \[' ) {throw " An error occured when running GitVersion.exe $buildRoot " }
163177 try {
164178 $GitVersionInfo = $GitVersionOutput | ConvertFrom-JSON - ErrorAction stop
165179 } catch {
166- throw " There was an error when running GitVersion.exe $env: BHProjectPath . The output of the command (if any) follows:"
180+ throw " There was an error when running GitVersion.exe $buildRoot . The output of the command (if any) follows:"
167181 $GitVersionOutput
168182 }
169183
@@ -186,9 +200,12 @@ task Version {
186200
187201# Copy all powershell module "artifacts" to Build Directory
188202task CopyFilesToBuildDir {
189- $FilesToCopy = " Public" , " Private" , " lib" , " Types" , " $ ( $Env: BHProjectName ) .psm1" , " $ ( $Env: BHProjectName ) .psd1" , " .\LICENSE" , " README.md"
190- # Make sure we are in the project location in case somethign changed
191- Set-Location $ENV: BHProjectPath
203+ # Make sure we are in the project location in case somethign changedf
204+ Set-Location $buildRoot
205+
206+ # The file or file paths to copy, excluding the powershell psm1 and psd1 module and manifest files which will be autodetected
207+ # TODO: Move this somewhere higher in the hierarchy into a settings file, or rather go the "exclude" route
208+ $FilesToCopy = " lib" , " Public" , " Private" , " Types" , " LICENSE" , " README.md" , " $ ( $Env: BHProjectName ) .psm1" , " $ ( $Env: BHProjectName ) .psd1"
192209 copy-item - Recurse - Path $FilesToCopy - Destination $ProjectBuildPath @PassThruParams
193210}
194211
@@ -212,7 +229,6 @@ task UpdateMetadata CopyFilesToBuildDir,Version,{
212229 Update-Metadata - Path $ProjectBuildManifest - PropertyName ModuleVersion - Value $ProjectBuildVersion
213230
214231 # Are we in the master or develop/development branch? Bump the version based on the powershell gallery if so, otherwise add a build tag
215- write-build Yellow " BranchName: $BranchName "
216232 if ($BranchName -match ' ^(master|dev(elop)?(ment)?)$' ) {
217233 write-build Green " In Master/Develop branch, adding Tag Version $ProjectBuildVersion to this build"
218234 $Script :ProjectVersion = $ProjectBuildVersion
@@ -234,12 +250,25 @@ task UpdateMetadata CopyFilesToBuildDir,Version,{
234250 } else {
235251 write-build Green " Not in Master/Develop branch, marking this as a feature prelease build"
236252 $Script :ProjectVersion = $ProjectSemVersion
237- if (-not (git tag - l " $ProjectSemVersion " )) {
238- exec { git tag " $ProjectSemVersion " - a - m " Automatic GitVersion Prerelease Tag Generated by Invoke-Build" }
239- } else {
240- write-warning " Tag $ProjectSemVersion already exists. This is normal if you are running multiple builds on the same commit, otherwise this should not happen"
253+ # Set an email address for tag commit to work if it isn't already present
254+ if (-not (git config user.email)) {
255+ git config user.email " buildtag@$env: ComputerName "
256+ $tempTagGitEmailSet = $true
257+ }
258+ try {
259+ $gitVersionTag = " v$ProjectSemVersion "
260+ if (-not (git tag - l $gitVersionTag )) {
261+ exec { git tag " $gitVersionTag " - a - m " Automatic GitVersion Prerelease Tag Generated by Invoke-Build" }
262+ } else {
263+ write-warning " Tag $gitVersionTag already exists. This is normal if you are running multiple builds on the same commit, otherwise this should not happen"
264+ }
265+ } finally {
266+ if ($tempTagGitEmailSet ) {
267+ git config -- unset user.email
268+ }
241269 }
242270
271+
243272 # Create an empty file in the root directory of the module for easy identification that its not a valid release.
244273 " This is a prerelease build and not meant for deployment!" > (Join-Path $ProjectBuildPath " PRERELEASE-$ProjectSemVersion " )
245274 }
@@ -255,6 +284,7 @@ task Pester {
255284 $PesterResultFile = " $ ( $env: BHBuildOutput ) \$ ( $env: BHProjectName ) -TestResults_PS$PSVersion `_$TimeStamp .xml"
256285
257286 $PesterParams = @ {
287+ Script = " Tests"
258288 OutputFile = $PesterResultFile
259289 OutputFormat = " NunitXML"
260290 PassThru = $true
@@ -266,13 +296,13 @@ task Pester {
266296 $PesterParams.PesterOption = (new-pesteroption - IncludeVSCodeMarker)
267297 }
268298
269- $PesterResult = Invoke-Pester @PesterParams
299+ Invoke-Pester @PesterParams | Out-Null
270300
271301 # In Appveyor? Upload our test results!
272302 If ($ENV: APPVEYOR ) {
273303 $UploadURL = " https://ci.appveyor.com/api/testresults/nunit/$ ( $env: APPVEYOR_JOB_ID ) "
274304 write-verbose " Detected we are running in AppVeyor"
275- write-verbose " Uploading Pester Results to $UploadURL "
305+ write-verbose " Uploading Pester Results to Appveyor: $UploadURL "
276306 (New-Object ' System.Net.WebClient' ).UploadFile(
277307 " https://ci.appveyor.com/api/testresults/nunit/$ ( $env: APPVEYOR_JOB_ID ) " ,
278308 $PesterResultFile )
@@ -286,7 +316,7 @@ task Pester {
286316 " `n "
287317}
288318
289- task PackageArtifacts Version, {
319+ task Package Version, {
290320 $ZipArchivePath = (join-path $env: BHBuildOutput " $env: BHProjectName -$ProjectVersion .zip" )
291321 write-build green " Writing Finished Module to $ZipArchivePath "
292322 # Package the Powershell Module
@@ -300,7 +330,7 @@ task PackageArtifacts Version,{
300330}
301331
302332# Deploy Supertask
303- task Deploy PackageArtifacts
333+ task Deploy Package
304334
305335# Build SuperTask
306336task Build Clean , CopyFilesToBuildDir, UpdateMetadata
0 commit comments