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); } }