Ejemplo n.º 1
0
        public async Task <ExitCode> ExecuteAsync(
            ILogger logger,
            IReadOnlyCollection <IVariable> buildVariables,
            CancellationToken cancellationToken)
        {
            bool enabled = buildVariables.GetBooleanByKey(WellKnownVariables.NuGetPackageEnabled, true);

            if (!enabled)
            {
                logger.WriteWarning(
                    $"NuGet Packer is disabled (build variable '{WellKnownVariables.NuGetPackageEnabled}' is set to false");
                return(ExitCode.Success);
            }

            _excludedNuSpecFiles =
                buildVariables.GetVariableValueOrDefault(
                    WellKnownVariables.NuGetPackageExcludesCommaSeparated,
                    string.Empty)
                .Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                .SafeToReadOnlyCollection();

            _pathLookupSpecification = DefaultPaths.DefaultPathLookupSpecification;

            string packageDirectory = PackageDirectory();

            IVariable artifacts         = buildVariables.Require(WellKnownVariables.Artifacts).ThrowIfEmptyValue();
            string    packagesDirectory = Path.Combine(artifacts.Value, "packages");

            string vcsRootDir = buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;

            NuGetPackageConfiguration packageConfiguration =
                NuGetPackager.GetNuGetPackageConfiguration(logger, buildVariables, packagesDirectory, vcsRootDir);

            IReadOnlyCollection <string> packageSpecifications = GetPackageSpecifications(
                logger,
                vcsRootDir,
                packageDirectory);

            if (!packageSpecifications.Any())
            {
                logger.Write("Could not find any NuGet specifications to create NuGet packages from");
                return(ExitCode.Success);
            }

            logger.Write($"Found {packageSpecifications.Count} NuGet specifications to create NuGet packages from");

            ExitCode result =
                await ProcessPackagesAsync(packageSpecifications, packageConfiguration, logger, cancellationToken);

            return(result);
        }
