示例#1
0
        public override void Log(ILogMessage message)
        {
            switch (message.Level)
            {
            case LogLevel.Verbose: _logger.Detailed(message.Message);
                break;

            case LogLevel.Debug: _logger.Detailed(message.Message);
                break;

            case LogLevel.Information: _logger.Detailed(message.Message);
                break;

            case LogLevel.Minimal: _logger.Normal(message.Message);
                break;

            case LogLevel.Warning: _logger.Normal(message.Message);
                break;

            case LogLevel.Error:
                _logger.Error(message.Message);
                break;

            default:
                throw new ArgumentOutOfRangeException($"Invalid log level {message.Level}");
            }
        }
示例#2
0
        public async Task Invoke(FileInfo file, NuGetSources sources)
        {
            _logger.Normal($"Nuget restore on {file.DirectoryName} {file.Name}");

            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                _logger.Normal("Cannot run NuGet.exe file restore as OS Platform is not Windows");
                return;
            }

            var nuget = NuGetPath.FindExecutable();

            if (string.IsNullOrWhiteSpace(nuget))
            {
                _logger.Normal("Cannot find NuGet exe for solution restore");
                return;
            }

            var sourcesCommandLine = sources.CommandLine("-Source");

            var arguments = $"restore {file.Name} {sourcesCommandLine}";

            _logger.Detailed($"{nuget} {arguments}");

            var processOutput = await _externalProcess.Run(file.DirectoryName, nuget, arguments, ensureSuccess : false);

            if (processOutput.Success)
            {
                _logger.Detailed($"Nuget restore on {file.Name} complete");
            }
            else
            {
                _logger.Detailed($"Nuget restore failed on {file.DirectoryName} {file.Name}:\n{processOutput.Output}\n{processOutput.ErrorOutput}");
            }
        }
示例#3
0
        public IEnumerable <PackageUpdateSet> Sort(IReadOnlyCollection <PackageUpdateSet> input)
        {
            if (input.Count < 2)
            {
                return(input);
            }

            _data = input
                    .Select(p => MakeNode(p, input))
                    .ToList();

            if (!_data.Any(i => i.Dependencies.Any()))
            {
                _logger.Detailed("No dependencies between packages being updated, no need to sort on this");
                return(input);
            }

            foreach (var item in _data)
            {
                if (item.Mark == Mark.None)
                {
                    Visit(item);
                }
            }

            if (_cycleFound)
            {
                return(input);
            }

            ReportSort(input.ToList(), _sortedList);
            return(_sortedList);
        }
示例#4
0
        private async Task <T> GetResourceOrEmpty <T>(string url, [CallerMemberName] string caller = null)
        {
            _logger.Detailed($"Getting from BitBucketLocal url {url}");
            var response = await _client.GetAsync(url);

            return(await HandleResponse <T>(response, caller));
        }
示例#5
0
        public void Report(
            OutputDestination destination,
            OutputFormat format,
            string reportName,
            string fileName,
            IReadOnlyCollection <PackageUpdateSet> updates)
        {
            if (updates == null)
            {
                throw new ArgumentNullException(nameof(updates));
            }

            var destinationDesc = destination == OutputDestination.File ?
                                  $" File '{fileName}'" :
                                  destination.ToString();

            _logger.Detailed($"Output report named {reportName}, is {format} to {destinationDesc}");

            using (var writer = MakeReportWriter(destination, fileName))
            {
                var reporter = MakeReporter(format, writer);
                reporter.Write(reportName, updates);
            }

            _logger.Detailed($"Wrote report for {updates.Count} updates");
        }
        private async Task<T> PostResource<T>(string url, HttpContent content, bool previewApi = false, [CallerMemberName] string caller = null)
        {
            var fullUrl = BuildAzureDevOpsUri(url, previewApi);
            _logger.Detailed($"{caller}: Requesting {fullUrl}");

            var response = await _client.PostAsync(fullUrl, content);
            return await HandleResponse<T>(response, caller);
        }
示例#7
0
        public async Task <ProcessOutput> Run(string workingDirectory, string command, string arguments, bool ensureSuccess)
        {
            return(await Task.Run(() =>
            {
                _logger.Detailed($"In path {workingDirectory}, running command: {command} {arguments}");

                System.Diagnostics.Process process;
                outputData = new StringBuilder();
                errorData = new StringBuilder();

                try
                {
                    var processInfo = MakeProcessStartInfo(workingDirectory, command, arguments);
                    process = System.Diagnostics.Process.Start(processInfo);
                }
                catch (Exception ex)
                {
                    _logger.Error($"External command failed:{command} {arguments}", ex);

                    if (ensureSuccess)
                    {
                        throw;
                    }

                    var message = $"Error starting external process for {command}: {ex.GetType().Name} {ex.Message}";
                    return new ProcessOutput(string.Empty, message, 1);
                }

                if (process == null)
                {
                    throw new NuKeeperException($"Could not start external process for {command}");
                }

                process.OutputDataReceived += (outSender, outArgs) => outputData.AppendLine(outArgs.Data);
                process.ErrorDataReceived += (errSender, errArgs) => errorData.AppendLine(errArgs.Data);
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                process.WaitForExit();
                var exitCode = process.ExitCode;

                string textOut = outputData.ToString();
                string errorOut = errorData.ToString();

                if (exitCode != 0)
                {
                    var message = $"Command {command} failed with exit code: {exitCode}\n\n{textOut}\n\n{errorOut}";
                    _logger.Detailed(message);

                    if (ensureSuccess)
                    {
                        throw new NuKeeperException(message);
                    }
                }

                return new ProcessOutput(textOut, errorOut, exitCode);
            }));
        }
示例#8
0
        public async Task Clone(Uri pullEndpoint, string branchName)
        {
            _logger.Normal($"Git clone {pullEndpoint}, branch {branchName ?? "default"}, to {WorkingFolder.FullPath}");
            var branchparam = branchName == null ? "" : $" -b {branchName}";

            await StartGitProcess($"clone{branchparam} {CreateCredentialsUri(pullEndpoint, _gitCredentials)} .", true); // Clone into current folder

            _logger.Detailed("Git clone complete");
        }
示例#9
0
        private async Task <T> GetResource <T>(string url, Func <HttpStatusCode, Result <T> > customErrorHandling = null, [CallerMemberName] string caller = null)
        {
            var fullUrl = new Uri(url, UriKind.Relative);

            _logger.Detailed($"{caller}: Requesting {fullUrl}");

            var response = await _client.GetAsync(fullUrl);

            return(await HandleResponse(response, customErrorHandling, caller));
        }
