taskcluster-taskgraph 5.4.0__tar.gz → 5.6.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 (133) hide show
  1. {taskcluster-taskgraph-5.4.0/src/taskcluster_taskgraph.egg-info → taskcluster-taskgraph-5.6.0}/PKG-INFO +1 -1
  2. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0/src/taskcluster_taskgraph.egg-info}/PKG-INFO +1 -1
  3. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/__init__.py +1 -1
  4. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/config.py +5 -0
  5. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/run-task/robustcheckout.py +15 -2
  6. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/run-task/run-task +5 -8
  7. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/job/common.py +0 -25
  8. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/task.py +20 -1
  9. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/dependencies.py +5 -0
  10. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/vcs.py +10 -3
  11. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_from_deps.py +43 -0
  12. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_task.py +74 -0
  13. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_vcs.py +25 -1
  14. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/LICENSE +0 -0
  15. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/MANIFEST.in +0 -0
  16. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/README.rst +0 -0
  17. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/pyproject.toml +0 -0
  18. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/requirements/base.in +0 -0
  19. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/requirements/base.txt +0 -0
  20. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/requirements/dev.in +0 -0
  21. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/requirements/dev.txt +0 -0
  22. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/requirements/test.in +0 -0
  23. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/requirements/test.txt +0 -0
  24. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/setup.cfg +0 -0
  25. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/setup.py +0 -0
  26. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskcluster_taskgraph.egg-info/SOURCES.txt +0 -0
  27. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskcluster_taskgraph.egg-info/dependency_links.txt +0 -0
  28. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskcluster_taskgraph.egg-info/entry_points.txt +0 -0
  29. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskcluster_taskgraph.egg-info/requires.txt +1 -1
  30. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskcluster_taskgraph.egg-info/top_level.txt +0 -0
  31. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/__init__.py +0 -0
  32. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/add_new_jobs.py +0 -0
  33. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/cancel.py +0 -0
  34. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/cancel_all.py +0 -0
  35. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/rebuild_cached_tasks.py +0 -0
  36. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/registry.py +0 -0
  37. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/retrigger.py +0 -0
  38. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/actions/util.py +0 -0
  39. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/create.py +0 -0
  40. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/decision.py +0 -0
  41. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/docker.py +0 -0
  42. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/files_changed.py +0 -0
  43. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/filter_tasks.py +0 -0
  44. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/generator.py +0 -0
  45. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/graph.py +0 -0
  46. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/loader/__init__.py +0 -0
  47. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/loader/default.py +0 -0
  48. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/loader/transform.py +0 -0
  49. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/main.py +0 -0
  50. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/morph.py +0 -0
  51. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/optimize/__init__.py +0 -0
  52. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/optimize/base.py +0 -0
  53. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/optimize/strategies.py +0 -0
  54. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/parameters.py +0 -0
  55. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/run-task/fetch-content +0 -0
  56. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/run-task/hgrc +0 -0
  57. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/target_tasks.py +0 -0
  58. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/task.py +0 -0
  59. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/taskgraph.py +0 -0
  60. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/__init__.py +0 -0
  61. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/base.py +0 -0
  62. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/cached_tasks.py +0 -0
  63. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/code_review.py +0 -0
  64. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/docker_image.py +0 -0
  65. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/fetch.py +0 -0
  66. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/from_deps.py +0 -0
  67. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/job/__init__.py +0 -0
  68. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/job/index_search.py +0 -0
  69. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/job/run_task.py +0 -0
  70. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/job/toolchain.py +0 -0
  71. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/transforms/notify.py +0 -0
  72. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/__init__.py +0 -0
  73. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/archive.py +0 -0
  74. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/attributes.py +0 -0
  75. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/cached_tasks.py +0 -0
  76. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/decision.py +0 -0
  77. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/docker.py +0 -0
  78. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/hash.py +0 -0
  79. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/keyed_by.py +0 -0
  80. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/memoize.py +0 -0
  81. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/parameterization.py +0 -0
  82. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/path.py +0 -0
  83. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/python_path.py +0 -0
  84. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/readonlydict.py +0 -0
  85. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/schema.py +0 -0
  86. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/shell.py +0 -0
  87. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/taskcluster.py +0 -0
  88. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/taskgraph.py +0 -0
  89. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/templates.py +0 -0
  90. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/time.py +0 -0
  91. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/treeherder.py +0 -0
  92. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/verify.py +0 -0
  93. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/workertypes.py +0 -0
  94. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/src/taskgraph/util/yaml.py +0 -0
  95. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_actions_rebuild_cached_tasks.py +0 -0
  96. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_actions_registry.py +0 -0
  97. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_create.py +0 -0
  98. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_decision.py +0 -0
  99. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_files_changed.py +0 -0
  100. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_generator.py +0 -0
  101. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_graph.py +0 -0
  102. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_main.py +0 -0
  103. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_morph.py +0 -0
  104. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_optimize.py +0 -0
  105. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_optimize_strategies.py +0 -0
  106. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_parameters.py +0 -0
  107. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_scripts_fetch_content.py +0 -0
  108. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_scripts_run_task.py +0 -0
  109. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_target_tasks.py +0 -0
  110. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_taskgraph.py +0 -0
  111. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transform_docker_image.py +0 -0
  112. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_base.py +0 -0
  113. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_fetch.py +0 -0
  114. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_job.py +0 -0
  115. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_job_run_task.py +0 -0
  116. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_job_toolchain.py +0 -0
  117. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_transforms_notify.py +0 -0
  118. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_attributes.py +0 -0
  119. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_dependencies.py +0 -0
  120. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_docker.py +0 -0
  121. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_memoize.py +0 -0
  122. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_parameterization.py +0 -0
  123. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_path.py +0 -0
  124. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_python_path.py +0 -0
  125. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_readonlydict.py +0 -0
  126. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_schema.py +0 -0
  127. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_taskcluster.py +0 -0
  128. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_templates.py +0 -0
  129. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_time.py +0 -0
  130. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_treeherder.py +0 -0
  131. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_verify.py +0 -0
  132. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_workertypes.py +0 -0
  133. {taskcluster-taskgraph-5.4.0 → taskcluster-taskgraph-5.6.0}/test/test_util_yaml.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: taskcluster-taskgraph
