/// <summary> /// Downloads and imports and artifact from Visual Studio Online. /// </summary> /// <param name="configurer">The configurer.</param> /// <param name="logger">The logger.</param> /// <param name="teamProject">The team project.</param> /// <param name="buildNumber">The build number.</param> /// <param name="artifactId">The artifact identifier.</param> public static string DownloadAndImport(TfsConfigurer configurer, ILogger logger, string teamProject, string buildNumber, string buildDefinitionName, ArtifactIdentifier artifactId) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (configurer == null) { throw new ArgumentNullException("A configurer must be configured or selected in order to import a VS online build."); } if (string.IsNullOrEmpty(configurer.BaseUrl)) { throw new InvalidOperationException("The base URL property of the TFS configurer must be set to import a VS online build."); } var api = new TfsRestApi(configurer.BaseUrl, teamProject) { UserName = string.IsNullOrEmpty(configurer.Domain) ? configurer.UserName : string.Format("{0}\\{1}", configurer.Domain, configurer.UserName), Password = configurer.Password }; logger.LogInformation($"Finding last successful build..."); var buildDefinitions = api.GetBuildDefinitions(); var buildDefinition = buildDefinitions.FirstOrDefault(b => b.name == buildDefinitionName); if (buildDefinition == null) { throw new InvalidOperationException($"The build definition {buildDefinitionName} could not be found."); } logger.LogInformation($"Finding {Util.CoalesceStr(buildNumber, "last successful")} build..."); var builds = api.GetBuilds( buildDefinition: buildDefinition.id, buildNumber: InedoLib.Util.NullIf(buildNumber, ""), resultFilter: "succeeded", statusFilter: "completed", top: 2 ); if (builds.Length == 0) { throw new InvalidOperationException($"Could not find build number {buildNumber}. Ensure there is a successful, completed build with this number."); } var build = builds.FirstOrDefault(); string tempFile = Path.GetTempFileName(); try { logger.LogInformation($"Downloading {artifactId.ArtifactName} artifact from VSO..."); logger.LogDebug("Downloading artifact file to: " + tempFile); api.DownloadArtifact(build.id, artifactId.ArtifactName, tempFile); logger.LogInformation("Artifact file downloaded from VSO, importing into BuildMaster artifact library..."); using (var stream = FileEx.Open(tempFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { ArtifactBuilder.ImportZip(artifactId, stream); } logger.LogInformation($"{artifactId.ArtifactName} artifact imported."); return(build.buildNumber); } finally { if (tempFile != null) { FileEx.Delete(tempFile); } } }
protected override void Execute() { var configurer = this.GetExtensionConfigurer(); if (configurer == null) { throw new InvalidOperationException("A configurer must be configured or selected in order to queue a VS online build."); } if (string.IsNullOrEmpty(configurer.BaseUrl)) { throw new InvalidOperationException("The base URL property of the TFS configurer must be set to queue a VS online build."); } var api = new TfsRestApi(configurer.BaseUrl, this.TeamProject) { UserName = string.IsNullOrEmpty(configurer.Domain) ? configurer.UserName : string.Format("{0}\\{1}", configurer.Domain, configurer.UserName), Password = configurer.Password }; this.LogDebug("Finding VSO build definition..."); var definition = api.GetBuildDefinitions() .FirstOrDefault(d => string.IsNullOrEmpty(this.BuildDefinition) || string.Equals(d.name, this.BuildDefinition, StringComparison.OrdinalIgnoreCase)); if (definition == null) { throw new InvalidOperationException("Could not find a build definition named: " + Util.CoalesceStr(this.BuildDefinition, "any")); } this.LogInformation($"Queueing VSO build of {this.TeamProject}, build definition {definition.name}..."); var queuedBuild = api.QueueBuild(definition.id); this.LogInformation($"Build number \"{queuedBuild.buildNumber}\" created for definition \"{queuedBuild.definition.name}\"."); if (this.CreateBuildNumberVariable) { this.LogDebug($"Setting $TfsBuildNumber build variable to {queuedBuild.buildNumber}..."); StoredProcs.Variables_CreateOrUpdateVariableDefinition( Variable_Name: "TfsBuildNumber", Environment_Id: null, Server_Id: null, ApplicationGroup_Id: null, Application_Id: this.Context.ApplicationId, Deployable_Id: null, Release_Number: this.Context.ReleaseNumber, Build_Number: this.Context.BuildNumber, Execution_Id: null, Value_Text: queuedBuild.buildNumber, Sensitive_Indicator: YNIndicator.No ).Execute(); this.LogInformation("$TfsBuildNumber build variable set to: " + queuedBuild.buildNumber); } if (this.WaitForCompletion) { string lastStatus = queuedBuild.status; this.LogInformation($"Current build status is \"{lastStatus}\", waiting for \"completed\" status..."); while (!string.Equals(queuedBuild.status, "completed", StringComparison.OrdinalIgnoreCase)) { this.ThrowIfCanceledOrTimeoutExpired(); Thread.Sleep(4000); queuedBuild = api.GetBuild(queuedBuild.id); if (queuedBuild.status != lastStatus) { this.LogInformation($"Current build status changed from \"{lastStatus}\" to \"{queuedBuild.status}\"..."); lastStatus = queuedBuild.status; } } this.LogInformation("Build status result is \"completed\"."); if (this.ValidateBuild) { this.LogInformation("Validating build status result is \"succeeded\"..."); if (!string.Equals("succeeded", queuedBuild.result, StringComparison.OrdinalIgnoreCase)) { this.LogError("Build status result was not \"succeeded\"."); return; } this.LogInformation("Build status result was \"succeeded\"."); } } this.LogInformation($"VSO build {queuedBuild.buildNumber} created."); }