taskcluster-taskgraph 20.0.0__tar.gz → 21.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 (269) hide show
  1. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.pre-commit-config.yaml +3 -3
  2. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.taskcluster.yml +8 -1
  3. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/CHANGELOG.md +19 -0
  4. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/PKG-INFO +1 -1
  5. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/bootstrap-taskgraph.rst +1 -1
  6. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/migrations.rst +9 -0
  7. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/pyproject.toml +1 -1
  8. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/decision.py +14 -0
  9. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/main.py +6 -0
  10. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/run-task/run-task +14 -1
  11. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/task.py +4 -19
  12. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/vcs.py +20 -0
  13. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/verify.py +12 -6
  14. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/run-task/Dockerfile +1 -1
  15. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_decision.py +59 -0
  16. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_scripts_run_task.py +46 -0
  17. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_vcs.py +21 -0
  18. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_verify.py +33 -0
  19. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/uv.lock +1 -1
  20. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.codespell-ignore-words.txt +0 -0
  21. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.github/CODEOWNERS +0 -0
  22. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.github/dependabot.yml +0 -0
  23. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.github/workflows/codeql-analysis.yml +0 -0
  24. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.github/workflows/pre-commit-autoupdate.yml +0 -0
  25. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.github/workflows/pre-commit.yml +0 -0
  26. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.github/workflows/pypi-publish.yml +0 -0
  27. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.gitignore +0 -0
  28. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.readthedocs.yaml +0 -0
  29. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/.yamllint +0 -0
  30. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/CODE_OF_CONDUCT.md +0 -0
  31. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/CONTRIBUTING.rst +0 -0
  32. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/LICENSE +0 -0
  33. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/Makefile +0 -0
  34. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/README.rst +0 -0
  35. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/index.rst +0 -0
  36. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/kind.rst +0 -0
  37. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/loading.rst +0 -0
  38. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/optimization.rst +0 -0
  39. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/overview.rst +0 -0
  40. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/scopes.rst +0 -0
  41. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/task-graphs.rst +0 -0
  42. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/concepts/transforms.rst +0 -0
  43. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/conf.py +0 -0
  44. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/contributing.rst +0 -0
  45. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/glossary.rst +0 -0
  46. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/create-actions.rst +0 -0
  47. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/create-tasks.rst +0 -0
  48. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/debugging.rst +0 -0
  49. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/docker.rst +0 -0
  50. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/index.rst +0 -0
  51. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/load-task-locally.rst +0 -0
  52. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/resolve-keyed-by.rst +0 -0
  53. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/run-locally.rst +0 -0
  54. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/send-notifications.rst +0 -0
  55. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/howto/use-fetches.rst +0 -0
  56. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/index.rst +0 -0
  57. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/cli.rst +0 -0
  58. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/index.rst +0 -0
  59. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/optimization-strategies.rst +0 -0
  60. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/parameters.rst +0 -0
  61. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/modules.rst +0 -0
  62. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/taskgraph.actions.rst +0 -0
  63. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/taskgraph.loader.rst +0 -0
  64. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/taskgraph.optimize.rst +0 -0
  65. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/taskgraph.rst +0 -0
  66. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/taskgraph.transforms.rst +0 -0
  67. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/taskgraph.transforms.run.rst +0 -0
  68. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/source/taskgraph.util.rst +0 -0
  69. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/transforms/chunking.rst +0 -0
  70. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/transforms/from_deps.rst +0 -0
  71. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/transforms/index.rst +0 -0
  72. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/transforms/matrix.rst +0 -0
  73. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/reference/transforms/task_context.rst +0 -0
  74. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/tutorials/connecting-taskcluster.rst +0 -0
  75. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/tutorials/creating-a-task-graph.rst +0 -0
  76. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/tutorials/example-taskcluster.yml +0 -0
  77. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/tutorials/getting-started.rst +0 -0
  78. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/docs/tutorials/index.rst +0 -0
  79. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/make.bat +0 -0
  80. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/pytest-taskgraph/README.md +0 -0
  81. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/pytest-taskgraph/pyproject.toml +0 -0
  82. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/pytest-taskgraph/src/pytest_taskgraph/__init__.py +0 -0
  83. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/pytest-taskgraph/src/pytest_taskgraph/fixtures/gen.py +0 -0
  84. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/pytest-taskgraph/src/pytest_taskgraph/fixtures/vcs.py +0 -0
  85. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/sphinx-taskgraph/README.md +0 -0
  86. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/sphinx-taskgraph/pyproject.toml +0 -0
  87. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/sphinx-taskgraph/src/sphinx_taskgraph/__init__.py +0 -0
  88. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/packages/sphinx-taskgraph/src/sphinx_taskgraph/autoschema.py +0 -0
  89. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/__init__.py +0 -0
  90. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/__init__.py +0 -0
  91. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/add_new_jobs.py +0 -0
  92. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/cancel.py +0 -0
  93. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/cancel_all.py +0 -0
  94. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/rebuild_cached_tasks.py +0 -0
  95. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/registry.py +0 -0
  96. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/retrigger.py +0 -0
  97. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/actions/util.py +0 -0
  98. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/config.py +0 -0
  99. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/create.py +0 -0
  100. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/docker.py +0 -0
  101. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/filter_tasks.py +0 -0
  102. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/generator.py +0 -0
  103. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/graph.py +0 -0
  104. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/loader/__init__.py +0 -0
  105. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/loader/default.py +0 -0
  106. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/loader/transform.py +0 -0
  107. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/morph.py +0 -0
  108. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/optimize/__init__.py +0 -0
  109. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/optimize/base.py +0 -0
  110. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/optimize/strategies.py +0 -0
  111. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/parameters.py +0 -0
  112. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/run-task/fetch-content +0 -0
  113. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/run-task/hgrc +0 -0
  114. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/run-task/robustcheckout.py +0 -0
  115. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/target_tasks.py +0 -0
  116. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/task.py +0 -0
  117. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/taskgraph.py +0 -0
  118. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/__init__.py +0 -0
  119. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/base.py +0 -0
  120. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/cached_tasks.py +0 -0
  121. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/chunking.py +0 -0
  122. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/code_review.py +0 -0
  123. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/docker_image.py +0 -0
  124. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/fetch.py +0 -0
  125. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/from_deps.py +0 -0
  126. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/matrix.py +0 -0
  127. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/notify.py +0 -0
  128. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/run/__init__.py +0 -0
  129. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/run/common.py +0 -0
  130. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/run/index_search.py +0 -0
  131. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/run/run_task.py +0 -0
  132. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/run/toolchain.py +0 -0
  133. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/transforms/task_context.py +0 -0
  134. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/__init__.py +0 -0
  135. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/archive.py +0 -0
  136. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/attributes.py +0 -0
  137. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/cached_tasks.py +0 -0
  138. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/caches.py +0 -0
  139. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/copy.py +0 -0
  140. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/dependencies.py +0 -0
  141. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/docker.py +0 -0
  142. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/hash.py +0 -0
  143. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/json.py +0 -0
  144. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/keyed_by.py +0 -0
  145. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/parameterization.py +0 -0
  146. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/path.py +0 -0
  147. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/python_path.py +0 -0
  148. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/readonlydict.py +0 -0
  149. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/schema.py +0 -0
  150. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/set_name.py +0 -0
  151. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/shell.py +0 -0
  152. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/taskcluster.py +0 -0
  153. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/taskgraph.py +0 -0
  154. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/templates.py +0 -0
  155. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/time.py +0 -0
  156. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/treeherder.py +0 -0
  157. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/workertypes.py +0 -0
  158. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/src/taskgraph/util/yaml.py +0 -0
  159. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/config.yml +0 -0
  160. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/REGISTRY +0 -0
  161. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/decision/Dockerfile +0 -0
  162. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/decision/HASH +0 -0
  163. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/decision/README.md +0 -0
  164. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/decision/VERSION +0 -0
  165. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/decision/system-setup.sh +0 -0
  166. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/fetch/Dockerfile +0 -0
  167. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/image_builder/README.rst +0 -0
  168. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/index-task/Dockerfile +0 -0
  169. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/index-task/README +0 -0
  170. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/index-task/insert-indexes.js +0 -0
  171. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/index-task/package.json +0 -0
  172. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/index-task/yarn.lock +0 -0
  173. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/python/Dockerfile +0 -0
  174. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/run-task/system-setup.sh +0 -0
  175. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/skopeo/Dockerfile +0 -0
  176. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/skopeo/policy.json +0 -0
  177. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/docker/skopeo/push_image.sh +0 -0
  178. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/check/kind.yml +0 -0
  179. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/codecov/kind.yml +0 -0
  180. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/complete/kind.yml +0 -0
  181. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/doc/kind.yml +0 -0
  182. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/docker-image/kind.yml +0 -0
  183. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/fetch/kind.yml +0 -0
  184. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/push-image/kind.yml +0 -0
  185. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/test/kind.yml +0 -0
  186. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/test/linux.yml +0 -0
  187. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/kinds/test/windows.yml +0 -0
  188. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/scripts/codecov-upload.py +0 -0
  189. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/scripts/external_tools/tooltool.py +0 -0
  190. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/self_taskgraph/__init__.py +0 -0
  191. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/self_taskgraph/custom_parameters.py +0 -0
  192. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/self_taskgraph/custom_target_tasks.py +0 -0
  193. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/self_taskgraph/transforms/add_pr_route.py +0 -0
  194. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/self_taskgraph/transforms/push_image.py +0 -0
  195. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/test/params/main-repo-pull-request-untrusted.yml +0 -0
  196. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/test/params/main-repo-pull-request.yml +0 -0
  197. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/test/params/main-repo-push.yml +0 -0
  198. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/test/params/main-repo-release-pytest-taskgraph.yml +0 -0
  199. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/taskcluster/test/params/main-repo-release-taskcluster-taskgraph.yml +0 -0
  200. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/cookiecutter.json +0 -0
  201. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/hooks/post_gen_project.py +0 -0
  202. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/{{cookiecutter.project_name}}/taskcluster/config.yml +0 -0
  203. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/{{cookiecutter.project_name}}/taskcluster/docker/linux/Dockerfile +0 -0
  204. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/{{cookiecutter.project_name}}/taskcluster/kinds/docker-image/kind.yml +0 -0
  205. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/{{cookiecutter.project_name}}/taskcluster/kinds/hello/kind.yml +0 -0
  206. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/{{cookiecutter.project_name}}/taskcluster/{{cookiecutter.project_slug}}_taskgraph/transforms/hello.py +0 -0
  207. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/template/{{cookiecutter.project_name}}/taskcluster.github.yml +0 -0
  208. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/__init__.py +0 -0
  209. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/automationrelevance.json +0 -0
  210. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/conftest.py +0 -0
  211. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/task_context.yml +0 -0
  212. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/config.yml +0 -0
  213. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/docker/hello-world/Dockerfile +0 -0
  214. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/docker/hello-world-tag/Dockerfile +0 -0
  215. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/docker/hello-world-tag/REGISTRY +0 -0
  216. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/docker/hello-world-tag/VERSION +0 -0
  217. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/kinds/docker-image/kind.yml +0 -0
  218. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/scripts/toolchain/run.ps1 +0 -0
  219. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/scripts/toolchain/run.sh +0 -0
  220. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/taskcluster/test_taskgraph/transforms/foo.py +0 -0
  221. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/data/testmod/thing.py +0 -0
  222. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/mockedopen.py +0 -0
  223. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_actions_rebuild_cached_tasks.py +0 -0
  224. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_actions_registry.py +0 -0
  225. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_config.py +0 -0
  226. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_create.py +0 -0
  227. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_docker.py +0 -0
  228. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_generator.py +0 -0
  229. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_graph.py +0 -0
  230. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_main.py +0 -0
  231. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_morph.py +0 -0
  232. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_optimize.py +0 -0
  233. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_optimize_strategies.py +0 -0
  234. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_parameters.py +0 -0
  235. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_scripts_fetch_content.py +0 -0
  236. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_target_tasks.py +0 -0
  237. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_taskgraph.py +0 -0
  238. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transform_chunking.py +0 -0
  239. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transform_docker_image.py +0 -0
  240. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transform_task_context.py +0 -0
  241. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_base.py +0 -0
  242. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_cached_tasks.py +0 -0
  243. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_fetch.py +0 -0
  244. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_from_deps.py +0 -0
  245. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_matrix.py +0 -0
  246. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_notify.py +0 -0
  247. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_run.py +0 -0
  248. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_run_run_task.py +0 -0
  249. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_run_toolchain.py +0 -0
  250. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_transforms_task.py +0 -0
  251. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_archive.py +0 -0
  252. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_attributes.py +0 -0
  253. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_cached_tasks.py +0 -0
  254. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_copy.py +0 -0
  255. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_dependencies.py +0 -0
  256. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_docker.py +0 -0
  257. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_json.py +0 -0
  258. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_keyed_by.py +0 -0
  259. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_parameterization.py +0 -0
  260. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_path.py +0 -0
  261. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_python_path.py +0 -0
  262. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_readonlydict.py +0 -0
  263. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_schema.py +0 -0
  264. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_taskcluster.py +0 -0
  265. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_templates.py +0 -0
  266. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_time.py +0 -0
  267. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_treeherder.py +0 -0
  268. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_workertypes.py +0 -0
  269. {taskcluster_taskgraph-20.0.0 → taskcluster_taskgraph-21.0.0}/test/test_util_yaml.py +0 -0
