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.");
        }
Example #2
0
        /// <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);
                }
            }
        }
Example #3
0
        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
                );
        }