public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken)
        {
            DedupManifestArtifactClient dedupManifestClient = DedupManifestArtifactClientFactory.CreateDedupManifestClient(
                this.context, this.connection, cancellationToken, out BlobStoreClientTelemetry clientTelemetry);

            using (clientTelemetry) {
                var artifactNameAndManifestIds = buildArtifacts.ToDictionary(
                    keySelector: (a) => a.Name, // keys should be unique, if not something is really wrong
                    elementSelector: (a) => DedupIdentifier.Create(a.Resource.Data));
                // 2) download to the target path
                var options = DownloadDedupManifestArtifactOptions.CreateWithMultiManifestIds(
                    artifactNameAndManifestIds,
                    downloadParameters.TargetDirectory,
                    proxyUri: null,
                    minimatchPatterns: downloadParameters.MinimatchFilters,
                    minimatchFilterWithArtifactName: downloadParameters.MinimatchFilterWithArtifactName);

                PipelineArtifactActionRecord downloadRecord = clientTelemetry.CreateRecord <PipelineArtifactActionRecord>((level, uri, type) =>
                                                                                                                          new PipelineArtifactActionRecord(level, uri, type, nameof(DownloadMultipleArtifactsAsync), this.context));
                await clientTelemetry.MeasureActionAsync(
                    record : downloadRecord,
                    actionAsync : async() =>
                {
                    await dedupManifestClient.DownloadAsync(options, cancellationToken);
                });

                // Send results to CustomerIntelligence
                this.context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
            }
        }
        public async Task DownloadSingleArtifactAsync(PipelineArtifactDownloadParameters downloadParameters, BuildArtifact buildArtifact, CancellationToken cancellationToken)
        {
            DedupManifestArtifactClient dedupManifestClient = DedupManifestArtifactClientFactory.CreateDedupManifestClient(
                this.context, this.connection, cancellationToken, out BlobStoreClientTelemetry clientTelemetry);

            using (clientTelemetry) {
                var manifestId = DedupIdentifier.Create(buildArtifact.Resource.Data);
                var options    = DownloadDedupManifestArtifactOptions.CreateWithManifestId(
                    manifestId,
                    downloadParameters.TargetDirectory,
                    proxyUri: null,
                    minimatchPatterns: downloadParameters.MinimatchFilters);

                PipelineArtifactActionRecord downloadRecord = clientTelemetry.CreateRecord <PipelineArtifactActionRecord>((level, uri, type) =>
                                                                                                                          new PipelineArtifactActionRecord(level, uri, type, nameof(DownloadMultipleArtifactsAsync), this.context));
                await clientTelemetry.MeasureActionAsync(
                    record : downloadRecord,
                    actionAsync : async() =>
                {
                    await dedupManifestClient.DownloadAsync(options, cancellationToken);
                });

                // Send results to CustomerIntelligence
                this.context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
            }
        }
 public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken)
 {
     foreach (var buildArtifact in buildArtifacts)
     {
         var downloadRootPath  = Path.Combine(buildArtifact.Resource.Data, buildArtifact.Name);
         var minimatchPatterns = downloadParameters.MinimatchFilters.Select(pattern => Path.Combine(buildArtifact.Resource.Data, pattern));
         await this.CopyFileShareAsync(downloadRootPath, Path.Combine(downloadParameters.TargetDirectory, buildArtifact.Name), minimatchPatterns, cancellationToken);
     }
 }
 public async Task DownloadSingleArtifactAsync(PipelineArtifactDownloadParameters downloadParameters, BuildArtifact buildArtifact, CancellationToken cancellationToken)
 {
     var manifestId = DedupIdentifier.Create(buildArtifact.Resource.Data);
     var options    = DownloadDedupManifestArtifactOptions.CreateWithManifestId(
         manifestId,
         downloadParameters.TargetDirectory,
         proxyUri: null,
         minimatchPatterns: downloadParameters.MinimatchFilters);
     await dedupManifestArtifactClient.DownloadAsync(options, cancellationToken);
 }
Example #5
0
 public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken)
 {
     var artifactNameAndManifestIds = buildArtifacts.ToDictionary(
         keySelector: (a) => a.Name, // keys should be unique, if not something is really wrong
         elementSelector: (a) => DedupIdentifier.Create(a.Resource.Data));
     // 2) download to the target path
     var options = DownloadPipelineArtifactOptions.CreateWithMultiManifestIds(
         artifactNameAndManifestIds,
         downloadParameters.TargetDirectory,
         proxyUri: null,
         minimatchPatterns: downloadParameters.MinimatchFilters);
     await buildDropManager.DownloadAsync(options, cancellationToken);
 }
Example #6
0
        private async Task <FileShareDownloadResult> DownloadArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken)
        {
            var  records          = new List <ArtifactRecord>();
            long totalContentSize = 0;
            int  totalFileCount   = 0;

            foreach (var buildArtifact in buildArtifacts)
            {
                var downloadRootPath  = Path.Combine(buildArtifact.Resource.Data, buildArtifact.Name);
                var minimatchPatterns = downloadParameters.MinimatchFilters.Select(pattern => Path.Combine(buildArtifact.Resource.Data, pattern));
                var record            = await this.DownloadFileShareArtifactAsync(downloadRootPath, Path.Combine(downloadParameters.TargetDirectory, buildArtifact.Name), defaultParallelCount, cancellationToken, minimatchPatterns);

                totalContentSize += record.ContentSize;
                totalFileCount   += record.FileCount;
                records.Add(record);
            }

            return(new FileShareDownloadResult(records, totalFileCount, totalContentSize));
        }
