blob: 093d00d49e659ad23c53d52284a372183d8b5eef [file] [log] [blame]
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for triggering CQ+2 on changes which meet submitability criteria and have opted in via Auto-Submit+1."""
from PB.recipe_engine import result
from PB.go.chromium.org.luci.buildbucket.proto import common
from recipe_engine.recipe_api import Property
DEPS = [
"fuchsia/gerrit",
"fuchsia/status_check",
"recipe_engine/buildbucket",
"recipe_engine/cipd",
"recipe_engine/context",
"recipe_engine/json",
"recipe_engine/file",
"recipe_engine/path",
"recipe_engine/platform",
"recipe_engine/properties",
"recipe_engine/raw_io",
"recipe_engine/step",
"recipe_engine/url",
]
PROPERTIES = {
"auto_submit_label": Property(
kind=str,
help="Label to trigger auto-submission",
default="Fuchsia-Auto-Submit",
),
"gerrit_host": Property(
kind=str,
help="Gerrit host to run against.",
default="fuchsia-review.googlesource.com",
),
"dry_run": Property(kind=bool, help="", default=False),
}
change_query_test_data = [
{
"id": "myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940",
"project": "myProject",
"branch": "master",
"change_id": "I8473b95934b5732ac55d26311a706c9c2bde9940",
"subject": 'Revert "Implementing Feature X"',
"status": "NEW",
"created": "2013-02-01 09:59:32.126000000",
"updated": "2013-02-21 11:16:36.775000000",
"_number": 3965,
"owner": {"name": "John Doe"},
}
]
def _get_change_url(host, change):
return "https://%s/c/%s/+/%s" % (host, change["project"], change["_number"])
def get_eligible_changes(api, host, auto_submit_label):
raw_query = (
"is:submittable -is:wip -(label:Commit-Queue+1 OR label:Commit-Queue+2) "
"label:{}+1"
).format(auto_submit_label)
changes = api.gerrit.change_query(
name="get changes for %s" % host,
query_string=raw_query,
host=host,
test_data=api.json.test_api.output(change_query_test_data),
).json.output
# API returns None if there is no search results instead of [].
if not changes:
return []
eligible_changes = []
for change in changes:
with api.step.nest("get details for %s" % change["_number"]) as presentation:
presentation.links["change"] = _get_change_url(host, change)
other_changes_info = api.gerrit.changes_submitted_together(
"find dependent changes",
api.url.unquote(change["id"]),
query_params=["NON_VISIBLE_CHANGES"],
host=host,
).json.output
if (
len(other_changes_info["changes"]) > 1
or other_changes_info.get("non_visible_changes", 0) != 0
):
continue
change_mergeability = api.gerrit.get_mergeable(
"get mergeable", change_id=api.url.unquote(change["id"]), host=host,
).json.output
if not change_mergeability["mergeable"]:
continue
eligible_changes.append(change)
return eligible_changes
def set_commit_queue(api, host, change):
labels = {"Commit-Queue": 2}
with api.step.nest("%s" % change["_number"]) as presentation:
api.gerrit.set_review(
name="CQ",
change_id=api.url.unquote(change["id"]),
labels=labels,
host=host,
notify="NONE",
)
presentation.links["change"] = _get_change_url(host, change)
def raw_result(host, changes, dry_run):
if changes:
contents = [
"Submitted the following CLs{}:".format(" (dry run)" if dry_run else "")
]
contents.extend(_get_change_url(host, change) for change in changes)
else:
contents = ["No CLs to submit."]
return result.RawResult(
summary_markdown="\n".join(contents), status=common.SUCCESS,
)
def RunSteps(api, gerrit_host, dry_run, auto_submit_label):
with api.step.nest("get eligible") as presentation:
changes = get_eligible_changes(api, gerrit_host, auto_submit_label)
if not changes:
presentation.step_text = "\nno eligible changes."
if changes:
with api.step.nest("set cq+2") as presentation:
if dry_run:
for change in [
_get_change_url(gerrit_host, change) for change in changes
]:
presentation.links[change] = change
else:
for change in changes:
set_commit_queue(api, gerrit_host, change)
return raw_result(gerrit_host, changes, dry_run)
def GenTests(api):
changes_submitted_together = {
"changes": [
{"id": "myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9941",},
],
"non_visible_changes": 1,
}
no_changes_submitted_together = {"changes": [], "non_visible_changes": 0}
mergeable_test_data = {
"mergeable": True,
}
unmergeable_test_data = {
"mergeable": False,
}
yield (
api.status_check.test("default")
+ api.step_data(
"get eligible.get details for 3965.find dependent changes",
api.json.output(no_changes_submitted_together),
)
+ api.step_data(
"get eligible.get details for 3965.get mergeable",
api.json.output(mergeable_test_data),
)
)
yield (
api.status_check.test("no_changes")
+ api.step_data(
"get eligible.get changes for fuchsia-review.googlesource.com",
api.json.output(None),
)
)
yield (
api.status_check.test("changes_submitted_together")
+ api.step_data(
"get eligible.get details for 3965.find dependent changes",
api.json.output(changes_submitted_together),
)
)
yield (
api.status_check.test("unmergeable")
+ api.step_data(
"get eligible.get details for 3965.find dependent changes",
api.json.output(no_changes_submitted_together),
)
+ api.step_data(
"get eligible.get details for 3965.get mergeable",
api.json.output(unmergeable_test_data),
)
)
yield (
api.status_check.test("dry_run")
+ api.step_data(
"get eligible.get details for 3965.find dependent changes",
api.json.output(no_changes_submitted_together),
)
+ api.step_data(
"get eligible.get details for 3965.get mergeable",
api.json.output(mergeable_test_data),
)
+ api.properties(dry_run=True)
)