Example #1
0
        private static void DoUpdate(object discarded)
        {
            // Check pending repositories
            for (int i = 0; i < PendingRepositories.Count; i++)
            {
                var repo = PendingRepositories[i];
                if (repo.Expiry < DateTime.Now || GitHub.GetPullRequestStatus(repo.PullRequest, repo.Origin) == "closed")
                {
                    // Delete repository
                    Console.WriteLine("Deleting " + repo.Name);
                    GitHub.DeleteRepository(repo.Name);
                    PendingRepositories.Remove(repo);
                    i--;
                }
            }
            SaveSession();
            // Check pending issues
            var issues = GitHub.GetActiveIssues(BaseRepository);
            var toFix  = issues.Where(i => i.Title.StartsWith("Fix ") && !PendingIssues.Contains(i.IssueNumber));

            if (toFix.Count() != 0)
            {
                new Thread(() => FixRepository(toFix.First())).Start();
            }
        }
Example #2
0
        private static void FixRepository(Issue issue)
        {
            const string CloneUrl = "git://github.com/{0}.git";

            try
            {
                PendingIssues.Add(issue.IssueNumber);
                var repositories   = GitHub.GetUserRepositories();
                var repositoryName = issue.Title.Substring(4).Trim();
                var fullName       = GitHub.GetRepositoryFullName(repositoryName);
                if (fullName == null)
                {
                    GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository, "Unable to find " +
                                          repositoryName + ". Did you spell it right?");
                    GitHub.CloseIssue(issue.IssueNumber, BaseRepository);
                    return;
                }
                if (repositories.Count(r => GetName(r) == GetName(repositoryName)) != 0)
                {
                    GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository,
                                          "We're already tracking a repository by that name, try later.");
                    GitHub.CloseIssue(issue.IssueNumber, BaseRepository);
                    return;
                }

                // Comment on the issue indicating progress is being made
                GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository, "Working on it.");

                Console.WriteLine("Cloning " + fullName);
                var cloneDir   = Path.Combine(TempDirectory, Guid.NewGuid().ToString().Replace("-", ""));
                var repository = CloneRepository(string.Format(CloneUrl, fullName), cloneDir);

                // Run analytics
                Console.WriteLine("Analyzing " + fullName);
                var project = Enforcer.AnalyzeDirectory(cloneDir);
                GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository, QualityEnforcer.Program.GenerateAnalysis(project));

                var details = GitHub.GetIssueBody(issue.IssueNumber, BaseRepository);
                var rules   = QualityRules.Parse(details);

                // Run cleanup
                Console.WriteLine("Cleaning up " + fullName);
                var results = Enforcer.EnforceQuality(project, rules);
                var status  = GetStatus(repository);
                if (!results.Any || status.IsClean())
                {
                    GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository, "No changes to apply.");
                    GitHub.CloseIssue(issue.IssueNumber, BaseRepository);
                    Directory.Delete(cloneDir, true);
                    Console.WriteLine("No changes to apply.");
                    return;
                }
                var changes = QualityEnforcer.Program.CreateChangeList(results);
                Console.WriteLine("Committing changes");
                DoCommit(repository, "Code quality enforcement");

                var reader = new StreamReader(
                    Assembly.GetExecutingAssembly().GetManifestResourceStream("QualityEnforcerBot.PullRequestTemplate.txt"));
                var template = reader.ReadToEnd();
                reader.Close();

                template = template.Replace("{changes}", changes);

                // Create fork
                Console.WriteLine("Forking repository");
                var fork = GitHub.Fork(repositoryName);
                Console.WriteLine("Pushing to fork");
                var push = repository.Push();
                push.SetCredentialsProvider(new UsernamePasswordCredentialsProvider(GitHub.Username, GitHub.Password));
                push.SetRemote(fork.Remote);
                push.SetRefSpecs(new RefSpec("refs/heads/master:refs/heads/master"));
                push.Call();

                // Create pull request
                int requestNumber = -1;
                int i;
                for (i = 0; i < 10; i++)
                {
                    try
                    {
                        Console.WriteLine("Sending pull request..."); // TODO: Use the default branch on the repo
                        var originOwner = repositoryName.Remove(repositoryName.IndexOf('/'));
                        requestNumber = GitHub.PullRequest(repositoryName, GitHub.Username + ":master",
                                                           "master", "Code quality enforcement", template);
                        break;
                    }
                    catch
                    {
                        Thread.Sleep(5000);
                        // Most of the errors creating a pull request are from GitHub lagging beind
                        // yes I know this is terrible
                    }
                }
                if (i == 10)
                {
                    GitHub.DeleteRepository(fork.Name);
                    GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository, "Unable to submit pull request.");
                    GitHub.CloseIssue(issue.IssueNumber, BaseRepository);
                    Directory.Delete(cloneDir, true);
                    return;
                }
                Console.WriteLine("Finished " + repositoryName);
                PendingRepositories.Add(new ForkedRepository
                {
                    Expiry      = DateTime.Now.AddDays(7),
                    Name        = fork.Name,
                    Origin      = fullName,
                    PullRequest = requestNumber
                });
                SaveSession();
                GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository, "Done! You have one week to merge the changes before the fork is deleted.");
                GitHub.CloseIssue(issue.IssueNumber, BaseRepository);
                try
                {
                    Directory.Delete(cloneDir, true);
                } catch { }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception occured during repository processing:");
                Console.WriteLine(e.ToString());
                GitHub.CommentOnIssue(issue.IssueNumber, BaseRepository,
                                      "An exception occured while processing this repository:\n" + e.ToString());
                GitHub.CloseIssue(issue.IssueNumber, BaseRepository);
            }
        }