Show info about flags doesn't break Bazel owned/co-owned projects (#939)
* Show info about flags doesn't break Bazel owned/co-owned projects
1. Print a summary of flags that doesn't break Bazel team owned/co-owned
projects
2. Mark Bazel owned/co-owned pipelines as red
Change-Id: Ie0225e5cc654604ff3bf82d1de88470a769bd753
* Address reviewer comments
Change-Id: Id23c77ff7fb600366c58eb11d26fdc466fd9241d
* refactor
Change-Id: I7a04ed0fa88ebbb48aeaaad84250c038efa718b1
diff --git a/buildkite/aggregate_incompatible_flags_test_result.py b/buildkite/aggregate_incompatible_flags_test_result.py
index bb55d8b..5640673 100755
--- a/buildkite/aggregate_incompatible_flags_test_result.py
+++ b/buildkite/aggregate_incompatible_flags_test_result.py
@@ -195,15 +195,38 @@
return f'<a href="{link}" target="_blank">{content}</a>'
+# Check if any of the given jobs needs to be migrated by the Bazel team
+def needs_bazel_team_migrate(jobs):
+ for job in jobs:
+ pipeline, _ = get_pipeline_and_platform(job)
+ if bazelci.DOWNSTREAM_PROJECTS[pipeline].get("owned_by_bazel"):
+ return True
+ return False
+
+
def print_flags_ready_to_flip(failed_jobs_per_flag, details_per_flag):
- info_text = ["#### The following flags didn't break any passing jobs"]
+ info_text1 = ["#### The following flags didn't break any passing projects"]
for flag in sorted(list(details_per_flag.keys())):
if flag not in failed_jobs_per_flag:
- github_url = details_per_flag[flag].issue_url
- info_text.append(f"* **{flag}** " + get_html_link_text(":github:", github_url))
- if len(info_text) == 1:
- return
- print_info("flags_ready_to_flip", "success", info_text)
+ html_link_text = get_html_link_text(":github:", details_per_flag[flag].issue_url)
+ info_text1.append(f"* **{flag}** {html_link_text}")
+
+ if len(info_text1) == 1:
+ info_text1 = []
+
+ info_text2.append("#### The following flags didn't break any passing Bazel team owned/co-owned projects"):
+ for flag, jobs in failed_jobs_per_flag.items():
+ if not needs_bazel_team_migrate(jobs):
+ failed_cnt = len(jobs)
+ s1 = "" if failed_cnt == 1 else "s"
+ s2 = "s" if failed_cnt == 1 else ""
+ html_link_text = get_html_link_text(":github:", details_per_flag[flag].issue_url)
+ info_text2.append(f"* **{flag}** {html_link_text} ({failed_cnt} other job{s1} need{s2} migration)")
+
+ if len(info_text2) == 1:
+ info_text2 = []
+
+ print_info("flags_ready_to_flip", "success", info_text1 + info_text2)
def print_already_fail_jobs(already_failing_jobs):
@@ -264,16 +287,31 @@
if jobs:
github_url = details_per_flag[flag].issue_url
info_text = [f"* **{flag}** " + get_html_link_text(":github:", github_url)]
- info_text += merge_and_format_jobs(jobs.values(), " - **{}**: {}")
+ jobs_per_pipeline = merge_jobs(jobs.values())
+ for pipeline, platforms in jobs_per_pipeline.items():
+ color = "red" if bazelci.DOWNSTREAM_PROJECTS[pipeline].get("owned_by_bazel") else "black"
+ platforms_text = ", ".join(platforms)
+ info_text.append(f" <li><strong style=\"color: {color}\">{pipeline}</strong>: {platforms_text}</li>")
# Use flag as the context so that each flag gets a different info box.
print_info(flag, "error", info_text)
printed_flag_boxes = True
if not printed_flag_boxes:
return
- info_text = ["#### Downstream projects need to migrate for the following flags:"]
+ info_text = [
+ "#### Downstream projects need to migrate for the following flags:",
+ " Projects with <strong style=\"color: red;\">red title</strong> need to be migrated by the Bazel team.",
+ ]
print_info("flags_need_to_migrate", "error", info_text)
+def merge_jobs(jobs):
+ jobs_per_pipeline = collections.defaultdict(list)
+ for job in sorted(jobs, key=lambda s: s["name"].lower()):
+ pipeline, platform = get_pipeline_and_platform(job)
+ jobs_per_pipeline[pipeline].append(get_html_link_text(platform, job["web_url"]))
+ return jobs_per_pipeline
+
+
def merge_and_format_jobs(jobs, line_pattern):
# Merges all jobs for a single pipeline into one line.
# Example:
@@ -282,13 +320,7 @@
# pipeline (platform3)
# with line_pattern ">> {}: {}" becomes
# >> pipeline: platform1, platform2, platform3
- jobs = list(jobs)
- jobs.sort(key=lambda s: s["name"].lower())
- jobs_per_pipeline = collections.defaultdict(list)
- for job in jobs:
- pipeline, platform = get_pipeline_and_platform(job)
- jobs_per_pipeline[pipeline].append(get_html_link_text(platform, job["web_url"]))
-
+ jobs_per_pipeline = merge_jobs(jobs)
return [
line_pattern.format(pipeline, ", ".join(platforms))
for pipeline, platforms in jobs_per_pipeline.items()
diff --git a/buildkite/bazelci.py b/buildkite/bazelci.py
index 98fb253..1eade27 100755
--- a/buildkite/bazelci.py
+++ b/buildkite/bazelci.py
@@ -128,6 +128,7 @@
"git_repository": "https://github.com/bazelbuild/bazel-skylib.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/bazel-skylib/master/.bazelci/presubmit.yml",
"pipeline_slug": "bazel-skylib",
+ "owned_by_bazel": True,
},
"Bazel toolchains": {
"git_repository": "https://github.com/bazelbuild/bazel-toolchains.git",
@@ -213,16 +214,19 @@
"git_repository": "https://github.com/google/protobuf.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/continuous-integration/master/buildkite/pipelines/protobuf-postsubmit.yml",
"pipeline_slug": "protobuf",
+ "owned_by_bazel": True,
},
"Skydoc": {
"git_repository": "https://github.com/bazelbuild/skydoc.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/skydoc/master/.bazelci/presubmit.yml",
"pipeline_slug": "skydoc",
+ "owned_by_bazel": True,
},
"Subpar": {
"git_repository": "https://github.com/google/subpar.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/continuous-integration/master/buildkite/pipelines/subpar-postsubmit.yml",
"pipeline_slug": "subpar",
+ "owned_by_bazel": True,
},
"TensorFlow": {
"git_repository": "https://github.com/tensorflow/tensorflow.git",
@@ -258,11 +262,13 @@
"git_repository": "https://github.com/bazelbuild/rules_cc.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/rules_cc/master/.bazelci/presubmit.yml",
"pipeline_slug": "rules-cc",
+ "owned_by_bazel": True,
},
"rules_closure": {
"git_repository": "https://github.com/bazelbuild/rules_closure.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/rules_closure/master/.bazelci/presubmit.yml",
"pipeline_slug": "rules-closure-closure-compiler",
+ "owned_by_bazel": True,
},
"rules_d": {
"git_repository": "https://github.com/bazelbuild/rules_d.git",
@@ -278,6 +284,7 @@
"git_repository": "https://github.com/bazelbuild/rules_foreign_cc.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/rules_foreign_cc/master/.bazelci/config.yaml",
"pipeline_slug": "rules-foreign-cc",
+ "owned_by_bazel": True,
},
"rules_go": {
"git_repository": "https://github.com/bazelbuild/rules_go.git",
@@ -308,11 +315,13 @@
"git_repository": "https://github.com/bazelbuild/rules_jvm_external.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/rules_jvm_external/master/.bazelci/presubmit.yml",
"pipeline_slug": "rules-jvm-external",
+ "owned_by_bazel": True,
},
"rules_jvm_external - examples": {
"git_repository": "https://github.com/bazelbuild/rules_jvm_external.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/rules_jvm_external/master/.bazelci/examples.yml",
"pipeline_slug": "rules-jvm-external-examples",
+ "owned_by_bazel": True,
},
"rules_k8s": {
"git_repository": "https://github.com/bazelbuild/rules_k8s.git",
@@ -338,11 +347,13 @@
"git_repository": "https://github.com/bazelbuild/rules_proto.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/rules_proto/master/.bazelci/presubmit.yml",
"pipeline_slug": "rules-proto",
+ "owned_by_bazel": True,
},
"rules_python": {
"git_repository": "https://github.com/bazelbuild/rules_python.git",
"http_config": "https://raw.githubusercontent.com/bazelbuild/rules_python/master/.bazelci/presubmit.yml",
"pipeline_slug": "rules-python-python",
+ "owned_by_bazel": True,
},
"rules_rust": {
"git_repository": "https://github.com/bazelbuild/rules_rust.git",