public override async Task ExecuteAsync(IOperationExecutionContext context) { var sourcePath = context.ResolvePath(this.SourceFileName); var targetPath = context.ResolvePath(this.TargetFileName); this.LogInformation($"Renaming {sourcePath} to {targetPath}..."); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); this.LogDebug($"Verifying source file {sourcePath} exists..."); if (!await fileOps.FileExistsAsync(sourcePath).ConfigureAwait(false)) { this.LogError("Source path does not exist."); return; } if (sourcePath.Equals(targetPath, StringComparison.OrdinalIgnoreCase)) { this.LogWarning("The source and target file names are the same."); return; } if (!this.Overwrite && await fileOps.FileExistsAsync(targetPath).ConfigureAwait(false)) { this.LogError(this.TargetFileName + " already exists and overwrite is set to false."); return; } await fileOps.MoveFileAsync(sourcePath, targetPath, this.Overwrite).ConfigureAwait(false); this.LogInformation("File renamed."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var zipFilePath = context.ResolvePath(this.FileName); var sourceDirectory = context.ResolvePath(this.DirectoryToZip); this.LogDebug($"Zipping {sourceDirectory} to {zipFilePath}..."); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); var targetDirectory = PathEx.GetDirectoryName(zipFilePath); this.LogDebug($"Ensuring that {targetDirectory} exists..."); await fileOps.CreateDirectoryAsync(targetDirectory).ConfigureAwait(false); this.LogInformation("Creating zip file..."); if (this.Overwrite) { this.LogDebug($"Deleting {zipFilePath} if it already exists..."); await fileOps.DeleteFileAsync(zipFilePath).ConfigureAwait(false); } else if (await fileOps.FileExistsAsync(zipFilePath).ConfigureAwait(false)) { this.LogDebug(zipFilePath + " aready exists."); this.LogError(zipFilePath + " already exists and overwrite is set to false."); } await fileOps.CreateZipFileAsync(sourceDirectory, zipFilePath).ConfigureAwait(false); this.LogInformation(zipFilePath + " file created."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); var nugetExe = await this.GetNuGetExePathAsync(context).ConfigureAwait(false); if (string.IsNullOrEmpty(nugetExe)) { this.LogError("nuget.exe path was empty."); return; } var sourceDirectory = context.ResolvePath(this.SourceDirectory); var outputDirectory = context.ResolvePath(this.OutputDirectory, this.SourceDirectory); var fullProjectPath = context.ResolvePath(this.ProjectPath, this.SourceDirectory); if (!await fileOps.FileExistsAsync(fullProjectPath).ConfigureAwait(false)) { this.LogError(fullProjectPath + " does not exist."); return; } fileOps.CreateDirectory(outputDirectory); this.LogInformation($"Creating NuGet package from {fullProjectPath} to {outputDirectory}..."); await this.ExecuteNuGet(context, nugetExe, fullProjectPath, sourceDirectory, outputDirectory).ConfigureAwait(false); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var sourceDirectory = context.ResolvePath(this.SourceDirectory); this.LogInformation($"Concatenating files in {sourceDirectory}..."); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); var files = (await fileOps.GetFileSystemInfosAsync(sourceDirectory, new MaskingContext(this.Includes, this.Excludes)).ConfigureAwait(false)) .OfType <SlimFileInfo>() .ToList(); if (files.Count == 0) { this.LogWarning("No files to concatenate."); return; } var encoding = this.GetOrGuessEncoding(); var outputFileName = context.ResolvePath(this.OutputFile); this.LogInformation($"Concatenating {files.Count} files into {PathEx.GetFileName(outputFileName)}..."); this.LogDebug($"Output file {outputFileName}, encoding: {encoding.EncodingName}"); var outputDirectory = PathEx.GetDirectoryName(outputFileName); if (!string.IsNullOrEmpty(outputDirectory)) { await fileOps.CreateDirectoryAsync(outputDirectory).ConfigureAwait(false); } using (var outputStream = await fileOps.OpenFileAsync(outputFileName, FileMode.Create, FileAccess.Write).ConfigureAwait(false)) using (var outputWriter = new StreamWriter(outputStream, encoding)) { bool first = true; foreach (var file in files) { context.CancellationToken.ThrowIfCancellationRequested(); if (!first) { await outputWriter.WriteAsync(this.ContentSeparationText ?? "").ConfigureAwait(false); } else { first = false; } using (var inputStream = await fileOps.OpenFileAsync(file.FullName, FileMode.Open, FileAccess.Read).ConfigureAwait(false)) using (var inputReader = new StreamReader(inputStream)) { await inputReader.CopyToAsync(outputWriter, 4096, context.CancellationToken).ConfigureAwait(false); } } } this.LogInformation(outputFileName + " file created."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var targetDirectory = context.ResolvePath(this.TargetDirectory); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); var zipFilePath = context.ResolvePath(this.FileName); this.LogInformation($"Extracting zip file {zipFilePath}..."); if (!await fileOps.DirectoryExistsAsync(targetDirectory).ConfigureAwait(false)) { this.LogDebug($"Target directory {targetDirectory} does not exist; creating..."); await fileOps.CreateDirectoryAsync(targetDirectory).ConfigureAwait(false); } if (this.ClearTargetDirectory) { this.LogDebug($"Clearing {targetDirectory}..."); await fileOps.ClearDirectoryAsync(targetDirectory).ConfigureAwait(false); } this.LogDebug($"Unzipping {zipFilePath} to {targetDirectory}..."); await fileOps.ExtractZipFileAsync(zipFilePath, targetDirectory, this.Overwrite).ConfigureAwait(false); this.LogInformation(zipFilePath + " extracted."); }
public override Task ExecuteAsync(IOperationExecutionContext context) { var sourceDirectory = context.ResolvePath(this.SourceDirectory); var targetDirectory = context.ResolvePath(this.TargetDirectory); this.LogInformation($"Copying files from {sourceDirectory} to {targetDirectory}..."); return(this.CopyDirectoryAsync(context.Agent.GetService <IFileOperationsExecuter>(), sourceDirectory, targetDirectory, context)); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { try { new Uri(this.Url); } catch (Exception ex) { this.LogError($"The URL \"{this.Url}\" is invalid because: {ex.Message}"); return; } this.ResolvedFilePath = context.ResolvePath(this.FileName); this.LogDebug("File path resolved to: " + this.ResolvedFilePath); if (!this.ProxyRequest) { var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); await fileOps.CreateDirectoryAsync(PathEx.GetDirectoryName(this.ResolvedFilePath)).ConfigureAwait(false); using (var fileStream = await fileOps.OpenFileAsync(this.ResolvedFilePath, FileMode.Create, FileAccess.Write).ConfigureAwait(false)) { this.LogInformation($"Downloading {this.Url} to {this.FileName}..."); await this.PerformRequestAsync(fileStream, context.CancellationToken).ConfigureAwait(false); this.LogInformation("HTTP file download completed."); return; } } this.LogInformation($"Downloading {this.Url} to {this.FileName}..."); await this.CallRemoteAsync(context).ConfigureAwait(false); this.LogInformation("HTTP file download completed."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { if (string.IsNullOrEmpty(this.MavenPath)) { this.LogError("Could not determine the location of mvn on this server. To resolve this issue, ensure that Maven is available on this server and create a server-scoped variable named $MavenPath set to the location of mvn (or mvn.bat on Windows)."); return; } var fileOps = context.Agent.GetService <IFileOperationsExecuter>(); if (!fileOps.FileExists(this.MavenPath)) { this.LogError("Maven not found at: " + this.MavenPath); return; } var sourceDirectory = context.ResolvePath(this.SourceDirectory); this.LogDebug("Source directory: " + sourceDirectory); fileOps.CreateDirectory(sourceDirectory); await this.ExecuteCommandLineAsync( context, new RemoteProcessStartInfo { FileName = this.MavenPath, Arguments = this.GoalsAndPhases + " " + this.AdditionalArguments, WorkingDirectory = sourceDirectory } ); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); var nugetExe = await this.GetNuGetExePathAsync(context).ConfigureAwait(false); if (string.IsNullOrEmpty(nugetExe)) { this.LogError("nuget.exe path was empty."); return; } var sourceDirectory = context.ResolvePath(this.SourceDirectory); var outputDirectory = context.ResolvePath(PathEx.Combine(sourceDirectory, this.PackageOutputDirectory)); this.LogInformation($"Installing packages for projects in {sourceDirectory} to {outputDirectory}..."); if (!await fileOps.DirectoryExistsAsync(sourceDirectory).ConfigureAwait(false)) { this.LogWarning(sourceDirectory + " does not exist."); return; } await fileOps.CreateDirectoryAsync(outputDirectory).ConfigureAwait(false); this.LogInformation($"Finding packages.config files in {sourceDirectory}..."); var configFiles = (from e in fileOps.GetFileSystemInfos(sourceDirectory, new MaskingContext(new[] { "**packages.config" }, Enumerable.Empty <string>())) where string.Equals(e.Name, "packages.config", System.StringComparison.OrdinalIgnoreCase) let f = e as SlimFileInfo where f != null select f).ToArray(); if (configFiles.Length == 0) { this.LogWarning("No packages.config files found."); return; } foreach (var configFile in configFiles) { this.LogInformation($"Installing packages for {configFile.FullName}..."); await this.ExecuteNuGetAsync(context, nugetExe, configFile.FullName, outputDirectory).ConfigureAwait(false); } this.LogInformation("Done installing packages!"); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { try { var dotStar = this.Version.EndsWith(".*"); var version = dotStar ? this.Version.Substring(0, this.Version.Length - 2) : this.Version; new Version(version); } catch { this.LogError($"The specified version ({this.Version}) is not a valid .NET assembly version."); return; } this.LogInformation($"Setting assembly version attributes to {this.Version}..."); var fileOps = context.Agent.GetService <IFileOperationsExecuter>(); var matches = (await fileOps.GetFileSystemInfosAsync(context.ResolvePath(this.SourceDirectory), new MaskingContext(this.Includes, this.Excludes)).ConfigureAwait(false)) .OfType <SlimFileInfo>() .ToList(); if (matches.Count == 0) { this.LogWarning("No matching files found."); return; } foreach (var match in matches) { this.LogInformation($"Writing assembly versions attributes to {match.FullName}..."); string text; Encoding encoding; using (var stream = await fileOps.OpenFileAsync(match.FullName, FileMode.Open, FileAccess.Read).ConfigureAwait(false)) using (var reader = new StreamReader(stream, true)) { text = await reader.ReadToEndAsync().ConfigureAwait(false); encoding = reader.CurrentEncoding; } if (AttributeRegex.IsMatch(text)) { text = AttributeRegex.Replace(text, this.GetReplacement); var attr = match.Attributes; if ((attr & FileAttributes.ReadOnly) != 0) { await fileOps.SetAttributesAsync(match.FullName, attr& ~FileAttributes.ReadOnly).ConfigureAwait(false); } using (var stream = await fileOps.OpenFileAsync(match.FullName, FileMode.Create, FileAccess.Write).ConfigureAwait(false)) using (var writer = new StreamWriter(stream, encoding)) { await writer.WriteAsync(text).ConfigureAwait(false); } } } }
public override Task ExecuteAsync(IOperationExecutionContext context) { var sourcePath = PackageInstaller.PackageContentsPath; if (string.IsNullOrEmpty(sourcePath)) { throw new ExecutionFailureException(true, "Romp package contents path not set."); } if (!PathEx.IsPathRooted(sourcePath)) { throw new ExecutionFailureException(true, "Romp package contents path is not absolute."); } var deployTarget = context.ResolvePath(this.TargetDirectory); foreach (var sourceFileName in Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories)) { if (sourceFileName.Length <= sourcePath.Length) { continue; } var relativePath = sourceFileName.Substring(sourcePath.Length).TrimStart('\\', '/'); var targetPath = PathEx.Combine(deployTarget, relativePath); try { if (File.Exists(targetPath)) { this.LogDebug($"Deleting {targetPath}..."); File.Delete(targetPath); } } catch (Exception ex) when(!(ex is FileNotFoundException) && !(ex is DirectoryNotFoundException)) { this.LogError($"Unable to delete {targetPath}: {ex.Message}"); } } var remainingDirs = Directory.EnumerateDirectories(deployTarget, "*", SearchOption.AllDirectories) .OrderByDescending(d => d.Count(c => c == '\\' || c == '/')) .Concat(new[] { deployTarget }); foreach (var dir in remainingDirs) { try { this.LogDebug($"Removing directory {dir}..."); Directory.Delete(dir); } catch { this.LogDebug($"Directory {dir} is not empty; will not remove."); } } return(Complete); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var packagePath = context.ResolvePath(this.PackagePath); if (string.IsNullOrEmpty(packagePath)) { this.LogError("Missing required argument \"Package\"."); return; } var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); if (!await fileOps.FileExistsAsync(packagePath)) { this.LogError($"Package file {packagePath} not found."); return; } this.LogDebug($"Using package source {this.PackageSource}."); var packageSource = (NuGetPackageSource)SecureResource.Create(this.PackageSource, (IResourceResolutionContext)context); var nugetInfo = await this.GetNuGetInfoAsync(context); this.LogDebug($"Using credentials {packageSource.CredentialName}."); var credentials = packageSource.GetCredentials((ICredentialResolutionContext)context); if (credentials is not TokenCredentials tokenCredentials) { this.LogError("Pushing a NuGet package requires an API key specified in Token credentials."); return; } this.LogInformation($"Pushing package {packagePath}..."); if (nugetInfo.IsNuGetExe) { await this.ExecuteNuGetAsync( context, nugetInfo, $"push \"{packagePath}\" -ApiKey \"{AH.Unprotect(tokenCredentials.Token)}\" -Source \"{packageSource.ApiEndpointUrl}\" -NonInteractive", null, $"push \"{packagePath}\" -ApiKey XXXXX -Source \"{packageSource.ApiEndpointUrl}\" -NonInteractive" ); } else { await this.ExecuteNuGetAsync( context, nugetInfo, $"nuget push \"{packagePath}\" --api-key \"{AH.Unprotect(tokenCredentials.Token)}\" --source \"{packageSource.ApiEndpointUrl}\"", null, $"nuget push \"{packagePath}\" --api-key XXXXX --source \"{packageSource.ApiEndpointUrl}\"" ); } }
public override async Task ConfigureAsync(IOperationExecutionContext context) { var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); var fileName = context.ResolvePath(this.FileName); if (context.Simulation && !await fileOps.FileExistsAsync(fileName)) { this.LogWarning("File does not exist and execution is in simulation mode."); return; } XDocument doc; using (var file = await fileOps.OpenFileAsync(fileName, FileMode.Open, FileAccess.Read)) { doc = XDocument.Load(file); var appSettings = this.GetAppSettingsElements(doc).FirstOrDefault(); if (appSettings == null) { this.LogError("The appSettings element does not exist in " + fileName); return; } var keyElement = appSettings .Elements("add") .FirstOrDefault(e => string.Equals((string)e.Attribute("key"), this.ConfigurationKey, StringComparison.OrdinalIgnoreCase)); if (keyElement == null) { this.LogDebug("Key was not found, adding..."); appSettings.Add(new XElement("add", new XAttribute("key", this.ConfigurationKey), new XAttribute("value", this.ExpectedValue))); this.LogDebug("AppSetting key and value added."); } else { this.LogDebug($"Changing appSetting value to {this.ExpectedValue}..."); keyElement.SetAttributeValue("value", this.ExpectedValue); this.LogDebug("AppSetting value changed."); } } if (!context.Simulation) { using (var file = await fileOps.OpenFileAsync(fileName, FileMode.Create, FileAccess.Write)) { doc.Save(file); } } this.LogInformation($"AppSetting \"{this.ConfigurationKey}\" set to \"{this.ExpectedValue}\"."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var vsTestPath = await this.GetVsTestPathAsync(context); if (string.IsNullOrEmpty(vsTestPath)) { return; } var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); var containerPath = context.ResolvePath(this.TestContainer); var sourceDirectory = PathEx.GetDirectoryName(containerPath); var resultsPath = PathEx.Combine(sourceDirectory, "TestResults"); if (this.ClearExistingTestResults) { this.LogDebug($"Clearing {resultsPath} directory..."); await fileOps.ClearDirectoryAsync(resultsPath); } await this.ExecuteCommandLineAsync( context, new RemoteProcessStartInfo { FileName = vsTestPath, Arguments = $"\"{containerPath}\" /logger:trx {this.AdditionalArguments}", WorkingDirectory = sourceDirectory } ); if (!await fileOps.DirectoryExistsAsync(resultsPath)) { this.LogError("Could not find the generated \"TestResults\" directory after running unit tests at: " + sourceDirectory); return; } var trxFiles = (await fileOps.GetFileSystemInfosAsync(resultsPath, new MaskingContext(new[] { "*.trx" }, Enumerable.Empty <string>()))) .OfType <SlimFileInfo>() .ToList(); if (trxFiles.Count == 0) { this.LogError("There are no .trx files in the \"TestResults\" directory."); return; } var trxPath = trxFiles .Aggregate((latest, next) => next.LastWriteTimeUtc > latest.LastWriteTimeUtc ? next : latest) .FullName; await context.RecordUnitTestResultsAsync(trxPath, this.TestGroup); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { this.LogInformation("Executing SVN export..."); var(c, r) = this.GetCredentialsAndResource(context); var client = new SvnClient(context, c, this.SvnExePath, this); var sourcePath = new SvnPath(r?.RepositoryUrl, this.SourcePath); var result = await client.ExportAsync(sourcePath, context.ResolvePath(this.DestinationPath), this.AdditionalArguments).ConfigureAwait(false); this.LogClientResult(result); this.LogInformation("SVN export executed."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { string repositoryUrl = await this.GetRepositoryUrlAsync(context.CancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(repositoryUrl)) { this.LogError("RepositoryUrl is not specified. It must be included in either the referenced credential or in the RepositoryUrl argument of the operation."); return; } string branchDesc = string.IsNullOrEmpty(this.Branch) ? "" : $" on '{this.Branch}' branch"; string refDesc = string.IsNullOrEmpty(this.Ref) ? "" : $", commit '{this.Ref}'"; this.LogInformation($"Getting source from '{repositoryUrl}'{branchDesc}{refDesc}..."); var workspacePath = WorkspacePath.Resolve(context, repositoryUrl, this.WorkspaceDiskPath); if (this.CleanWorkspace) { this.LogDebug($"Clearing workspace path '{workspacePath.FullPath}'..."); var fileOps = context.Agent.GetService <IFileOperationsExecuter>(); await fileOps.ClearDirectoryAsync(workspacePath.FullPath).ConfigureAwait(false); } var client = this.CreateClient(context, repositoryUrl, workspacePath); bool valid = await client.IsRepositoryValidAsync().ConfigureAwait(false); if (!valid) { await client.CloneAsync( new GitCloneOptions { Branch = this.Branch, RecurseSubmodules = this.RecurseSubmodules } ).ConfigureAwait(false); } this.CommitHash = await client.UpdateAsync( new GitUpdateOptions { RecurseSubmodules = this.RecurseSubmodules, Branch = this.Branch, Ref = this.Ref } ).ConfigureAwait(false); this.LogDebug($"Current commit is {this.CommitHash}."); await client.ArchiveAsync(context.ResolvePath(this.DiskPath), this.KeepInternals).ConfigureAwait(false); this.LogInformation("Get source complete."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var sourcePath = PackageInstaller.PackageContentsPath; if (string.IsNullOrEmpty(sourcePath)) { throw new ExecutionFailureException(true, "Romp package contents path not set."); } if (!PathEx.IsPathRooted(sourcePath)) { throw new ExecutionFailureException(true, "Romp package contents path is not absolute."); } var deployTarget = context.ResolvePath(this.TargetDirectory); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); if (await fileOps.DirectoryExistsAsync(sourcePath).ConfigureAwait(false)) { await copyDirectoryAsync(sourcePath, deployTarget).ConfigureAwait(false); } async Task copyDirectoryAsync(string src, string dest) { context.CancellationToken.ThrowIfCancellationRequested(); await fileOps.CreateDirectoryAsync(dest).ConfigureAwait(false); var items = new Queue <SlimFileSystemInfo>( from i in await fileOps.GetFileSystemInfosAsync(src, MaskingContext.Default).ConfigureAwait(false) orderby i is SlimFileInfo descending select i ); // do it this awkward way to reduce GC pressure if there are lots of files SlimFileSystemInfo current; while ((current = items.Count > 0 ? items.Dequeue() : null) != null) { context.CancellationToken.ThrowIfCancellationRequested(); var targetPath = fileOps.CombinePath(dest, current.Name); if (current is SlimFileInfo) { this.LogDebug($"Deploying {targetPath}..."); await fileOps.CopyFileAsync(current.FullName, targetPath, true).ConfigureAwait(false); } else { await copyDirectoryAsync(current.FullName, targetPath).ConfigureAwait(false); } } } }
private async Task <string> GetNuGetExePathAsync(IOperationExecutionContext context) { if (!string.IsNullOrEmpty(this.NuGetExePath)) { return(context.ResolvePath(this.NuGetExePath)); } var executer = await context.Agent.GetServiceAsync <IRemoteMethodExecuter>().ConfigureAwait(false); string assemblyDir = await executer.InvokeFuncAsync(GetNuGetExeDirectory).ConfigureAwait(false); return(PathEx.Combine(assemblyDir, "nuget.exe")); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { this.LogInformation("Executing SVN update..."); var(c, r) = this.GetCredentialsAndResource(context); var client = new SvnClient(context, c, this.SvnExePath, this); var result = await client.UpdateAsync(context.ResolvePath(this.DiskPath), this.AdditionalArguments).ConfigureAwait(false); this.LogClientResult(result); this.LogInformation("SVN update executed."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var credentials = this.GetCredentials(context as ICredentialResolutionContext); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); var sourceDirectory = context.ResolvePath(this.SourceDirectory); if (!await fileOps.DirectoryExistsAsync(sourceDirectory)) { this.LogWarning($"Source directory {sourceDirectory} does not exist; nothing to upload."); return; } var files = (await fileOps.GetFileSystemInfosAsync(sourceDirectory, new MaskingContext(this.Includes, this.Excludes))) .OfType <SlimFileInfo>() .ToList(); if (files.Count == 0) { this.LogWarning($"No files match the specified masks in {sourceDirectory}; nothing to upload."); return; } var prefix = string.Empty; if (!string.IsNullOrEmpty(this.KeyPrefix)) { prefix = this.KeyPrefix.Trim('/') + "/"; } Interlocked.Exchange(ref this.totalUploadBytes, files.Sum(f => f.Size)); using var s3 = this.CreateClient(credentials); foreach (var file in files) { var keyName = prefix + file.FullName.Substring(sourceDirectory.Length).Replace(Path.DirectorySeparatorChar, '/').Trim('/'); this.LogInformation($"Transferring {file.FullName} to {keyName} ({AH.FormatSize(file.Size)})..."); using var fileStream = await fileOps.OpenFileAsync(file.FullName, FileMode.Open, FileAccess.Read); if (file.Size < this.PartSize * 2) { await this.UploadSmallFileAsync(s3, fileStream, keyName, context); } else { await this.MultipartUploadAsync(s3, fileStream, keyName, context); } } }
public override async Task ExecuteAsync(IOperationExecutionContext context) { if (string.IsNullOrEmpty(this.AntPath)) { this.LogError("Could not determine the location of ant on this server. To resolve this issue, ensure that ant is available on this server and create a server-scoped variable named $AntPath set to the location of ant (or ant.exe on Windows)."); return; } var fileOps = context.Agent.GetService <IFileOperationsExecuter>(); if (!fileOps.FileExists(this.AntPath)) { this.LogError("Ant not found at: " + this.AntPath); return; } var buildPath = context.ResolvePath(this.BuildPath); this.LogDebug("Build path: " + buildPath); var buffer = new StringBuilder(); buffer.Append($"-buildfile \"{this.BuildPath}\" "); var properties = this.BuildProperties?.ToList(); if (properties != null && properties.Count > 0) { foreach (var property in properties) { buffer.Append($"\"-D{property}\" "); } } buffer.Append(this.ProjectBuildTarget); fileOps.CreateDirectory(context.WorkingDirectory); await this.ExecuteCommandLineAsync( context, new RemoteProcessStartInfo { FileName = this.AntPath, Arguments = buffer.ToString(), WorkingDirectory = context.WorkingDirectory } ); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { var path = context.ResolvePath(this.FileName); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); if (await fileOps.FileExistsAsync(path).ConfigureAwait(false)) { this.LogDebug($"File {path} already exists."); if (!this.Overwrite) { this.LogError(this.FileName + " already exists and overwrite is set to false."); return; } } this.LogInformation("Creating file..."); this.LogDebug($"Creating directories for {path}..."); await fileOps.CreateDirectoryAsync(PathEx.GetDirectoryName(path)).ConfigureAwait(false); this.LogDebug($"Creating {path}..."); var linuxFileOps = fileOps as ILinuxFileOperationsExecuter; if (linuxFileOps != null) { int?mode = AH.ParseInt(AH.CoalesceString(this.PosixFileMode ?? "644")); if (mode == null) { this.LogError("Invalid file mode specified."); return; } using (var stream = await linuxFileOps.OpenFileAsync(path, FileMode.Create, FileAccess.Write, Extensions.PosixFileMode.FromDecimal(mode.Value).OctalValue)) using (var writer = new StreamWriter(stream, InedoLib.UTF8Encoding) { NewLine = linuxFileOps.NewLine }) { await writer.WriteAsync(this.Text ?? string.Empty); } } else { await fileOps.WriteAllTextAsync(path, this.Text ?? string.Empty); } this.LogInformation(path + " file created."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { string repositoryUrl = await this.GetRepositoryUrlAsync().ConfigureAwait(false); string branchDesc = string.IsNullOrEmpty(this.Branch) ? "" : $" on '{this.Branch}' branch"; string tagDesc = string.IsNullOrEmpty(this.Tag) ? "" : $" tagged '{this.Tag}'"; this.LogInformation($"Getting source from '{repositoryUrl}'{branchDesc}{tagDesc}..."); var workspacePath = WorkspacePath.Resolve(context, repositoryUrl, this.WorkspaceDiskPath); if (this.CleanWorkspace) { this.LogDebug($"Clearing workspace path '{workspacePath.FullPath}'..."); var fileOps = context.Agent.GetService <IFileOperationsExecuter>(); await fileOps.ClearDirectoryAsync(workspacePath.FullPath).ConfigureAwait(false); } var client = this.CreateClient(context, repositoryUrl, workspacePath); bool valid = await client.IsRepositoryValidAsync().ConfigureAwait(false); if (!valid) { await client.CloneAsync( new GitCloneOptions { Branch = this.Branch, RecurseSubmodules = this.RecurseSubmodules } ).ConfigureAwait(false); } await client.UpdateAsync( new GitUpdateOptions { RecurseSubmodules = this.RecurseSubmodules, Branch = this.Branch, Tag = this.Tag } ).ConfigureAwait(false); await client.ArchiveAsync(context.ResolvePath(this.DiskPath)).ConfigureAwait(false); this.LogInformation("Get source complete."); }
private async Task DownloadZipAsync(IOperationExecutionContext context) { string targetDirectory = context.ResolvePath(this.TargetDirectory); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); this.LogDebug("Creating remote temporary file..."); using (var tempFile = new RemoteTemporaryFile(fileOps, this)) { this.LogDebug("Downloading artifact to: " + tempFile.Path); var client = this.CreateClient(context); using (var artifact = await client.OpenArtifactAsync(this.JobName, this.BranchName, this.BuildNumber).ConfigureAwait(false)) using (var tempFileStream = await tempFile.OpenAsync().ConfigureAwait(false)) { await artifact.Content.CopyToAsync(tempFileStream).ConfigureAwait(false); this.LogDebug("Artifact downloaded."); } this.LogDebug("Ensuring target directory exists: " + targetDirectory); await fileOps.CreateDirectoryAsync(targetDirectory).ConfigureAwait(false); if (this.ExtractFilesToTargetDirectory) { this.LogDebug("Extracting contents to: " + targetDirectory); await fileOps.ExtractZipFileAsync(tempFile.Path, targetDirectory, FileCreationOptions.OverwriteReadOnly).ConfigureAwait(false); this.LogDebug("Files extracted."); } else { string path = fileOps.CombinePath(targetDirectory, "archive.zip"); this.LogDebug("Copying file to: " + path); await fileOps.CopyFileAsync(tempFile.Path, path, true).ConfigureAwait(false); this.LogDebug("File copied."); } } this.LogInformation("Artifact downloaded."); }
private async Task DownloadFileAsync(IOperationExecutionContext context, JenkinsBuildArtifact artifact) { string targetDirectory = context.ResolvePath(this.TargetDirectory); var fileName = PathEx.Combine(targetDirectory, artifact.FileName); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); this.LogDebug("Ensuring target directory exists: " + targetDirectory); await fileOps.CreateDirectoryAsync(targetDirectory).ConfigureAwait(false); this.LogDebug("Downloading artifact to: " + fileName); using (var singleArtifact = await this.Client.OpenSingleArtifactAsync(this.JobName, this.BuildNumber, artifact).ConfigureAwait(false)) using (var tempFileStream = await fileOps.OpenFileAsync(fileName, FileMode.Create, FileAccess.Write).ConfigureAwait(false)) { await singleArtifact.Content.CopyToAsync(tempFileStream).ConfigureAwait(false); this.LogDebug("Artifact downloaded."); } }
public static WorkspacePath Resolve(IOperationExecutionContext context, string suggestedRelativePath, string overriddenPath) { if (!string.IsNullOrWhiteSpace(overriddenPath)) { return(new WorkspacePath(context.ResolvePath(overriddenPath))); } else { string rootWorkspacePath = PathEx.Combine(context.Agent.GetService <IFileOperationsExecuter>().GetBaseWorkingDirectory(), "GitWorkspaces"); suggestedRelativePath = suggestedRelativePath.Trim('/'); if (suggestedRelativePath.Contains("/")) { suggestedRelativePath = suggestedRelativePath.Substring(suggestedRelativePath.LastIndexOf('/') + 1); } return(new WorkspacePath(rootWorkspacePath, suggestedRelativePath)); } }
public override async Task ExecuteAsync(IOperationExecutionContext context) { try { new Uri(this.Url); } catch (Exception ex) { this.LogError($"The URL \"{this.Url}\" is invalid because: {ex.Message}"); return; } var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); var fileName = context.ResolvePath(this.FileName); if (!await fileOps.FileExistsAsync(fileName).ConfigureAwait(false)) { this.LogError($"The file \"{fileName}\" does not exist."); return; } this.LogInformation($"Uploading file {fileName} to {this.Url}..."); using (var stream = await fileOps.OpenFileAsync(fileName, FileMode.Open, FileAccess.Read).ConfigureAwait(false)) { using (var client = this.CreateClient()) using (var streamContent = new StreamContent(stream)) using (var formData = new MultipartFormDataContent()) { streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); formData.Add(streamContent, "file", PathEx.GetFileName(this.FileName)); using (var response = await client.PostAsync(this.Url, formData, context.CancellationToken).ConfigureAwait(false)) { await this.ProcessResponseAsync(response).ConfigureAwait(false); } } } this.LogInformation("HTTP file upload completed."); }
public override async Task ExecuteAsync(IOperationExecutionContext context) { this.progress = null; var sourceDirectory = context.ResolvePath(this.SourceDirectory); var fileOps = await context.Agent.GetServiceAsync <IFileOperationsExecuter>().ConfigureAwait(false); var files = await fileOps.GetFileSystemInfosAsync(sourceDirectory, new MaskingContext(this.Includes, this.Excludes)).ConfigureAwait(false); if (files.Count == 0) { this.LogWarning("No files matched."); return; } var github = new GitHubClient(this.ApiUrl, this.UserName, this.Password, this.OrganizationName); var ownerName = AH.CoalesceString(this.OrganizationName, this.UserName); foreach (var info in files) { var file = info as SlimFileInfo; if (file == null) { this.LogWarning($"Not a file: {info.FullName}"); continue; } using (var stream = await fileOps.OpenFileAsync(file.FullName, FileMode.Open, FileAccess.Read).ConfigureAwait(false)) { this.LogDebug($"Uploading {file.Name} ({AH.FormatSize(file.Size)})"); await github.UploadReleaseAssetAsync(ownerName, this.RepositoryName, this.Tag, file.Name, this.ContentType, new PositionStream(stream, file.Size), pos => this.progress = new OperationProgress((int)(100 * pos / file.Size), $"Uploading {file.Name} ({AH.FormatSize(pos)} / {AH.FormatSize(file.Size)})"), context.CancellationToken).ConfigureAwait(false); this.progress = null; } } }
public async override Task ExecuteAsync(IOperationExecutionContext context) { if (context.Agent == null) { this.LogError("Server context is required to execute a process."); return; } var startInfo = GetFileNameAndArguments(this.FileName, this.Arguments, this.Target); if (startInfo == null) { this.LogError("Invalid configuration; Target or FileName must be specified."); return; } var fileOps = context.Agent.GetService <IFileOperationsExecuter>(); startInfo.FileName = context.ResolvePath(startInfo.FileName); startInfo.WorkingDirectory = context.ResolvePath(this.WorkingDirectory); this.LogDebug("Process: " + startInfo.FileName); this.LogDebug("Arguments: " + startInfo.Arguments); this.LogDebug("Working directory: " + startInfo.WorkingDirectory); this.LogDebug($"Ensuring that {startInfo.WorkingDirectory} exists..."); await fileOps.CreateDirectoryAsync(startInfo.WorkingDirectory).ConfigureAwait(false); this.LogInformation($"Executing {startInfo.FileName}..."); var remoteProcess = context.Agent.GetService <IRemoteProcessExecuter>(); int exitCode; using (var process = remoteProcess.CreateProcess(startInfo)) { process.OutputDataReceived += this.Process_OutputDataReceived; process.ErrorDataReceived += this.Process_ErrorDataReceived; process.Start(); try { await process.WaitAsync(context.CancellationToken).ConfigureAwait(false); } catch { try { process.Terminate(); } catch { } throw; } exitCode = process.ExitCode ?? -1; } bool exitCodeLogged = false; if (!string.IsNullOrEmpty(this.SuccessExitCode)) { var comparator = ExitCodeComparator.TryParse(this.SuccessExitCode); if (comparator != null) { bool result = comparator.Evauluate(exitCode); if (result) { this.LogInformation($"Process exited with code: {exitCode} (success)"); } else { this.LogError($"Process exited with code: {exitCode} (failure)"); } exitCodeLogged = true; } } if (!exitCodeLogged) { this.LogDebug("Process exited with code: " + exitCode); } }
protected virtual async Task RunDockerComposeAsync(IOperationExecutionContext context, IEnumerable <string> args) { var fileOps = await context.Agent.TryGetServiceAsync <ILinuxFileOperationsExecuter>() ?? await context.Agent.GetServiceAsync <IFileOperationsExecuter>(); var procExec = await context.Agent.GetServiceAsync <IRemoteProcessExecuter>(); var workingDirectory = context.ResolvePath(string.IsNullOrWhiteSpace(this.WorkingDirectory) ? context.WorkingDirectory : this.WorkingDirectory); this.LogDebug($"Working directory: {workingDirectory}"); await fileOps.CreateDirectoryAsync(workingDirectory); var isYamlPathSpecified = this.ComposeFileYaml.EndsWith(".yml", StringComparison.OrdinalIgnoreCase); string composeFileName = null; if (isYamlPathSpecified) { composeFileName = context.ResolvePath(this.ComposeFileYaml, workingDirectory); } else { await fileOps.CreateDirectoryAsync(fileOps.CombinePath(workingDirectory, "scripts")); composeFileName = fileOps.CombinePath(workingDirectory, "scripts", Guid.NewGuid().ToString("N") + ".yml"); } var startInfo = new RemoteProcessStartInfo { FileName = "docker-compose", WorkingDirectory = workingDirectory }; startInfo.AppendArgs(procExec, new[] { "--file", composeFileName, "--project-name", this.ProjectName, this.Verbose ? "--verbose" : null, "--no-ansi", this.Command } .Concat(this.AddArgs ?? new string[0]) .Concat(args ?? new string[0]) .Where(arg => arg != null)); try { if (!isYamlPathSpecified) { await fileOps.WriteAllTextAsync(composeFileName, this.ComposeFileYaml); } this.LogDebug($"Running command: {startInfo.FileName} {startInfo.Arguments}"); int?exitCode; using (var process = procExec.CreateProcess(startInfo)) { process.OutputDataReceived += (s, e) => this.LogProcessOutput(e.Data); process.ErrorDataReceived += (s, e) => this.LogProcessError(e.Data); process.Start(); await process.WaitAsync(context.CancellationToken); exitCode = process.ExitCode; } if (exitCode == 0) { this.LogInformation("Process exit code indicates success."); return; } this.LogError($"Process exit code indicates failure. ({AH.CoalesceString(exitCode, "(unknown)")})"); } finally { if (!isYamlPathSpecified) { await fileOps.DeleteFileAsync(composeFileName); } } // Command failed. Try to give a better error message if docker-compose isn't even installed. var verifyInstalledStartInfo = new RemoteProcessStartInfo { FileName = fileOps is ILinuxFileOperationsExecuter ? "/usr/bin/which" : "System32\\where.exe", Arguments = procExec.EscapeArg(startInfo.FileName), WorkingDirectory = workingDirectory }; if (fileOps is ILinuxFileOperationsExecuter) { verifyInstalledStartInfo.Arguments = "-- " + verifyInstalledStartInfo.Arguments; } else { verifyInstalledStartInfo.FileName = fileOps.CombinePath(await procExec.GetEnvironmentVariableValueAsync("SystemRoot"), verifyInstalledStartInfo.FileName); } using (var process = procExec.CreateProcess(verifyInstalledStartInfo)) { // Don't care about output. process.Start(); await process.WaitAsync(context.CancellationToken); // 0 = file exists, anything other than 0 or 1 = error trying to run which/where.exe if (process.ExitCode == 1) { this.LogWarning("Is docker-compose installed and in the PATH?"); } } }