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.
Files changed (30) hide show
  1. {scriptworker-63.6.1 → scriptworker-64.0.0}/HISTORY.rst +29 -0
  2. {scriptworker-63.6.1 → scriptworker-64.0.0}/PKG-INFO +1 -1
  3. {scriptworker-63.6.1 → scriptworker-64.0.0}/pyproject.toml +1 -1
  4. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/constants.py +1 -13
  5. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/cot/verify.py +58 -14
  6. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/github.py +90 -30
  7. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/task.py +11 -5
  8. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/utils.py +2 -0
  9. {scriptworker-63.6.1 → scriptworker-64.0.0}/.gitignore +0 -0
  10. {scriptworker-63.6.1 → scriptworker-64.0.0}/CONTRIBUTING.rst +0 -0
  11. {scriptworker-63.6.1 → scriptworker-64.0.0}/LICENSE +0 -0
  12. {scriptworker-63.6.1 → scriptworker-64.0.0}/README.rst +0 -0
  13. {scriptworker-63.6.1 → scriptworker-64.0.0}/renovate.json +0 -0
  14. {scriptworker-63.6.1 → scriptworker-64.0.0}/scripts/gen_ed25519_key.py +0 -0
  15. {scriptworker-63.6.1 → scriptworker-64.0.0}/scriptworker.yaml.tmpl +0 -0
  16. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/__init__.py +0 -0
  17. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/artifacts.py +0 -0
  18. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/client.py +0 -0
  19. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/config.py +0 -0
  20. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/context.py +0 -0
  21. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/cot/__init__.py +0 -0
  22. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/cot/generate.py +0 -0
  23. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/data/cot_v1_schema.json +0 -0
  24. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/data/scriptworker_task_schema.json +0 -0
  25. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/ed25519.py +0 -0
  26. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/exceptions.py +0 -0
  27. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/log.py +0 -0
  28. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/task_process.py +0 -0
  29. {scriptworker-63.6.1 → scriptworker-64.0.0}/src/scriptworker/worker.py +0 -0
  30. {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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: scriptworker
3
- Version: 63.6.1
3
+ Version: 64.0.0
4
4
  Summary: Taskcluster scriptworker
5
5
  Author-email: Mozilla Release Engineering <releng@mozilla.com>
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "scriptworker"
3
- version = "63.6.1"
3
+ version = "64.0.0"
4
4
  description = "Taskcluster scriptworker"
5
5
  authors = [
6
6
  { name = "Mozilla Release Engineering", email = "releng@mozilla.com" },
@@ -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-esr140", "/releases/comm-esr153"),
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
- """bool: the task is either a try or a pull request one."""
298
- return await is_try_or_pull_request(self.context, self.task)
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
- async def get_scm_level(context, project):
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
- # TODO: we should be using the branch that the task is actually
1057
- # being run on
1058
- default_branch = config.get("default_branch", "main")
1059
- for branch in config["branches"]:
1060
- if branch["name"] == default_branch:
1061
- return str(branch["level"])
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, retry_request, retry_sync
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 present in one of the branches of the main repository
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 uses unofficial API on github, which we can't easily
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
- revision = await self.get_tag_hash(tag_name=revision)
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
- repository = await self._get_repository()
221
- html_text = await _fetch_github_branch_commits_data(context, repository.html_url, revision)
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
- # https://github.com/{repo_owner}/{repo_name}/branch_commits/{revision} just returns some \n
224
- # when the commit hasn't landed on the origin repo. Otherwise, some HTML data is returned - it
225
- # represents the branches on which the given revision is present.
226
- return html_text != ""
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
- if cache_key in _BRANCH_COMMITS_CACHE:
239
- return await _BRANCH_COMMITS_CACHE[cache_key]
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
- _BRANCH_COMMITS_CACHE[cache_key] = future
273
+ _COMPARE_CACHE[cache_key] = future
243
274
 
244
275
  try:
245
- url = "/".join((repo_html_url.rstrip("/"), "branch_commits", revision))
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
- _BRANCH_COMMITS_CACHE_TTL_IN_SECONDS,
251
- _BRANCH_COMMITS_CACHE.pop,
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
- _BRANCH_COMMITS_CACHE.pop(cache_key, None)
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