Last active
August 29, 2015 14:15
-
-
Save grenade/cce374cb4e27e366bc5b to your computer and use it in GitHub Desktop.
Generate common build definition in TFS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client") | |
| #[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Build.Client") | |
| #[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Build.Common") | |
| #[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.VersionControl.Client") | |
| #[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.VersionControl.Client.VersionSpec") | |
| function Update-AssemblyInfo { | |
| param( | |
| [string] $assemblyInfoFile, | |
| [hashtable] $parameters | |
| ) | |
| Write-Host ("`$assemblyInfoFile: {0}" -f $assemblyInfoFile) | |
| foreach ($key in $($parameters.Keys)) { | |
| if ($parameters[$key] -ne $null) { | |
| $assemblyInfo = Get-Content $assemblyInfoFile | |
| $pattern = ('\[assembly: {0}\("(.*)"\)\]' -f $key) | |
| try{ | |
| $oldValue = ($assemblyInfo | Select-String -Pattern $pattern | % { $_.Matches } ).Groups[1].Value | |
| } | |
| catch{ | |
| $oldValue = $null | |
| } | |
| if($oldValue){ | |
| $match = ('[assembly: {0}("{1}")]' -f $key, $oldValue) | |
| $replace = ('[assembly: {0}("{1}")]' -f $key, $parameters[$key]) | |
| Set-ItemProperty $assemblyInfoFile -name IsReadOnly -value $false | |
| (($assemblyInfo) | ForEach-Object { % { $_ -Replace [regex]::escape($match), $replace } }) | Set-Content $assemblyInfoFile | |
| Write-Host ("{0} changed from: '{1}', to: '{2}'." -f $key, $oldValue, $parameters[$key]) | |
| } else { | |
| Write-Host ("No value for {0} found." -f $key) | |
| } | |
| } | |
| } | |
| } | |
| function New-Version { | |
| param( | |
| [string] $packageId, | |
| [string] $nugetSource, | |
| [string] $versionSuffix = $null, | |
| [string] $nugetExe, | |
| [string] $incrementPosition = "patch", | |
| [int] $majorDefault = 0, | |
| [int] $minorDefault = 0, | |
| [int] $patchDefault = 0 | |
| ) | |
| if($nugetSource.ToUpper().Contains($env:USERDNSDOMAIN.ToUpper())){ | |
| #if nuget finds a proxy setting in env vars, it'll use it. disable that for local nuget sources | |
| $http_proxy_tmp = $env:HTTP_PROXY | |
| $https_proxy_tmp = $env:HTTPS_PROXY | |
| $env:HTTP_PROXY='' | |
| $env:HTTPS_PROXY='' | |
| } | |
| $nugetArgs = "list", $packageId, "-s", $nugetSource | |
| if ($versionSuffix) { $nugetArgs += "-pre" } | |
| try { | |
| (& $nugetExe $nugetArgs) | Where { $_.StartsWith(("{0} " -f $packageId)) } | % { $publishedVersion = $_.Split(" ")[1] } | |
| } | |
| catch { | |
| Write-Error ("Failed to query NuGet source: {0}, for package: {1}." -f $nugetSource, $packageId) | |
| } | |
| if($nugetSource.ToUpper().Contains($env:USERDNSDOMAIN.ToUpper())){ | |
| #reset proxy vars | |
| $env:HTTP_PROXY = $http_proxy_tmp | |
| $env:HTTPS_PROXY = $https_proxy_tmp | |
| } | |
| if (!$publishedVersion) { | |
| Write-Host ("Assuming no published version of package id: {0}, on NuGet source: {1}." -f $packageId, $nugetSource) | |
| $publishedVersion = ("{0}.{1}.{2}" -f $majorDefault, $minorDefault, $patchDefault) | |
| if ($versionSuffix) { | |
| $publishedVersion += $versionSuffix | |
| } | |
| } | |
| if ($versionSuffix) { | |
| $major, $minor, $patch, $build = $publishedVersion.Split("-")[0].Split(".") | |
| } else { | |
| $major, $minor, $patch, $build = $publishedVersion.Split(".") | |
| } | |
| if ($majorDefault -gt ([int] $major)) { | |
| $major = $majorDefault | |
| } | |
| if ($minorDefault -gt ([int] $minor)) { | |
| $minor = $minorDefault | |
| } | |
| Write-Host ("Incrementing {0} position of semver: {1}." -f $incrementPosition, $publishedVersion) | |
| switch ($incrementPosition) { | |
| "major" { $semanticVersion = ("{0}.{1}.{2}" -f (([int] $major) + 1), 0, 0) } | |
| "minor" { $semanticVersion = ("{0}.{1}.{2}" -f $major, (([int] $minor) + 1), 0) } | |
| default { $semanticVersion = ("{0}.{1}.{2}" -f $major, $minor, (([int] $patch) + 1)) } | |
| } | |
| return $semanticVersion | |
| } | |
| function Get-Version { | |
| param( | |
| [string] $assemblyInfoFile | |
| ) | |
| Write-Host ("`$assemblyInfoFile: {0}" -f $assemblyInfoFile) | |
| $assemblyInfo = Get-Content $assemblyInfoFile | |
| $pattern = ('\[assembly: {0}\("(.*)"\)\]' -f 'AssemblyInformationalVersion') | |
| try{ | |
| $version = ($assemblyInfo | Select-String -Pattern $pattern | % { $_.Matches } ).Groups[1].Value.Split('+')[0] | |
| } | |
| catch{ | |
| $version = $null | |
| } | |
| return $version | |
| } | |
| function Pack { | |
| param( | |
| [string] $projectFile, | |
| [string] $packageDirectory, | |
| [string] $version, | |
| [string] $nugetExe, | |
| [string] $properties | |
| ) | |
| $projectDirectory = (Split-Path -Parent $projectFile) | |
| Copy-Item ("{0}\..\build\nuget.config" -f $projectDirectory) "$projectDirectory" | |
| #Get-ReleaseNotes $tfsBuildName | |
| if ($version) { | |
| $nugetArgs = 'pack', "$projectFile", '-OutputDirectory', "$packageDirectory", '-Version', "$version", '-IncludeReferencedProjects', '-Properties', "$properties" | |
| } else { | |
| $nugetArgs = 'pack', "$projectFile", '-OutputDirectory', "$packageDirectory", '-IncludeReferencedProjects', '-Properties', "$properties" | |
| } | |
| & $nugetExe $nugetArgs | |
| } | |
| function Publish { | |
| param( | |
| [string] $package, | |
| [string] $apiKey, | |
| [string] $nugetSource, | |
| [string] $nugetExe | |
| ) | |
| if($nugetSource.ToUpper().Contains($env:USERDNSDOMAIN.ToUpper())){ | |
| #if nuget finds a proxy setting in env vars, it'll use it. disable that for local nuget sources | |
| $http_proxy_tmp = $env:HTTP_PROXY | |
| $https_proxy_tmp = $env:HTTPS_PROXY | |
| $env:HTTP_PROXY='' | |
| $env:HTTPS_PROXY='' | |
| } | |
| $nugetArgs = "push", "$package", "-ApiKey", $apiKey, "-Source", $nugetSource | |
| & $nugetExe $nugetArgs | |
| if($nugetSource.ToUpper().Contains($env:USERDNSDOMAIN.ToUpper())){ | |
| #reset proxy vars | |
| $env:HTTP_PROXY = $http_proxy_tmp | |
| $env:HTTPS_PROXY = $https_proxy_tmp | |
| } | |
| } | |
| function Restore { | |
| param( | |
| [string] $packagesConfig, | |
| [string] $nugetSource, | |
| [string] $nugetExe | |
| ) | |
| Write-Host ("`$packagesConfig: {0}" -f $packagesConfig) | |
| $projectDirectory = (Split-Path -Parent $packagesConfig) | |
| if($nugetSource.ToUpper().Contains($env:USERDNSDOMAIN.ToUpper())){ | |
| #if nuget finds a proxy setting in env vars, it'll use it. disable that for local nuget sources | |
| $http_proxy_tmp = $env:HTTP_PROXY | |
| $https_proxy_tmp = $env:HTTPS_PROXY | |
| $env:HTTP_PROXY='' | |
| $env:HTTPS_PROXY='' | |
| } | |
| $nugetArgs = 'install', "$packagesConfig", '-Source', $nugetSource, '-NonInteractive', '-RequireConsent', '-SolutionDir', ($projectDirectory, ".." -join '\') | |
| & $nugetExe $nugetArgs | |
| if($nugetSource.ToUpper().Contains($env:USERDNSDOMAIN.ToUpper())){ | |
| #reset proxy vars | |
| $env:HTTP_PROXY = $http_proxy_tmp | |
| $env:HTTPS_PROXY = $https_proxy_tmp | |
| } | |
| } | |
| #function Get-ReleaseNotes { | |
| # param ( | |
| # [string] $tfsCollectionUrl = 'https://imstfs.bisinfo.org/tfs/DevBIS', | |
| # [string] $tfsBuildName, | |
| # [string] $tfsPath, | |
| # [string] $tfsProjectName = $tfsPath.Split('/')[1] | |
| # ) | |
| # $server = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection(New-Object Uri($tfsCollectionUrl)) | |
| # $buildServer = $server.GetService([Microsoft.TeamFoundation.Build.Client.IBuildServer]) | |
| # $buildDetail = $buildServer.QueryBuilds("$tfsProjectName", "$tfsBuildName") | where { $_.BuildDefinition.LastGoodBuildUri -eq $_.Uri } | |
| # $versionControlServer = $server.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer]) | |
| # $dateVersionSpec = New-Object Microsoft.TeamFoundation.VersionControl.Client.DateVersionSpec($buildDetail.StartTime) | |
| # $latest = [Microsoft.TeamFoundation.VersionControl.Client.VersionSpec]::Latest | |
| # $recursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full | |
| # $historySinceLastGoodBuild = $versionControlServer.QueryHistory($tfsPath, $latest, 0, $recursionType, $null, $dateVersionSpec, $latest,[Int32]::MaxValue, $true, $false) | |
| # $workItemsSinceLastGoodBuild = $historySinceLastGoodBuild | foreach-object {$_.workitems} | |
| # return $workItemsSinceLastGoodBuild | foreach-object {$_.Id, $_.Title, $_.State} | |
| #} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections.Generic; | |
| namespace devopsutil | |
| { | |
| internal static class Config | |
| { | |
| internal const string TfsCollectionUrl = "https://tfs.example.com/tfs/some-collection"; | |
| internal const string TfsBuildController = "some-controller"; | |
| internal const string TeamProject = "SomeProject Common"; | |
| internal const string TeamProjectNamespace = "SomeProject.Common"; | |
| internal const string Configuration = "Release"; | |
| internal const string Platform = "AnyCPU"; | |
| private const string OutputPath = "bin"; | |
| internal static readonly string[] AgentTags = { "some-tag" }; | |
| private const string NuGetApiKey = "00000000-0000-0000-0000-000000000000"; | |
| internal static readonly KeyValuePair<string, string> PreBuildScript = new KeyValuePair<string, string>(string.Format("$/{0}/Trunk/build/set-version.ps1", TeamProject), null); | |
| internal static readonly KeyValuePair<string, string> PostBuildScript = new KeyValuePair<string, string>(string.Format("$/{0}/Trunk/build/publish-project.ps1", TeamProject), string.Format("-apiKey {0}", NuGetApiKey)); | |
| internal static readonly Dictionary<string, string> MsBuildProperties = new Dictionary<string, string> | |
| { | |
| { "Configuration", Configuration }, | |
| { "Platform", Platform }, | |
| { "OutputPath", OutputPath }, | |
| { "DefineConstants", "TRACE" }, | |
| { "TargetFrameworkVersion", "v4.5" } | |
| }; | |
| internal static Dictionary<string, object> GetAgentSettings( | |
| IEnumerable<string> tags, | |
| string maxExecutionTime = "00:00:00", | |
| string maxWaitTime = "00:30:00", | |
| string name = "*", | |
| string tagComparison = "MatchAtLeast") | |
| { | |
| return new Dictionary<string, object> | |
| { | |
| { "MaxExecutionTime", maxExecutionTime }, | |
| { "MaxWaitTime", maxWaitTime }, | |
| { "Name", name }, | |
| { "Tags", tags }, | |
| { "TagComparison", tagComparison } | |
| }; | |
| } | |
| internal static Dictionary<string, string> GetDefaultMappings(string project) | |
| { | |
| return new Dictionary<string, string> | |
| { | |
| { | |
| string.Format("$/{0}/Trunk/build", TeamProject), | |
| @"$(SourceDir)\build" | |
| }, | |
| { | |
| string.Format("$/{0}/Trunk/src/Common/.nuget", TeamProject), | |
| @"$(SourceDir)\.nuget" | |
| }, | |
| { | |
| string.Format("$/{0}/Trunk/src/Common/{1}", TeamProject, project), | |
| @"$(SourceDir)\src" | |
| }, | |
| { | |
| string.Format("$/{0}/Trunk/src/Common/SharedAssemblyInfo.cs", TeamProject), | |
| @"$(SourceDir)\SharedAssemblyInfo.cs" | |
| } | |
| }; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Linq; | |
| using Microsoft.TeamFoundation.Build.Client; | |
| namespace devopsutil | |
| { | |
| static class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| var buildDefinitionNames = args.Any() | |
| ? args | |
| : TfsUtil.GetBuildDefinitionNames(Config.TeamProject); | |
| foreach (var buildDefinitionName in buildDefinitionNames) | |
| CreateBuildDefinition(buildDefinitionName); | |
| Console.WriteLine("All done."); | |
| Console.ReadKey(); | |
| } | |
| private static void CreateBuildDefinition(string project) | |
| { | |
| if ((project ?? string.Empty).StartsWith(Config.TeamProjectNamespace)) | |
| TfsUtil.CreateBuildDefinition( | |
| projectPath: string.Format("src/{0}.csproj", project), | |
| teamProject: Config.TeamProject, | |
| buildDefinitionName: project, | |
| workspaceMappings: Config.GetDefaultMappings(project), | |
| buildDefinitionDescription: string.Format("NuGet Release: build, package and publish for {0}.", project), | |
| msBuildProperties: Config.MsBuildProperties, | |
| preBuildScript: Config.PreBuildScript, | |
| postBuildScript: Config.PostBuildScript, | |
| continuousIntegrationType: ContinuousIntegrationType.Batch, | |
| agentTags: Config.AgentTags); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .Synopsis | |
| - Create and publish NuGet package from project source | |
| #> | |
| param( | |
| [string] $projectDirectory = ("{0}\..\src" -f (Split-Path -Parent $MyInvocation.MyCommand.Path)), | |
| [string] $project = (Get-ChildItem -Path $projectDirectory -Filter "*.csproj" | Select -ExpandProperty Name).Replace('.csproj', ''), | |
| [string] $nugetSource = 'http://nuget.example.com', | |
| [string] $nugetExe = "$projectDirectory\..\.nuget\nuget.exe", | |
| [string] $configuration = "Release", | |
| [string] $platform = "AnyCPU", | |
| [string] $outputPath = "bin", | |
| [string] $apiKey = '00000000-0000-0000-0000-000000000000' | |
| ) | |
| Import-Module ("{0}\build-util.psm1" -f (Split-Path -Parent $MyInvocation.MyCommand.Path)) | |
| $packageDirectory = ($projectDirectory, "..", ".nuget" -join '\') | |
| $version = Get-Version ($projectDirectory, 'Properties', 'AssemblyInfo.cs' -join '\') | |
| $projectFile = ($projectDirectory, "$project.csproj" -join '\') | |
| Pack -projectFile $projectFile -packageDirectory $packageDirectory -version $version -nugetExe $nugetExe -properties "Configuration=$configuration;Platform=$platform;OutputPath=$outputPath" | |
| Publish ($packageDirectory, ($project, $version, 'nupkg' -join '.') -join '\') $apiKey $nugetSource $nugetExe |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .Synopsis | |
| - Create and publish NuGet package from project source | |
| #> | |
| param( | |
| [string] $projectDirectory = ("{0}\..\src" -f (Split-Path -Parent $MyInvocation.MyCommand.Path)), | |
| [string] $project = (Get-ChildItem -Path $projectDirectory -Filter "*.csproj" | Select -ExpandProperty Name).Replace('.csproj', ''), | |
| [string] $nugetSource = 'http://nuget.exampl.com/api/v2/', | |
| [string] $nugetExe = "$projectDirectory\..\.nuget\nuget.exe", | |
| [int] $buildNumber = $env:TF_BUILD_BUILDNUMBER.Split('.')[-1], | |
| [string] $vcsRevision = $env:TF_BUILD_SOURCEGETVERSION, | |
| [string] $versionSuffix = $null, | |
| [string] $revisionPrefix = $null, | |
| [string] $tfsProjectPath = ('$/SomeProject Common/Trunk/src/Common/{0}' -f $project) | |
| ) | |
| $workDirectory = (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)) | |
| Import-Module ("{0}\build-util.psm1" -f (Split-Path -Parent $MyInvocation.MyCommand.Path)) | |
| Write-Host ("projectDirectory: {0}" -f $projectDirectory) | |
| Write-Host ("project: {0}" -f $project) | |
| $sourceVersion = (Get-Version ($projectDirectory, 'Properties', 'AssemblyInfo.cs' -join '\')) | |
| Write-Host ("sourceVersion: {0}" -f $sourceVersion) | |
| $majorDefault, $minorDefault, $patchDefault, $buildDefault = $sourceVersion.Split(".") | |
| $semanticVersion = New-Version -packageId $project -nugetSource $nugetSource -nugetExe $nugetExe -majorDefault $majorDefault -minorDefault $minorDefault -patchDefault $patchDefault | |
| Write-Host ("New semver: [{0}]." -f $semanticVersion) | |
| $assemblyVersion = ("{0}.{1}" -f $semanticVersion, $buildNumber) | |
| $assemblyInformationalVersion = $semanticVersion | |
| if ($versionSuffix) { | |
| $assemblyInformationalVersion += $versionSuffix | |
| } | |
| $assemblyInformationalVersion += ("+{0}{1}.{2}" -f $revisionPrefix, $vcsRevision, $buildNumber) | |
| $assemblyInfoValues = @{ AssemblyVersion = $assemblyVersion; AssemblyFileVersion = $assemblyVersion; AssemblyInformationalVersion = $assemblyInformationalVersion } | |
| Update-AssemblyInfo ($projectDirectory, 'Properties', 'AssemblyInfo.cs' -join "\") $assemblyInfoValues | |
| #$tfsPath = ('{0}/{1}' -f $tfsProjectPath, $project) | |
| #$notes = (Get-ReleaseNotes -tfsBuildName "$env:TF_BUILD_BUILDDEFINITIONNAME" -tfsPath "$tfsPath") | |
| #Write-Host ($notes | Format-Table | Out-String) | |
| $packagesConfig = ($workDirectory, 'src', 'packages.config' -join '\') | |
| if (Test-Path "$packagesConfig") | |
| { | |
| Restore -packagesConfig "$packagesConfig" -nugetSource "$nugetSource" -nugetExe "$nugetExe" | |
| } else { | |
| Write-Host ("Package restore skipped because config not found: '{0}'" -f $packagesConfig) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using Microsoft.TeamFoundation.Build.Common; | |
| using Microsoft.TeamFoundation.Client; | |
| using Microsoft.TeamFoundation.Build.Client; | |
| using Microsoft.TeamFoundation.Build.Workflow; | |
| using Microsoft.TeamFoundation.VersionControl.Client; | |
| namespace devopsutil | |
| { | |
| internal static class TfsUtil | |
| { | |
| private static TfsTeamProjectCollection _tfsTeamProjectCollection; | |
| private static TfsTeamProjectCollection TfsTeamProjectCollection | |
| { | |
| get | |
| { | |
| if (_tfsTeamProjectCollection == null) | |
| { | |
| _tfsTeamProjectCollection = new TfsTeamProjectCollection(new Uri(Config.TfsCollectionUrl)); | |
| _tfsTeamProjectCollection.EnsureAuthenticated(); | |
| } | |
| return _tfsTeamProjectCollection; | |
| } | |
| } | |
| private static IBuildServer _buildServer; | |
| private static IBuildServer BuildServer | |
| { | |
| get { return _buildServer ?? (_buildServer = TfsTeamProjectCollection.GetService<IBuildServer>()); } | |
| } | |
| private static VersionControlServer _versionControlServer; | |
| private static VersionControlServer VersionControlServer | |
| { | |
| get | |
| { | |
| return _versionControlServer ?? | |
| (_versionControlServer = TfsTeamProjectCollection.GetService<VersionControlServer>()); | |
| } | |
| } | |
| public static void CreateBuildDefinition( | |
| string projectPath, | |
| string teamProject, | |
| string buildDefinitionName, | |
| IEnumerable<KeyValuePair<string, string>> workspaceMappings, | |
| IEnumerable<string> cloakedWorkspaceMappings = null, | |
| string buildDefinitionDescription = null, | |
| IDictionary<string, string> msBuildProperties = null, | |
| string platform = Config.Platform, | |
| string configuration = Config.Configuration, | |
| KeyValuePair<string, string> preBuildScript = new KeyValuePair<string, string>(), | |
| KeyValuePair<string, string> postBuildScript = new KeyValuePair<string, string>(), | |
| ContinuousIntegrationType continuousIntegrationType = ContinuousIntegrationType.Individual, | |
| int continuousIntegrationQuietPeriod = 10, | |
| string outputLocation = "AsConfigured", | |
| bool includeTestRunSettings = false, | |
| string symbolStorePath = null, // eg: @"\\server\symbols\somepath" | |
| string dropLocation = null, // eg: "#/" | |
| string[] agentTags = null | |
| ) | |
| { | |
| var buildDefinition = GetOrCreateBuildDefinition(teamProject, buildDefinitionName); | |
| if (!string.IsNullOrWhiteSpace(buildDefinitionDescription)) | |
| buildDefinition.Description = buildDefinitionDescription; | |
| Console.WriteLine("set continuous integration type: {0}", continuousIntegrationType); | |
| buildDefinition.ContinuousIntegrationType = continuousIntegrationType; | |
| if (continuousIntegrationType == ContinuousIntegrationType.Batch) | |
| { | |
| Console.WriteLine("set continuous integration quiet period: {0}", continuousIntegrationQuietPeriod); | |
| buildDefinition.ContinuousIntegrationQuietPeriod = continuousIntegrationQuietPeriod; | |
| } | |
| //Controller and default build process template | |
| buildDefinition.BuildController = BuildServer.GetBuildController(Config.TfsBuildController); | |
| var defaultTemplate = | |
| BuildServer.QueryProcessTemplates(teamProject).First(p => p.TemplateType == ProcessTemplateType.Default); | |
| Console.WriteLine("set template: {0}", defaultTemplate.Description); | |
| buildDefinition.Process = defaultTemplate; | |
| //Drop location | |
| if (!string.IsNullOrWhiteSpace(dropLocation)) | |
| { | |
| Console.WriteLine("set default drop location: {0}", dropLocation); | |
| buildDefinition.DefaultDropLocation = dropLocation; | |
| } | |
| //Source Settings | |
| foreach (var workspaceMapping in workspaceMappings) | |
| { | |
| Console.WriteLine("add mapping: server: {0}, local: {1}", workspaceMapping.Key, workspaceMapping.Value); | |
| buildDefinition.Workspace.AddMapping(workspaceMapping.Key, workspaceMapping.Value, WorkspaceMappingType.Map); | |
| } | |
| foreach (var cloakedWorkspaceMapping in (cloakedWorkspaceMappings ?? Enumerable.Empty<string>())) | |
| { | |
| Console.WriteLine("add cloaked mapping: {0}", cloakedWorkspaceMapping); | |
| buildDefinition.Workspace.AddMapping(cloakedWorkspaceMapping, string.Empty, WorkspaceMappingType.Cloak); | |
| } | |
| //Process params | |
| var processParameters = WorkflowHelpers.DeserializeProcessParameters(buildDefinition.ProcessParameters); | |
| //What to build | |
| Console.WriteLine("set ProjectsToBuild: {0}", projectPath); | |
| if (processParameters.ContainsKey("ProjectsToBuild")) | |
| processParameters["ProjectsToBuild"] = new[] {projectPath}; | |
| else | |
| processParameters.Add("ProjectsToBuild", new[] {projectPath}); | |
| Console.WriteLine("set ConfigurationsToBuild: {0}", string.Format("{0}|{1}", platform, configuration)); | |
| if (processParameters.ContainsKey("ConfigurationsToBuild")) | |
| processParameters["ConfigurationsToBuild"] = new[] { string.Format("{0}|{1}", platform, configuration) }; | |
| else | |
| processParameters.Add("ConfigurationsToBuild", new[] { string.Format("{0}|{1}", platform, configuration) }); | |
| if (processParameters.ContainsKey("OutputLocation")) | |
| processParameters["OutputLocation"] = outputLocation; | |
| else | |
| processParameters.Add("OutputLocation", outputLocation); | |
| //Advanced build settings | |
| var buildParams = new Dictionary<string, string>(); | |
| if (msBuildProperties != null && msBuildProperties.Any()) | |
| { | |
| var msBuildArguments = string.Concat("/p:", string.Join(";", msBuildProperties.Select(p => string.Concat(p.Key, '=', p.Value)))); | |
| Console.WriteLine("set MSBuildArguments: {0}", msBuildArguments); | |
| buildParams.Add("MSBuildArguments", msBuildArguments); | |
| } | |
| if (!string.IsNullOrWhiteSpace(preBuildScript.Key)) | |
| { | |
| Console.WriteLine("set PreActionScriptPath: {0}", preBuildScript.Key); | |
| buildParams.Add("PreActionScriptPath", preBuildScript.Key); | |
| } | |
| if (!string.IsNullOrWhiteSpace(preBuildScript.Value)) | |
| { | |
| Console.WriteLine("set PreActionScriptArguments: {0}", preBuildScript.Value); | |
| buildParams.Add("PreActionScriptArguments", preBuildScript.Value); | |
| } | |
| if (!string.IsNullOrWhiteSpace(postBuildScript.Key)) | |
| { | |
| Console.WriteLine("set PostActionScriptPath: {0}", postBuildScript.Key); | |
| buildParams.Add("PostActionScriptPath", postBuildScript.Key); | |
| } | |
| if (!string.IsNullOrWhiteSpace(postBuildScript.Value)) | |
| { | |
| Console.WriteLine("set PostActionScriptArguments: {0}", postBuildScript.Value); | |
| buildParams.Add("PostActionScriptArguments", postBuildScript.Value); | |
| } | |
| if (buildParams.Any()) | |
| { | |
| if (processParameters.ContainsKey("AdvancedBuildSettings")) | |
| processParameters["AdvancedBuildSettings"] = new BuildParameter(buildParams); | |
| else | |
| processParameters.Add("AdvancedBuildSettings", new BuildParameter(buildParams)); | |
| } | |
| else if (processParameters.ContainsKey("AdvancedBuildSettings")) | |
| { | |
| processParameters.Remove("AdvancedBuildSettings"); | |
| } | |
| //test settings | |
| if (includeTestRunSettings) | |
| { | |
| if (processParameters.ContainsKey("AutomatedTests")) | |
| processParameters["AutomatedTests"] = new[] {new BuildParameter(GetTestParameters())}; | |
| else | |
| processParameters.Add("AutomatedTests", new[] {new BuildParameter(GetTestParameters())}); | |
| } | |
| else if (processParameters.ContainsKey("AutomatedTests")) | |
| { | |
| processParameters.Remove("AutomatedTests"); | |
| } | |
| //Symbol settings | |
| if (!string.IsNullOrWhiteSpace(symbolStorePath)) | |
| { | |
| if (processParameters.ContainsKey("SymbolStorePath")) | |
| processParameters["SymbolStorePath"] = symbolStorePath; | |
| else | |
| processParameters.Add("SymbolStorePath", symbolStorePath); | |
| } | |
| else if (processParameters.ContainsKey("SymbolStorePath")) | |
| { | |
| processParameters.Remove("SymbolStorePath"); | |
| } | |
| if (agentTags != null && agentTags.Any()) | |
| { | |
| if (processParameters.ContainsKey("AgentSettings")) | |
| processParameters["AgentSettings"] = new BuildParameter(Config.GetAgentSettings(agentTags)); | |
| else | |
| processParameters.Add("AgentSettings", new BuildParameter(Config.GetAgentSettings(agentTags))); | |
| } | |
| buildDefinition.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(processParameters); | |
| //Retention policy | |
| buildDefinition.RetentionPolicyList.Clear(); | |
| buildDefinition.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Succeeded, 10, DeleteOptions.All); | |
| buildDefinition.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Failed, 10, DeleteOptions.All); | |
| buildDefinition.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.Stopped, 1, DeleteOptions.All); | |
| buildDefinition.AddRetentionPolicy(BuildReason.Triggered, BuildStatus.PartiallySucceeded, 10, DeleteOptions.All); | |
| Console.WriteLine("save build definition: {0}", buildDefinition.Name); | |
| buildDefinition.Save(); | |
| } | |
| private static IBuildDefinition GetOrCreateBuildDefinition(string teamProject, string buildDefinitionName) | |
| { | |
| IBuildDefinition buildDefinition; | |
| if ((BuildServer.QueryBuildDefinitions(teamProject).Any(d => d.Name == buildDefinitionName))) | |
| { | |
| Console.WriteLine("update build definition: {0}/{1}", teamProject, buildDefinitionName); | |
| buildDefinition = BuildServer.GetBuildDefinition(teamProject, buildDefinitionName); | |
| RemoveWorkspaceMappings(buildDefinition); | |
| } | |
| else | |
| { | |
| Console.WriteLine("create build definition: {0}/{1}", teamProject, buildDefinitionName); | |
| buildDefinition = BuildServer.CreateBuildDefinition(teamProject); | |
| buildDefinition.Name = buildDefinitionName; | |
| } | |
| return buildDefinition; | |
| } | |
| private static void DeleteBuilds(IBuildDefinition buildDefinition) | |
| { | |
| var builds = BuildServer.QueryBuilds(buildDefinition); | |
| if (builds != null && builds.Any()) | |
| { | |
| Console.WriteLine("delete {0} builds for build definition: {1}", builds.Count(), | |
| buildDefinition.Name); | |
| BuildServer.DeleteBuilds(builds); | |
| } | |
| } | |
| private static void RemoveWorkspaceMappings(IBuildDefinition buildDefinition) | |
| { | |
| if (buildDefinition.Workspace.Mappings.Any()) | |
| { | |
| var mappings = buildDefinition.Workspace.Mappings.Select(m => m.ServerItem).ToArray(); | |
| foreach (var mapping in mappings) | |
| { | |
| Console.WriteLine("remove workspace mapping: {0}", mapping); | |
| buildDefinition.Workspace.RemoveMapping(mapping); | |
| } | |
| } | |
| } | |
| private static void DeleteWorkspaces(string buildDefinitionId) | |
| { | |
| var workspaceNamePrefix = string.Concat(buildDefinitionId, '_'); | |
| var workSpaces = VersionControlServer.QueryWorkspaces(null, null, null).Where(w => w.Name.StartsWith(workspaceNamePrefix)).ToArray(); | |
| for (var i = workSpaces.Count() - 1; i > -1; i--) | |
| { | |
| try | |
| { | |
| workSpaces[i].Delete(); | |
| Console.WriteLine("delete workspace: {0}", workSpaces[i].Name); | |
| } | |
| catch (ResourceAccessException rae) | |
| { | |
| Console.ForegroundColor = ConsoleColor.Yellow; | |
| Console.WriteLine(rae.Message); | |
| Console.ForegroundColor = ConsoleColor.Red; | |
| Console.WriteLine("workspace needs to be deleted by an administrator using the following command:"); | |
| Console.ForegroundColor = ConsoleColor.Green; | |
| Console.WriteLine("tf workspace /delete {0};{1}", workSpaces[i].Name, workSpaces[i].OwnerName); | |
| Console.ResetColor(); | |
| } | |
| } | |
| } | |
| private static Dictionary<string, object> GetTestParameters() | |
| { | |
| return new Dictionary<string, object> | |
| { | |
| { "AssemblyFileSpec", "*.exe" }, | |
| { "HasRunSettingsFile", true }, | |
| { "ExecutionPlatform", "X86" }, | |
| { "FailBuildOnFailure", true }, | |
| { "RunName", "MyTestRunName" }, | |
| { "HasTestCaseFilter", false }, | |
| { "TestCaseFilter", null }, | |
| { "RunSettingsForTestRun", new Dictionary<string, object> | |
| { | |
| { "HasRunSettingsFile", true }, | |
| { "ServerRunSettingsFile", "" }, | |
| { "TypeRunSettings", "CodeCoverageEnabled" } | |
| } | |
| } | |
| }; | |
| } | |
| public static IEnumerable<string> GetBuildDefinitionNames(string teamProject) | |
| { | |
| return BuildServer.QueryBuildDefinitions(teamProject).Select(d => d.Name); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment