diff --git a/recipes/README.recipes.md b/recipes/README.recipes.md
index 74de48566..04d80a278 100644
--- a/recipes/README.recipes.md
+++ b/recipes/README.recipes.md
@@ -795,54 +795,56 @@ Returns:
[DEPS](/recipes/recipe_modules/tryserver/__init__.py#5): [gerrit](#recipe_modules-gerrit), [git](#recipe_modules-git), [git\_cl](#recipe_modules-git_cl), [recipe\_engine/buildbucket][recipe_engine/recipe_modules/buildbucket], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/platform][recipe_engine/recipe_modules/platform], [recipe\_engine/properties][recipe_engine/recipe_modules/properties], [recipe\_engine/python][recipe_engine/recipe_modules/python], [recipe\_engine/raw\_io][recipe_engine/recipe_modules/raw_io], [recipe\_engine/step][recipe_engine/recipe_modules/step]
-#### **class [TryserverApi](/recipes/recipe_modules/tryserver/api.py#11)([RecipeApi][recipe_engine/wkt/RecipeApi]):**
+#### **class [TryserverApi](/recipes/recipe_modules/tryserver/api.py#26)([RecipeApi][recipe_engine/wkt/RecipeApi]):**
- **@property**
— **def [gerrit\_change](/recipes/recipe_modules/tryserver/api.py#29)(self):**
+ **@property**
— **def [constants](/recipes/recipe_modules/tryserver/api.py#48)(self):**
+
+ **@property**
— **def [gerrit\_change](/recipes/recipe_modules/tryserver/api.py#53)(self):**
Returns current gerrit change, if there is exactly one.
Returns a self.m.buildbucket.common_pb2.GerritChange or None.
- **@property**
— **def [gerrit\_change\_fetch\_ref](/recipes/recipe_modules/tryserver/api.py#106)(self):**
+ **@property**
— **def [gerrit\_change\_fetch\_ref](/recipes/recipe_modules/tryserver/api.py#130)(self):**
Returns gerrit patch ref, e.g. "refs/heads/45/12345/6, or None.
Populated iff gerrit_change is populated.
- **@property**
— **def [gerrit\_change\_number](/recipes/recipe_modules/tryserver/api.py#124)(self):**
+ **@property**
— **def [gerrit\_change\_number](/recipes/recipe_modules/tryserver/api.py#148)(self):**
Returns gerrit change patchset, e.g. 12345 for a patch ref of
"refs/heads/45/12345/6".
Populated iff gerrit_change is populated. Returns None if not populated.
- **@property**
— **def [gerrit\_change\_owner](/recipes/recipe_modules/tryserver/api.py#45)(self):**
+ **@property**
— **def [gerrit\_change\_owner](/recipes/recipe_modules/tryserver/api.py#69)(self):**
Returns owner of the current Gerrit CL.
Populated iff gerrit_change is populated.
Is a dictionary with keys like "name".
- **@property**
— **def [gerrit\_change\_repo\_url](/recipes/recipe_modules/tryserver/api.py#37)(self):**
+ **@property**
— **def [gerrit\_change\_repo\_url](/recipes/recipe_modules/tryserver/api.py#61)(self):**
Returns canonical URL of the gitiles repo of the current Gerrit CL.
Populated iff gerrit_change is populated.
- **@property**
— **def [gerrit\_change\_target\_ref](/recipes/recipe_modules/tryserver/api.py#115)(self):**
+ **@property**
— **def [gerrit\_change\_target\_ref](/recipes/recipe_modules/tryserver/api.py#139)(self):**
Returns gerrit change destination ref, e.g. "refs/heads/master".
Populated iff gerrit_change is populated.
- **@property**
— **def [gerrit\_patchset\_number](/recipes/recipe_modules/tryserver/api.py#136)(self):**
+ **@property**
— **def [gerrit\_patchset\_number](/recipes/recipe_modules/tryserver/api.py#160)(self):**
Returns gerrit change patchset, e.g. 6 for a patch ref of
"refs/heads/45/12345/6".
Populated iff gerrit_change is populated Returns None if not populated..
-— **def [get\_files\_affected\_by\_patch](/recipes/recipe_modules/tryserver/api.py#169)(self, patch_root, report_files_via_property=None, \*\*kwargs):**
+— **def [get\_files\_affected\_by\_patch](/recipes/recipe_modules/tryserver/api.py#193)(self, patch_root, report_files_via_property=None, \*\*kwargs):**
Returns list of paths to files affected by the patch.
@@ -854,43 +856,43 @@ Args:
Returned paths will be relative to to patch_root.
-— **def [get\_footer](/recipes/recipe_modules/tryserver/api.py#306)(self, tag, patch_text=None):**
+— **def [get\_footer](/recipes/recipe_modules/tryserver/api.py#330)(self, tag, patch_text=None):**
Gets a specific tag from a CL description
-— **def [get\_footers](/recipes/recipe_modules/tryserver/api.py#273)(self, patch_text=None):**
+— **def [get\_footers](/recipes/recipe_modules/tryserver/api.py#297)(self, patch_text=None):**
Retrieves footers from the patch description.
footers are machine readable tags embedded in commit messages. See
git-footers documentation for more information.
-— **def [initialize](/recipes/recipe_modules/tryserver/api.py#24)(self):**
+— **def [initialize](/recipes/recipe_modules/tryserver/api.py#39)(self):**
- **@property**
— **def [is\_gerrit\_issue](/recipes/recipe_modules/tryserver/api.py#153)(self):**
+ **@property**
— **def [is\_gerrit\_issue](/recipes/recipe_modules/tryserver/api.py#177)(self):**
Returns true iff the properties exist to match a Gerrit issue.
- **@property**
— **def [is\_patch\_in\_git](/recipes/recipe_modules/tryserver/api.py#163)(self):**
+ **@property**
— **def [is\_patch\_in\_git](/recipes/recipe_modules/tryserver/api.py#187)(self):**
- **@property**
— **def [is\_tryserver](/recipes/recipe_modules/tryserver/api.py#148)(self):**
+ **@property**
— **def [is\_tryserver](/recipes/recipe_modules/tryserver/api.py#172)(self):**
Returns true iff we have a change to check out.
-— **def [normalize\_footer\_name](/recipes/recipe_modules/tryserver/api.py#310)(self, footer):**
+— **def [normalize\_footer\_name](/recipes/recipe_modules/tryserver/api.py#334)(self, footer):**
-— **def [set\_change](/recipes/recipe_modules/tryserver/api.py#313)(self, change):**
+— **def [set\_change](/recipes/recipe_modules/tryserver/api.py#337)(self, change):**
Set the gerrit change for this module.
Args:
* change: a self.m.buildbucket.common_pb2.GerritChange.
-— **def [set\_compile\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#234)(self):**
+— **def [set\_compile\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#258)(self):**
Mark the tryjob result as a compile failure.
-— **def [set\_invalid\_test\_results\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#246)(self):**
+— **def [set\_invalid\_test\_results\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#270)(self):**
Mark the tryjob result as having invalid test results.
@@ -898,37 +900,39 @@ This means we run some tests, but the results were not valid
(e.g. no list of specific test cases that failed, or too many
tests failing, etc).
-— **def [set\_patch\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#230)(self):**
+— **def [set\_patch\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#254)(self):**
Mark the tryjob result as failure to apply the patch.
-— **def [set\_subproject\_tag](/recipes/recipe_modules/tryserver/api.py#208)(self, subproject_tag):**
+— **def [set\_subproject\_tag](/recipes/recipe_modules/tryserver/api.py#232)(self, subproject_tag):**
Adds a subproject tag to the build.
This can be used to distinguish between builds that execute different steps
depending on what was patched, e.g. blink vs. pure chromium patches.
-— **def [set\_test\_expired\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#263)(self):**
+— **def [set\_test\_expired\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#287)(self):**
Mark the tryjob result as a test expiration.
This means a test task expired and was never scheduled, most likely due to
lack of capacity.
-— **def [set\_test\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#238)(self):**
+— **def [set\_test\_failure\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#262)(self):**
Mark the tryjob result as a test failure.
This means we started running actual tests (not prerequisite steps
like checkout or compile), and some of these tests have failed.
-— **def [set\_test\_timeout\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#255)(self):**
+— **def [set\_test\_timeout\_tryjob\_result](/recipes/recipe_modules/tryserver/api.py#279)(self):**
Mark the tryjob result as a test timeout.
This means tests were scheduled but didn't finish executing within the
timeout.
+
+ **@property**
— **def [valid\_footers](/recipes/recipe_modules/tryserver/api.py#44)(self):**
### *recipe_modules* / [windows\_sdk](/recipes/recipe_modules/windows_sdk)
[DEPS](/recipes/recipe_modules/windows_sdk/__init__.py#5): [recipe\_engine/cipd][recipe_engine/recipe_modules/cipd], [recipe\_engine/context][recipe_engine/recipe_modules/context], [recipe\_engine/json][recipe_engine/recipe_modules/json], [recipe\_engine/path][recipe_engine/recipe_modules/path], [recipe\_engine/step][recipe_engine/recipe_modules/step]
diff --git a/recipes/recipe_modules/tryserver/api.py b/recipes/recipe_modules/tryserver/api.py
index 88c3c7302..03ce8ef65 100644
--- a/recipes/recipe_modules/tryserver/api.py
+++ b/recipes/recipe_modules/tryserver/api.py
@@ -8,6 +8,21 @@ import hashlib
from recipe_engine import recipe_api
+class Constants:
+ def __init__(self):
+ self.NONTRIVIAL_ROLL_FOOTER = 'Recipe-Nontrivial-Roll'
+ self.MANUAL_CHANGE_FOOTER = 'Recipe-Manual-Change'
+ self.BYPASS_FOOTER = 'Recipe-Tryjob-Bypass-Reason'
+ self.SKIP_RETRY_FOOTER = 'Disable-Retries'
+ self.ALL_VALID_FOOTERS = set([
+ self.NONTRIVIAL_ROLL_FOOTER, self.MANUAL_CHANGE_FOOTER,
+ self.BYPASS_FOOTER, self.SKIP_RETRY_FOOTER
+ ])
+
+
+constants = Constants()
+
+
class TryserverApi(recipe_api.RecipeApi):
def __init__(self, *args, **kwargs):
super(TryserverApi, self).__init__(*args, **kwargs)
@@ -26,6 +41,15 @@ class TryserverApi(recipe_api.RecipeApi):
if len(changes) == 1:
self.set_change(changes[0])
+ @property
+ def valid_footers(self): #pragma: nocover
+ return constants.ALL_VALID_FOOTERS
+
+ @property
+ def constants(self): #pragma: nocover
+ # Nocover to be removed when callers (not within depot_tools) exercise this
+ return constants
+
@property
def gerrit_change(self):
"""Returns current gerrit change, if there is exactly one.