3
- Version: 5.4.0
3
+ Version: 5.6.0
4
4
  Summary: Build taskcluster taskgraphs
5
5
  Home-page: https://github.com/taskcluster/taskgraph
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: taskcluster-taskgraph
3
- Version: 5.4.0
3
+ Version: 5.6.0
4
4
  Summary: Build taskcluster taskgraphs
5
5
  Home-page: https://github.com/taskcluster/taskgraph
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -2,7 +2,7 @@
2
2
  # License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
4
 
5
- __version__ = "5.4.0"
5
+ __version__ = "5.6.0"
6
6
 
7
7
  # Maximum number of dependencies a single task can have
8
8
  # https://docs.taskcluster.net/reference/platform/taskcluster-queue/references/api#createTask
@@ -35,6 +35,11 @@ graph_config_schema = Schema(
35
35
  "lowest",
36
36
  ),
37
37
  ),
38
+ Optional(
39
+ "task-deadline-after",
40
+ description="Default 'deadline' for tasks, in relative date format. "
41
+ "Eg: '1 week'",
42
+ ): optionally_keyed_by("project", str),
38
43
  Required("workers"): {
39
44
  Required("aliases"): {
40
45
  str: {
@@ -41,7 +41,9 @@ from mercurial import (
41
41
  # Causes worker to purge caches on process exit and for task to retry.
42
42
  EXIT_PURGE_CACHE = 72
43
43
 
44
- testedwith = b"4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9"
44
+ testedwith = (
45
+ b"4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4"
46
+ )
45
47
  minimumhgversion = b"4.5"
46
48
 
47
49
  cmdtable = {}
@@ -496,6 +498,10 @@ def _docheckout(
496
498
  ui.warn(b"ssl error: %s\n" % pycompat.bytestr(str(e)))
497
499
  handlenetworkfailure()
498
500
  return True
501
+ elif isinstance(e, urllibcompat.urlerr.httperror) and e.code >= 500:
502
+ ui.warn(b"http error: %s\n" % pycompat.bytestr(str(e.reason)))
503
+ handlenetworkfailure()
504
+ return True
499
505
  elif isinstance(e, urllibcompat.urlerr.urlerror):
500
506
  if isinstance(e.reason, socket.error):
501
507
  ui.warn(b"socket error: %s\n" % pycompat.bytestr(str(e.reason)))
@@ -806,7 +812,14 @@ def _docheckout(
806
812
  # one to change the sparse profile and another to update to the new
807
813
  # revision. This is not desired. But there's not a good API in
808
814
  # Mercurial to do this as one operation.
809
- with repo.wlock(), repo.dirstate.parentchange(), timeit(
815
+ # TRACKING hg64 - Mercurial 6.4 and later require call to
816
+ # dirstate.changing_parents(repo)
817
+ def parentchange(repo):
818
+ if util.safehasattr(repo.dirstate, "changing_parents"):
819
+ return repo.dirstate.changing_parents(repo)
820
+ return repo.dirstate.parentchange()
821
+
822
+ with repo.wlock(), parentchange(repo), timeit(
810
823
  "sparse_update_config", "sparse-update-config"
811
824
  ):
812
825
  # pylint --py3k: W1636
@@ -14,20 +14,17 @@ current time to improve log usefulness.
14
14
  """
15
15
 
16
16
  import sys
17
- from typing import Optional
18
17
 
19
18
  if sys.version_info[0:2] < (3, 5):
20
19
  print("run-task requires Python 3.5+")
21
20
  sys.exit(1)
22
21
 
23
-
24
22
  import argparse
25
23
  import datetime
26
24
  import errno
27
25
  import io
28
26
  import json
29
27
  import os
30
- from pathlib import Path
31
28
  import platform
32
29
  import re
33
30
  import shutil
@@ -36,11 +33,11 @@ import socket
36
33
  import stat
37
34
  import subprocess
38
35
  import time
39
-
40
36
  import urllib.error
41
37
  import urllib.request
42
-
38
+ from pathlib import Path
43
39
  from threading import Thread
40
+ from typing import Optional
44
41
 
45
42
  SECRET_BASEURL_TPL = "http://taskcluster/secrets/v1/secret/{}"
46
43
 
@@ -711,6 +708,7 @@ def git_checkout(
711
708
  "git",
712
709
  "submodule",
713
710
  "update",
711
+ "--force", # Overrides any potential local changes
714
712
  ]
715
713
 
716
714
  run_required_command(b"vcs", args, cwd=destination_path)
@@ -926,7 +924,6 @@ def collect_vcs_options(args, project, name):
926
924
 
927
925
 
928
926
  def vcs_checkout_from_args(options):
929
-
930
927
  if not options["checkout"]:
931
928
  if options["ref"] and not options["revision"]:
932
929
  print("task should be defined in terms of non-symbolic revision")
@@ -1072,10 +1069,10 @@ def maybe_run_resource_monitoring():
1072
1069
  monitor_process.start()
1073
1070
  return process
1074
1071
 
1072
+
1075
1073
  def _display_python_version():
1076
1074
  print_line(
1077
- b"setup",
1078
- b"Python version: "+ bytes(platform.python_version(), 'utf-8')
1075
+ b"setup", b"Python version: %s\n" % platform.python_version().encode("utf-8")
1079
1076
  )
1080
1077
 
1081
1078
 
@@ -60,31 +60,6 @@ def add_cache(job, taskdesc, name, mount_point, skip_untrusted=False):
60
60
  pass
61
61
 
62
62
 
63
- def docker_worker_add_workspace_cache(config, job, taskdesc, extra=None):
64
- """Add the workspace cache.
65
-
66
- Args:
67
- config (TransformConfig): Transform configuration object.
68
- job (dict): Task's job description.
69
- taskdesc (dict): Target task description to modify.
70
- extra (str): Optional context passed in that supports extending the cache
71
- key name to avoid undesired conflicts with other caches.
72
- """
73
- cache_name = "{}-build-{}-{}-workspace".format(
74
- config.params["project"],
75
- taskdesc["attributes"]["build_platform"],
76
- taskdesc["attributes"]["build_type"],
77
- )
78
- if extra:
79
- cache_name = f"{cache_name}-{extra}"
80
-
81
- mount_point = "{workdir}/workspace".format(**job["run"])
82
-
83
- # Don't enable the workspace cache when we can't guarantee its
84
- # behavior, like on Try.
85
- add_cache(job, taskdesc, cache_name, mount_point, skip_untrusted=True)
86
-
87
-
88
63
  def add_artifacts(config, job, taskdesc, path):
89
64
  taskdesc["worker"].setdefault("artifacts", []).append(
90
65
  {
@@ -221,6 +221,13 @@ def get_default_priority(graph_config, project):
221
221
  )
222
222
 
223
223
 
224
+ @memoize
225
+ def get_default_deadline(graph_config, project):
226
+ return evaluate_keyed_by(
227
+ graph_config["task-deadline-after"], "Graph Config", {"project": project}
228
+ )
229
+
230
+
224
231
  # define a collection of payload builders, depending on the worker implementation
225
232
  payload_builders = {}
226
233
 
@@ -617,6 +624,11 @@ def build_docker_worker_payload(config, task, task_def):
617
624
  Required("env"): {str: taskref_or_string},
618
625
  # the maximum time to run, in seconds
619
626
  Required("max-run-time"): int,
627
+ # the exit status code(s) that indicates the task should be retried
628
+ Optional("retry-exit-status"): [int],
629
+ # the exit status code(s) that indicates the caches used by the task
630
+ # should be purged
631
+ Optional("purge-caches-exit-status"): [int],
620
632
  # os user groups for test task workers
621
633
  Optional("os-groups"): [str],
622
634
  # feature for test task to run as administarotr
@@ -639,6 +651,8 @@ def build_generic_worker_payload(config, task, task_def):
639
651
  on_exit_status = {}
640
652
  if "retry-exit-status" in worker:
641
653
  on_exit_status["retry"] = worker["retry-exit-status"]
654
+ if "purge-caches-exit-status" in worker:
655
+ on_exit_status["purgeCaches"] = worker["purge-caches-exit-status"]
642
656
  if worker["os"] == "windows":
643
657
  on_exit_status.setdefault("retry", []).extend(
644
658
  [
@@ -1062,7 +1076,12 @@ def build_task(config, tasks):
1062
1076
  task["expires-after"] = "28 days" if config.params.is_try() else "1 year"
1063
1077
 
1064
1078
  if "deadline-after" not in task:
1065
- task["deadline-after"] = "1 day"
1079
+ if "task-deadline-after" in config.graph_config:
1080
+ task["deadline-after"] = get_default_deadline(
1081
+ config.graph_config, config.params["project"]
1082
+ )
1083
+ else:
1084
+ task["deadline-after"] = "1 day"
1066
1085
 
1067
1086
  if "priority" not in task:
1068
1087
  task["priority"] = get_default_priority(
@@ -27,6 +27,11 @@ def group_by_single(config, tasks):
27
27
  yield [task]
28
28
 
29
29
 
30
+ @group_by("all")
31
+ def group_by_all(config, tasks):
32
+ return [[task for task in tasks]]
33
+
34
+
30
35
  @group_by("attribute", schema=Schema(str))
31
36
  def group_by_attribute(config, tasks, attr):
32
37
  groups = {}
@@ -166,7 +166,10 @@ class Repository(ABC):
166
166
  @abstractmethod
167
167
  def find_latest_common_revision(self, base_ref_or_rev, head_rev):
168
168
  """Find the latest revision that is common to both the given
169
- ``head_rev`` and ``base_ref_or_rev``"""
169
+ ``head_rev`` and ``base_ref_or_rev``.
170
+
171
+ If no common revision exists, ``Repository.NULL_REVISION`` will
172
+ be returned."""
170
173
 
171
174
  @abstractmethod
172
175
  def does_revision_exist_locally(self, revision):
@@ -296,13 +299,14 @@ class HgRepository(Repository):
296
299
  return self.run("update", "--check", ref)
297
300
 
298
301
  def find_latest_common_revision(self, base_ref_or_rev, head_rev):
299
- return self.run(
302
+ ancestor = self.run(
300
303
  "log",
301
304
  "-r",
302
305
  f"last(ancestors('{base_ref_or_rev}') and ancestors('{head_rev}'))",
303
306
  "--template",
304
307
  "{node}",
305
308
  ).strip()
309
+ return ancestor or self.NULL_REVISION
306
310
 
307
311
  def does_revision_exist_locally(self, revision):
308
312
  try:
@@ -482,7 +486,10 @@ class GitRepository(Repository):
482
486
  self.run("checkout", ref)
483
487
 
484
488
  def find_latest_common_revision(self, base_ref_or_rev, head_rev):
485
- return self.run("merge-base", base_ref_or_rev, head_rev).strip()
489
+ try:
490
+ return self.run("merge-base", base_ref_or_rev, head_rev).strip()
491
+ except subprocess.CalledProcessError:
492
+ return self.NULL_REVISION
486
493
 
487
494
  def does_revision_exist_locally(self, revision):
488
495
  try:
@@ -74,6 +74,18 @@ def assert_copy_attributes(tasks):
74
74
  }
75
75
 
76
76
 
77
+ def assert_group_by_all(tasks):
78
+ handle_exception(tasks)
79
+ assert len(tasks) == 1
80
+ assert tasks[0]["dependencies"] == {"foo": "a", "bar": "bar-b"}
81
+
82
+
83
+ def assert_group_by_all_dupe_allowed(tasks):
84
+ handle_exception(tasks)
85
+ assert len(tasks) == 1
86
+ assert tasks[0]["dependencies"] == {"a": "a", "b": "b", "c": "c"}
87
+
88
+
77
89
  @pytest.mark.parametrize(
78
90
  "task, kind_config, deps",
79
91
  (
@@ -178,6 +190,37 @@ def assert_copy_attributes(tasks):
178
190
  },
179
191
  id="copy_attributes",
180
192
  ),
193
+ pytest.param(
194
+ # task
195
+ {
196
+ "from-deps": {
197
+ "group-by": "all",
198
+ }
199
+ },
200
+ # kind config
201
+ None,
202
+ # deps
203
+ None,
204
+ id="group_by_all",
205
+ ),
206
+ pytest.param(
207
+ # task
208
+ {
209
+ "from-deps": {
210
+ "unique-kinds": False,
211
+ "group-by": "all",
212
+ }
213
+ },
214
+ # kind config
215
+ None,
216
+ # deps
217
+ {
218
+ "a": make_task("a", kind="foo"),
219
+ "b": make_task("b", kind="foo"),
220
+ "c": make_task("c", kind="foo"),
221
+ },
222
+ id="group_by_all_dupe_allowed",
223
+ ),
181
224
  ),
182
225
  )
183
226
  def test_transforms(
@@ -794,3 +794,77 @@ def test_check_task_dependencies(graph_config, test_task, expectation):
794
794
  assert (
795
795
  len(list(task.check_task_dependencies(transform_config, [test_task]))) == 1
796
796
  )
797
+
798
+
799
+ @pytest.mark.parametrize(
800
+ "deadline_after, test_task",
801
+ (
802
+ (
803
+ None,
804
+ {
805
+ "description": "fake description",
806
+ "name": "fake-task-name",
807
+ "worker-type": "t-linux",
808
+ "worker": {
809
+ "docker-image": "fake-image-name",
810
+ "max-run-time": 1800,
811
+ },
812
+ },
813
+ ),
814
+ (
815
+ "2 weeks",
816
+ {
817
+ "description": "fake description",
818
+ "name": "fake-task-name",
819
+ "worker-type": "t-linux",
820
+ "worker": {
821
+ "docker-image": "fake-image-name",
822
+ "max-run-time": 1800,
823
+ },
824
+ },
825
+ ),
826
+ ),
827
+ )
828
+ def test_default_deadline_after(run_transform, graph_config, deadline_after, test_task):
829
+ if deadline_after:
830
+ graph_config._config["task-deadline-after"] = deadline_after
831
+
832
+ params = FakeParameters(
833
+ {
834
+ "base_repository": "git@github.com://github.com/mozilla/example.git",
835
+ "build_date": 0,
836
+ "build_number": 1,
837
+ "head_repository": "git@github.com://github.com/mozilla/example.git",
838
+ "head_rev": "abcdef",
839
+ "head_ref": "default",
840
+ "level": "1",
841
+ "moz_build_date": 0,
842
+ "next_version": "1.0.1",
843
+ "owner": "some-owner",
844
+ "project": "some-project",
845
+ "pushlog_id": 1,
846
+ "repository_type": "git",
847
+ "target_tasks_method": "test_method",
848
+ "tasks_for": "github-pull-request",
849
+ "try_mode": None,
850
+ "version": "1.0.0",
851
+ },
852
+ )
853
+
854
+ transform_config = TransformConfig(
855
+ "check_deadline",
856
+ str(here),
857
+ {},
858
+ params,
859
+ {},
860
+ graph_config,
861
+ write_artifacts=False,
862
+ )
863
+
864
+ task_dict = deepcopy(test_task)
865
+
866
+ task_dict = run_transform(task.transforms, task_dict, config=transform_config)[0]
867
+ if deadline_after:
868
+ assert task_dict["task"]["deadline"] == {"relative-datestamp": deadline_after}
869
+ else:
870
+ assert task_dict["task"]["deadline"] == {"relative-datestamp": "1 day"}
@@ -421,7 +421,17 @@ def test_find_latest_common_revision(repo_with_remote):
421
421
  repo.find_latest_common_revision(base_ref, repo.head_rev)
422
422
  == expected_latest_common_revision
423
423
  )
424
- else:
424
+
425
+ # Test no common ancestors
426
+ repo.run("checkout", "--orphan", "new_branch")
427
+ repo.run("add", ".")
428
+ repo.run("commit", "-m", "Add another new revision")
429
+ base_ref = f"{remote_name}/{repo.branch}"
430
+ assert (
431
+ repo.find_latest_common_revision(base_ref, repo.head_rev)
432
+ == Repository.NULL_REVISION
433
+ )
434
+ elif repo.tool == "hg":
425
435
  # hg doesn't have the concept of remote branches
426
436
  assert (
427
437
  repo.find_latest_common_revision(
@@ -430,6 +440,20 @@ def test_find_latest_common_revision(repo_with_remote):
430
440
  == expected_latest_common_revision
431
441
  )
432
442
 
443
+ # Test no common ancestors
444
+ repo.run("update", Repository.NULL_REVISION)
445
+ with open(os.path.join(repo.path, "some_file"), "w") as f:
446
+ f.write("some content")
447
+
448
+ repo.run("add", ".")
449
+ repo.run("commit", "-m", "Add another new revision")
450
+ assert (
451
+ repo.find_latest_common_revision(
452
+ repo.head_rev, expected_latest_common_revision
453
+ )
454
+ == Repository.NULL_REVISION
455
+ )
456
+
433
457
 
434
458
  def test_does_revision_exist_locally(repo):
435
459
  first_revision = repo.head_rev
@@ -1,8 +1,8 @@
1
- PyYAML>=5.4
2
1
  appdirs>=1.4
3
2
  cookiecutter~=2.1
4
3
  json-e>=2.7
5
4
  mozilla-repo-urls
5
+ PyYAML>=5.4
6
6
  redo>=2.0
7
7
  requests>=2.25
8
8
  requests_unixsocket>=0.2