示例#10
0
        private async Task <T> GetResourceOrEmpty <T>(string url)
        {
            _logger.Detailed($"Getting from BitBucket url {url}");
            var response = await _client.GetAsync(url);

            var responseBody = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode)
            {
                _logger.Detailed($"Response {response.StatusCode} is not success, body:\n{responseBody}");
                return(default);
示例#11
0
        public async Task <ProcessOutput> Run(string workingDirectory, string command, string arguments, bool ensureSuccess)
        {
            _logger.Detailed($"In path {workingDirectory}, running command: {command} {arguments}");

            System.Diagnostics.Process process;

            try
            {
                var processInfo = MakeProcessStartInfo(workingDirectory, command, arguments);
                process = System.Diagnostics.Process.Start(processInfo);
            }
            catch (Exception ex)
            {
                _logger.Error($"External command failed:{command} {arguments}", ex);

                if (ensureSuccess)
                {
                    throw;
                }

                var message = $"Error starting external process for {command}: {ex.GetType().Name} {ex.Message}";
                return(new ProcessOutput(string.Empty, message, 1));
            }

            if (process == null)
            {
                throw new NuKeeperException($"Could not start external process for {command}");
            }

            var outputs = await Task.WhenAll(
                process.StandardOutput.ReadToEndAsync(),
                process.StandardError.ReadToEndAsync()
                );

            var textOut  = outputs[0];
            var errorOut = outputs[1];

            process.WaitForExit();

            var exitCode = process.ExitCode;

            if (exitCode != 0)
            {
                var message = $"Command {command} failed with exit code: {exitCode}\n\n{textOut}\n\n{errorOut}";
                _logger.Detailed(message);

                if (ensureSuccess)
                {
                    throw new NuKeeperException(message);
                }
            }

            return(new ProcessOutput(textOut, errorOut, exitCode));
        }
        public NuGetSources ReadNugetSources(IFolder workingFolder)
        {
            var settings = Settings.LoadDefaultSettings(workingFolder.FullPath);

            foreach (var file in settings.GetConfigFilePaths())
            {
                _logger.Detailed($"Reading file {file} for package sources");
            }

            var enabledSources = SettingsUtility.GetEnabledSources(settings).ToList();

            return(ReadFromFile(enabledSources));
        }
示例#13
0
        public NuGetSources ReadNugetSources(IFolder workingFolder)
        {
            var settings = Settings.LoadDefaultSettings(workingFolder.FullPath);

            foreach (var file in settings.Priority)
            {
                _logger.Detailed($"Reading file {Path.Combine(file.Root, file.FileName)} for package sources");
            }

            var enabledSources = SettingsUtility.GetEnabledSources(settings).ToList();

            return(ReadFromFile(enabledSources));
        }
示例#14
0
        private string FindLocalNuget()
        {
            var appDir   = AppDomain.CurrentDomain.BaseDirectory;
            var fullPath = Path.Combine(appDir, "NuGet.exe");

            if (File.Exists(fullPath))
            {
                _logger.Detailed("Found NuGet.exe: " + fullPath);
                return(fullPath);
            }

            return(string.Empty);
        }
示例#15
0
        public async Task Invoke(FileInfo file, NuGetSources sources)
        {
            _logger.Normal($"Nuget restore on {file.DirectoryName} {file.Name}");

            var nuget = _nuGetPath.Executable;

            if (string.IsNullOrWhiteSpace(nuget))
            {
                _logger.Normal("Cannot find NuGet.exe for solution restore");
                return;
            }

            var sourcesCommandLine = sources.CommandLine("-Source");

            var restoreCommand = $"restore {file.Name} {sourcesCommandLine}  -NonInteractive";

            ProcessOutput processOutput;

            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                if (await _monoExecutor.CanRun())
                {
                    processOutput = await _monoExecutor.Run(file.DirectoryName,
                                                            nuget,
                                                            restoreCommand,
                                                            ensureSuccess : false);
                }
                else
                {
                    _logger.Error("Cannot run NuGet.exe. It requires either Windows OS Platform or Mono installation");
                    return;
                }
            }
            else
            {
                processOutput = await _externalProcess.Run(file.DirectoryName,
                                                           nuget,
                                                           restoreCommand,
                                                           ensureSuccess : false);
            }

            if (processOutput.Success)
            {
                _logger.Detailed($"Nuget restore on {file.Name} complete");
            }
            else
            {
                _logger.Detailed(
                    $"Nuget restore failed on {file.DirectoryName} {file.Name}:\n{processOutput.Output}\n{processOutput.ErrorOutput}");
            }
        }
示例#16
0
        public void TryDelete()
        {
            _logger.Detailed($"Attempting delete of folder {_root.FullName}");

            try
            {
                DeleteDirectoryInternal(_root.FullName);
                _logger.Detailed($"Deleted folder {_root.FullName}");
            }
            catch (Exception ex)
            {
                _logger.Detailed($"Folder delete failed: {ex.GetType().Name} {ex.Message}");
            }
        }