Example #7
0
        // Download pipeline artifact from Azure DevOps BlobStore service through DedupManifestArtifactClient to a target path
        // Old V0 function
        internal Task DownloadAsync(
            AgentTaskPluginExecutionContext context,
            Guid projectId,
            int pipelineId,
            string artifactName,
            string targetDir,
            CancellationToken cancellationToken)
        {
            var downloadParameters = new PipelineArtifactDownloadParameters
            {
                ProjectRetrievalOptions = BuildArtifactRetrievalOptions.RetrieveByProjectId,
                ProjectId       = projectId,
                PipelineId      = pipelineId,
                ArtifactName    = artifactName,
                TargetDirectory = targetDir
            };

            return(this.DownloadAsync(context, downloadParameters, DownloadOptions.SingleDownload, cancellationToken));
        }
        public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken, AgentTaskPluginExecutionContext context)
        {
            var(dedupManifestClient, clientTelemetry) = await DedupManifestArtifactClientFactory.Instance.CreateDedupManifestClientAsync(
                this.context, this.connection, cancellationToken);

            using (clientTelemetry) {
                var artifactNameAndManifestIds = buildArtifacts.ToDictionary(
                    keySelector: (a) => a.Name, // keys should be unique, if not something is really wrong
                    elementSelector: (a) => DedupIdentifier.Create(a.Resource.Data));
                // 2) download to the target path
                var options = DownloadDedupManifestArtifactOptions.CreateWithMultiManifestIds(
                    artifactNameAndManifestIds,
                    downloadParameters.TargetDirectory,
                    proxyUri: null,
                    minimatchPatterns: downloadParameters.MinimatchFilters,
                    minimatchFilterWithArtifactName: downloadParameters.MinimatchFilterWithArtifactName);

                PipelineArtifactActionRecord downloadRecord = clientTelemetry.CreateRecord <PipelineArtifactActionRecord>((level, uri, type) =>
                                                                                                                          new PipelineArtifactActionRecord(level, uri, type, nameof(DownloadMultipleArtifactsAsync), this.context));
                await clientTelemetry.MeasureActionAsync(
                    record : downloadRecord,
                    actionAsync : async() =>
                {
                    await AsyncHttpRetryHelper.InvokeVoidAsync(
                        async() =>
                    {
                        await dedupManifestClient.DownloadAsync(options, cancellationToken);
                    },
                        maxRetries: 3,
                        tracer: tracer,
                        canRetryDelegate: e => true,
                        context: nameof(DownloadMultipleArtifactsAsync),
                        cancellationToken: cancellationToken,
                        continueOnCapturedContext: false);
                });

                // Send results to CustomerIntelligence
                this.context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
            }
        }
Example #9
0
        public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken, AgentTaskPluginExecutionContext context)
        {
            context.Warning(StringUtil.Loc("DownloadArtifactWarning", "UNC"));
            var(dedupManifestClient, clientTelemetry) = await this.factory.CreateDedupManifestClientAsync(context, connection, cancellationToken);

            using (clientTelemetry)
            {
                FileShareActionRecord downloadRecord = clientTelemetry.CreateRecord <FileShareActionRecord>((level, uri, type) =>
                                                                                                            new FileShareActionRecord(level, uri, type, nameof(DownloadArtifactsAsync), context));

                await clientTelemetry.MeasureActionAsync(
                    record : downloadRecord,
                    actionAsync : async() =>
                {
                    return(await DownloadArtifactsAsync(downloadParameters, buildArtifacts, cancellationToken));
                }
                    );

                // Send results to CustomerIntelligence
                context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
            }
        }
Example #10
0
        public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken)
        {
            BlobStoreClientTelemetry    clientTelemetry;
            DedupManifestArtifactClient dedupManifestClient = this.factory.CreateDedupManifestClient(context, connection, cancellationToken, out clientTelemetry);

            using (clientTelemetry)
            {
                FileShareActionRecord downloadRecord = clientTelemetry.CreateRecord <FileShareActionRecord>((level, uri, type) =>
                                                                                                            new FileShareActionRecord(level, uri, type, nameof(DownloadArtifactsAsync), context));

                await clientTelemetry.MeasureActionAsync(
                    record : downloadRecord,
                    actionAsync : async() =>
                {
                    return(await DownloadArtifactsAsync(downloadParameters, buildArtifacts, cancellationToken));
                }
                    );

                // Send results to CustomerIntelligence
                context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
            }
        }
        public async Task DownloadSingleArtifactAsync(PipelineArtifactDownloadParameters downloadParameters, BuildArtifact buildArtifact, CancellationToken cancellationToken, AgentTaskPluginExecutionContext context)
        {
            var(dedupManifestClient, clientTelemetry) = await DedupManifestArtifactClientFactory.Instance.CreateDedupManifestClientAsync(
                this.context, this.connection, cancellationToken);

            using (clientTelemetry) {
                var manifestId = DedupIdentifier.Create(buildArtifact.Resource.Data);
                var options    = DownloadDedupManifestArtifactOptions.CreateWithManifestId(
                    manifestId,
                    downloadParameters.TargetDirectory,
                    proxyUri: null,
                    minimatchPatterns: downloadParameters.MinimatchFilters);

                PipelineArtifactActionRecord downloadRecord = clientTelemetry.CreateRecord <PipelineArtifactActionRecord>((level, uri, type) =>
                                                                                                                          new PipelineArtifactActionRecord(level, uri, type, nameof(DownloadMultipleArtifactsAsync), this.context));
                await clientTelemetry.MeasureActionAsync(
                    record : downloadRecord,
                    actionAsync : async() =>
                {
                    await AsyncHttpRetryHelper.InvokeVoidAsync(
                        async() =>
                    {
                        await dedupManifestClient.DownloadAsync(options, cancellationToken);
                    },
                        maxRetries: 3,
                        tracer: tracer,
                        canRetryDelegate: e => true,
                        context: nameof(DownloadSingleArtifactAsync),
                        cancellationToken: cancellationToken,
                        continueOnCapturedContext: false);
                });

                // Send results to CustomerIntelligence
                this.context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
            }
        }
