1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import logging
import subprocess
import requests
from mozbuild.util import memoize
from redo import retry
logger = logging.getLogger(__name__)
PUSHLOG_CHANGESET_TMPL = (
"{repository}/json-pushes?version=2&changeset={revision}&tipsonly=1"
)
PUSHLOG_PUSHES_TMPL = (
"{repository}/json-pushes/?version=2&startID={push_id_start}&endID={push_id_end}"
)
def _query_pushlog(url):
response = retry(
requests.get,
attempts=5,
sleeptime=10,
args=(url,),
kwargs={"timeout": 60, "headers": {"User-Agent": "TaskCluster"}},
)
return response.json()["pushes"]
def find_hg_revision_push_info(repository, revision):
"""Given the parameters for this action and a revision, find the
pushlog_id of the revision."""
url = PUSHLOG_CHANGESET_TMPL.format(repository=repository, revision=revision)
pushes = _query_pushlog(url)
if len(pushes) != 1:
raise RuntimeError(
f"Found {len(pushes)} pushlog_ids, expected 1, for {repository} revision {revision}: {pushes}"
)
pushid = list(pushes.keys())[0]
return {
"pushdate": pushes[pushid]["date"],
"pushid": pushid,
"user": pushes[pushid]["user"],
}
@memoize
def get_push_data(repository, project, push_id_start, push_id_end):
url = PUSHLOG_PUSHES_TMPL.format(
repository=repository,
push_id_start=push_id_start - 1,
push_id_end=push_id_end,
)
try:
pushes = _query_pushlog(url)
return {
push_id: pushes[str(push_id)]
for push_id in range(push_id_start, push_id_end + 1)
}
# In the event of request times out, requests will raise a TimeoutError.
except requests.exceptions.Timeout:
logger.warning("json-pushes timeout")
# In the event of a network problem (e.g. DNS failure, refused connection, etc),
# requests will raise a ConnectionError.
except requests.exceptions.ConnectionError:
logger.warning("json-pushes connection error")
# In the event of the rare invalid HTTP response(e.g 404, 401),
# requests will raise an HTTPError exception
except requests.exceptions.HTTPError:
logger.warning("Bad Http response")
# When we get invalid JSON (i.e. 500 error), it results in a ValueError (bug 1313426)
except ValueError as error:
logger.warning(f"Invalid JSON, possible server error: {error}")
# We just print the error out as a debug message if we failed to catch the exception above
except requests.exceptions.RequestException as error:
logger.warning(error)
return None
@memoize
def get_json_pushchangedfiles(repository, revision):
url = "{}/json-pushchangedfiles/{}".format(repository.rstrip("/"), revision)
logger.debug("Querying version control for metadata: %s", url)
def get_pushchangedfiles():
response = requests.get(url, timeout=60)
response.raise_for_status()
return response.json()
return retry(get_pushchangedfiles, attempts=10, sleeptime=10)
def get_hg_revision_branch(root, revision):
"""Given the parameters for a revision, find the hg_branch (aka
relbranch) of the revision."""
return get_hg_revision_info(root, revision, "branch")
def get_hg_revision_info(root, revision, info):
return subprocess.check_output(
[
"hg",
"identify",
"-T",
f"{{{info}}}",
"--rev",
revision,
],
cwd=root,
universal_newlines=True,
)
# For these functions, we assume that run-task has correctly checked out the
# revision indicated by GECKO_HEAD_REF, so all that remains is to see what the
# current revision is. Mercurial refers to that as `.`.
def get_hg_commit_message(root, rev="."):
return subprocess.check_output(
["hg", "log", "-r", rev, "-T", "{desc}"], cwd=root, universal_newlines=True
)
def calculate_head_rev(root):
return subprocess.check_output(
["hg", "log", "-r", ".", "-T", "{node}"], cwd=root, universal_newlines=True
)
|