示例#17
0
        public async Task <bool> RepositoryBranchExists(string projectName, string repositoryName, string branchName)
        {
            var branches = await _client.GetGitRepositoryBranches(projectName, repositoryName);

            var count = branches.Count(x => x.DisplayId.Equals(branchName, StringComparison.OrdinalIgnoreCase));

            if (count > 0)
            {
                _logger.Detailed($"Branch found for {projectName} / {repositoryName} / {branchName}");
                return(true);
            }
            _logger.Detailed($"No branch found for {projectName} / {repositoryName} / {branchName}");
            return(false);
        }
示例#18
0
        public async Task<bool> RepositoryBranchExists(string projectName, string repositoryName, string branchName)
        {
            var repos = await _client.GetGitRepositories(projectName);
            var repo = repos.Single(x => x.name.Equals(repositoryName, StringComparison.OrdinalIgnoreCase));
            var refs = await _client.GetRepositoryRefs(projectName, repo.id);
            var count = refs.Count(x => x.name.EndsWith(branchName, StringComparison.OrdinalIgnoreCase));
            if (count > 0)
            {
                _logger.Detailed($"Branch found for {projectName} / {repositoryName} / {branchName}");
                return true;
            }

            _logger.Detailed($"No branch found for {projectName} / {repositoryName} / {branchName}");
            return false;
        }
示例#19
0
        public async Task <int> Run(SettingsContainer settings)
        {
            var github = _githubCreator.Create(settings);
            var repositoryDiscovery = _repositoryDiscoveryCreator.Create(settings);
            var repositoryEngine    = _repositoryEngineCreator.Create(settings);

            _logger.Detailed($"{Now()}: Started");

            _folderFactory.DeleteExistingTempDirs();

            var githubUser = await github.GetCurrentUser();

            var gitCreds = new UsernamePasswordCredentials
            {
                Username = githubUser.Login,
                Password = settings.GithubAuthSettings.Token
            };

            var userIdentity = GetUserIdentity(githubUser);

            var repositories = await repositoryDiscovery.GetRepositories();

            var reposUpdated = 0;

            foreach (var repository in repositories)
            {
                if (reposUpdated >= settings.UserSettings.MaxRepositoriesChanged)
                {
                    _logger.Detailed($"Reached max of {reposUpdated} repositories changed");
                    break;
                }

                var updatesInThisRepo = await repositoryEngine.Run(repository, gitCreds, userIdentity);

                if (updatesInThisRepo > 0)
                {
                    reposUpdated++;
                }
            }

            if (reposUpdated > 1)
            {
                _logger.Detailed($"{reposUpdated} repositories were updated");
            }

            _logger.Detailed($"Done at {Now()}");
            return(reposUpdated);
        }
示例#20
0
        public async Task Update(PackageUpdateSet updateSet, NuGetSources sources)
        {
            if (updateSet == null)
            {
                throw new ArgumentNullException(nameof(updateSet));
            }

            var sortedUpdates = Sort(updateSet.CurrentPackages);

            _logger.Detailed($"Updating '{updateSet.SelectedId}' to {updateSet.SelectedVersion} in {sortedUpdates.Count} projects");



            var updateTasks = sortedUpdates.ToList().Select(current =>
            {
                return(Task.Factory.StartNew(async() =>
                {
                    var updateCommands = GetUpdateCommands(current.Path.PackageReferenceType);
                    foreach (var updateCommand in updateCommands)
                    {
                        await updateCommand.Invoke(current,
                                                   updateSet.SelectedVersion, updateSet.Selected.Source,
                                                   sources);
                    }
                }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default));
            });

            await Task.WhenAll(updateTasks);
        }
示例#21
0
        private async Task UpdateNuspec(FileStream fileContents, NuGetVersion newVersion,
                                        PackageInProject currentPackage)
        {
            var xml = XDocument.Load(fileContents);

            var packagesNode = xml.Element("package")?.Element("metadata")?.Element("dependencies");

            if (packagesNode == null)
            {
                return;
            }

            var packageNodeList = packagesNode.Elements()
                                  .Where(x => x.Name == "dependency" && x.Attributes("id")
                                         .Any(a => a.Value == currentPackage.Id));

            foreach (var dependencyToUpdate in packageNodeList)
            {
                _logger.Detailed($"Updating nuspec depenencies: {currentPackage.Id} in path {currentPackage.Path.FullName}");
                dependencyToUpdate.Attribute("version").Value = newVersion.ToString();
            }

            fileContents.Seek(0, SeekOrigin.Begin);
            await xml.SaveAsync(fileContents, SaveOptions.None, CancellationToken.None);
        }
