scriptworker 63.6.1__tar.gz → 64.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scriptworker-63.6.1 → scriptworker-64.0.0}/HISTORY.rst +29 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/PKG-INFO +1 -1
- {scriptworker-63.6.1 → scriptworker-64.0.0}/pyproject.toml +1 -1
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/constants.py +1 -13
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/cot/verify.py +58 -14
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/github.py +90 -30
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/task.py +11 -5
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/utils.py +2 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/.gitignore +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/CONTRIBUTING.rst +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/LICENSE +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/README.rst +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/renovate.json +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/scripts/gen_ed25519_key.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/scriptworker.yaml.tmpl +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/__init__.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/artifacts.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/client.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/config.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/context.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/cot/__init__.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/cot/generate.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/data/cot_v1_schema.json +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/data/scriptworker_task_schema.json +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/ed25519.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/exceptions.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/log.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/task_process.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/worker.py +0 -0
- {scriptworker-63.6.1 → scriptworker-64.0.0}/tox.ini +0 -0
|
@@ -4,6 +4,35 @@ Change Log
|
|
|
4
4
|
All notable changes to this project will be documented in this file.
|
|
5
5
|
This project adheres to `Semantic Versioning <http://semver.org/>`__.
|
|
6
6
|
|
|
7
|
+
64.0.0 - 2026-11-05
|
|
8
|
+
-------------------
|
|
9
|
+
|
|
10
|
+
Fixed
|
|
11
|
+
~~~~~
|
|
12
|
+
|
|
13
|
+
- use the compare API to tell if a commit landed on a github repo (bug 2089531, #855)
|
|
14
|
+
|
|
15
|
+
Removed
|
|
16
|
+
~~~~~~~
|
|
17
|
+
|
|
18
|
+
- {mozilla,comm}-esr140 support (bug 2081292)
|
|
19
|
+
|
|
20
|
+
63.7.1 - 2026-10-27
|
|
21
|
+
-------------------
|
|
22
|
+
|
|
23
|
+
Fixed
|
|
24
|
+
~~~~~
|
|
25
|
+
|
|
26
|
+
- CoT verification crash due to long github CSP response header (bug 2085468)
|
|
27
|
+
|
|
28
|
+
63.7.0 - 2026-10-13
|
|
29
|
+
-------------------
|
|
30
|
+
|
|
31
|
+
Added
|
|
32
|
+
~~~~~
|
|
33
|
+
|
|
34
|
+
- take a git project's scm level from the task branch (#839)
|
|
35
|
+
|
|
7
36
|
63.6.1 - 2026-10-08
|
|
8
37
|
-------------------
|
|
9
38
|
|
|
@@ -464,7 +464,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
464
464
|
"/releases/mozilla-beta": "/mozilla-firefox/firefox",
|
|
465
465
|
"/releases/mozilla-release": "/mozilla-firefox/firefox",
|
|
466
466
|
"/releases/mozilla-esr115": "/mozilla-firefox/firefox",
|
|
467
|
-
"/releases/mozilla-esr140": "/mozilla-firefox/firefox",
|
|
468
467
|
"/releases/mozilla-esr153": "/mozilla-firefox/firefox",
|
|
469
468
|
}
|
|
470
469
|
),
|
|
@@ -634,7 +633,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
634
633
|
"project:releng:lando:repo:beta": "beta",
|
|
635
634
|
"project:releng:lando:repo:release": "release",
|
|
636
635
|
"project:releng:lando:repo:esr115": "esr115",
|
|
637
|
-
"project:releng:lando:repo:esr140": "esr140",
|
|
638
636
|
"project:releng:lando:repo:esr153": "esr153",
|
|
639
637
|
}
|
|
640
638
|
),
|
|
@@ -730,7 +728,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
730
728
|
"/releases/mozilla-beta",
|
|
731
729
|
"/releases/mozilla-release",
|
|
732
730
|
"/releases/mozilla-esr115",
|
|
733
|
-
"/releases/mozilla-esr140",
|
|
734
731
|
"/releases/mozilla-esr153",
|
|
735
732
|
"/projects/birch",
|
|
736
733
|
# Bug 1821839 hneiva using to test hardened signing
|
|
@@ -740,7 +737,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
740
737
|
"/releases/mozilla-beta",
|
|
741
738
|
"/releases/mozilla-release",
|
|
742
739
|
"/releases/mozilla-esr115",
|
|
743
|
-
"/releases/mozilla-esr140",
|
|
744
740
|
"/releases/mozilla-esr153",
|
|
745
741
|
"/projects/birch",
|
|
746
742
|
"/projects/maple",
|
|
@@ -754,11 +750,9 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
754
750
|
"/releases/mozilla-release",
|
|
755
751
|
),
|
|
756
752
|
"esr115": ("/releases/mozilla-esr115",),
|
|
757
|
-
"esr140": ("/releases/mozilla-esr140",),
|
|
758
753
|
"esr153": ("/releases/mozilla-esr153",),
|
|
759
754
|
"esr": (
|
|
760
755
|
"/releases/mozilla-esr115",
|
|
761
|
-
"/releases/mozilla-esr140",
|
|
762
756
|
"/releases/mozilla-esr153",
|
|
763
757
|
),
|
|
764
758
|
"nightly": ("/mozilla-central",),
|
|
@@ -770,7 +764,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
770
764
|
"/releases/mozilla-beta",
|
|
771
765
|
"/releases/mozilla-release",
|
|
772
766
|
"/releases/mozilla-esr115",
|
|
773
|
-
"/releases/mozilla-esr140",
|
|
774
767
|
"/releases/mozilla-esr153",
|
|
775
768
|
# bug 1845368: a permanent project branch for testing updates
|
|
776
769
|
"/projects/pine",
|
|
@@ -783,7 +776,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
783
776
|
"/releases/mozilla-beta",
|
|
784
777
|
"/releases/mozilla-release",
|
|
785
778
|
"/releases/mozilla-esr115",
|
|
786
|
-
"/releases/mozilla-esr140",
|
|
787
779
|
"/releases/mozilla-esr153",
|
|
788
780
|
),
|
|
789
781
|
"all-production-branches-and-autoland": (
|
|
@@ -791,7 +783,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
791
783
|
"/releases/mozilla-beta",
|
|
792
784
|
"/releases/mozilla-release",
|
|
793
785
|
"/releases/mozilla-esr115",
|
|
794
|
-
"/releases/mozilla-esr140",
|
|
795
786
|
"/releases/mozilla-esr153",
|
|
796
787
|
"/integration/autoland",
|
|
797
788
|
),
|
|
@@ -820,7 +811,6 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
820
811
|
"/releases/comm-beta",
|
|
821
812
|
"/releases/comm-release",
|
|
822
813
|
"/releases/comm-esr115",
|
|
823
|
-
"/releases/comm-esr140",
|
|
824
814
|
"/releases/comm-esr153",
|
|
825
815
|
),
|
|
826
816
|
"beta": ("/releases/comm-beta",),
|
|
@@ -828,16 +818,14 @@ DEFAULT_CONFIG: immutabledict[str, Any] = immutabledict(
|
|
|
828
818
|
"release-or-esr": (
|
|
829
819
|
"/releases/comm-release",
|
|
830
820
|
"/releases/comm-esr115",
|
|
831
|
-
"/releases/comm-esr140",
|
|
832
821
|
"/releases/comm-esr153",
|
|
833
822
|
),
|
|
834
|
-
"esr": ("/releases/comm-esr115", "/releases/comm-
|
|
823
|
+
"esr": ("/releases/comm-esr115", "/releases/comm-esr153"),
|
|
835
824
|
"all-nightly-branches": (
|
|
836
825
|
"/comm-central",
|
|
837
826
|
"/releases/comm-beta",
|
|
838
827
|
"/releases/comm-release",
|
|
839
828
|
"/releases/comm-esr115",
|
|
840
|
-
"/releases/comm-esr140",
|
|
841
829
|
"/releases/comm-esr153",
|
|
842
830
|
),
|
|
843
831
|
"nightly": ("/comm-central",),
|
|
@@ -151,12 +151,34 @@ class ChainOfTrust(object):
|
|
|
151
151
|
bool: True if a task is a try task.
|
|
152
152
|
|
|
153
153
|
"""
|
|
154
|
-
tasks = [asyncio.ensure_future(link.is_try_or_pull_request()) for link in self.links]
|
|
155
|
-
tasks.insert(0, asyncio.ensure_future(is_try_or_pull_request(self.context, self.task)))
|
|
154
|
+
tasks = [asyncio.ensure_future(link.is_try_or_pull_request(fallback_ref=self._get_decision_ref(link.decision_task_id))) for link in self.links]
|
|
155
|
+
tasks.insert(0, asyncio.ensure_future(is_try_or_pull_request(self.context, self.task, fallback_ref=self._get_decision_ref(self.decision_task_id))))
|
|
156
156
|
|
|
157
157
|
conditions = await raise_future_exceptions(tasks)
|
|
158
158
|
return any(conditions)
|
|
159
159
|
|
|
160
|
+
def _get_decision_ref(self, decision_task_id):
|
|
161
|
+
"""Get the ref (branch or tag) of a decision task in the chain.
|
|
162
|
+
|
|
163
|
+
Some tasks, like docker-image or scriptworker ones, don't define their
|
|
164
|
+
own ref. Their decision task does, and it's the push the task comes from.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
decision_task_id (str): the task id of the decision task.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
str: the ref, or None if the decision task isn't in the chain or doesn't define one.
|
|
171
|
+
|
|
172
|
+
"""
|
|
173
|
+
if decision_task_id == self.task_id:
|
|
174
|
+
task = self.task
|
|
175
|
+
else:
|
|
176
|
+
try:
|
|
177
|
+
task = self.get_link(decision_task_id).task
|
|
178
|
+
except CoTError:
|
|
179
|
+
return None
|
|
180
|
+
return get_branch(task, self.context.config["source_env_prefix"])
|
|
181
|
+
|
|
160
182
|
def get_link(self, task_id):
|
|
161
183
|
"""Get a ``LinkOfTrust`` by task id.
|
|
162
184
|
|
|
@@ -293,9 +315,18 @@ class LinkOfTrust(object):
|
|
|
293
315
|
self.parent_task_id = get_parent_task_id(self.task)
|
|
294
316
|
self.worker_impl = guess_worker_impl(self)
|
|
295
317
|
|
|
296
|
-
async def is_try_or_pull_request(self):
|
|
297
|
-
"""
|
|
298
|
-
|
|
318
|
+
async def is_try_or_pull_request(self, fallback_ref=None):
|
|
319
|
+
"""Determine if the task is either a try or a pull request one.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
fallback_ref (str, optional): the ref to check commits against if the
|
|
323
|
+
task doesn't define one. See ``scriptworker.task.is_pull_request``.
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
bool: True if the task is either a try or a pull request one.
|
|
327
|
+
|
|
328
|
+
"""
|
|
329
|
+
return await is_try_or_pull_request(self.context, self.task, fallback_ref=fallback_ref)
|
|
299
330
|
|
|
300
331
|
@property
|
|
301
332
|
def cot(self):
|
|
@@ -1031,7 +1062,16 @@ async def get_pushlog_info(decision_link):
|
|
|
1031
1062
|
|
|
1032
1063
|
|
|
1033
1064
|
# get_scm_level {{{1
|
|
1034
|
-
|
|
1065
|
+
def _branch_matches(pattern, branch):
|
|
1066
|
+
"""Whether ``branch`` matches a ``projects.yml`` branch name, which may end in ``*``."""
|
|
1067
|
+
if pattern == "*":
|
|
1068
|
+
return True
|
|
1069
|
+
if pattern.endswith("*"):
|
|
1070
|
+
return branch.startswith(pattern[:-1])
|
|
1071
|
+
return branch == pattern
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
async def get_scm_level(context, project, branch=None):
|
|
1035
1075
|
"""Get the scm level for a project from ``projects.yml``.
|
|
1036
1076
|
|
|
1037
1077
|
We define all known projects in ``projects.yml``. Let's make sure we have
|
|
@@ -1043,6 +1083,8 @@ async def get_scm_level(context, project):
|
|
|
1043
1083
|
Args:
|
|
1044
1084
|
context (scriptworker.context.Context): the scriptworker context
|
|
1045
1085
|
project (str): the project to get the scm level for.
|
|
1086
|
+
branch (str, optional): the branch the task runs on. Required for git
|
|
1087
|
+
projects, where each branch has its own level. Ignored for hg.
|
|
1046
1088
|
|
|
1047
1089
|
Returns:
|
|
1048
1090
|
str: the level of the project, as a string.
|
|
@@ -1053,14 +1095,16 @@ async def get_scm_level(context, project):
|
|
|
1053
1095
|
if config["repo_type"] == "hg":
|
|
1054
1096
|
return config["access"].replace("scm_level_", "")
|
|
1055
1097
|
elif config["repo_type"] == "git":
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1098
|
+
if branch is None:
|
|
1099
|
+
raise ValueError("{} is a git project, so a branch is required to find its level".format(project))
|
|
1100
|
+
if branch.startswith("refs/heads/"):
|
|
1101
|
+
branch = branch[len("refs/heads/") :]
|
|
1102
|
+
# the first matching entry wins, like fxci-config's Project.get_branch()
|
|
1103
|
+
for branch_config in config["branches"]:
|
|
1104
|
+
if _branch_matches(branch_config["name"], branch):
|
|
1105
|
+
return str(branch_config["level"])
|
|
1062
1106
|
|
|
1063
|
-
raise ValueError("Can't find level for project {}".format(project))
|
|
1107
|
+
raise ValueError("Can't find level for project {} on branch {}".format(project, branch))
|
|
1064
1108
|
|
|
1065
1109
|
|
|
1066
1110
|
async def _get_additional_hg_action_jsone_context(parent_link, decision_link):
|
|
@@ -1190,7 +1234,7 @@ async def _get_additional_git_cron_jsone_context(decision_link):
|
|
|
1190
1234
|
"sender": {"login": user},
|
|
1191
1235
|
},
|
|
1192
1236
|
# Taskgraph cron contexts mirror hg-push contexts
|
|
1193
|
-
"repository": {"url": repo, "project": repo_name, "level": await get_scm_level(decision_link.context, repo_name), "type": "git"},
|
|
1237
|
+
"repository": {"url": repo, "project": repo_name, "level": await get_scm_level(decision_link.context, repo_name, branch), "type": "git"},
|
|
1194
1238
|
"push": {"revision": revision, "branch": branch},
|
|
1195
1239
|
}
|
|
1196
1240
|
|
|
@@ -8,14 +8,15 @@ from pathlib import Path
|
|
|
8
8
|
from urllib.parse import unquote, urlparse
|
|
9
9
|
|
|
10
10
|
from github3 import GitHub
|
|
11
|
-
from github3.exceptions import GitHubException
|
|
11
|
+
from github3.exceptions import GitHubException, NotFoundError
|
|
12
12
|
from taskcluster.aio import Auth
|
|
13
13
|
from taskcluster.exceptions import TaskclusterFailure
|
|
14
14
|
|
|
15
15
|
from scriptworker.exceptions import ConfigError
|
|
16
|
-
from scriptworker.utils import get_parts_of_url_path, get_single_item_from_sequence, retry_async_decorator,
|
|
16
|
+
from scriptworker.utils import get_parts_of_url_path, get_single_item_from_sequence, retry_async_decorator, retry_sync
|
|
17
17
|
|
|
18
18
|
_GIT_FULL_HASH_PATTERN = re.compile(r"^[0-9a-f]{40}$")
|
|
19
|
+
_GIT_HASH_LIKE_PATTERN = re.compile(r"^[0-9a-f]{7,40}$")
|
|
19
20
|
# The github3 library already retries requests. It gives a round of waiting of usually 15 seconds.
|
|
20
21
|
# A delay factor of 7.5s means the second round of waiting will occur ~15s after the first one,
|
|
21
22
|
# the third one ~30s and so on.
|
|
@@ -196,64 +197,92 @@ class GitHubRepository:
|
|
|
196
197
|
|
|
197
198
|
return tag_object.commit.sha
|
|
198
199
|
|
|
199
|
-
async def has_commit_landed_on_repository(self, context, revision):
|
|
200
|
-
"""Tell if a commit was landed on the repository or if it just comes from a pull request.
|
|
200
|
+
async def has_commit_landed_on_repository(self, context, revision, ref):
|
|
201
|
+
"""Tell if a commit was landed on the repository or if it just comes from a fork or a pull request.
|
|
202
|
+
|
|
203
|
+
GitHub serves commits from forks through the upstream repository, so the
|
|
204
|
+
commit merely existing isn't enough: it must be reachable from a ref of
|
|
205
|
+
this repository.
|
|
201
206
|
|
|
202
207
|
Args:
|
|
203
208
|
context (scriptworker.context.Context): the scriptworker context.
|
|
204
209
|
revision (str): the commit hash or the tag name.
|
|
210
|
+
ref (str): the branch or tag of this repository that ``revision`` is
|
|
211
|
+
expected to be on, e.g. ``refs/heads/main``. Ignored if ``revision``
|
|
212
|
+
is a tag name.
|
|
205
213
|
|
|
206
214
|
Returns:
|
|
207
|
-
bool: True if the commit is
|
|
215
|
+
bool: True if the commit is reachable from ``ref`` in this repository
|
|
208
216
|
|
|
209
217
|
"""
|
|
210
218
|
if any(vcs_rule.get("require_secret") for vcs_rule in context.config["trusted_vcs_rules"]):
|
|
211
|
-
# This check
|
|
212
|
-
# check for private repos, assume its true in the private case.
|
|
219
|
+
# XXX This check isn't implemented for private repositories, assume it's true.
|
|
213
220
|
log.info("has_commit_landed_on_repository() not implemented for private repositories, assume True")
|
|
214
221
|
return True
|
|
215
222
|
|
|
216
|
-
# Revision may be a tag name. `branch_commits` doesn't work on tags
|
|
217
223
|
if not _is_git_full_hash(revision):
|
|
218
|
-
|
|
224
|
+
# The tag is looked up in this repository, so the commit it points to
|
|
225
|
+
# is reachable from one of its refs. This raises if there's no such tag.
|
|
226
|
+
await self.get_tag_hash(tag_name=revision)
|
|
227
|
+
return True
|
|
219
228
|
|
|
220
|
-
|
|
221
|
-
|
|
229
|
+
qualified_ref = _qualify_ref(ref)
|
|
230
|
+
if qualified_ref is None:
|
|
231
|
+
log.warning(f"Cannot tell if {revision} landed on {self._owner}/{self._repo_name}: no usable ref (got {ref!r})")
|
|
232
|
+
return False
|
|
233
|
+
|
|
234
|
+
status = await _fetch_github_compare_status(self, qualified_ref, revision)
|
|
235
|
+
# "behind" and "identical" mean that `revision` is an ancestor of, or equal to, `ref`.
|
|
236
|
+
# "ahead" and "diverged" mean that `revision` isn't reachable from `ref`.
|
|
237
|
+
landed = status in ("behind", "identical")
|
|
238
|
+
if not landed:
|
|
239
|
+
log.warning(f"{revision} is not on {ref} of {self._owner}/{self._repo_name} (comparison status: {status})")
|
|
240
|
+
return landed
|
|
241
|
+
|
|
242
|
+
@retry_async_decorator(retry_exceptions=GitHubException)
|
|
243
|
+
async def get_compare_status(self, base, head):
|
|
244
|
+
"""Compare two commitishes of the repository.
|
|
222
245
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
246
|
+
Args:
|
|
247
|
+
base (str): the base ref or commit
|
|
248
|
+
head (str): the head ref or commit
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
str: the status of ``head`` relative to ``base``: one of "ahead", "behind",
|
|
252
|
+
"diverged" or "identical", or None if either side doesn't exist
|
|
227
253
|
|
|
254
|
+
"""
|
|
255
|
+
repository = await self._get_repository()
|
|
256
|
+
try:
|
|
257
|
+
return repository.compare_commits(base, head).status
|
|
258
|
+
except NotFoundError:
|
|
259
|
+
return None
|
|
228
260
|
|
|
229
|
-
_BRANCH_COMMITS_CACHE_TTL_IN_SECONDS = 10 * 60 # 10 minutes
|
|
230
|
-
_BRANCH_COMMITS_CACHE = {}
|
|
231
261
|
|
|
262
|
+
_COMPARE_CACHE_TTL_IN_SECONDS = 10 * 60 # 10 minutes
|
|
263
|
+
_COMPARE_CACHE = {}
|
|
232
264
|
|
|
233
|
-
async def _fetch_github_branch_commits_data(context, repo_html_url, revision):
|
|
234
|
-
# Include context identity because different contexts carry
|
|
235
|
-
# different HTTP sessions that may be closed independently.
|
|
236
|
-
cache_key = (id(context), repo_html_url, revision)
|
|
237
265
|
|
|
238
|
-
|
|
239
|
-
|
|
266
|
+
async def _fetch_github_compare_status(github_repository, base, head):
|
|
267
|
+
cache_key = (github_repository._owner, github_repository._repo_name, base, head)
|
|
268
|
+
|
|
269
|
+
if cache_key in _COMPARE_CACHE:
|
|
270
|
+
return await _COMPARE_CACHE[cache_key]
|
|
240
271
|
|
|
241
272
|
future = asyncio.get_running_loop().create_future()
|
|
242
|
-
|
|
273
|
+
_COMPARE_CACHE[cache_key] = future
|
|
243
274
|
|
|
244
275
|
try:
|
|
245
|
-
|
|
246
|
-
html_text = await retry_request(context, url)
|
|
247
|
-
result = html_text.strip()
|
|
276
|
+
result = await github_repository.get_compare_status(base, head)
|
|
248
277
|
future.set_result(result)
|
|
249
278
|
asyncio.get_running_loop().call_later(
|
|
250
|
-
|
|
251
|
-
|
|
279
|
+
_COMPARE_CACHE_TTL_IN_SECONDS,
|
|
280
|
+
_COMPARE_CACHE.pop,
|
|
252
281
|
cache_key,
|
|
253
282
|
None,
|
|
254
283
|
)
|
|
255
284
|
except BaseException as e:
|
|
256
|
-
|
|
285
|
+
_COMPARE_CACHE.pop(cache_key, None)
|
|
257
286
|
future.set_exception(e)
|
|
258
287
|
raise
|
|
259
288
|
|
|
@@ -400,6 +429,37 @@ def _is_git_full_hash(revision):
|
|
|
400
429
|
return _GIT_FULL_HASH_PATTERN.match(revision) is not None
|
|
401
430
|
|
|
402
431
|
|
|
432
|
+
def _qualify_ref(ref):
|
|
433
|
+
"""Turn ``ref`` into a branch or tag ref that can prove a commit is in the repository.
|
|
434
|
+
|
|
435
|
+
Only branches and tags count: GitHub also exposes refs like ``refs/pull/123/head``
|
|
436
|
+
for pull requests, including ones from forks. GitHub resolves short names
|
|
437
|
+
loosely (``pull/123/head`` matches that pull request ref), so bare names are
|
|
438
|
+
qualified as branches, e.g. ``main`` becomes ``refs/heads/main``.
|
|
439
|
+
|
|
440
|
+
A commit is trivially reachable from itself, so (possibly abbreviated) hashes
|
|
441
|
+
prove nothing. ``owner:ref`` would make GitHub look up the ref in another
|
|
442
|
+
repository of the network, like a fork.
|
|
443
|
+
|
|
444
|
+
Args:
|
|
445
|
+
ref (str): the ref, e.g. ``refs/heads/main``, ``refs/tags/v1.0.0`` or ``main``
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
str: the fully qualified ref, or None if ``ref`` can't be used.
|
|
449
|
+
|
|
450
|
+
"""
|
|
451
|
+
if not ref or not isinstance(ref, str) or ":" in ref or ".." in ref:
|
|
452
|
+
return None
|
|
453
|
+
if ref.startswith("refs/"):
|
|
454
|
+
prefix, _, name = ref.partition("/")[2].partition("/")
|
|
455
|
+
if prefix in ("heads", "tags") and name:
|
|
456
|
+
return ref
|
|
457
|
+
return None
|
|
458
|
+
if _GIT_HASH_LIKE_PATTERN.match(ref):
|
|
459
|
+
return None
|
|
460
|
+
return f"refs/heads/{ref}"
|
|
461
|
+
|
|
462
|
+
|
|
403
463
|
def _check_github_url_is_supported(url):
|
|
404
464
|
if not is_github_url(url):
|
|
405
465
|
raise ValueError('"{}" is not a supported GitHub URL!'.format(url))
|
|
@@ -505,7 +505,7 @@ def is_try(task, source_env_prefix):
|
|
|
505
505
|
)
|
|
506
506
|
|
|
507
507
|
|
|
508
|
-
async def is_pull_request(context, task):
|
|
508
|
+
async def is_pull_request(context, task, fallback_ref=None):
|
|
509
509
|
"""Determine if a task is a pull-request-like task (restricted privs).
|
|
510
510
|
|
|
511
511
|
This goes further than checking ``tasks_for``. We may or may not want
|
|
@@ -516,11 +516,15 @@ async def is_pull_request(context, task):
|
|
|
516
516
|
* ``task.extra.env.tasks_for`` is "github-pull-request" or "github-pull-request-untrusted"
|
|
517
517
|
* ``task.payload.env.MOBILE_HEAD_REPOSITORY`` doesn't come from an official repo
|
|
518
518
|
* ``task.metadata.source`` doesn't come from an official repo, either
|
|
519
|
-
* The last 2 items are landed on the official repo
|
|
519
|
+
* The last 2 items are landed on the official repo, i.e. reachable from the
|
|
520
|
+
task's ref (``*_HEAD_REF``/``*_HEAD_BRANCH``), or from ``fallback_ref``
|
|
521
|
+
when the task doesn't define one
|
|
520
522
|
|
|
521
523
|
Args:
|
|
522
524
|
context (scriptworker.context.Context): the scriptworker context.
|
|
523
525
|
task (dict): the task definition to check.
|
|
526
|
+
fallback_ref (str, optional): the ref to check commits against when the task
|
|
527
|
+
doesn't define one, typically the one of the task's decision task.
|
|
524
528
|
|
|
525
529
|
Returns:
|
|
526
530
|
bool: True if it's a pull-request. False if it either comes from the official repos or if
|
|
@@ -531,6 +535,7 @@ async def is_pull_request(context, task):
|
|
|
531
535
|
tasks_for = task.get("extra", {}).get("tasks_for")
|
|
532
536
|
repo_url_from_payload = get_repo(task, context.config["source_env_prefix"])
|
|
533
537
|
revision_from_payload = get_revision(task, context.config["source_env_prefix"])
|
|
538
|
+
ref = get_branch(task, context.config["source_env_prefix"]) or fallback_ref
|
|
534
539
|
|
|
535
540
|
metadata_source_url = task["metadata"].get("source", "")
|
|
536
541
|
repo_from_source_url, revision_from_source_url = extract_github_repo_and_revision_from_source_url(metadata_source_url)
|
|
@@ -551,12 +556,12 @@ async def is_pull_request(context, task):
|
|
|
551
556
|
continue
|
|
552
557
|
|
|
553
558
|
github_repository = GitHubRepository(context, repo_owner, repo_name)
|
|
554
|
-
conditions.append(not await github_repository.has_commit_landed_on_repository(context, revision))
|
|
559
|
+
conditions.append(not await github_repository.has_commit_landed_on_repository(context, revision, ref))
|
|
555
560
|
|
|
556
561
|
return any(conditions)
|
|
557
562
|
|
|
558
563
|
|
|
559
|
-
async def is_try_or_pull_request(context, task):
|
|
564
|
+
async def is_try_or_pull_request(context, task, fallback_ref=None):
|
|
560
565
|
"""Determine if a task is a try or a pull-request-like task (restricted privs).
|
|
561
566
|
|
|
562
567
|
Checks are the ones done in ``is_try`` and ``is_pull_request``
|
|
@@ -564,13 +569,14 @@ async def is_try_or_pull_request(context, task):
|
|
|
564
569
|
Args:
|
|
565
570
|
context (scriptworker.context.Context): the scriptworker context.
|
|
566
571
|
task (dict): the task definition to check.
|
|
572
|
+
fallback_ref (str, optional): passed to ``is_pull_request``.
|
|
567
573
|
|
|
568
574
|
Returns:
|
|
569
575
|
bool: True if it's a pull-request or a try task
|
|
570
576
|
|
|
571
577
|
"""
|
|
572
578
|
if is_github_task(task):
|
|
573
|
-
return await is_pull_request(context, task)
|
|
579
|
+
return await is_pull_request(context, task, fallback_ref=fallback_ref)
|
|
574
580
|
else:
|
|
575
581
|
return is_try(task, context.config["source_env_prefix"])
|
|
576
582
|
|
|
@@ -44,6 +44,8 @@ log = logging.getLogger(__name__)
|
|
|
44
44
|
def scriptworker_session(*args, **kwargs):
|
|
45
45
|
"""Return an ``aiohttp.ClientSession`` with the scriptworker User-Agent header set."""
|
|
46
46
|
kwargs.setdefault("headers", {}).setdefault("User-Agent", f"scriptworker {scriptworker.__version__}")
|
|
47
|
+
kwargs.setdefault("max_line_size", 8190 * 2)
|
|
48
|
+
kwargs.setdefault("max_field_size", 8190 * 2)
|
|
47
49
|
return aiohttp.ClientSession(*args, **kwargs)
|
|
48
50
|
|
|
49
51
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/data/scriptworker_task_schema.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|