Ejemplo n.º 2
0
        public Task <ExitCode> ExecuteAsync(
            ILogger logger,
            IReadOnlyCollection <IVariable> buildVariables,
            CancellationToken cancellationToken)
        {
            _logger = logger;

            string kuduJobsEnabledKey = WellKnownVariables.KuduJobsEnabled;
            bool   kuduWebJobsEnabled = buildVariables.GetBooleanByKey(kuduJobsEnabledKey, false);

            if (!kuduWebJobsEnabled)
            {
                _logger.Write("Kudu web jobs are disabled");
                return(Task.FromResult(ExitCode.Success));
            }

            PathLookupSpecification pathLookupSpecification = DefaultPaths.DefaultPathLookupSpecification;

            string rootDir = buildVariables.GetVariable(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;

            _logger.Write("Kudu web jobs are enabled");

            string sourceRoot = buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;

            var sourceRootDirectory = new DirectoryInfo(sourceRoot);
            IReadOnlyCollection <FileInfo> csharpProjectFiles =
                sourceRootDirectory.GetFilesRecursive(new List <string> {
                ".csproj"
            }, pathLookupSpecification, rootDir);

            List <KuduWebProjectDetails> kuduWebJobProjects = csharpProjectFiles
                                                              .Select(IsKuduWebJobProject)
                                                              .Where(project => project.IsKuduWebJobProject)
                                                              .ToList();

            if (kuduWebJobProjects.Any())
            {
                logger.Write(string.Join(
                                 Environment.NewLine,
                                 kuduWebJobProjects.Select(
                                     webProject => $"Found Kudu web job project: {webProject}")));
            }
            else
            {
                logger.Write("No Kudu web job projects were found");
            }

            return(Task.FromResult(ExitCode.Success));
        }
Ejemplo n.º 3
0
        public async Task <ExitCode> ExecuteAsync(
            ILogger logger,
            IReadOnlyCollection <IVariable> buildVariables,
            CancellationToken cancellationToken)
        {
            bool enabled = buildVariables.GetBooleanByKey(WellKnownVariables.DotNetRestoreEnabled, false);

            if (!enabled)
            {
                return(ExitCode.Success);
            }

            string rootPath = buildVariables.GetVariable(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;

            string dotNetExePath =
                buildVariables.GetVariableValueOrDefault(WellKnownVariables.DotNetExePath, string.Empty);

            if (string.IsNullOrWhiteSpace(dotNetExePath))
            {
                logger.Write(
                    $"Path to 'dotnet.exe' has not been specified, set variable '{WellKnownVariables.DotNetExePath}' or ensure the dotnet.exe is installed in its standard location");
                return(ExitCode.Failure);
            }

            var pathLookupSpecification = new PathLookupSpecification();

            FileInfo[] solutionFiles = new DirectoryInfo(rootPath)
                                       .GetFiles("*.sln", SearchOption.AllDirectories)
                                       .Where(file => !pathLookupSpecification.IsFileBlackListed(file.FullName, rootPath).Item1)
                                       .ToArray();

            foreach (FileInfo solutionFile in solutionFiles)
            {
                ExitCode result = await ProcessHelper.ExecuteAsync(
                    dotNetExePath,
                    new[] { "restore", solutionFile.FullName },
                    logger,
                    cancellationToken : cancellationToken);

                if (!result.IsSuccess)
                {
                    return(result);
                }
            }

            return(ExitCode.Success);
        }
Ejemplo n.º 4
0
        private IReadOnlyCollection <string> GetPackageSpecifications(
            ILogger logger,
            string vcsRootDir,
            string packageDirectory)
        {
            var vcsRootDirectory = new DirectoryInfo(vcsRootDir);

            List <string> packageSpecifications =
                vcsRootDirectory.GetFilesRecursive(new List <string> {
                ".nuspec"
            }, _pathLookupSpecification, vcsRootDir)
                .Where(file => file.FullName.IndexOf(packageDirectory, StringComparison.Ordinal) < 0)
                .Select(f => f.FullName)
                .ToList();

            PathLookupSpecification pathLookupSpecification = DefaultPaths.DefaultPathLookupSpecification;

            IReadOnlyCollection <FileInfo> filtered =
                packageSpecifications.Where(
                    packagePath => !pathLookupSpecification.IsFileBlackListed(packagePath, vcsRootDir).Item1)
                .Select(file => new FileInfo(file))
                .ToReadOnlyCollection();

            IReadOnlyCollection <FileInfo> notExcluded =
                filtered.Where(
                    nuspec =>
                    !_excludedNuSpecFiles.Any(
                        exludedNuSpec => exludedNuSpec.Equals(
                            nuspec.Name,
                            StringComparison.InvariantCultureIgnoreCase)))
                .SafeToReadOnlyCollection();

            logger.WriteVerbose(
                $"Found nuspec files [{filtered.Count}]: {Environment.NewLine}{string.Join(Environment.NewLine, filtered)}");
            IReadOnlyCollection <string> allIncluded = notExcluded.Select(file => file.FullName)
                                                       .SafeToReadOnlyCollection();

            return(allIncluded);
        }
Ejemplo n.º 5
0
        public async Task <ExitCode> ExecuteAsync(
            ILogger logger,
            IReadOnlyCollection <IVariable> buildVariables,
            CancellationToken cancellationToken)
        {
            var app = new CastaneaApplication();

            PathLookupSpecification pathLookupSpecification = DefaultPaths.DefaultPathLookupSpecification;

            string vcsRoot       = buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;
            string nuGetExetPath = buildVariables.Require(WellKnownVariables.ExternalTools_NuGet_ExePath)
                                   .ThrowIfEmptyValue()
                                   .Value;

            var rootDirectory = new DirectoryInfo(vcsRoot);

            int listFilesAttempt = 1;

            int listFilesMaxAttempts = 5;

            bool listFilesSucceeded = false;

            IReadOnlyCollection <string>   packagesConfigFiles = new List <string>();
            IReadOnlyCollection <FileInfo> solutionFiles       = new List <FileInfo>();

            while (listFilesAttempt <= listFilesMaxAttempts && !listFilesSucceeded)
            {
                try
                {
                    rootDirectory.Refresh();

                    packagesConfigFiles =
                        rootDirectory.EnumerateFiles("packages.config", SearchOption.AllDirectories)
                        .Where(file => !pathLookupSpecification.IsFileBlackListed(file.FullName, vcsRoot).Item1)
                        .Select(file => file.FullName)
                        .ToReadOnlyCollection();

                    rootDirectory.Refresh();

                    solutionFiles =
                        rootDirectory.EnumerateFiles("*.sln", SearchOption.AllDirectories)
                        .Where(file => !pathLookupSpecification.IsFileBlackListed(file.FullName, vcsRoot).Item1)
                        .ToReadOnlyCollection();

                    listFilesSucceeded = true;
                }
                catch (Exception ex)
                {
                    if (listFilesAttempt == listFilesMaxAttempts)
                    {
                        logger.WriteError($"Could not enumerable packages.config files or solutions files. {ex}");
                        return(ExitCode.Failure);
                    }

                    logger.WriteWarning(
                        $"Attempt {listFilesAttempt} of {listFilesMaxAttempts} failed, retrying. {ex}");
                    listFilesAttempt++;
                }
            }

            if (!packagesConfigFiles.Any())
            {
                logger.WriteWarning("Could not find any packages.config files, skipping package restore");
                return(ExitCode.Success);
            }

            if (!solutionFiles.Any())
            {
                logger.WriteError("Could not find any solution file, cannot determine package output directory");
                return(ExitCode.Failure);
            }

            if (solutionFiles.Count > 1)
            {
                logger.WriteError("Found more than one solution file, cannot determine package output directory");
                return(ExitCode.Failure);
            }

            FileInfo solutionFile = solutionFiles.Single();

            string allFiles = string.Join(Environment.NewLine, packagesConfigFiles);

            try
            {
// ReSharper disable once PossibleNullReferenceException
                string outputDirectoryPath = Path.Combine(solutionFile.Directory.FullName, "packages");

                new DirectoryInfo(outputDirectoryPath).EnsureExists();

                bool disableParallelProcessing =
                    buildVariables.GetBooleanByKey(
                        WellKnownVariables.NuGetRestoreDisableParallelProcessing,
                        false);

                bool noCache = buildVariables.GetBooleanByKey(
                    WellKnownVariables.NuGetRestoreNoCache,
                    false);

                var nuGetConfig = new NuGetConfig
                {
                    NuGetExePath              = nuGetExetPath,
                    OutputDirectory           = outputDirectoryPath,
                    DisableParallelProcessing = disableParallelProcessing,
                    NoCache = noCache
                };

                nuGetConfig.PackageConfigFiles.AddRange(packagesConfigFiles);

                Action <string> debugAction = null;

                string prefix = typeof(CastaneaApplication).Namespace;

                if (logger.LogLevel.IsLogging(LogLevel.Verbose))
                {
                    debugAction = message => logger.WriteVerbose(message, prefix);
                }

                int restoredPackages = 0;

                int attempt = 1;

                int maxAttempts = 5;

                bool succeeded = false;

                while (attempt <= maxAttempts && !succeeded)
                {
                    try
                    {
                        restoredPackages = app.RestoreAllSolutionPackages(
                            nuGetConfig,
                            message => logger.Write(message, prefix),
                            message => logger.WriteError(message, prefix),
                            debugAction);

                        if (restoredPackages == 0)
                        {
                            logger.WriteWarning($"No packages was restored as defined in {allFiles}");
                            return(ExitCode.Success);
                        }

                        succeeded = true;
                    }
                    catch (Exception ex)
                    {
                        if (attempt < maxAttempts)
                        {
                            logger.WriteWarning(
                                $"Attempt {attempt} of {maxAttempts}: could not restore NuGet packages, trying againg. {ex.Message}");
                        }
                        else
                        {
                            logger.WriteError($"Could not restore NuGet packages.{ex}");
                            return(ExitCode.Failure);
                        }

                        attempt++;
                    }
                }

                logger.Write($"Restored {restoredPackages} package configurations defined in {allFiles}");
            }
            catch (Exception ex)
            {
                logger.WriteError($"Could not restore packages defined in '{allFiles}'. {ex}");
                return(ExitCode.Failure);
            }

            try
            {
                foreach (FileInfo fileInfo in solutionFiles)
                {
                    // ReSharper disable once PossibleNullReferenceException
                    string packagesDirectory = Path.Combine(fileInfo.Directory.FullName, "packages");

                    if (Directory.Exists(packagesDirectory))
                    {
                        foreach (INuGetPackageRestoreFix nuGetPackageRestoreFix in _fixes)
                        {
                            await nuGetPackageRestoreFix.FixAsync(packagesDirectory, logger);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (ExceptionExtensions.IsFatal(ex))
                {
                    throw;
                }

                logger.WriteWarning(ex.ToString());
            }

            return(ExitCode.Success);
        }
Ejemplo n.º 6
0
        public async Task <ExitCode> ExecuteAsync(
            ILogger logger,
            IReadOnlyCollection <IVariable> buildVariables,
            CancellationToken cancellationToken)
        {
            var sourceRoot =
                new DirectoryInfo(buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value);

            logger.Write($"Looking for paket.exe in source root {sourceRoot.FullName}");

            PathLookupSpecification pathLookupSpecification = DefaultPaths.DefaultPathLookupSpecification.WithIgnoredFileNameParts(new List <string>());

            FileInfo paketExe = null;

            List <string> packageSpecifications =
                sourceRoot.GetFilesRecursive(new List <string> {
                ".exe"
            }, pathLookupSpecification)
                .Where(file => file.Name.Equals("paket.exe", StringComparison.Ordinal))
                .Select(f => f.FullName)
                .ToList();

            if (!packageSpecifications.Any())
            {
                FileInfo normalSearch = sourceRoot.GetFiles("paket.exe", SearchOption.AllDirectories)
                                        .OrderBy(file => file.FullName.Length).FirstOrDefault();

                if (normalSearch != null)
                {
                    paketExe = normalSearch;
                }
                else
                {
                    logger.Write("Could not find paket.exe, skipping paket restore");
                    return(ExitCode.Success);
                }
            }

            if (paketExe == null)
            {
                IReadOnlyCollection <FileInfo> filtered =
                    packageSpecifications.Where(
                        packagePath =>
                        !pathLookupSpecification.IsFileBlackListed(
                            packagePath,
                            sourceRoot.FullName,
                            logger: logger).Item1)
                    .Select(file => new FileInfo(file))
                    .ToReadOnlyCollection();

                if (!filtered.Any())
                {
                    logger.Write(
                        $"Could not find paket.exe, filtered out: {string.Join(", ", packageSpecifications)}, skipping paket restore");
                    return(ExitCode.Success);
                }

                paketExe = filtered.First();
            }

            logger.Write($"Found paket.exe at '{paketExe.FullName}'");

            string copyFromPath = buildVariables.GetVariableValueOrDefault("Arbor.X.Build.Tools.Paket.CopyExeFromPath", string.Empty);

            if (!string.IsNullOrWhiteSpace(copyFromPath))
            {
                if (File.Exists(copyFromPath))
                {
                    File.Copy(copyFromPath, paketExe.FullName, overwrite: true);
                    logger.Write($"Copied paket.exe to {paketExe.FullName}");
                }
                else
                {
                    logger.Write($"The specified paket.exe path '{copyFromPath}' does not exist");
                }
            }
            else
            {
                logger.Write($"Found no paket.exe to copy");
            }

            Directory.SetCurrentDirectory(sourceRoot.FullName);

            ExitCode exitCode = await ProcessHelper.ExecuteAsync(
                paketExe.FullName,
                new List <string> {
                "restore"
            },
                logger,
                cancellationToken : cancellationToken);

            return(exitCode);
        }
Ejemplo n.º 7
0
        public Task <ExitCode> ExecuteAsync(
            ILogger logger,
            IReadOnlyCollection <IVariable> buildVariables,
            CancellationToken cancellationToken)
        {
            bool assemblyVersionPatchingEnabled =
                buildVariables.GetBooleanByKey(WellKnownVariables.AssemblyFilePatchingEnabled, true);

            if (!assemblyVersionPatchingEnabled)
            {
                logger.WriteWarning("Assembly version patching is disabled");
                return(Task.FromResult(ExitCode.Success));
            }

            var delegateLogger = new DelegateLogger(
                logger.WriteError,
                logger.WriteWarning,
                logger.Write,
                logger.WriteVerbose,
                logger.WriteDebug)
            {
                LogLevel = Sorbus.Core.LogLevel.TryParse(logger.LogLevel.Level)
            };

            var app = new AssemblyPatcherApp(delegateLogger);

            _filePattern = buildVariables.GetVariableValueOrDefault(
                WellKnownVariables.AssemblyFilePatchingFilePattern,
                "AssemblyInfo.cs");

            logger.WriteVerbose($"Using assembly version file pattern '{_filePattern}' to lookup files to patch");

            string sourceRoot = buildVariables.Require(WellKnownVariables.SourceRoot).ThrowIfEmptyValue().Value;

            IVariable netAssemblyVersionVar =
                buildVariables.SingleOrDefault(var => var.Key == WellKnownVariables.NetAssemblyVersion);
            string netAssemblyVersion;

            if (netAssemblyVersionVar == null || string.IsNullOrWhiteSpace(netAssemblyVersionVar.Value))
            {
                logger.WriteWarning(
                    $"The build variable {WellKnownVariables.NetAssemblyVersion} is not defined or empty");
                netAssemblyVersion = "0.0.1.0";

                logger.WriteWarning($"Using fall-back version {netAssemblyVersion}");
            }
            else
            {
                netAssemblyVersion = netAssemblyVersionVar.Value;
            }

            var assemblyVersion = new Version(netAssemblyVersion);

            IVariable netAssemblyFileVersionVar =
                buildVariables.SingleOrDefault(var => var.Key == WellKnownVariables.NetAssemblyFileVersion);
            string netAssemblyFileVersion;

            if (string.IsNullOrWhiteSpace(netAssemblyFileVersionVar?.Value))
            {
                logger.WriteWarning(
                    $"The build variable {WellKnownVariables.NetAssemblyFileVersion} is not defined or empty");
                netAssemblyFileVersion = "0.0.1.1";

                logger.WriteWarning($"Using fall-back version {netAssemblyFileVersion}");
            }
            else
            {
                netAssemblyFileVersion = netAssemblyFileVersionVar.Value;
            }

            var assemblyFileVersion = new Version(netAssemblyFileVersion);

            AssemblyMetaData assemblyMetadata = null;

            if (buildVariables.GetBooleanByKey(WellKnownVariables.NetAssemblyMetadataEnabled, false))
            {
                string company     = buildVariables.GetVariableValueOrDefault(WellKnownVariables.NetAssemblyCompany, null);
                string description =
                    buildVariables.GetVariableValueOrDefault(WellKnownVariables.NetAssemblyDescription, null);
                string configuration =
                    buildVariables.GetVariableValueOrDefault(WellKnownVariables.NetAssemblyConfiguration, null);
                string copyright =
                    buildVariables.GetVariableValueOrDefault(WellKnownVariables.NetAssemblyCopyright, null);
                string product   = buildVariables.GetVariableValueOrDefault(WellKnownVariables.NetAssemblyProduct, null);
                string trademark =
                    buildVariables.GetVariableValueOrDefault(WellKnownVariables.NetAssemblyTrademark, null);

                assemblyMetadata = new AssemblyMetaData(
                    description,
                    configuration,
                    company,
                    product,
                    copyright,
                    trademark);
            }

            try
            {
                logger.WriteVerbose(
                    $"Patching assembly info files with assembly version {assemblyVersion}, assembly file version {assemblyFileVersion} for directory source root directory '{sourceRoot}'");

                var sourceDirectory = new DirectoryInfo(sourceRoot);

                PathLookupSpecification defaultPathLookupSpecification = DefaultPaths.DefaultPathLookupSpecification;

                IReadOnlyCollection <AssemblyInfoFile> assemblyFiles = sourceDirectory
                                                                       .GetFilesRecursive(new[] { ".cs" }, defaultPathLookupSpecification, sourceRoot)
                                                                       .Where(file => file.Name.Equals(_filePattern, StringComparison.InvariantCultureIgnoreCase))
                                                                       .Select(file => new AssemblyInfoFile(file.FullName))
                                                                       .ToReadOnlyCollection();

                logger.WriteDebug(string.Format(
                                      "Using file pattern '{0}' to find assembly info files. Found these files: [{3}] {1}{2}",
                                      _filePattern,
                                      Environment.NewLine,
                                      string.Join(Environment.NewLine, assemblyFiles.Select(item => " * " + item.FullPath)),
                                      assemblyFiles.Count));

                app.Patch(
                    new AssemblyVersion(assemblyVersion),
                    new AssemblyFileVersion(assemblyFileVersion),
                    sourceRoot,
                    assemblyFiles,
                    assemblyMetadata);
            }
            catch (Exception ex)
            {
                logger.WriteError($"Could not patch assembly infos. {ex}");
                return(Task.FromResult(ExitCode.Failure));
            }

            return(Task.FromResult(ExitCode.Success));
        }