示例#22
0
        private void UpdateFile(Stream fileContents, NuGetVersion newVersion,
                                PackageInProject currentPackage, XDocument xml)
        {
            var packagesNode = xml.Element("Project")?.Elements("ItemGroup");

            if (packagesNode == null)
            {
                return;
            }

            var packageNodeList = packagesNode.Elements("PackageReference")
                                  .Where(x =>
                                         (x.Attributes("Include").Any(a => a.Value.Equals(currentPackage.Id, StringComparison.InvariantCultureIgnoreCase)) ||
                                          x.Attributes("Update").Any(a => a.Value.Equals(currentPackage.Id, StringComparison.InvariantCultureIgnoreCase))));

            foreach (var dependencyToUpdate in packageNodeList)
            {
                _logger.Detailed(
                    $"Updating directory-level dependencies: {currentPackage.Id} in path {currentPackage.Path.FullName}");
                var attribute = dependencyToUpdate.Attribute("Version");
                if (attribute != null)
                {
                    attribute.Value = newVersion.ToString();
                }
                else
                {
                    dependencyToUpdate.Element("Version").Value = newVersion.ToString();
                }
            }

            xml.Save(fileContents);
        }
示例#23
0
        public async Task ApplyAnUpdate(
            IReadOnlyCollection <PackageUpdateSet> updates,
            NuGetSources sources)
        {
            if (!updates.Any())
            {
                return;
            }

            var filtered = await _selection
                           .Filter(updates, p => Task.FromResult(true));

            if (!filtered.Any())
            {
                _logger.Detailed("All updates were filtered out");
                return;
            }

            var candidate = filtered.First();

            var reporter = new ConsoleReporter();

            _logger.Minimal("Updating " + reporter.Describe(candidate));

            await _updateRunner.Update(candidate, sources);
        }
示例#24
0
        public void Report(string name, IReadOnlyCollection <PackageUpdateSet> updates)
        {
            using (var writer = _reportStreamSource.GetStream(name))
            {
                _logger.Detailed($"writing {updates.Count} lines to report");
                WriteHeading(writer);

                foreach (var update in updates)
                {
                    WriteLine(writer, update);
                }

                writer.Close();
                _logger.Detailed("Report written");
            }
        }
示例#25
0
        public async Task <bool> ContainsDotNetProjects(RepositorySettings repository)
        {
            const string dotNetCodeFiles = "\"packages.config\" OR \".csproj\" OR \".fsproj\" OR \".vbproj\"";

            var repos = new List <SearchRepo>
            {
                new SearchRepo(repository.RepositoryOwner, repository.RepositoryName)
            };

            var searchCodeRequest = new SearchCodeRequest(dotNetCodeFiles, repos)
            {
                PerPage = 1
            };

            try
            {
                var result = await _collaborationFactory.CollaborationPlatform.Search(searchCodeRequest);

                if (result.TotalCount <= 0)
                {
                    _logger.Detailed(
                        $"Repository {repository.RepositoryOwner}/{repository.RepositoryName} contains no .NET code on the default branch, skipping.");
                    return(false);
                }

                return(true);
            }
            catch (Exception ex)
            {
                _logger.Error("Repository search failed.", ex);
            }

            return(true);
        }
