blob: 6c58e5373ae3bda315a469037836195fa3021aa4 [file] [log] [blame]
# Copyright 2022 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 flagging large-scale changes (LSCs) that may impact downstream projects."""
import datetime
from recipe_engine import post_process
from PB.recipes.fuchsia.lsc_suggester import InputProperties
DEPS = [
"fuchsia/gerrit",
"fuchsia/status_check",
"recipe_engine/json",
"recipe_engine/properties",
"recipe_engine/url",
]
PROPERTIES = InputProperties
# TODO(akbiggs): Remove message once changes to add comment have been tested.
FX_LSC_MESSAGE = """
Please run `fx lsc presubmit` on API+1 changes. See http://go/run-fx-lsc-presubmit.
Note that the LSC tryjobs are non-blocking. You will need to check the results manually.
"""
FX_LSC_COMMENT = """
`fx lsc presubmit` must be run on API+1 changes. Please run `fx lsc presubmit` and then resolve this comment. See http://go/run-fx-lsc-presubmit.
Note that the LSC tryjobs are non-blocking. You will need to check the results manually.
"""
FX_LSC_TAG = "autogenerated:suggest-fx-lsc"
def RunSteps(api, props):
assert props.gerrit_host, "props.gerrit_host must be specified"
for change in get_eligible_changes_with_messages(api, props.gerrit_host):
# Only comment on the change if it has not been commented on before
# regardless of patchset. change["messages"] contains messages from all
# patchsets.
assert "messages" in change, "change %s must have a `messages` key" % change
has_fx_lsc_tag = any(
message.get("tag") == FX_LSC_TAG for message in change["messages"]
)
# Add an unresolved comment instead of a message when
# akbiggs@google.com is the author of the commit.
# TODO(akbiggs): Simplify this logic once changes have been tested.
author_is_akbiggs = (
change.get("author") and change["author"]["email"] == "akbiggs@google.com"
)
comment = None
step_name = "add fx lsc message to %d" % change["_number"]
if author_is_akbiggs:
comment = {"message": FX_LSC_COMMENT, "unresolved": True}
step_name = "add fx lsc message V2 to %d" % change["_number"]
if not has_fx_lsc_tag:
api.gerrit.set_review(
step_name,
api.url.unquote(change["id"]),
patchset_level_comment=comment,
# We leave a message on the commit with a tag to easily identify
# commits that have already been commented on. We need a message
# because get_eligible_changes_with_messages uses
# Gerrit.ChangeQuery, which can only retrieve messages, not comments.
message=FX_LSC_MESSAGE,
tag=FX_LSC_TAG,
notify="OWNER",
host=props.gerrit_host,
)
def get_eligible_changes_with_messages(api, gerrit_host):
"""Finds changes to suggest running fx lsc.
Eligible changes have the following properties:
* unsubmitted
* recently modified/created
* need the API-Review label or have API+1 label
* in directory:sdk
Args:
gerrit_host (str): Gerrit Host to query.
Returns:
changes ([]json ChangeInfo): list of changes that are suggested to run
fx lsc. See
https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-info.
"""
# We restrict the results to recently modified/created changes. This is to
# avoid messaging abandoned changes so that we do not spam users.
#
# The following change fxr/644416 had 80 messages and the result size was
# ~52KB -> 100KB. We expect a max of O(10) eligible changes, where result
# size will be 1MB.
raw_query = "is:open -is:wip (label:Api-Review=need OR label:Api-Review+1) -age:1h directory:sdk"
# Query for unsubmitted changes that are api+1. Get the messages so that we
# can determine if the change has been fx lsc commented before. The query
# will get all the messages from all patchsets from a change.
changes = api.gerrit.change_query(
name="get eligible changes",
query_string=raw_query,
query_params=["MESSAGES"],
host=gerrit_host,
max_attempts=3,
timeout=datetime.timedelta(seconds=120),
).json.output
# API returns None if there is no search results instead of [].
return changes or []
def GenTests(api):
# For this test, check that there are no fx lsc comments added.
yield api.status_check.test("empty") + api.properties(
gerrit_host="fuchsia-review.googlesource.com"
) + api.step_data("get eligible changes", api.json.output([]))
# For this test, check that only change 1000, 1001 and 1002 got
# a fx lsc comment added. 1002 should use the new logic with an
# unresolved comment.
yield api.status_check.test("default") + api.properties(
gerrit_host="fuchsia-review.googlesource.com"
) + api.step_data(
"get eligible changes",
api.json.output(
[
{
"id": "myProject~main~1000",
"project": "myProject",
"status": "NEW",
"_number": 1000,
"messages": [],
},
{
"id": "myProject~main~1001",
"project": "myProject",
"status": "NEW",
"_number": 1001,
"messages": [
{"message": ""},
{"message": "nothing"},
],
},
{
"id": "myProject~main~1002",
"project": "myProject",
"status": "NEW",
"_number": 1002,
"author": {
"name": "Alexander Biggs",
"email": "akbiggs@google.com",
"date": "2012-04-24 18:08:08.000000000",
"tz": 120,
},
"messages": [
{"message": ""},
{"message": "nothing"},
],
},
{
"id": "myProject~main~1003",
"project": "myProject",
"status": "NEW",
"_number": 1003,
"messages": [
{"message": ""},
{"message": FX_LSC_MESSAGE, "tag": FX_LSC_TAG},
{"message": "nothing"},
],
},
{
"id": "myProject~main~1004",
"project": "myProject",
"status": "NEW",
"_number": 1004,
"messages": [
{
"message": "Different from current FX_LSC_MESSAGE",
"tag": FX_LSC_TAG,
},
],
},
]
),
) + api.post_process(
post_process.MustRun,
"add fx lsc message to 1000",
"add fx lsc message to 1001",
"add fx lsc message V2 to 1002",
)