@@ -13,13 +13,13 @@ repos:
13
13
  exclude: template
14
14
  - id: check-added-large-files
15
15
  - repo: https://github.com/astral-sh/ruff-pre-commit
16
- rev: v0.15.4
16
+ rev: v0.15.8
17
17
  hooks:
18
18
  - id: ruff
19
19
  args: [--fix, --exit-non-zero-on-fix]
20
20
  - id: ruff-format
21
21
  - repo: https://github.com/astral-sh/uv-pre-commit
22
- rev: 0.10.7
22
+ rev: 0.11.2
23
23
  hooks:
24
24
  - id: uv-lock
25
25
  - repo: https://github.com/adrienverge/yamllint.git
@@ -28,7 +28,7 @@ repos:
28
28
  - id: yamllint
29
29
  exclude: template
30
30
  - repo: https://github.com/codespell-project/codespell
31
- rev: v2.4.1
31
+ rev: v2.4.2
32
32
  hooks:
33
33
  - id: codespell
34
34
  entry: codespell -I .codespell-ignore-words.txt
@@ -226,6 +226,7 @@ tasks:
226
226
  - $if: 'isPullRequest'
227
227
  then:
228
228
  TASKGRAPH_PULL_REQUEST_NUMBER: '${event.pull_request.number}'
229
+ TASKGRAPH_EXTRA_REFS: {$json: ["refs/notes/decision-parameters"]}
229
230
  - $if: 'tasks_for == "action" || tasks_for == "pr-action"'
230
231
  then:
231
232
  ACTION_TASK_GROUP_ID: '${action.taskGroupId}' # taskGroupId of the target task
@@ -251,7 +252,13 @@ tasks:
251
252
  - bash
252
253
  - -cx
253
254
  - $let:
254
- extraArgs: {$if: 'tasks_for == "cron"', then: '${cron.quoted_args}', else: ''}
255
+ extraArgs:
256
+ $if: 'tasks_for == "cron"'
257
+ then: '${cron.quoted_args}'
258
+ else:
259
+ $if: 'tasks_for == "github-pull-request"'
260
+ then: '--allow-parameter-override'
261
+ else: ''
255
262
  in:
256
263
  $if: 'tasks_for == "action" || tasks_for == "pr-action"'
257
264
  then: >
@@ -1,5 +1,24 @@
1
1
  # Change Log
2
2
 
3
+ ## [21.0.0] - 2026-04-13
4
+
5
+ ### Added
6
+
7
+ - Ability for `run-task` to fetch arbitrary extra refs
8
+ - Ability for Decision task to override params via Git notes
9
+
10
+ ### Fixed
11
+
12
+ - Improved index route verification
13
+
14
+ ### Changed
15
+
16
+ - BREAKING CHANGE: run-task and decision images now use Debian 13
17
+
18
+ ### Removed
19
+
20
+ - BREAKING CHANGE: Removed docker-worker features: dind, privileged, loopback-audio
21
+
3
22
  ## [20.0.0] - 2026-03-17
