If you are using Visual Studio Release Management vNext to release your applications you’ll probably have DSC (Desired State Configuration) configurations that are shared between applications or provided by your operations team. In both cases they have a different lifecycle than your application and should be provisioned individually. But how do you publish PowerShell scripts or other files with the TFS build engine without creating empty solutions and adding the files?
What you can do is to add a simple project file like TFSBuild.proj that calls a PowerShell script. This project file can be used in a team build. The project file is really simple and all the logic is in the script file.
<?xml version="1.0" encoding="utf-8"?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <Target Name="EndToEndIteration"> <Exec Command="powershell.exe -file .\Package.ps1 -verbose" /> </Target> </Project>
The script uses TFS build variables $Env:TF_BUILD_SOURCESDIRECTORY and $Env:TF_BUILD_BINARIESDIRECTORY to copy files to the output directory. The build engine then takes care of copying the output to the drop folder.
# Specify file types to exclude $FileTypes = $("*.log";"*.proj";"*.vsprops") $SourceDir = "$($Env:TF_BUILD_SOURCESDIRECTORY.TrimEnd('\'))\DSCResources" # Find the files $files = gci $SourceDir -Recurse -Exclude $FileTypes if($files) { Write-Verbose "Found $files.count files:" foreach ($file in $files) { Write-Verbose $file.FullName } } else { Write-Warning "Found no files." } # If binary output directory exists, make sure it is empty # If it does not exist, create one # (this happens when 'Clean workspace' build process parameter is set to True) if ([IO.Directory]::Exists($Env:TF_BUILD_BINARIESDIRECTORY)) { $DeletePath = $Env:TF_BUILD_BINARIESDIRECTORY + "\*" Write-Verbose "$Env:TF_BUILD_BINARIESDIRECTORY exists." if(-not $Disable) { Write-Verbose "Ready to delete $DeletePath" Remove-Item $DeletePath -recurse Write-Verbose "Files deleted." } } else { Write-Verbose "$Env:TF_BUILD_BINARIESDIRECTORY does not exist." if(-not $Disable) { Write-Verbose "Ready to create it." [IO.Directory]::CreateDirectory($Env:TF_BUILD_BINARIESDIRECTORY) | Out-Null Write-Verbose "Directory created." } } # Copy the binaries Write-Verbose "Ready to copy files." if(-not $Disable) { Copy $SourceDir $Env:TF_BUILD_BINARIESDIRECTORY -Recurse -Exclude $FileTypes Write-Verbose "Files copied." }
With the project file you can create a team build and use its output for a component is Release Management that can be reused in every project.
You can use the same technique to ensure that your custom DSC resources and the resources from the resource kit are present on all servers. Put all the resources in a repository an create a build to publish them. Use a configuration like DSCResourcesConfiguration.ps1 in your release templates as the first action.
Configuration DSCResourceConfiguration { Node $env:COMPUTERNAME { File DSCModules { SourcePath = "$applicationPath\DSCResources" DestinationPath = "$env:ProgramFiles\WindowsPowerShell\Modules" Type = "Directory" Recurse = $true Ensure = "Present" } } } DSCResourceConfiguration
I use this technique a lot to separate things from my application that I might use in other projects. I can also give the operations team its own git repostitory where they can easily store their DSC configurations. If you find it usefull you can get the file from my script repository on GitHub.
this is very interesting thank you for the writeup