private void CreateArtifact(string artifactName, string path) { if (string.IsNullOrEmpty(artifactName) || artifactName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { throw new InvalidOperationException("Artifact Name cannot contain invalid file name characters: " + new string(Path.GetInvalidFileNameChars())); } if (StoredProcs.Releases_GetRelease(this.Context.ApplicationId, this.Context.ReleaseNumber) .Execute().ReleaseDeployables_Extended .Any(rd => rd.Deployable_Id == this.Context.DeployableId && rd.InclusionType_Code == Domains.DeployableInclusionTypes.Referenced)) { this.LogError( "An Artifact cannot be created for this Deployable because the Deployable is Referenced (as opposed to Included) by this Release. " + "To prevent this error, either include this Deployable in the Release or use a Predicate to prevent this action group from being executed."); return; } var fileOps = this.Context.Agent.GetService <IFileOperationsExecuter>(); var zipPath = fileOps.CombinePath(this.Context.TempDirectory, artifactName + ".zip"); this.LogDebug("Preparing directories..."); fileOps.DeleteFiles(new[] { zipPath }); this.ThrowIfCanceledOrTimeoutExpired(); var rootEntry = fileOps.GetDirectoryEntry( new GetDirectoryEntryCommand { Path = path, Recurse = false, IncludeRootPath = false } ).Entry; if ((rootEntry.Files == null || rootEntry.Files.Length == 0) && (rootEntry.SubDirectories == null || rootEntry.SubDirectories.Length == 0)) { this.LogWarning("There are no files to capture in this artifact."); } this.LogDebug("Zipping output..."); this.Context.Agent.GetService <IRemoteZip>().CreateZipFile(path, zipPath); var zipFileEntry = fileOps.GetFileEntry(zipPath); this.ThrowIfCanceledOrTimeoutExpired(); this.LogDebug("Transferring file to artifact library..."); var artifactId = new ArtifactIdentifier(this.Context.ApplicationId, this.Context.ReleaseNumber, this.Context.BuildNumber, this.Context.DeployableId, artifactName); ArtifactBuilder.ImportZip(artifactId, fileOps, zipFileEntry); this.LogDebug("Cleaning up..."); fileOps.DeleteFiles(new[] { zipPath }); this.LogInformation("Artfact captured from TFS."); }
/// <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); } } }
public override void Import(IBuildImporterContext context) { string zipFileName = null; string jenkinsBuildNumber = this.ResolveJenkinsBuildNumber(); if (string.IsNullOrEmpty(jenkinsBuildNumber)) { this.LogError("An error occurred attempting to resolve Jenkins build number \"{0}\". This can mean that " + "the special build type was not found, there are no builds for job \"{1}\", or that the job was not found or is disabled.", this.BuildNumber, this.JobName); return; } try { this.LogInformation("Importing {0} from {1}...", this.ArtifactName, this.JobName); var client = new JenkinsClient((JenkinsConfigurer)this.GetExtensionConfigurer(), this); zipFileName = Path.GetTempFileName(); this.LogDebug("Temp file: " + zipFileName); this.LogDebug("Downloading artifact..."); client.DownloadArtifact(this.JobName, jenkinsBuildNumber, zipFileName); this.LogInformation("Artifact downloaded."); using (var agent = Util.Agents.CreateLocalAgent()) { ArtifactBuilder.ImportZip( new ArtifactIdentifier( context.ApplicationId, context.ReleaseNumber, context.BuildNumber, context.DeployableId, this.ArtifactName), agent.GetService <IFileOperationsExecuter>(), new FileEntryInfo(Path.GetFileName(zipFileName), zipFileName) ); } } finally { try { if (zipFileName != null) { File.Delete(zipFileName); } } catch (Exception ex) { this.LogWarning("Error deleting temp file:" + ex.Message); } } this.LogDebug("Creating $JenkinsBuildNumber variable..."); DB.Variables_CreateOrUpdateVariableDefinition( Variable_Name: "JenkinsBuildNumber", Environment_Id: null, Server_Id: null, ApplicationGroup_Id: null, Application_Id: context.ApplicationId, Deployable_Id: null, Release_Number: context.ReleaseNumber, Build_Number: context.BuildNumber, Execution_Id: null, Promotion_Id: null, Value_Text: jenkinsBuildNumber, Sensitive_Indicator: false ); }