4
23
 
5
24
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskcluster-taskgraph
3
- Version: 20.0.0
3
+ Version: 21.0.0
4
4
  Summary: Build taskcluster taskgraphs
5
5
  Project-URL: Repository, https://github.com/taskcluster/taskgraph
6
6
  Project-URL: Issues, https://github.com/taskcluster/taskgraph/issues
@@ -101,7 +101,7 @@ in addition to ``taskcluster-taskgraph`` we also want to depend on
101
101
  EOF
102
102
 
103
103
  # This works best if you use the same Python as the one used in the Decision
104
- # image (currently 3.11).
104
+ # image (currently 3.13).
105
105
  pip-compile --generate-hashes --output-file requirements.txt requirements.in
106
106
 
107
107
  .. note::
@@ -3,6 +3,15 @@ Migration Guide
3
3
 
4
4
  This page can help when migrating Taskgraph across major versions.
5
5
 
6
+ 20.x -> 21.x
7
+ ------------
8
+
9
+ * If you have tasks using `docker-worker`'s `dind`, `privileged` or `loopback-audio`
10
+ features, they are no longer supported. Either avoid using these features or migrate
11
+ to a `generic-worker` pool with D2G payloads enabled.
12
+ * Ensure any task's using the `run-task` or `decision` images work with the new
13
+ Debian 13 base.
14
+
6
15
  19.x -> 20.x
7
16
  ------------
8
17
 
@@ -1,7 +1,7 @@
1
1
  ### Project
2
2
  [project]
3
3
  name = "taskcluster-taskgraph"
4
- version = "20.0.0"
4
+ version = "21.0.0"
5
5
  description = "Build taskcluster taskgraphs"
6
6
  readme = "README.rst"
7
7
  authors = [
@@ -264,6 +264,20 @@ def get_decision_parameters(graph_config, options):
264
264
  ] == "github-pull-request":
265
265
  set_try_config(parameters, task_config_file)
266
266
 
267
+ # load extra parameters from vcs note if able
268
+ note_ref = "refs/notes/decision-parameters"
269
+ if options.get("allow_parameter_override") and (
270
+ note_params := repo.get_note(note_ref)
271
+ ):
272
+ try:
273
+ note_params = json.loads(note_params)
274
+ logger.info(
275
+ f"Overriding parameters from {note_ref}:\n{json.dumps(note_params, indent=2)}"
276
+ )
277
+ parameters.update(note_params)
278
+ except ValueError as e:
279
+ raise Exception(f"Failed to parse {note_ref} as JSON: {e}") from e
280
+
267
281
  result = Parameters(**parameters)
268
282
  result.check()
269
283
  return result
@@ -933,6 +933,12 @@ def load_task(args):
933
933
  @argument(
934
934
  "--verbose", "-v", action="store_true", help="include debug-level logging output"
935
935
  )
936
+ @argument(
937
+ "--allow-parameter-override",
938
+ default=False,
939
+ action="store_true",
940
+ help="Allow user to override computed decision task parameters.",
941
+ )
936
942
  def decision(options):
937
943
  from taskgraph.decision import taskgraph_decision # noqa: PLC0415
938
944
 
@@ -31,7 +31,7 @@ import time
31
31
  import urllib.error
32
32
  import urllib.request
33
33
  from pathlib import Path
34
- from typing import Dict, Optional
34
+ from typing import Dict, List, Optional
35
35
 
36
36
  SECRET_BASEURL_TPL = "{}/secrets/v1/secret/{{}}".format(
37
37
  os.environ.get("TASKCLUSTER_PROXY_URL", "http://taskcluster").rstrip("/")
@@ -640,6 +640,7 @@ def git_checkout(
640
640
  ssh_key_file: Optional[Path],
641
641
  ssh_known_hosts_file: Optional[Path],
642
642
  shallow: bool = False,
643
+ extra_refs: Optional[List[str]] = None,
643
644
  ):
644
645
  assert head_ref or head_rev
645
646
 
@@ -734,6 +735,14 @@ def git_checkout(
734
735
  env=env,
735
736
  )
736
737
 
738
+ if extra_refs:
739
+ git_fetch(
740
+ destination_path,
741
+ *[f"{ref}:{ref}" for ref in extra_refs],
742
+ remote=head_repo,
743
+ env=env,
744
+ )
745
+
737
746
  args = [
738
747
  "git",
739
748
  "checkout",
@@ -932,6 +941,8 @@ def collect_vcs_options(args, project, name):
932
941
  head_rev = os.environ.get(f"{env_prefix}_HEAD_REV")
933
942
  pip_requirements = os.environ.get(f"{env_prefix}_PIP_REQUIREMENTS")
934
943
  private_key_secret = os.environ.get(f"{env_prefix}_SSH_SECRET_NAME")
944
+ if extra_refs := os.environ.get(f"{env_prefix}_EXTRA_REFS"):
945
+ extra_refs = json.loads(extra_refs)
935
946
 
936
947
  store_path = os.environ.get("HG_STORE_PATH")
937
948
 
@@ -965,6 +976,7 @@ def collect_vcs_options(args, project, name):
965
976
  "ssh-secret-name": private_key_secret,
966
977
  "pip-requirements": pip_requirements,
967
978
  "shallow-clone": shallow_clone,
979
+ "extra-refs": extra_refs,
968
980
  }
969
981
 
970
982
 
@@ -1014,6 +1026,7 @@ def vcs_checkout_from_args(options):
1014
1026
  ssh_key_file,
1015
1027
  ssh_known_hosts_file,
1016
1028
  shallow=options.get("shallow-clone", False),
1029
+ extra_refs=options.get("extra-refs"),
1017
1030
  )
1018
1031
  elif options["repo-type"] == "hg":