示例#26
0
        public async Task ApplyUpdates(
            IReadOnlyCollection <PackageUpdateSet> updates,
            IFolder workingFolder,
            NuGetSources sources,
            SettingsContainer settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            if (!updates.Any())
            {
                return;
            }

            var filtered = _selection
                           .Filter(updates, settings.PackageFilters);

            if (!filtered.Any())
            {
                _logger.Detailed("All updates were filtered out");
                return;
            }

            await ApplyUpdates(filtered, workingFolder, sources);
        }
示例#27
0
        private async Task <int> MakeUpdatePullRequests(
            IGitDriver git, RepositoryData repository,
            NuGetSources sources, SettingsContainer settings,
            IReadOnlyCollection <PackageUpdateSet> updates)
        {
            _logger.Normal(UpdatesLogger.OldVersionsToBeUpdated(updates));

            git.Checkout(repository.DefaultBranch);

            // branch
            var branchName = BranchNamer.MakeName(updates);

            _logger.Detailed($"Using branch name: '{branchName}'");
            git.CheckoutNewBranch(branchName);

            foreach (var updateSet in updates)
            {
                await _updateRunner.Update(updateSet, sources);

                var commitMessage = CommitWording.MakeCommitMessage(updateSet);
                git.Commit(commitMessage);
            }

            git.Push("nukeeper_push", branchName);

            var title = CommitWording.MakePullRequestTitle(updates);
            var body  = CommitWording.MakeCommitDetails(updates);
            await _gitHub.CreatePullRequest(repository, title, body, branchName,
                                            settings.SourceControlServerSettings.Labels);

            git.Checkout(repository.DefaultBranch);
            return(updates.Count);
        }
        public void Report(PackageLookupResult lookupResult)
        {
            var highestVersion = lookupResult.Major?.Identity?.Version;

            if (highestVersion == null)
            {
                return;
            }

            var allowing = lookupResult.AllowedChange == VersionChange.Major
                ? string.Empty
                : $" Allowing {lookupResult.AllowedChange} version updates.";

            var highestMatchVersion = lookupResult.Selected()?.Identity?.Version;

            var packageId = lookupResult.Major.Identity.Id;

            if (highestMatchVersion == null)
            {
                _logger.Normal($"Package {packageId} version {highestVersion} is available but is not allowed.{allowing}");
                return;
            }

            if (highestVersion > highestMatchVersion)
            {
                _logger.Normal($"Selected update of package {packageId} to version {highestMatchVersion}, but version {highestVersion} is also available.{allowing}");
            }
            else
            {
                _logger.Detailed($"Selected update of package {packageId} to highest version, {highestMatchVersion}.{allowing}");
            }
        }
        public IEnumerable <T> Sort(
            IReadOnlyCollection <SortItemData <T> > inputMap)
        {
            if (inputMap == null)
            {
                throw new ArgumentNullException(nameof(inputMap));
            }

            var inputItems = inputMap
                             .Select(i => i.Item)
                             .ToList();

            if (inputMap.Count < 2)
            {
                return(inputItems);
            }

            if (!inputMap.Any(i => i.Dependencies.Any()))
            {
                _logger.Detailed("No dependencies between items, no need to sort on dependencies");
                return(inputItems);
            }

            _data = inputMap.ToList();

            return(DoSortVisits(inputItems));
        }
示例#30
0
        public async Task <bool> ContainsDotNetProjects(RepositorySettings repository)
        {
            var request = new SearchCodeRequest("\"packages.config\" OR \".csproj\" OR \".fsproj\" OR \".vbproj\"")
            {
                Repos = new RepositoryCollection {
                    { repository.RepositoryOwner, repository.RepositoryName }
                },
                In      = new [] { CodeInQualifier.Path },
                PerPage = 1
            };

            try
            {
                var result = await _gitHubClient.Search(request);

                if (result.TotalCount <= 0)
                {
                    _logger.Detailed(
                        $"Repository {repository.RepositoryOwner}/{repository.RepositoryName} contains no .NET code on the default branch, skipping.");
                    return(false);
                }
            }
            catch (Exception ex)
            {
                _logger.Error("GitHub Repository search failed.", ex);
            }

            return(true);
        }