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")); }
protected override async Task ProcessCommandInternalAsync( AgentTaskPluginExecutionContext context, CancellationToken token) { string artifactName = context.GetInput(ArtifactEventProperties.ArtifactName, required: false); if (string.IsNullOrEmpty(artifactName)) { context.Output($"Artifact name was not inserted for publishing."); } else { context.Output($"Artifact name input: {artifactName}"); } string targetPath = context.GetInput(TargetPath, required: true); string artifactType = context.GetInput(ArtifactEventProperties.ArtifactType, required: false); artifactType = string.IsNullOrEmpty(artifactType) ? pipelineType : artifactType.ToLower(); string defaultWorkingDirectory = context.Variables.GetValueOrDefault("system.defaultworkingdirectory").Value; bool onPrem = !String.Equals(context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.ServerType)?.Value, "Hosted", StringComparison.OrdinalIgnoreCase); if (onPrem) { throw new InvalidOperationException(StringUtil.Loc("OnPremIsNotSupported")); } targetPath = Path.IsPathFullyQualified(targetPath) ? targetPath : Path.GetFullPath(Path.Combine(defaultWorkingDirectory, targetPath)); // Project ID var teamProjectId = context.Variables.GetValueOrDefault(BuildVariables.TeamProjectId)?.Value; Guid projectId = teamProjectId != null ? new Guid(teamProjectId) : Guid.Empty; ArgUtil.NotEmpty(projectId, nameof(projectId)); // Build ID string buildIdStr = context.Variables.GetValueOrDefault(BuildVariables.BuildId)?.Value ?? string.Empty; if (!int.TryParse(buildIdStr, out int buildId)) { // 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", buildIdStr)); } if (artifactType == pipelineType) { string hostType = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.HostType)?.Value; if (!string.Equals(hostType, "Build", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException( StringUtil.Loc("CannotUploadFromCurrentEnvironment", hostType ?? string.Empty)); } if (String.IsNullOrWhiteSpace(artifactName)) { string jobIdentifier = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobIdentifier).Value; var normalizedJobIdentifier = NormalizeJobIdentifier(jobIdentifier); artifactName = normalizedJobIdentifier; } if (!PipelineArtifactPathHelper.IsValidArtifactName(artifactName)) { throw new ArgumentException(StringUtil.Loc("ArtifactNameIsNotValid", artifactName)); } string fullPath = Path.GetFullPath(targetPath); bool isFile = File.Exists(fullPath); bool isDir = Directory.Exists(fullPath); if (!isFile && !isDir) { // if local path is neither file nor folder throw new FileNotFoundException(StringUtil.Loc("PathDoesNotExist", targetPath)); } // Upload to VSTS BlobStore, and associate the artifact with the build. context.Output(StringUtil.Loc("UploadingPipelineArtifact", fullPath, buildId)); PipelineArtifactServer server = new PipelineArtifactServer(tracer); await server.UploadAsync(context, projectId, buildId, artifactName, fullPath, token); context.Output(StringUtil.Loc("UploadArtifactFinished")); } else if (artifactType == fileShareType) { string fileSharePath = context.GetInput(ArtifactEventProperties.FileSharePath, required: true); fileSharePath = Path.IsPathFullyQualified(fileSharePath) ? fileSharePath : Path.GetFullPath(Path.Combine(defaultWorkingDirectory, fileSharePath)); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { FilePathServer server = new FilePathServer(); await server.UploadAsync(context, projectId, buildId, artifactName, targetPath, fileSharePath, token); } else { // file share artifacts are not currently supported on OSX/Linux. throw new InvalidOperationException(StringUtil.Loc("FileShareOperatingSystemNotSupported")); } } }
protected override async Task ProcessCommandInternalAsync( AgentTaskPluginExecutionContext context, CancellationToken token) { string artifactName = context.GetInput(ArtifactEventProperties.ArtifactName, required: false); string targetPath = context.GetInput(TargetPath, required: true); string defaultWorkingDirectory = context.Variables.GetValueOrDefault("system.defaultworkingdirectory").Value; targetPath = Path.IsPathFullyQualified(targetPath) ? targetPath : Path.GetFullPath(Path.Combine(defaultWorkingDirectory, targetPath)); string hostType = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.HostType)?.Value; if (!string.Equals(hostType, "Build", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException( StringUtil.Loc("CannotUploadFromCurrentEnvironment", hostType ?? string.Empty)); } if (String.IsNullOrWhiteSpace(artifactName)) { string jobIdentifier = context.Variables.GetValueOrDefault(WellKnownDistributedTaskVariables.JobIdentifier).Value; var normalizedJobIdentifier = NormalizeJobIdentifier(jobIdentifier); artifactName = normalizedJobIdentifier; } if (!PipelineArtifactPathHelper.IsValidArtifactName(artifactName)) { throw new ArgumentException(StringUtil.Loc("ArtifactNameIsNotValid", artifactName)); } // Project ID Guid projectId = new Guid(context.Variables.GetValueOrDefault(BuildVariables.TeamProjectId)?.Value ?? Guid.Empty.ToString()); ArgUtil.NotEmpty(projectId, nameof(projectId)); // Build ID string buildIdStr = context.Variables.GetValueOrDefault(BuildVariables.BuildId)?.Value ?? string.Empty; if (!int.TryParse(buildIdStr, out int buildId)) { // 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", buildIdStr)); } string fullPath = Path.GetFullPath(targetPath); bool isFile = File.Exists(fullPath); bool isDir = Directory.Exists(fullPath); if (!isFile && !isDir) { // if local path is neither file nor folder throw new FileNotFoundException(StringUtil.Loc("PathDoesNotExist", targetPath)); } // Upload to VSTS BlobStore, and associate the artifact with the build. context.Output(StringUtil.Loc("UploadingPipelineArtifact", fullPath, buildId)); PipelineArtifactServer server = new PipelineArtifactServer(); await server.UploadAsync(context, projectId, buildId, artifactName, fullPath, token); context.Output(StringUtil.Loc("UploadArtifactFinished")); }
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 allowPartiallySucceededBuilds = context.GetInput(ArtifactEventProperties.AllowPartiallySucceededBuilds, required: false); string allowFailedBuilds = context.GetInput(ArtifactEventProperties.AllowFailedBuilds, required: false); string allowCanceledBuilds = context.GetInput(ArtifactEventProperties.AllowCanceledBuilds, required: false); string userSpecifiedRunId = context.GetInput(RunId, required: false); string defaultWorkingDirectory = context.Variables.GetValueOrDefault("system.defaultworkingdirectory").Value; targetPath = Path.IsPathFullyQualified(targetPath) ? targetPath : Path.GetFullPath(Path.Combine(defaultWorkingDirectory, targetPath)); context.Debug($"TargetPath: {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)); } context.Debug($"ArtifactName: {artifactName}"); string[] minimatchPatterns = itemPattern.Split( new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries ); string[] tagsInput = tags.Split( new[] { "," }, StringSplitOptions.None ); if (!bool.TryParse(allowPartiallySucceededBuilds, out var allowPartiallySucceededBuildsBool)) { allowPartiallySucceededBuildsBool = false; } if (!bool.TryParse(allowFailedBuilds, out var allowFailedBuildsBool)) { allowFailedBuildsBool = false; } if (!bool.TryParse(allowCanceledBuilds, out var allowCanceledBuildsBool)) { allowCanceledBuildsBool = false; } var resultFilter = GetResultFilter(allowPartiallySucceededBuildsBool, allowFailedBuildsBool, allowCanceledBuildsBool); context.Debug($"BuildResult: {resultFilter.ToString()}"); PipelineArtifactServer server = new PipelineArtifactServer(tracer); ArtifactDownloadParameters downloadParameters; if (sourceRun == sourceRunCurrent) { context.Debug("Run: CurrentRun"); // 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(StringUtil.Loc("CannotBeNullOrEmpty"), "Project ID"); } Guid projectId = Guid.Parse(projectIdStr); ArgUtil.NotEmpty(projectId, nameof(projectId)); context.Debug($"ProjectId: {projectId.ToString()}"); int pipelineId = 0; if (int.TryParse(environmentBuildId, out pipelineId) && pipelineId != 0) { OutputBuildInfo(context, 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 ArtifactDownloadParameters { ProjectRetrievalOptions = BuildArtifactRetrievalOptions.RetrieveByProjectId, ProjectId = projectId, PipelineId = pipelineId, ArtifactName = artifactName, TargetDirectory = targetPath, MinimatchFilters = minimatchPatterns, MinimatchFilterWithArtifactName = true }; } else if (sourceRun == sourceRunSpecific) { context.Debug("Run: Specific"); if (String.IsNullOrEmpty(projectName)) { throw new ArgumentNullException(StringUtil.Loc("CannotBeNullOrEmpty"), "Project Name"); } Guid projectId; bool isProjGuid = Guid.TryParse(projectName, out projectId); if (!isProjGuid) { projectId = await GetProjectIdAsync(context, projectName); } context.Debug($"ProjectId: {projectId.ToString()}"); // Set the default pipelineId to 0, which is an invalid build id and it has to be reassigned to a valid build id. int pipelineId = 0; bool pipelineTriggeringBool; if (bool.TryParse(pipelineTriggering, out pipelineTriggeringBool) && pipelineTriggeringBool) { context.Debug("TrigerringPipeline: true"); string hostType = context.Variables.GetValueOrDefault("system.hostType").Value; string triggeringPipeline = null; if (!string.IsNullOrWhiteSpace(hostType) && !hostType.Equals("build", StringComparison.OrdinalIgnoreCase)) // RM env. { context.Debug("Environment: Release"); var releaseAlias = context.Variables.GetValueOrDefault("release.triggeringartifact.alias")?.Value; var definitionIdTriggered = context.Variables.GetValueOrDefault("release.artifacts." + releaseAlias ?? string.Empty + ".definitionId")?.Value; if (!string.IsNullOrWhiteSpace(definitionIdTriggered) && definitionIdTriggered.Equals(pipelineDefinition, StringComparison.OrdinalIgnoreCase)) { triggeringPipeline = context.Variables.GetValueOrDefault("release.artifacts." + releaseAlias ?? string.Empty + ".buildId")?.Value; context.Debug($"TrigerringPipeline: {triggeringPipeline}"); } } else { context.Debug("Environment: Build"); var definitionIdTriggered = context.Variables.GetValueOrDefault("build.triggeredBy.definitionId")?.Value; if (!string.IsNullOrWhiteSpace(definitionIdTriggered) && definitionIdTriggered.Equals(pipelineDefinition, StringComparison.OrdinalIgnoreCase)) { triggeringPipeline = context.Variables.GetValueOrDefault("build.triggeredBy.buildId")?.Value; context.Debug($"TrigerringPipeline: {triggeringPipeline}"); } } if (!string.IsNullOrWhiteSpace(triggeringPipeline)) { pipelineId = int.Parse(triggeringPipeline); } context.Debug($"PipelineId from trigerringBuild: {pipelineId}"); } if (pipelineId == 0) { context.Debug($"PipelineVersionToDownload: {pipelineVersionToDownload}"); if (pipelineVersionToDownload == pipelineVersionToDownloadLatest) { pipelineId = await this.GetPipelineIdAsync(context, pipelineDefinition, pipelineVersionToDownload, projectId.ToString(), tagsInput, resultFilter, null, cancellationToken : token); } else if (pipelineVersionToDownload == pipelineVersionToDownloadSpecific) { bool isPipelineIdNum = Int32.TryParse(userSpecifiedRunId, out pipelineId); if (!isPipelineIdNum) { throw new ArgumentException(StringUtil.Loc("RunIDNotValid", userSpecifiedRunId)); } } else if (pipelineVersionToDownload == pipelineVersionToDownloadLatestFromBranch) { pipelineId = await this.GetPipelineIdAsync(context, pipelineDefinition, pipelineVersionToDownload, projectId.ToString(), tagsInput, resultFilter, branchName, cancellationToken : token); } else { throw new InvalidOperationException("Unreachable code!"); } context.Debug($"PipelineId from non-trigerringBuild: {pipelineId}"); } OutputBuildInfo(context, pipelineId); downloadParameters = new ArtifactDownloadParameters { ProjectRetrievalOptions = BuildArtifactRetrievalOptions.RetrieveByProjectName, ProjectName = projectName, ProjectId = projectId, PipelineId = pipelineId, 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")); }