1019
1032
  revision = hg_checkout(
@@ -273,9 +273,6 @@ class DockerWorkerPayloadSchema(Schema, forbid_unknown_fields=False, kw_only=Tru
273
273
  taskcluster_proxy: bool
274
274
  allow_ptrace: bool
275
275
  loopback_video: bool
276
- loopback_audio: bool
277
- docker_in_docker: bool # (aka 'dind')
278
- privileged: bool
279
276
  # environment variables
280
277
  env: dict[str, taskref_or_string_msgspec]
281
278
  # the maximum time to run, in seconds
@@ -356,9 +353,6 @@ def build_docker_worker_payload(config, task, task_def):
356
353
  if worker.get("chain-of-trust"):
357
354
  features["chainOfTrust"] = True
358
355
 
359
- if worker.get("docker-in-docker"):
360
- features["dind"] = True
361
-
362
356
  if task.get("needs-sccache"):
363
357
  features["taskclusterProxy"] = True
364
358
  task_def["scopes"].append(
@@ -375,16 +369,10 @@ def build_docker_worker_payload(config, task, task_def):
375
369
 
376
370
  capabilities = {}
377
371
 
378
- for lo in "audio", "video":
379
- if worker.get("loopback-" + lo):
380
- capitalized = "loopback" + lo.capitalize()
381
- devices = capabilities.setdefault("devices", {})
382
- devices[capitalized] = True
383
- task_def["scopes"].append("docker-worker:capability:device:" + capitalized)
384
-
385
- if worker.get("privileged"):
386
- capabilities["privileged"] = True
387
- task_def["scopes"].append("docker-worker:capability:privileged")
372
+ if worker.get("loopback-video"):
373
+ devices = capabilities.setdefault("devices", {})
374
+ devices["loopbackVideo"] = True
375
+ task_def["scopes"].append("docker-worker:capability:device:loopbackVideo")
388
376
 
389
377
  task_def["payload"] = payload = {
390
378
  "image": image,
@@ -815,9 +803,6 @@ def set_defaults(config, tasks):
815
803
  worker.setdefault("taskcluster-proxy", False)
816
804
  worker.setdefault("allow-ptrace", False)
817
805
  worker.setdefault("loopback-video", False)
818
- worker.setdefault("loopback-audio", False)
819
- worker.setdefault("docker-in-docker", False)
820
- worker.setdefault("privileged", False)
821
806
  worker.setdefault("volumes", [])
822
807
  worker.setdefault("env", {})
823
808
  if "caches" in worker:
@@ -215,6 +215,14 @@ class Repository(ABC):
215
215
  If this function returns an unexpected value, then make sure
216
216
  the revision was fetched from the remote repository."""
217
217
 
218
+ def get_note(self, note: str, revision: Optional[str] = None) -> Optional[str]:
219
+ """Read a note attached to the given revision (defaults to HEAD).
220
+
221
+ Returns the note content as a string, or ``None`` if no note exists.
222
+ Only supported by Git; returns ``None`` for all other VCS types.
223
+ """
224
+ return None
225
+
218
226
 
219
227
  class HgRepository(Repository):
220
228
  @property
@@ -586,6 +594,18 @@ class GitRepository(Repository):
586
594
  return False
587
595
  raise
588
596
 
597
+ def get_note(self, note: str, revision: Optional[str] = None) -> Optional[str]:
598
+ if not note.startswith("refs/notes/"):
599
+ note = f"refs/notes/{note}"
600
+
601
+ revision = revision or "HEAD"
602
+ try:
603
+ return self.run("notes", f"--ref={note}", "show", revision).strip()
604
+ except subprocess.CalledProcessError as e:
605
+ if e.returncode == 1:
606
+ return None
607
+ raise
608
+
589
609
 
590
610
  def get_repository(path: str):
591
611
  """Get a repository object for the repository at `path`.
@@ -235,10 +235,14 @@ def verify_routes_notification_filters(
235
235
  )
236
236
 
237
237
 
238
+ # https://docs.taskcluster.net/docs/reference/core/index#valid-characters
239
+ INDEX_NAMESPACE_RE = re.compile(r"^([a-zA-Z0-9_!~*'()%-]+\.)*[a-zA-Z0-9_!~*'()%-]+$")
240
+
241
+
238
242
  @verifications.add("full_task_graph")
239
243
  def verify_index_route(task, taskgraph, scratch_pad, graph_config, parameters):
240
244
  """
241
- This function ensures that routes do not contain forward slashes.
245
+ This function ensures that index routes would create valid taskcluster index paths
242
246
  """
243
247
  if task is None:
244
248
  return
@@ -247,11 +251,13 @@ def verify_index_route(task, taskgraph, scratch_pad, graph_config, parameters):
247
251
  route_prefix = "index."
248
252
 
249
253
  for route in routes:
250
- # Check for invalid / in the index route
251
- if route.startswith(route_prefix) and "/" in route:
252
- raise Exception(
253
- f"{task.label} has invalid route with forward slash: {route}"
254
- )
254
+ if route.startswith(route_prefix):
255
+ namespace = route[len(route_prefix) :]
256
+ if not INDEX_NAMESPACE_RE.match(namespace):
257
+ raise Exception(
258
+ f"{task.label} has invalid index route namespace: {route}. "
259
+ f"Namespace must match {INDEX_NAMESPACE_RE.pattern}"
260
+ )
255
261
 
256
262
 
257
263
  @verifications.add("full_task_graph")
@@ -1,4 +1,4 @@
1
- FROM debian:12-slim
1
+ FROM debian:13-slim
2
2
  LABEL maintainer="Release Engineering <release+taskgraph-ci@mozilla.com>"
3
3
 
4
4
  # Add worker user
@@ -10,6 +10,8 @@ import tempfile
10
10
  import unittest
11
11
  from pathlib import Path
12
12
 
13
+ import pytest
14
+
13
15
  from taskgraph import decision
14
16
  from taskgraph.util.vcs import GitRepository, HgRepository
15
17
  from taskgraph.util.yaml import load_yaml
@@ -137,3 +139,60 @@ class TestGetDecisionParameters(unittest.TestCase):
137
139
  self.options["tasks_for"] = "hg-push"
138
140
  params = decision.get_decision_parameters(FAKE_GRAPH_CONFIG, self.options)
139
141
  self.assertEqual(params["target_tasks_method"], "nothing")
142
+
143
+
144
+ _BASE_OPTIONS = {
145
+ "base_repository": "https://hg.mozilla.org/mozilla-unified",
146
+ "base_rev": "aaaa",
147
+ "head_repository": "https://hg.mozilla.org/mozilla-central",
148
+ "head_rev": "bbbb",
149
+ "head_ref": "default",
150
+ "head_tag": "",
151
+ "project": "mozilla-central",
152
+ "pushlog_id": "1",
153
+ "pushdate": 0,
154
+ "repository_type": "git",
155
+ "owner": "nobody@mozilla.com",
156
+ "tasks_for": "github-push",
157
+ "level": "1",
158
+ }
159
+
160
+
161
+ @unittest.mock.patch.object(
162
+ GitRepository,
163
+ "get_note",
164
+ return_value=json.dumps({"build_number": 99}),
165
+ )
166
+ @unittest.mock.patch.object(GitRepository, "get_changed_files", return_value=[])
167
+ def test_decision_parameters_note(mock_files_changed, mock_get_note):
168
+ options = {**_BASE_OPTIONS, "allow_parameter_override": True}
169
+ params = decision.get_decision_parameters(FAKE_GRAPH_CONFIG, options)
170
+ mock_get_note.assert_called_once_with("refs/notes/decision-parameters")
171
+ assert params["build_number"] == 99
172
+
173
+
174
+ @unittest.mock.patch.object(
175
+ GitRepository,
176
+ "get_note",
177
+ return_value=json.dumps({"build_number": 99}),
178
+ )
179
+ @unittest.mock.patch.object(GitRepository, "get_changed_files", return_value=[])
180
+ def test_decision_parameters_note_disallow_override(mock_files_changed, mock_get_note):
181
+ options = {**_BASE_OPTIONS, "allow_parameter_override": False}
182
+ params = decision.get_decision_parameters(FAKE_GRAPH_CONFIG, options)
183
+ mock_get_note.assert_not_called()
184
+ assert params["build_number"] == 1
185
+
186
+
187
+ @unittest.mock.patch.object(
188
+ GitRepository,
189
+ "get_note",
190
+ return_value="not valid json {",
191
+ )
192
+ @unittest.mock.patch.object(GitRepository, "get_changed_files", return_value=[])
193
+ def test_decision_parameters_note_invalid_json(mock_files_changed, mock_get_note):
194
+ options = {**_BASE_OPTIONS, "allow_parameter_override": True}
195
+ with pytest.raises(
196
+ Exception, match="Failed to parse refs/notes/decision-parameters as JSON"
197
+ ):
198
+ decision.get_decision_parameters(FAKE_GRAPH_CONFIG, options)
@@ -1,4 +1,5 @@
1
1
  import functools
2
+ import json
2
3
  import os
3
4
  import site
4
5
  import stat
@@ -179,6 +180,17 @@ def test_install_pip_requirements_with_uv(
179
180
  {"shallow-clone": True},
180
181
  id="git_with_shallow_clone",
181
182
  ),
183
+ pytest.param(
184
+ {},
185
+ {
186
+ "REPOSITORY_TYPE": "git",
187
+ "HEAD_REPOSITORY": "https://github.com/example/repo",
188
+ "HEAD_REV": "abc123",
189
+ "EXTRA_REFS": json.dumps(["refs/notes/taskgraph", "refs/notes/other"]),
190
+ },
191
+ {"extra-refs": ["refs/notes/taskgraph", "refs/notes/other"]},
192
+ id="git_with_extra_refs",
193
+ ),
182
194
  ],
183
195
  )
184
196
  def test_collect_vcs_options(
@@ -216,6 +228,7 @@ def test_collect_vcs_options(
216
228
  "shallow-clone": False,
217
229
  "ssh-secret-name": env.get("SSH_SECRET_NAME"),
218
230
  "store-path": env.get("HG_STORE_PATH"),
231
+ "extra-refs": None,
219
232
  }
220
233
  if "PIP_REQUIREMENTS" in env:
221
234
  expected["pip-requirements"] = os.path.join(
@@ -638,3 +651,36 @@ def test_main_abspath_environment(mocker, run_main):
638
651
  assert env.get("MOZ_UV_HOME") == "/builds/worker/dir/uv"
639
652
  for key in envvars:
640
653
  assert env[key] == "/builds/worker/file"
654
+
655
+
656
+ def test_git_checkout_extra_refs(mock_stdin, run_task_mod, mock_git_repo, tmp_path):
657
+ """extra_refs are fetched into the local repo during checkout."""
658
+ # Add a notes ref to the source repo
659
+ rev = mock_git_repo["main"][-1]
660
+ subprocess.check_call(
661
+ ["git", "notes", "--ref=refs/notes/taskgraph", "add", "-m", "test", rev],
662
+ cwd=mock_git_repo["path"],
663
+ )
664
+
665
+ destination = tmp_path / "destination"
666
+ run_task_mod.git_checkout(
667
+ destination_path=str(destination),
668
+ head_repo=mock_git_repo["path"],
669
+ base_repo=mock_git_repo["path"],
670
+ base_rev=None,
671
+ head_ref="main",
672
+ head_rev=None,
673
+ ssh_key_file=None,
674
+ ssh_known_hosts_file=None,
675
+ extra_refs=["refs/notes/taskgraph"],
676
+ )
677
+
678
+ # Verify the notes ref is available locally
679
+ result = subprocess.run(
680
+ ["git", "notes", "--ref=refs/notes/taskgraph", "show", rev],
681
+ cwd=str(destination),
682
+ capture_output=True,
683
+ text=True,
684
+ )
685
+ assert result.returncode == 0
686
+ assert "test" in result.stdout
@@ -3,6 +3,7 @@
3
3
  # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
4
 
5
5
  import os
6
+ import shutil
6
7
  import subprocess
7
8
  from pathlib import Path
8
9
  from textwrap import dedent
@@ -648,3 +649,23 @@ def test_get_changed_files_with_null_base_revision_shallow_clone(
648
649
  assert "first_file" in changed_files
649
650
  assert "file1.txt" in changed_files
650
651
  assert "file2.txt" in changed_files
652
+
653
+
654
+ def test_get_note_git(git_repo, tmpdir):
655
+ """get_note returns note content when present, None otherwise."""
656
+ repo_path = tmpdir.join("git")
657
+ shutil.copytree(git_repo, repo_path)
658
+ repo = get_repository(str(repo_path))
659
+
660
+ # No note yet
661
+ assert repo.get_note("try-config") is None
662
+
663
+ rev = repo.head_rev
664
+ subprocess.check_call(
665
+ ["git", "notes", "--ref=refs/notes/try-config", "add", "-m", "test note", rev],
666
+ cwd=repo.path,
667
+ )
668
+
669
+ assert repo.get_note("try-config") == "test note"
670
+ assert repo.get_note("try-config", rev) == "test note"
671
+ assert repo.get_note("other") is None
@@ -211,6 +211,17 @@ def make_task_treeherder(label, symbol, platform="linux/opt"):
211
211
  pytest.raises(DeprecationWarning),
212
212
  id="routes_notfication_filter: deprecated",
213
213
  ),
214
+ pytest.param(
215
+ "verify_index_route",
216
+ make_graph(
217
+ make_task(
218
+ "valid_route",
219
+ task_def={"routes": ["index.example.v2.latest.taskgraph.decision"]},
220
+ ),
221
+ ),
222
+ does_not_raise(),
223
+ id="verify_index_route: valid route",
224
+ ),
214
225
  pytest.param(
215
226
  "verify_index_route",
216
227
  make_graph(
@@ -226,6 +237,28 @@ def make_task_treeherder(label, symbol, platform="linux/opt"):
226
237
  pytest.raises(Exception),
227
238
  id="verify_index_route: invalid slash in route",
228
239
  ),
240
+ pytest.param(
241
+ "verify_index_route",
242
+ make_graph(
243
+ make_task(
244
+ "invalid_plus",
245
+ task_def={"routes": ["index.example.1.0+hotfix1.latest"]},
246
+ ),
247
+ ),
248
+ pytest.raises(Exception),
249
+ id="verify_index_route: invalid plus in route",
250
+ ),
251
+ pytest.param(
252
+ "verify_index_route",
253
+ make_graph(
254
+ make_task(
255
+ "invalid_space",
256
+ task_def={"routes": ["index.example.some namespace.latest"]},
257
+ ),
258
+ ),
259
+ pytest.raises(Exception),
260
+ id="verify_index_route: invalid space in route",
261
+ ),
229
262
  pytest.param(
230
263
  "verify_task_dependencies",
231
264
  make_graph(
@@ -2587,7 +2587,7 @@ wheels = [
2587
2587
 
2588
2588
  [[package]]
2589
2589
  name = "taskcluster-taskgraph"
2590
- version = "20.0.0"
2590
+ version = "21.0.0"
2591
2591
  source = { editable = "." }
2592
2592
  dependencies = [
2593
2593
  { name = "appdirs" },