Example #12
0
        // Download with minimatch patterns, V1.
        internal async Task DownloadAsync(
            AgentTaskPluginExecutionContext context,
            PipelineArtifactDownloadParameters downloadParameters,
            DownloadOptions downloadOptions,
            CancellationToken cancellationToken)
        {
            VssConnection               connection = context.VssConnection;
            BlobStoreClientTelemetry    clientTelemetry;
            DedupManifestArtifactClient dedupManifestClient = DedupManifestArtifactClientFactory.CreateDedupManifestClient(context, connection, out clientTelemetry);
            BuildServer buildHelper = new BuildServer(connection);

            using (clientTelemetry)
            {
                // download all pipeline artifacts if artifact name is missing
                if (downloadOptions == DownloadOptions.MultiDownload)
                {
                    List <BuildArtifact> artifacts;
                    if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectId)
                    {
                        artifacts = await buildHelper.GetArtifactsAsync(downloadParameters.ProjectId, downloadParameters.PipelineId, cancellationToken);
                    }
                    else if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectName)
                    {
                        if (string.IsNullOrEmpty(downloadParameters.ProjectName))
                        {
                            throw new InvalidOperationException("Project name can't be empty when trying to fetch build artifacts!");
                        }
                        else
                        {
                            artifacts = await buildHelper.GetArtifactsWithProjectNameAsync(downloadParameters.ProjectName, downloadParameters.PipelineId, cancellationToken);
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException($"Invalid {nameof(downloadParameters.ProjectRetrievalOptions)}!");
                    }

                    IEnumerable <BuildArtifact> pipelineArtifacts = artifacts.Where(a => a.Resource.Type == PipelineArtifactConstants.PipelineArtifact);
                    if (pipelineArtifacts.Count() == 0)
                    {
                        throw new ArgumentException("Could not find any pipeline artifacts in the build.");
                    }
                    else
                    {
                        context.Output(StringUtil.Loc("DownloadingMultiplePipelineArtifacts", pipelineArtifacts.Count()));

                        var artifactNameAndManifestIds = pipelineArtifacts.ToDictionary(
                            keySelector: (a) => a.Name, // keys should be unique, if not something is really wrong
                            elementSelector: (a) => DedupIdentifier.Create(a.Resource.Data));
                        // 2) download to the target path
                        var options = DownloadPipelineArtifactOptions.CreateWithMultiManifestIds(
                            artifactNameAndManifestIds,
                            downloadParameters.TargetDirectory,
                            proxyUri: null,
                            minimatchPatterns: downloadParameters.MinimatchFilters);

                        PipelineArtifactActionRecord downloadRecord = clientTelemetry.CreateRecord <PipelineArtifactActionRecord>((level, uri, type) =>
                                                                                                                                  new PipelineArtifactActionRecord(level, uri, type, nameof(DownloadAsync), context));
                        await clientTelemetry.MeasureActionAsync(
                            record : downloadRecord,
                            actionAsync : async() =>
                        {
                            await dedupManifestClient.DownloadAsync(options, cancellationToken);
                        });

                        // Send results to CustomerIntelligence
                        context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
                    }
                }
                else if (downloadOptions == DownloadOptions.SingleDownload)
                {
                    // 1) get manifest id from artifact data
                    BuildArtifact buildArtifact;
                    if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectId)
                    {
                        buildArtifact = await buildHelper.GetArtifact(downloadParameters.ProjectId, downloadParameters.PipelineId, downloadParameters.ArtifactName, cancellationToken);
                    }
                    else if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectName)
                    {
                        if (string.IsNullOrEmpty(downloadParameters.ProjectName))
                        {
                            throw new InvalidOperationException("Project name can't be empty when trying to fetch build artifacts!");
                        }
                        else
                        {
                            buildArtifact = await buildHelper.GetArtifactWithProjectNameAsync(downloadParameters.ProjectName, downloadParameters.PipelineId, downloadParameters.ArtifactName, cancellationToken);
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException($"Invalid {nameof(downloadParameters.ProjectRetrievalOptions)}!");
                    }

                    var manifestId = DedupIdentifier.Create(buildArtifact.Resource.Data);
                    var options    = DownloadPipelineArtifactOptions.CreateWithManifestId(
                        manifestId,
                        downloadParameters.TargetDirectory,
                        proxyUri: null,
                        minimatchPatterns: downloadParameters.MinimatchFilters);

                    PipelineArtifactActionRecord downloadRecord = clientTelemetry.CreateRecord <PipelineArtifactActionRecord>((level, uri, type) =>
                                                                                                                              new PipelineArtifactActionRecord(level, uri, type, nameof(DownloadAsync), context));
                    await clientTelemetry.MeasureActionAsync(
                        record : downloadRecord,
                        actionAsync : async() =>
                    {
                        await dedupManifestClient.DownloadAsync(options, cancellationToken);
                    });

                    // Send results to CustomerIntelligence
                    context.PublishTelemetry(area: PipelineArtifactConstants.AzurePipelinesAgent, feature: PipelineArtifactConstants.PipelineArtifact, record: downloadRecord);
                }
                else
                {
                    throw new InvalidOperationException($"Invalid {nameof(downloadOptions)}!");
                }
            }
        }
Example #13
0
        // Download for version 2. This decision was made because version 1 is sealed and we didn't want to break any existing customers.
        internal async Task DownloadAsyncV2(
            AgentTaskPluginExecutionContext context,
            PipelineArtifactDownloadParameters downloadParameters,
            DownloadOptions downloadOptions,
            CancellationToken cancellationToken)
        {
            VssConnection connection  = context.VssConnection;
            BuildServer   buildHelper = new BuildServer(connection);

            // download all pipeline artifacts if artifact name is missing
            if (downloadOptions == DownloadOptions.MultiDownload)
            {
                List <BuildArtifact> artifacts;
                if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectId)
                {
                    artifacts = await buildHelper.GetArtifactsAsync(downloadParameters.ProjectId, downloadParameters.PipelineId, cancellationToken);
                }
                else if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectName)
                {
                    if (string.IsNullOrEmpty(downloadParameters.ProjectName))
                    {
                        throw new InvalidOperationException("Project name can't be empty when trying to fetch build artifacts!");
                    }
                    else
                    {
                        artifacts = await buildHelper.GetArtifactsWithProjectNameAsync(downloadParameters.ProjectName, downloadParameters.PipelineId, cancellationToken);
                    }
                }
                else
                {
                    throw new InvalidOperationException($"Invalid {nameof(downloadParameters.ProjectRetrievalOptions)}!");
                }

                IEnumerable <BuildArtifact> buildArtifacts    = artifacts.Where(a => a.Resource.Type == PipelineArtifactConstants.Container);
                IEnumerable <BuildArtifact> pipelineArtifacts = artifacts.Where(a => a.Resource.Type == PipelineArtifactConstants.PipelineArtifact);
                if (buildArtifacts.Any())
                {
                    FileContainerProvider provider = new FileContainerProvider(connection, this.CreateTracer(context));
                    await provider.DownloadMultipleArtifactsAsync(downloadParameters, buildArtifacts, cancellationToken);
                }

                if (pipelineArtifacts.Any())
                {
                    PipelineArtifactProvider provider = new PipelineArtifactProvider(context, connection, this.CreateTracer(context));
                    await provider.DownloadMultipleArtifactsAsync(downloadParameters, pipelineArtifacts, cancellationToken);
                }
            }
            else if (downloadOptions == DownloadOptions.SingleDownload)
            {
                // 1) get manifest id from artifact data
                BuildArtifact buildArtifact;
                if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectId)
                {
                    buildArtifact = await buildHelper.GetArtifact(downloadParameters.ProjectId, downloadParameters.PipelineId, downloadParameters.ArtifactName, cancellationToken);
                }
                else if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectName)
                {
                    if (string.IsNullOrEmpty(downloadParameters.ProjectName))
                    {
                        throw new InvalidOperationException("Project name can't be empty when trying to fetch build artifacts!");
                    }
                    else
                    {
                        buildArtifact = await buildHelper.GetArtifactWithProjectNameAsync(downloadParameters.ProjectName, downloadParameters.PipelineId, downloadParameters.ArtifactName, cancellationToken);
                    }
                }
                else
                {
                    throw new InvalidOperationException($"Invalid {nameof(downloadParameters.ProjectRetrievalOptions)}!");
                }

                ArtifactProviderFactory factory  = new ArtifactProviderFactory(context, connection, this.CreateTracer(context));
                IArtifactProvider       provider = factory.GetProvider(buildArtifact);
                await provider.DownloadSingleArtifactAsync(downloadParameters, buildArtifact, cancellationToken);
            }
            else
            {
                throw new InvalidOperationException($"Invalid {nameof(downloadOptions)}!");
            }
        }
        protected override async Task ProcessCommandInternalAsync(
            AgentTaskPluginExecutionContext context,
            CancellationToken token)
        {
            ArgUtil.NotNull(context, nameof(context));
            string artifactName              = context.GetInput(ArtifactEventProperties.ArtifactName, required: false);
            string branchName                = context.GetInput(ArtifactEventProperties.BranchName, required: false);
            string pipelineDefinition        = context.GetInput(ArtifactEventProperties.PipelineDefinition, required: false);
            string sourceRun                 = context.GetInput(ArtifactEventProperties.SourceRun, required: true);
            string pipelineTriggering        = context.GetInput(ArtifactEventProperties.PipelineTriggering, required: false);
            string pipelineVersionToDownload = context.GetInput(ArtifactEventProperties.PipelineVersionToDownload, required: false);
            string targetPath                = context.GetInput(DownloadPath, required: true);
            string environmentBuildId        = context.Variables.GetValueOrDefault(BuildVariables.BuildId)?.Value ?? string.Empty; // BuildID provided by environment.
            string itemPattern               = context.GetInput(ArtifactEventProperties.ItemPattern, required: false);
            string projectName               = context.GetInput(ArtifactEventProperties.Project, required: false);
            string tags = context.GetInput(ArtifactEventProperties.Tags, required: false);
            string userSpecifiedpipelineId = context.GetInput(pipelineRunId, required: false);
            string defaultWorkingDirectory = context.Variables.GetValueOrDefault("system.defaultworkingdirectory").Value;

            targetPath = Path.IsPathFullyQualified(targetPath) ? targetPath : Path.GetFullPath(Path.Combine(defaultWorkingDirectory, targetPath));

            bool onPrem = !String.Equals(context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.ServerType)?.Value, "Hosted", StringComparison.OrdinalIgnoreCase);

            if (onPrem)
            {
                throw new InvalidOperationException(StringUtil.Loc("OnPremIsNotSupported"));
            }

            if (!PipelineArtifactPathHelper.IsValidArtifactName(artifactName))
            {
                throw new ArgumentException(StringUtil.Loc("ArtifactNameIsNotValid", artifactName));
            }

            string[] minimatchPatterns = itemPattern.Split(
                new[] { "\n" },
                StringSplitOptions.RemoveEmptyEntries
                );

            string[] tagsInput = tags.Split(
                new[] { "," },
                StringSplitOptions.None
                );

            PipelineArtifactServer             server = new PipelineArtifactServer(tracer);
            PipelineArtifactDownloadParameters downloadParameters;

            if (sourceRun == sourceRunCurrent)
            {
                // TODO: use a constant for project id, which is currently defined in Microsoft.VisualStudio.Services.Agent.Constants.Variables.System.TeamProjectId (Ting)
                string projectIdStr = context.Variables.GetValueOrDefault("system.teamProjectId")?.Value;
                if (String.IsNullOrEmpty(projectIdStr))
                {
                    throw new ArgumentNullException("Project ID cannot be null.");
                }
                Guid projectId = Guid.Parse(projectIdStr);
                ArgUtil.NotEmpty(projectId, nameof(projectId));

                int pipelineId = 0;
                if (int.TryParse(environmentBuildId, out pipelineId) && pipelineId != 0)
                {
                    context.Output(StringUtil.Loc("DownloadingFromBuild", pipelineId));
                }
                else
                {
                    string hostType = context.Variables.GetValueOrDefault("system.hosttype")?.Value;
                    if (string.Equals(hostType, "Release", StringComparison.OrdinalIgnoreCase) ||
                        string.Equals(hostType, "DeploymentGroup", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException(StringUtil.Loc("BuildIdIsNotAvailable", hostType ?? string.Empty, hostType ?? string.Empty));
                    }
                    else if (!string.Equals(hostType, "Build", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException(StringUtil.Loc("CannotDownloadFromCurrentEnvironment", hostType ?? string.Empty));
                    }
                    else
                    {
                        // This should not happen since the build id comes from build environment. But a user may override that so we must be careful.
                        throw new ArgumentException(StringUtil.Loc("BuildIdIsNotValid", environmentBuildId));
                    }
                }

                downloadParameters = new PipelineArtifactDownloadParameters
                {
                    ProjectRetrievalOptions = BuildArtifactRetrievalOptions.RetrieveByProjectId,
                    ProjectId        = projectId,
                    PipelineId       = pipelineId,
                    ArtifactName     = artifactName,
                    TargetDirectory  = targetPath,
                    MinimatchFilters = minimatchPatterns,
                    MinimatchFilterWithArtifactName = true
                };
            }
            else if (sourceRun == sourceRunSpecific)
            {
                if (String.IsNullOrEmpty(projectName))
                {
                    throw new ArgumentNullException("Project Name cannot be null.");
                }
                Guid projectId  = Guid.Parse(projectName);
                int? pipelineId = null;

                bool pipelineTriggeringBool = false;
                if (bool.TryParse(pipelineTriggering, out pipelineTriggeringBool) && pipelineTriggeringBool)
                {
                    string triggeringPipeline = context.Variables.GetValueOrDefault("build.triggeredBy.buildId")?.Value;

                    if (!string.IsNullOrEmpty(triggeringPipeline))
                    {
                        pipelineId = int.Parse(triggeringPipeline);
                    }
                }

                if (!pipelineId.HasValue)
                {
                    if (pipelineVersionToDownload == pipelineVersionToDownloadLatest)
                    {
                        pipelineId = await this.GetPipelineIdAsync(context, pipelineDefinition, pipelineVersionToDownload, projectName, tagsInput);
                    }
                    else if (pipelineVersionToDownload == pipelineVersionToDownloadSpecific)
                    {
                        pipelineId = Int32.Parse(userSpecifiedpipelineId);
                    }
                    else if (pipelineVersionToDownload == pipelineVersionToDownloadLatestFromBranch)
                    {
                        pipelineId = await this.GetPipelineIdAsync(context, pipelineDefinition, pipelineVersionToDownload, projectName, tagsInput, branchName);
                    }
                    else
                    {
                        throw new InvalidOperationException("Unreachable code!");
                    }
                }

                context.Output(StringUtil.Loc("DownloadingFromBuild", pipelineId));

                downloadParameters = new PipelineArtifactDownloadParameters
                {
                    ProjectRetrievalOptions = BuildArtifactRetrievalOptions.RetrieveByProjectName,
                    ProjectName             = projectName,
                    ProjectId        = projectId,
                    PipelineId       = pipelineId.Value,
                    ArtifactName     = artifactName,
                    TargetDirectory  = targetPath,
                    MinimatchFilters = minimatchPatterns,
                    MinimatchFilterWithArtifactName = true
                };
            }
            else
            {
                throw new InvalidOperationException($"Build type '{sourceRun}' is not recognized.");
            }

            string fullPath = this.CreateDirectoryIfDoesntExist(targetPath);

            DownloadOptions downloadOptions;

            if (string.IsNullOrEmpty(downloadParameters.ArtifactName))
            {
                downloadOptions = DownloadOptions.MultiDownload;
            }
            else
            {
                downloadOptions = DownloadOptions.SingleDownload;
            }

            context.Output(StringUtil.Loc("DownloadArtifactTo", targetPath));
            await server.DownloadAsyncV2(context, downloadParameters, downloadOptions, token);

            context.Output(StringUtil.Loc("DownloadArtifactFinished"));
        }
        // Download with minimatch patterns.
        internal async Task DownloadAsync(
            AgentTaskPluginExecutionContext context,
            PipelineArtifactDownloadParameters downloadParameters,
            CancellationToken cancellationToken)
        {
            VssConnection connection       = context.VssConnection;
            var           buildDropManager = this.CreateBulidDropManager(context, connection);
            BuildServer   buildHelper      = new BuildServer(connection);

            // download all pipeline artifacts if artifact name is missing
            if (string.IsNullOrEmpty(downloadParameters.ArtifactName))
            {
                List <BuildArtifact> artifacts = await buildHelper.GetArtifactsAsync(downloadParameters.ProjectId, downloadParameters.BuildId, cancellationToken);

                IEnumerable <BuildArtifact> pipelineArtifacts = artifacts.Where(a => a.Resource.Type == PipelineArtifactTypeName);
                if (pipelineArtifacts.Count() == 0)
                {
                    throw new ArgumentException("Could not find any pipeline artifacts in the build.");
                }
                else
                {
                    context.Output(StringUtil.Loc("DownloadingMultiplePipelineArtifacts", pipelineArtifacts.Count()));
                    foreach (BuildArtifact pipelineArtifact in pipelineArtifacts)
                    {
                        // each pipeline artifact will have its own subroot to avoid file collisions
                        string pipelineArtifactRootPath = Path.Combine(downloadParameters.TargetDirectory, pipelineArtifact.Name);
                        await DownloadPipelineArtifact(
                            buildDropManager,
                            pipelineArtifact,
                            pipelineArtifactRootPath,
                            downloadParameters.MinimatchFilters,
                            cancellationToken);
                    }
                }
            }
            else
            {
                // 1) get manifest id from artifact data
                BuildArtifact buildArtifact;
                if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectId)
                {
                    buildArtifact = await buildHelper.GetArtifact(downloadParameters.ProjectId, downloadParameters.BuildId, downloadParameters.ArtifactName, cancellationToken);
                }
                else if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectName)
                {
                    if (string.IsNullOrEmpty(downloadParameters.ProjectName))
                    {
                        throw new InvalidOperationException("Project name can't be empty when trying to fetch build artifacts!");
                    }
                    else
                    {
                        buildArtifact = await buildHelper.GetArtifactWithProjectNameAsync(downloadParameters.ProjectName, downloadParameters.BuildId, downloadParameters.ArtifactName, cancellationToken);
                    }
                }
                else
                {
                    throw new InvalidOperationException("Unreachable code!");
                }

                await DownloadPipelineArtifact(
                    buildDropManager,
                    buildArtifact,
                    downloadParameters.TargetDirectory,
                    downloadParameters.MinimatchFilters,
                    cancellationToken);
            }
        }
        protected override async Task ProcessCommandInternalAsync(
            AgentTaskPluginExecutionContext context,
            CancellationToken token)
        {
            ArgUtil.NotNull(context, nameof(context));
            string artifactName            = this.GetArtifactName(context);
            string branchName              = context.GetInput(ArtifactEventProperties.BranchName, required: false);
            string buildPipelineDefinition = context.GetInput(ArtifactEventProperties.BuildPipelineDefinition, required: false);
            string buildType              = context.GetInput(ArtifactEventProperties.BuildType, required: true);
            string buildTriggering        = context.GetInput(ArtifactEventProperties.BuildTriggering, required: false);
            string buildVersionToDownload = context.GetInput(ArtifactEventProperties.BuildVersionToDownload, required: false);
            string downloadPath           = context.GetInput(ArtifactEventProperties.DownloadPath, required: true);
            string environmentBuildId     = context.Variables.GetValueOrDefault(BuildVariables.BuildId)?.Value ?? string.Empty; // BuildID provided by environment.
            string itemPattern            = context.GetInput(ArtifactEventProperties.ItemPattern, required: false);
            string projectName            = context.GetInput(ArtifactEventProperties.Project, required: false);
            string tags = context.GetInput(ArtifactEventProperties.Tags, required: false);
            string userSpecifiedBuildId = context.GetInput(ArtifactEventProperties.BuildId, required: false);

            string[] minimatchPatterns = itemPattern.Split(
                new[] { "\n" },
                StringSplitOptions.RemoveEmptyEntries
                );

            string[] tagsInput = tags.Split(
                new[] { "," },
                StringSplitOptions.None
                );

            PipelineArtifactServer             server = new PipelineArtifactServer();
            PipelineArtifactDownloadParameters downloadParameters;

            if (buildType == buildTypeCurrent)
            {
                // TODO: use a constant for project id, which is currently defined in Microsoft.VisualStudio.Services.Agent.Constants.Variables.System.TeamProjectId (Ting)
                string projectIdStr = context.Variables.GetValueOrDefault("system.teamProjectId")?.Value;
                if (String.IsNullOrEmpty(projectIdStr))
                {
                    throw new ArgumentNullException("Project ID cannot be null.");
                }
                Guid projectId = Guid.Parse(projectIdStr);
                ArgUtil.NotEmpty(projectId, nameof(projectId));

                int buildId = 0;
                if (int.TryParse(environmentBuildId, out buildId) && buildId != 0)
                {
                    context.Output(StringUtil.Loc("DownloadingFromBuild", buildId));
                }
                else
                {
                    string hostType = context.Variables.GetValueOrDefault("system.hosttype")?.Value;
                    if (string.Equals(hostType, "Release", StringComparison.OrdinalIgnoreCase) ||
                        string.Equals(hostType, "DeploymentGroup", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException(StringUtil.Loc("BuildIdIsNotAvailable", hostType ?? string.Empty));
                    }
                    else if (!string.Equals(hostType, "Build", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new InvalidOperationException(StringUtil.Loc("CannotDownloadFromCurrentEnvironment", hostType ?? string.Empty));
                    }
                    else
                    {
                        // This should not happen since the build id comes from build environment. But a user may override that so we must be careful.
                        throw new ArgumentException(StringUtil.Loc("BuildIdIsNotValid", environmentBuildId));
                    }
                }
                downloadParameters = new PipelineArtifactDownloadParameters
                {
                    ProjectRetrievalOptions = BuildArtifactRetrievalOptions.RetrieveByProjectId,
                    ProjectId        = projectId,
                    BuildId          = buildId,
                    ArtifactName     = artifactName,
                    TargetDirectory  = downloadPath,
                    MinimatchFilters = minimatchPatterns
                };
            }
            else if (buildType == buildTypeSpecific)
            {
                int buildId;
                if (buildVersionToDownload == buildVersionToDownloadLatest)
                {
                    buildId = await this.GetBuildIdAsync(context, buildPipelineDefinition, buildVersionToDownload, projectName, tagsInput);
                }
                else if (buildVersionToDownload == buildVersionToDownloadSpecific)
                {
                    buildId = Int32.Parse(userSpecifiedBuildId);
                }
                else if (buildVersionToDownload == buildVersionToDownloadLatestFromBranch)
                {
                    buildId = await this.GetBuildIdAsync(context, buildPipelineDefinition, buildVersionToDownload, projectName, tagsInput, branchName);
                }
                else
                {
                    throw new InvalidOperationException("Unreachable code!");
                }
                downloadParameters = new PipelineArtifactDownloadParameters
                {
                    ProjectRetrievalOptions = BuildArtifactRetrievalOptions.RetrieveByProjectName,
                    ProjectName             = projectName,
                    BuildId          = buildId,
                    ArtifactName     = artifactName,
                    TargetDirectory  = downloadPath,
                    MinimatchFilters = minimatchPatterns
                };
            }
            else
            {
                throw new InvalidOperationException($"Build type '{buildType}' is not recognized.");
            }

            string fullPath = this.CreateDirectoryIfDoesntExist(downloadPath);

            DownloadOptions downloadOptions;

            if (string.IsNullOrEmpty(downloadParameters.ArtifactName))
            {
                downloadOptions = DownloadOptions.MultiDownload;
            }
            else
            {
                downloadOptions = DownloadOptions.SingleDownload;
            }

            context.Output(StringUtil.Loc("DownloadArtifactTo", downloadPath));
            await server.DownloadAsync(context, downloadParameters, downloadOptions, token);

            context.Output(StringUtil.Loc("DownloadArtifactFinished"));
        }
Example #17
0
 public async Task DownloadSingleArtifactAsync(PipelineArtifactDownloadParameters downloadParameters, BuildArtifact buildArtifact, CancellationToken cancellationToken)
 {
     await DownloadMultipleArtifactsAsync(downloadParameters, new List <BuildArtifact> {
         buildArtifact
     }, cancellationToken);
 }
 public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken)
 {
     await this.DownloadFileContainersAsync(downloadParameters.ProjectId, buildArtifacts, downloadParameters.TargetDirectory, downloadParameters.MinimatchFilters, cancellationToken);
 }
 public async Task DownloadSingleArtifactAsync(PipelineArtifactDownloadParameters downloadParameters, BuildArtifact buildArtifact, CancellationToken cancellationToken)
 {
     await this.DownloadFileContainerAsync(downloadParameters.ProjectId, buildArtifact, downloadParameters.TargetDirectory, downloadParameters.MinimatchFilters, cancellationToken);
 }
Example #20
0
 public async Task DownloadMultipleArtifactsAsync(PipelineArtifactDownloadParameters downloadParameters, IEnumerable <BuildArtifact> buildArtifacts, CancellationToken cancellationToken, AgentTaskPluginExecutionContext context)
 {
     context.Warning(StringUtil.Loc("DownloadArtifactWarning", "Build Artifact"));
     await this.DownloadFileContainersAsync(downloadParameters.ProjectId, buildArtifacts, downloadParameters.TargetDirectory, downloadParameters.MinimatchFilters, cancellationToken);
 }
Example #21
0
 public async Task DownloadSingleArtifactAsync(PipelineArtifactDownloadParameters downloadParameters, BuildArtifact buildArtifact, CancellationToken cancellationToken, AgentTaskPluginExecutionContext context)
 {
     await DownloadMultipleArtifactsAsync(downloadParameters, new List <BuildArtifact> {
         buildArtifact
     }, cancellationToken, context);
 }
Example #22
0
        // Download with minimatch patterns.
        internal async Task DownloadAsync(
            AgentTaskPluginExecutionContext context,
            PipelineArtifactDownloadParameters downloadParameters,
            DownloadOptions downloadOptions,
            CancellationToken cancellationToken)
        {
            VssConnection connection       = context.VssConnection;
            var           buildDropManager = this.CreateBulidDropManager(context, connection);
            BuildServer   buildHelper      = new BuildServer(connection);

            // download all pipeline artifacts if artifact name is missing
            if (downloadOptions == DownloadOptions.MultiDownload)
            {
                List <BuildArtifact> artifacts;
                if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectId)
                {
                    artifacts = await buildHelper.GetArtifactsAsync(downloadParameters.ProjectId, downloadParameters.PipelineId, cancellationToken);
                }
                else if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectName)
                {
                    if (string.IsNullOrEmpty(downloadParameters.ProjectName))
                    {
                        throw new InvalidOperationException("Project name can't be empty when trying to fetch build artifacts!");
                    }
                    else
                    {
                        artifacts = await buildHelper.GetArtifactsWithProjectNameAsync(downloadParameters.ProjectName, downloadParameters.PipelineId, cancellationToken);
                    }
                }
                else
                {
                    throw new InvalidOperationException("Unreachable code!");
                }

                IEnumerable <BuildArtifact> pipelineArtifacts = artifacts.Where(a => a.Resource.Type == PipelineArtifactTypeName);
                if (pipelineArtifacts.Count() == 0)
                {
                    throw new ArgumentException("Could not find any pipeline artifacts in the build.");
                }
                else
                {
                    context.Output(StringUtil.Loc("DownloadingMultiplePipelineArtifacts", pipelineArtifacts.Count()));

                    var artifactNameAndManifestIds = pipelineArtifacts.ToDictionary(
                        keySelector: (a) => a.Name, // keys should be unique, if not something is really wrong
                        elementSelector: (a) => DedupIdentifier.Create(a.Resource.Data));
                    // 2) download to the target path
                    var options = DownloadPipelineArtifactOptions.CreateWithMultiManifestIds(
                        artifactNameAndManifestIds,
                        downloadParameters.TargetDirectory,
                        proxyUri: null,
                        minimatchPatterns: downloadParameters.MinimatchFilters);
                    await buildDropManager.DownloadAsync(options, cancellationToken);
                }
            }
            else if (downloadOptions == DownloadOptions.SingleDownload)
            {
                // 1) get manifest id from artifact data
                BuildArtifact buildArtifact;
                if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectId)
                {
                    buildArtifact = await buildHelper.GetArtifact(downloadParameters.ProjectId, downloadParameters.PipelineId, downloadParameters.ArtifactName, cancellationToken);
                }
                else if (downloadParameters.ProjectRetrievalOptions == BuildArtifactRetrievalOptions.RetrieveByProjectName)
                {
                    if (string.IsNullOrEmpty(downloadParameters.ProjectName))
                    {
                        throw new InvalidOperationException("Project name can't be empty when trying to fetch build artifacts!");
                    }
                    else
                    {
                        buildArtifact = await buildHelper.GetArtifactWithProjectNameAsync(downloadParameters.ProjectName, downloadParameters.PipelineId, downloadParameters.ArtifactName, cancellationToken);
                    }
                }
                else
                {
                    throw new InvalidOperationException("Unreachable code!");
                }

                var manifestId = DedupIdentifier.Create(buildArtifact.Resource.Data);
                var options    = DownloadPipelineArtifactOptions.CreateWithManifestId(
                    manifestId,
                    downloadParameters.TargetDirectory,
                    proxyUri: null,
                    minimatchPatterns: downloadParameters.MinimatchFilters);

                await buildDropManager.DownloadAsync(options, cancellationToken);
            }
            else
            {
                throw new InvalidOperationException("Unreachable code!");
            }
        }