diff --git a/components/scmprovider.py b/components/scmprovider.py index acd9134e..b7516456 100644 --- a/components/scmprovider.py +++ b/components/scmprovider.py @@ -30,6 +30,12 @@ def repo_and_commit_to_url(repo, commit): return repo.replace(".git", "") + "/commit/" + commit +def repo_and_compare_url(repo, old_commit, new_commit): + if not repo or not any(h in repo for h in ["github.com", "gitlab.com"]): + return None + return repo.replace(".git", "") + "/compare/" + old_commit + "..." + new_commit + + class Commit: def __init__(self, pretty_line): parts = pretty_line.split("|") @@ -239,70 +245,70 @@ def _print_differing_commit_lists(self, list_a, list_a_name, list_b, list_b_name self.logger.log(" - %s" % c, level=LogLevel.Error) raise Exception(problem) - def build_bug_description(self, list_of_commits, max_length): + def build_bug_description(self, list_of_commits, max_length, repo_url=None): # The commits are ordered oldest to newest. # But when we file a bug we want the newest commit to be at the top. list_of_commits = copy.deepcopy(list_of_commits) + oldest_revision = list_of_commits[0].revision + newest_revision = list_of_commits[-1].revision list_of_commits.reverse() - def _get_details(verbosity): - if verbosity == 0: - s = "----------------------------------------\n" - s += "%s commits elided, as they are too long for a bugzilla comment.\n\n" % len(list_of_commits) - s += "----------------------------------------\n" - return s - - s = "----------------------------------------\n" - for c in list_of_commits: - if not c.populated: - raise Exception("Tried to build bug description; but commit details not populated.") - - s += "%s by %s\n" % (c.revision, c.author) - s += c.revision_link + "\n" - - if verbosity >= 2: - s += "Authored: %s\n" % (c.author_date) - s += "Committed: %s\n" % (c.commit_date) - s += "\n" - s += c.summary + "\n" - - if verbosity >= 3: - s += "\n" - s += c.description + "\n" - - if c.files_added: - s += "\n" - s += "Files Added:\n" - for f in c.files_added: - s += " - %s\n" % f - - if c.files_deleted: - s += "\n" - s += "Files Deleted:\n" - for f in c.files_deleted: - s += " - %s\n" % f - - if c.files_modified: - s += "\n" - s += "Files Modified:\n" - for f in c.files_modified: - s += " - %s\n" % f - - if c.files_other: - s += "\n" - s += "Files Changed:\n" - for f in c.files_other: - s += " - %s\n" % f - s += "\n----------------------------------------\n" - + SEPARATOR = "----------------------------------------\n" + + def _commit_block(c): + if not c.populated: + raise Exception("Tried to build bug description; but commit details not populated.") + s = "%s by %s\n" % (c.revision, c.author) + s += c.revision_link + "\n" + s += "\n" + s += c.summary + "\n" + s += "Authored: %s\n" % c.author_date + s += "Committed: %s\n" % c.commit_date + if c.description: + s += "\n" + s += c.description + "\n" + if c.files_added: + s += "\nFiles Added:\n" + for f in c.files_added: + s += " - %s\n" % f + if c.files_deleted: + s += "\nFiles Deleted:\n" + for f in c.files_deleted: + s += " - %s\n" % f + if c.files_modified: + s += "\nFiles Modified:\n" + for f in c.files_modified: + s += " - %s\n" % f + if c.files_other: + s += "\nFiles Changed:\n" + for f in c.files_other: + s += " - %s\n" % f return s - # Bugzilla's limit is 65535 - details = _get_details(verbosity=3) - if len(details) > max_length: - details = _get_details(verbosity=2) - if len(details) > max_length: - details = _get_details(verbosity=1) - if len(details) > max_length: - details = _get_details(verbosity=0) - return details + entries = [_commit_block(c) + "\n" + SEPARATOR for c in list_of_commits] + + def _pack(entries, max_length, first_header=""): + chunks = [] + current = first_header + SEPARATOR + has_entries = False + for entry in entries: + if has_entries and len(current) + len(entry) > max_length: + chunks.append(current) + current = SEPARATOR + entry + has_entries = True + else: + current += entry + has_entries = True + if has_entries: + chunks.append(current) + return chunks or [first_header + SEPARATOR] + + chunks = _pack(entries, max_length) + if len(chunks) == 1: + return chunks + + compare_url = repo_and_compare_url(repo_url, oldest_revision, newest_revision) if repo_url else None + first_header = "" + if compare_url: + first_header = "All %s commits: %s\n(continued in following comments)\n\n" % (len(list_of_commits), compare_url) + return _pack(entries, max_length, first_header) diff --git a/tasktypes/commitalert.py b/tasktypes/commitalert.py index 592de037..5882ad56 100644 --- a/tasktypes/commitalert.py +++ b/tasktypes/commitalert.py @@ -105,7 +105,10 @@ def _process_new_commits(self, library, task, new_commits, all_library_jobs): depends_on = all_library_jobs[0].bugzilla_id if all_library_jobs else None open_dependencies = self.bugzillaProvider.find_open_bugs_info([j.bugzilla_id for j in all_library_jobs]) - description = CommentTemplates.EXAMINE_COMMITS_BODY(library, task, self.scmProvider.build_bug_description(filtered_commits, 65534 - 500), open_dependencies) + commit_chunks = self.scmProvider.build_bug_description(filtered_commits, 65534 - 500, library.repo_url) + description = CommentTemplates.EXAMINE_COMMITS_BODY(library, task, commit_chunks[0], open_dependencies) bugzilla_id = self.bugzillaProvider.file_bug(library, CommentTemplates.EXAMINE_COMMITS_SUMMARY(library, new_commits), description, task.cc, needinfo=task.needinfo, depends_on=depends_on, blocks=task.blocking, moco_confidential=True) + for chunk in commit_chunks[1:]: + self.bugzillaProvider.comment_on_bug(bugzilla_id, chunk) self.dbProvider.create_job(JOBTYPE.COMMITALERT, library, newest_commit.revision, JOBSTATUS.DONE, JOBOUTCOME.ALL_SUCCESS, bugzilla_id) diff --git a/tasktypes/vendoring.py b/tasktypes/vendoring.py index 132845d9..b33127e9 100644 --- a/tasktypes/vendoring.py +++ b/tasktypes/vendoring.py @@ -138,10 +138,15 @@ def _process_new_job(self, library, task, new_version, timestamp, most_recent_jo # File the bug ------------------------ all_upstream_commits, unseen_upstream_commits = self.scmProvider.check_for_update(library, task, new_version, most_recent_job.version if most_recent_job else None) commit_stats = self.mercurialProvider.diff_stats() - commit_details = self.scmProvider.build_bug_description(all_upstream_commits, 65534 - len(commit_stats) - 220) if library.should_show_commit_details else "" + if library.should_show_commit_details: + commit_chunks = self.scmProvider.build_bug_description(all_upstream_commits, 65534 - len(commit_stats) - 220, library.repo_url) + else: + commit_chunks = [""] - created_job.bugzilla_id = self.bugzillaProvider.file_bug(library, CommentTemplates.UPDATE_SUMMARY(library, new_version, timestamp), CommentTemplates.UPDATE_DETAILS(len(all_upstream_commits), len(unseen_upstream_commits), commit_stats, commit_details), task.cc, blocks=task.blocking) + created_job.bugzilla_id = self.bugzillaProvider.file_bug(library, CommentTemplates.UPDATE_SUMMARY(library, new_version, timestamp), CommentTemplates.UPDATE_DETAILS(len(all_upstream_commits), len(unseen_upstream_commits), commit_stats, commit_chunks[0]), task.cc, blocks=task.blocking) self.dbProvider.update_job_add_bug_id(created_job, created_job.bugzilla_id) + for chunk in commit_chunks[1:]: + self.bugzillaProvider.comment_on_bug(created_job.bugzilla_id, chunk) # Address any prior bug --------------- if most_recent_job and not most_recent_job.relinquished: