Пример #1
0
        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.");
        }
Пример #2
0
        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.");
        }
Пример #3
0
        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);
        }
Пример #4
0
        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.");
        }
Пример #5
0
        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));
        }
Пример #7
0
        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.");
        }
Пример #8
0
        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
            }
                );
        }
Пример #9
0
        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!");
        }
Пример #10
0
        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);
                        }
                }
            }
        }
Пример #11
0
        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);
        }
Пример #12
0
        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}\""
                    );
            }
        }
Пример #13
0
        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}\".");
        }
Пример #14
0
        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);
        }
Пример #15
0
        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.");
        }
Пример #16
0
        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.");
        }
Пример #17
0
        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);
                    }
                }
            }
        }
Пример #18
0
        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"));
        }
Пример #19
0
        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.");
        }
Пример #20
0
        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);
                }
            }
        }
Пример #21
0
        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
            }
                );
        }
Пример #22
0
        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.");
        }
Пример #23
0
        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.");
        }
Пример #24
0
        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.");
                }
        }
Пример #26
0
        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);
            }
        }
Пример #30
0
        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?");
                }
            }
        }