taskcluster-taskgraph 7.2.1__tar.gz → 7.3.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.
- taskcluster-taskgraph-7.3.0/PKG-INFO +112 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/setup.py +4 -0
- taskcluster-taskgraph-7.3.0/src/taskcluster_taskgraph.egg-info/PKG-INFO +112 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskcluster_taskgraph.egg-info/SOURCES.txt +1 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/__init__.py +1 -1
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/add_new_jobs.py +1 -1
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/rebuild_cached_tasks.py +1 -1
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/registry.py +20 -8
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/retrigger.py +6 -4
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/util.py +11 -4
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/archive.py +46 -6
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_actions_registry.py +11 -5
- taskcluster-taskgraph-7.3.0/test/test_util_archive.py +174 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_docker.py +0 -7
- taskcluster-taskgraph-7.2.1/PKG-INFO +0 -16
- taskcluster-taskgraph-7.2.1/src/taskcluster_taskgraph.egg-info/PKG-INFO +0 -16
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/LICENSE +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/MANIFEST.in +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/README.rst +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/pyproject.toml +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/requirements/base.in +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/requirements/base.txt +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/requirements/dev.in +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/requirements/dev.txt +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/requirements/test.in +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/requirements/test.txt +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/setup.cfg +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskcluster_taskgraph.egg-info/dependency_links.txt +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskcluster_taskgraph.egg-info/entry_points.txt +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskcluster_taskgraph.egg-info/requires.txt +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskcluster_taskgraph.egg-info/top_level.txt +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/__init__.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/cancel.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/cancel_all.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/config.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/create.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/decision.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/docker.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/files_changed.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/filter_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/generator.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/graph.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/loader/__init__.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/loader/default.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/loader/transform.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/main.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/morph.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/optimize/__init__.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/optimize/base.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/optimize/strategies.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/parameters.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/run-task/fetch-content +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/run-task/hgrc +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/run-task/robustcheckout.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/run-task/run-task +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/target_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/task.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/taskgraph.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/__init__.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/base.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/cached_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/chunking.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/code_review.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/docker_image.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/fetch.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/from_deps.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/notify.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/run/__init__.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/run/common.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/run/index_search.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/run/run_task.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/run/toolchain.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/task.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/transforms/task_context.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/__init__.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/attributes.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/cached_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/dependencies.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/docker.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/hash.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/keyed_by.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/memoize.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/parameterization.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/path.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/python_path.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/readonlydict.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/schema.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/shell.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/taskcluster.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/taskgraph.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/templates.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/time.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/treeherder.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/vcs.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/verify.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/workertypes.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/util/yaml.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_actions_rebuild_cached_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_create.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_decision.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_files_changed.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_generator.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_graph.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_main.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_morph.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_optimize.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_optimize_strategies.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_parameters.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_scripts_fetch_content.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_scripts_run_task.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_target_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_taskgraph.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transform_chunking.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transform_docker_image.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transform_task_context.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_base.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_cached_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_fetch.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_from_deps.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_notify.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_run.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_run_run_task.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_run_toolchain.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_transforms_task.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_attributes.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_cached_tasks.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_dependencies.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_memoize.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_parameterization.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_path.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_python_path.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_readonlydict.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_schema.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_taskcluster.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_templates.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_time.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_treeherder.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_vcs.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_verify.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_workertypes.py +0 -0
- {taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/test/test_util_yaml.py +0 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: taskcluster-taskgraph
|
|
3
|
+
Version: 7.3.0
|
|
4
|
+
Summary: Build taskcluster taskgraphs
|
|
5
|
+
Home-page: https://github.com/taskcluster/taskgraph
|
|
6
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
7
|
+
Classifier: Environment :: Console
|
|
8
|
+
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Software Development
|
|
15
|
+
Provides-Extra: load-image
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
.. image:: https://firefox-ci-tc.services.mozilla.com/api/github/v1/repository/taskcluster/taskgraph/main/badge.svg
|
|
20
|
+
:target: https://firefox-ci-tc.services.mozilla.com/api/github/v1/repository/taskcluster/taskgraph/main/latest
|
|
21
|
+
:alt: Task Status
|
|
22
|
+
|
|
23
|
+
.. image:: https://results.pre-commit.ci/badge/github/taskcluster/taskgraph/main.svg
|
|
24
|
+
:target: https://results.pre-commit.ci/latest/github/taskcluster/taskgraph/main
|
|
25
|
+
:alt: pre-commit.ci status
|
|
26
|
+
|
|
27
|
+
.. image:: https://codecov.io/gh/taskcluster/taskgraph/branch/main/graph/badge.svg?token=GJIV52ZQNP
|
|
28
|
+
:target: https://codecov.io/gh/taskcluster/taskgraph
|
|
29
|
+
:alt: Code Coverage
|
|
30
|
+
|
|
31
|
+
.. image:: https://badge.fury.io/py/taskcluster-taskgraph.svg
|
|
32
|
+
:target: https://badge.fury.io/py/taskcluster-taskgraph
|
|
33
|
+
:alt: Pypi Version
|
|
34
|
+
|
|
35
|
+
.. image:: https://readthedocs.org/projects/taskcluster-taskgraph/badge/?version=latest
|
|
36
|
+
:target: https://taskcluster-taskgraph.readthedocs.io/en/latest/?badge=latest
|
|
37
|
+
:alt: Documentation Status
|
|
38
|
+
|
|
39
|
+
.. image:: https://img.shields.io/badge/license-MPL%202.0-orange.svg
|
|
40
|
+
:target: http://mozilla.org/MPL/2.0
|
|
41
|
+
:alt: License
|
|
42
|
+
|
|
43
|
+
Taskgraph
|
|
44
|
+
=========
|
|
45
|
+
|
|
46
|
+
Taskgraph is a Python library to generate graphs of tasks for the `Taskcluster
|
|
47
|
+
CI`_ service. It is the recommended approach for configuring tasks once your
|
|
48
|
+
project outgrows a single `.taskcluster.yml`_ file and is what powers the over
|
|
49
|
+
30,000 tasks and counting that make up Firefox's CI.
|
|
50
|
+
|
|
51
|
+
For more information and usage instructions, `see the docs`_.
|
|
52
|
+
|
|
53
|
+
How It Works
|
|
54
|
+
------------
|
|
55
|
+
|
|
56
|
+
Taskgraph leverages the fact that Taskcluster is a generic task execution
|
|
57
|
+
platform. This means that tasks can be scheduled via its `comprehensive API`_,
|
|
58
|
+
and aren't limited to being triggered in response to supported events.
|
|
59
|
+
|
|
60
|
+
Taskgraph leverages this execution platform to allow CI systems to scale to any
|
|
61
|
+
size or complexity.
|
|
62
|
+
|
|
63
|
+
1. A *decision task* is created via Taskcluster's normal `.taskcluster.yml`_
|
|
64
|
+
file. This task invokes ``taskgraph``.
|
|
65
|
+
2. Taskgraph evaluates a series of yaml based task definitions (similar to
|
|
66
|
+
those other CI offerings provide).
|
|
67
|
+
3. Taskgraph applies transforms on top of these task definitions. Transforms
|
|
68
|
+
are Python functions that can programmatically alter or even clone a task
|
|
69
|
+
definition.
|
|
70
|
+
4. Taskgraph applies some optional optimization logic to remove unnecessary
|
|
71
|
+
tasks.
|
|
72
|
+
5. Taskgraph submits the resulting *task graph* to Taskcluster via its API.
|
|
73
|
+
|
|
74
|
+
Taskgraph's combination of declarative task configuration combined with
|
|
75
|
+
programmatic alteration are what allow it to support CI systems of any scale.
|
|
76
|
+
Taskgraph is the library that powers the 30,000+ tasks making up `Firefox's
|
|
77
|
+
CI`_.
|
|
78
|
+
|
|
79
|
+
.. _Taskcluster CI: https://taskcluster.net/
|
|
80
|
+
.. _comprehensive API: https://docs.taskcluster.net/docs/reference/platform/queue/api
|
|
81
|
+
.. _.taskcluster.yml: https://docs.taskcluster.net/docs/reference/integrations/github/taskcluster-yml-v1
|
|
82
|
+
.. _Firefox's CI: https://treeherder.mozilla.org/jobs?repo=mozilla-central
|
|
83
|
+
.. _see the docs: https://taskcluster-taskgraph.readthedocs.io
|
|
84
|
+
|
|
85
|
+
Installation
|
|
86
|
+
------------
|
|
87
|
+
|
|
88
|
+
Taskgraph supports Python 3.8 and up, and can be installed from Pypi:
|
|
89
|
+
|
|
90
|
+
.. code-block::
|
|
91
|
+
|
|
92
|
+
pip install taskcluster-taskgraph
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
Alternatively, the repo can be cloned and installed directly:
|
|
96
|
+
|
|
97
|
+
.. code-block::
|
|
98
|
+
|
|
99
|
+
git clone https://github.com/taskcluster/taskgraph
|
|
100
|
+
cd taskgraph
|
|
101
|
+
python setup.py install
|
|
102
|
+
|
|
103
|
+
In both cases, it's recommended to use a Python `virtual environment`_.
|
|
104
|
+
|
|
105
|
+
.. _virtual environment: https://docs.python.org/3/tutorial/venv.html
|
|
106
|
+
|
|
107
|
+
Get Involved
|
|
108
|
+
------------
|
|
109
|
+
|
|
110
|
+
If you'd like to get involved, please see our `contributing docs`_!
|
|
111
|
+
|
|
112
|
+
.. _contributing docs: https://github.com/taskcluster/taskgraph/blob/main/CONTRIBUTING.rst
|
|
@@ -13,10 +13,14 @@ with open(version_file) as fh:
|
|
|
13
13
|
with open(os.path.join(project_dir, "requirements/base.in")) as fp:
|
|
14
14
|
requirements = fp.read().splitlines()
|
|
15
15
|
|
|
16
|
+
with open(os.path.join(project_dir, "README.rst")) as fh:
|
|
17
|
+
long_description = fh.read()
|
|
18
|
+
|
|
16
19
|
setup(
|
|
17
20
|
name="taskcluster-taskgraph",
|
|
18
21
|
version=namespace["__version__"],
|
|
19
22
|
description="Build taskcluster taskgraphs",
|
|
23
|
+
long_description=long_description,
|
|
20
24
|
url="https://github.com/taskcluster/taskgraph",
|
|
21
25
|
packages=find_packages("src"),
|
|
22
26
|
package_dir={"": "src"},
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: taskcluster-taskgraph
|
|
3
|
+
Version: 7.3.0
|
|
4
|
+
Summary: Build taskcluster taskgraphs
|
|
5
|
+
Home-page: https://github.com/taskcluster/taskgraph
|
|
6
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
7
|
+
Classifier: Environment :: Console
|
|
8
|
+
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Software Development
|
|
15
|
+
Provides-Extra: load-image
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
.. image:: https://firefox-ci-tc.services.mozilla.com/api/github/v1/repository/taskcluster/taskgraph/main/badge.svg
|
|
20
|
+
:target: https://firefox-ci-tc.services.mozilla.com/api/github/v1/repository/taskcluster/taskgraph/main/latest
|
|
21
|
+
:alt: Task Status
|
|
22
|
+
|
|
23
|
+
.. image:: https://results.pre-commit.ci/badge/github/taskcluster/taskgraph/main.svg
|
|
24
|
+
:target: https://results.pre-commit.ci/latest/github/taskcluster/taskgraph/main
|
|
25
|
+
:alt: pre-commit.ci status
|
|
26
|
+
|
|
27
|
+
.. image:: https://codecov.io/gh/taskcluster/taskgraph/branch/main/graph/badge.svg?token=GJIV52ZQNP
|
|
28
|
+
:target: https://codecov.io/gh/taskcluster/taskgraph
|
|
29
|
+
:alt: Code Coverage
|
|
30
|
+
|
|
31
|
+
.. image:: https://badge.fury.io/py/taskcluster-taskgraph.svg
|
|
32
|
+
:target: https://badge.fury.io/py/taskcluster-taskgraph
|
|
33
|
+
:alt: Pypi Version
|
|
34
|
+
|
|
35
|
+
.. image:: https://readthedocs.org/projects/taskcluster-taskgraph/badge/?version=latest
|
|
36
|
+
:target: https://taskcluster-taskgraph.readthedocs.io/en/latest/?badge=latest
|
|
37
|
+
:alt: Documentation Status
|
|
38
|
+
|
|
39
|
+
.. image:: https://img.shields.io/badge/license-MPL%202.0-orange.svg
|
|
40
|
+
:target: http://mozilla.org/MPL/2.0
|
|
41
|
+
:alt: License
|
|
42
|
+
|
|
43
|
+
Taskgraph
|
|
44
|
+
=========
|
|
45
|
+
|
|
46
|
+
Taskgraph is a Python library to generate graphs of tasks for the `Taskcluster
|
|
47
|
+
CI`_ service. It is the recommended approach for configuring tasks once your
|
|
48
|
+
project outgrows a single `.taskcluster.yml`_ file and is what powers the over
|
|
49
|
+
30,000 tasks and counting that make up Firefox's CI.
|
|
50
|
+
|
|
51
|
+
For more information and usage instructions, `see the docs`_.
|
|
52
|
+
|
|
53
|
+
How It Works
|
|
54
|
+
------------
|
|
55
|
+
|
|
56
|
+
Taskgraph leverages the fact that Taskcluster is a generic task execution
|
|
57
|
+
platform. This means that tasks can be scheduled via its `comprehensive API`_,
|
|
58
|
+
and aren't limited to being triggered in response to supported events.
|
|
59
|
+
|
|
60
|
+
Taskgraph leverages this execution platform to allow CI systems to scale to any
|
|
61
|
+
size or complexity.
|
|
62
|
+
|
|
63
|
+
1. A *decision task* is created via Taskcluster's normal `.taskcluster.yml`_
|
|
64
|
+
file. This task invokes ``taskgraph``.
|
|
65
|
+
2. Taskgraph evaluates a series of yaml based task definitions (similar to
|
|
66
|
+
those other CI offerings provide).
|
|
67
|
+
3. Taskgraph applies transforms on top of these task definitions. Transforms
|
|
68
|
+
are Python functions that can programmatically alter or even clone a task
|
|
69
|
+
definition.
|
|
70
|
+
4. Taskgraph applies some optional optimization logic to remove unnecessary
|
|
71
|
+
tasks.
|
|
72
|
+
5. Taskgraph submits the resulting *task graph* to Taskcluster via its API.
|
|
73
|
+
|
|
74
|
+
Taskgraph's combination of declarative task configuration combined with
|
|
75
|
+
programmatic alteration are what allow it to support CI systems of any scale.
|
|
76
|
+
Taskgraph is the library that powers the 30,000+ tasks making up `Firefox's
|
|
77
|
+
CI`_.
|
|
78
|
+
|
|
79
|
+
.. _Taskcluster CI: https://taskcluster.net/
|
|
80
|
+
.. _comprehensive API: https://docs.taskcluster.net/docs/reference/platform/queue/api
|
|
81
|
+
.. _.taskcluster.yml: https://docs.taskcluster.net/docs/reference/integrations/github/taskcluster-yml-v1
|
|
82
|
+
.. _Firefox's CI: https://treeherder.mozilla.org/jobs?repo=mozilla-central
|
|
83
|
+
.. _see the docs: https://taskcluster-taskgraph.readthedocs.io
|
|
84
|
+
|
|
85
|
+
Installation
|
|
86
|
+
------------
|
|
87
|
+
|
|
88
|
+
Taskgraph supports Python 3.8 and up, and can be installed from Pypi:
|
|
89
|
+
|
|
90
|
+
.. code-block::
|
|
91
|
+
|
|
92
|
+
pip install taskcluster-taskgraph
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
Alternatively, the repo can be cloned and installed directly:
|
|
96
|
+
|
|
97
|
+
.. code-block::
|
|
98
|
+
|
|
99
|
+
git clone https://github.com/taskcluster/taskgraph
|
|
100
|
+
cd taskgraph
|
|
101
|
+
python setup.py install
|
|
102
|
+
|
|
103
|
+
In both cases, it's recommended to use a Python `virtual environment`_.
|
|
104
|
+
|
|
105
|
+
.. _virtual environment: https://docs.python.org/3/tutorial/venv.html
|
|
106
|
+
|
|
107
|
+
Get Involved
|
|
108
|
+
------------
|
|
109
|
+
|
|
110
|
+
If you'd like to get involved, please see our `contributing docs`_!
|
|
111
|
+
|
|
112
|
+
.. _contributing docs: https://github.com/taskcluster/taskgraph/blob/main/CONTRIBUTING.rst
|
|
@@ -116,6 +116,7 @@ test/test_transforms_run.py
|
|
|
116
116
|
test/test_transforms_run_run_task.py
|
|
117
117
|
test/test_transforms_run_toolchain.py
|
|
118
118
|
test/test_transforms_task.py
|
|
119
|
+
test/test_util_archive.py
|
|
119
120
|
test/test_util_attributes.py
|
|
120
121
|
test/test_util_cached_tasks.py
|
|
121
122
|
test/test_util_dependencies.py
|
|
@@ -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__ = "7.
|
|
5
|
+
__version__ = "7.3.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
|
{taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/add_new_jobs.py
RENAMED
|
@@ -40,7 +40,7 @@ from taskgraph.actions.util import (
|
|
|
40
40
|
)
|
|
41
41
|
def add_new_jobs_action(parameters, graph_config, input, task_group_id, task_id):
|
|
42
42
|
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
|
|
43
|
-
parameters, graph_config
|
|
43
|
+
parameters, graph_config, task_group_id=task_group_id
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
to_run = []
|
|
@@ -18,7 +18,7 @@ def rebuild_cached_tasks_action(
|
|
|
18
18
|
parameters, graph_config, input, task_group_id, task_id
|
|
19
19
|
):
|
|
20
20
|
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
|
|
21
|
-
parameters, graph_config
|
|
21
|
+
parameters, graph_config, task_group_id=task_group_id
|
|
22
22
|
)
|
|
23
23
|
cached_tasks = [
|
|
24
24
|
label
|
{taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/registry.py
RENAMED
|
@@ -163,11 +163,11 @@ def register_callback_action(
|
|
|
163
163
|
actionPerm = "generic" if generic else cb_name
|
|
164
164
|
|
|
165
165
|
# gather up the common decision-task-supplied data for this action
|
|
166
|
-
repo_param = "head_repository"
|
|
167
166
|
repository = {
|
|
168
|
-
"url": parameters[
|
|
167
|
+
"url": parameters["head_repository"],
|
|
169
168
|
"project": parameters["project"],
|
|
170
169
|
"level": parameters["level"],
|
|
170
|
+
"base_url": parameters["base_repository"],
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
revision = parameters["head_rev"]
|
|
@@ -179,6 +179,9 @@ def register_callback_action(
|
|
|
179
179
|
branch = parameters.get("head_ref")
|
|
180
180
|
if branch:
|
|
181
181
|
push["branch"] = branch
|
|
182
|
+
base_branch = parameters.get("base_ref")
|
|
183
|
+
if base_branch and branch != base_branch:
|
|
184
|
+
push["base_branch"] = base_branch
|
|
182
185
|
|
|
183
186
|
action = {
|
|
184
187
|
"name": name,
|
|
@@ -213,11 +216,16 @@ def register_callback_action(
|
|
|
213
216
|
if "/" in actionPerm:
|
|
214
217
|
raise Exception("`/` is not allowed in action names; use `-`")
|
|
215
218
|
|
|
219
|
+
if parameters["tasks_for"].startswith("github-pull-request"):
|
|
220
|
+
hookId = f"in-tree-pr-action-{level}-{actionPerm}/{tcyml_hash}"
|
|
221
|
+
else:
|
|
222
|
+
hookId = f"in-tree-action-{level}-{actionPerm}/{tcyml_hash}"
|
|
223
|
+
|
|
216
224
|
rv.update(
|
|
217
225
|
{
|
|
218
226
|
"kind": "hook",
|
|
219
227
|
"hookGroupId": f"project-{trustDomain}",
|
|
220
|
-
"hookId":
|
|
228
|
+
"hookId": hookId,
|
|
221
229
|
"hookPayload": {
|
|
222
230
|
# provide the decision-task parameters as context for triggerHook
|
|
223
231
|
"decision": {
|
|
@@ -293,16 +301,20 @@ def sanity_check_task_scope(callback, parameters, graph_config):
|
|
|
293
301
|
|
|
294
302
|
actionPerm = "generic" if action.generic else action.cb_name
|
|
295
303
|
|
|
296
|
-
|
|
297
|
-
raw_url = parameters[repo_param]
|
|
304
|
+
raw_url = parameters["base_repository"]
|
|
298
305
|
parsed_url = parse(raw_url)
|
|
299
|
-
|
|
306
|
+
action_scope = f"assume:{parsed_url.taskcluster_role_prefix}:action:{actionPerm}"
|
|
307
|
+
pr_action_scope = (
|
|
308
|
+
f"assume:{parsed_url.taskcluster_role_prefix}:pr-action:{actionPerm}"
|
|
309
|
+
)
|
|
300
310
|
|
|
301
311
|
# the scope should appear literally; no need for a satisfaction check. The use of
|
|
302
312
|
# get_current_scopes here calls the auth service through the Taskcluster Proxy, giving
|
|
303
313
|
# the precise scopes available to this task.
|
|
304
|
-
if
|
|
305
|
-
raise ValueError(
|
|
314
|
+
if not set((action_scope, pr_action_scope)) & set(taskcluster.get_current_scopes()):
|
|
315
|
+
raise ValueError(
|
|
316
|
+
f"Expected task scope {action_scope} or {pr_action_scope} for this action"
|
|
317
|
+
)
|
|
306
318
|
|
|
307
319
|
|
|
308
320
|
def trigger_action_callback(
|
{taskcluster-taskgraph-7.2.1 → taskcluster-taskgraph-7.3.0}/src/taskgraph/actions/retrigger.py
RENAMED
|
@@ -65,7 +65,9 @@ def retrigger_decision_action(parameters, graph_config, input, task_group_id, ta
|
|
|
65
65
|
# absolute timestamps relative to the current time.
|
|
66
66
|
task = taskcluster.get_task_definition(task_id)
|
|
67
67
|
task = relativize_datestamps(task)
|
|
68
|
-
create_task_from_def(
|
|
68
|
+
create_task_from_def(
|
|
69
|
+
slugid(), task, parameters["level"], graph_config["trust-domain"]
|
|
70
|
+
)
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
@register_callback_action(
|
|
@@ -142,7 +144,7 @@ def retrigger_decision_action(parameters, graph_config, input, task_group_id, ta
|
|
|
142
144
|
)
|
|
143
145
|
def retrigger_action(parameters, graph_config, input, task_group_id, task_id):
|
|
144
146
|
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
|
|
145
|
-
parameters, graph_config
|
|
147
|
+
parameters, graph_config, task_group_id=task_group_id
|
|
146
148
|
)
|
|
147
149
|
|
|
148
150
|
task = taskcluster.get_task_definition(task_id)
|
|
@@ -199,7 +201,7 @@ def rerun_action(parameters, graph_config, input, task_group_id, task_id):
|
|
|
199
201
|
task = taskcluster.get_task_definition(task_id)
|
|
200
202
|
parameters = dict(parameters)
|
|
201
203
|
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
|
|
202
|
-
parameters, graph_config
|
|
204
|
+
parameters, graph_config, task_group_id=task_group_id
|
|
203
205
|
)
|
|
204
206
|
label = task["metadata"]["name"]
|
|
205
207
|
if task_id not in label_to_taskid.values():
|
|
@@ -257,7 +259,7 @@ def _rerun_task(task_id, label):
|
|
|
257
259
|
)
|
|
258
260
|
def retrigger_multiple(parameters, graph_config, input, task_group_id, task_id):
|
|
259
261
|
decision_task_id, full_task_graph, label_to_taskid = fetch_graph_and_labels(
|
|
260
|
-
parameters, graph_config
|
|
262
|
+
parameters, graph_config, task_group_id=task_group_id
|
|
261
263
|
)
|
|
262
264
|
|
|
263
265
|
suffixes = []
|
|
@@ -32,8 +32,15 @@ def get_parameters(decision_task_id):
|
|
|
32
32
|
return get_artifact(decision_task_id, "public/parameters.yml")
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def fetch_graph_and_labels(parameters, graph_config):
|
|
36
|
-
|
|
35
|
+
def fetch_graph_and_labels(parameters, graph_config, task_group_id=None):
|
|
36
|
+
try:
|
|
37
|
+
# Look up the decision_task id in the index
|
|
38
|
+
decision_task_id = find_decision_task(parameters, graph_config)
|
|
39
|
+
except KeyError:
|
|
40
|
+
if not task_group_id:
|
|
41
|
+
raise
|
|
42
|
+
# Not found (e.g. from github-pull-request), fall back to the task group id.
|
|
43
|
+
decision_task_id = task_group_id
|
|
37
44
|
|
|
38
45
|
# First grab the graph and labels generated during the initial decision task
|
|
39
46
|
full_task_graph = get_artifact(decision_task_id, "public/full-task-graph.json")
|
|
@@ -90,7 +97,7 @@ def fetch_graph_and_labels(parameters, graph_config):
|
|
|
90
97
|
return (decision_task_id, full_task_graph, label_to_taskid)
|
|
91
98
|
|
|
92
99
|
|
|
93
|
-
def create_task_from_def(task_id, task_def, level):
|
|
100
|
+
def create_task_from_def(task_id, task_def, level, trust_domain):
|
|
94
101
|
"""Create a new task from a definition rather than from a label
|
|
95
102
|
that is already in the full-task-graph. The task definition will
|
|
96
103
|
have {relative-datestamp': '..'} rendered just like in a decision task.
|
|
@@ -98,7 +105,7 @@ def create_task_from_def(task_id, task_def, level):
|
|
|
98
105
|
It is useful if you want to "edit" the full_task_graph and then hand
|
|
99
106
|
it to this function. No dependencies will be scheduled. You must handle
|
|
100
107
|
this yourself. Seeing how create_tasks handles it might prove helpful."""
|
|
101
|
-
task_def["schedulerId"] = f"
|
|
108
|
+
task_def["schedulerId"] = f"{trust_domain}-level-{level}"
|
|
102
109
|
label = task_def["metadata"]["name"]
|
|
103
110
|
session = get_session()
|
|
104
111
|
create.create_task(session, task_id, label, task_def)
|
|
@@ -12,6 +12,40 @@ import tarfile
|
|
|
12
12
|
DEFAULT_MTIME = 1451606400
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
# Python 3.9 contains this change:
|
|
16
|
+
# https://github.com/python/cpython/commit/674935b8caf33e47c78f1b8e197b1b77a04992d2
|
|
17
|
+
# which changes the output of tar creation compared to earlier versions.
|
|
18
|
+
# As this code is used to generate tar files that are meant to be deterministic
|
|
19
|
+
# across versions of python (specifically, it's used as part of computing the hash
|
|
20
|
+
# of docker images, which needs to be identical between CI (which uses python 3.8),
|
|
21
|
+
# and developer environments (using arbitrary versions of python, at this point,
|
|
22
|
+
# most probably more recent than 3.9)).
|
|
23
|
+
# What we do is subblass TarInfo so that if used on python >= 3.9, it reproduces the
|
|
24
|
+
# behavior from python < 3.9.
|
|
25
|
+
# Here's how it goes:
|
|
26
|
+
# - the behavior in python >= 3.9 is the same as python < 3.9 when the type encoded
|
|
27
|
+
# in the tarinfo is CHRTYPE or BLKTYPE.
|
|
28
|
+
# - the value of the type is only compared in the context of choosing which behavior
|
|
29
|
+
# to take
|
|
30
|
+
# - we replace the type with the same value (so that using the value has no changes)
|
|
31
|
+
# but that pretends to be the same as CHRTYPE so that the condition that enables the
|
|
32
|
+
# old behavior is taken.
|
|
33
|
+
class HackedType(bytes):
|
|
34
|
+
def __eq__(self, other):
|
|
35
|
+
if other == tarfile.CHRTYPE:
|
|
36
|
+
return True
|
|
37
|
+
return self == other
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TarInfo(tarfile.TarInfo):
|
|
41
|
+
@staticmethod
|
|
42
|
+
def _create_header(info, format, encoding, errors):
|
|
43
|
+
info["type"] = HackedType(info["type"])
|
|
44
|
+
# ignore type checking because it looks like pyright complains because we're calling a
|
|
45
|
+
# non-public method
|
|
46
|
+
return tarfile.TarInfo._create_header(info, format, encoding, errors) # type: ignore
|
|
47
|
+
|
|
48
|
+
|
|
15
49
|
def create_tar_from_files(fp, files):
|
|
16
50
|
"""Create a tar file deterministically.
|
|
17
51
|
|
|
@@ -25,15 +59,23 @@ def create_tar_from_files(fp, files):
|
|
|
25
59
|
|
|
26
60
|
FUTURE accept a filename argument (or create APIs to write files)
|
|
27
61
|
"""
|
|
28
|
-
|
|
62
|
+
# The format is explicitly set to tarfile.GNU_FORMAT, because this default format
|
|
63
|
+
# has been changed in Python 3.8.
|
|
64
|
+
with tarfile.open(
|
|
65
|
+
name="", mode="w", fileobj=fp, dereference=True, format=tarfile.GNU_FORMAT
|
|
66
|
+
) as tf:
|
|
29
67
|
for archive_path, f in sorted(files.items()):
|
|
30
68
|
if isinstance(f, str):
|
|
31
|
-
|
|
69
|
+
s = os.stat(f)
|
|
70
|
+
mode = s.st_mode
|
|
71
|
+
size = s.st_size
|
|
32
72
|
f = open(f, "rb")
|
|
33
73
|
else:
|
|
34
74
|
mode = 0o0644
|
|
75
|
+
size = len(f.read())
|
|
76
|
+
f.seek(0)
|
|
35
77
|
|
|
36
|
-
ti =
|
|
78
|
+
ti = TarInfo(archive_path)
|
|
37
79
|
ti.mode = mode
|
|
38
80
|
ti.type = tarfile.REGTYPE
|
|
39
81
|
|
|
@@ -56,9 +98,7 @@ def create_tar_from_files(fp, files):
|
|
|
56
98
|
# Set mtime to a constant value.
|
|
57
99
|
ti.mtime = DEFAULT_MTIME
|
|
58
100
|
|
|
59
|
-
|
|
60
|
-
ti.size = f.tell()
|
|
61
|
-
f.seek(0, 0)
|
|
101
|
+
ti.size = size
|
|
62
102
|
# tarfile wants to pass a size argument to read(). So just
|
|
63
103
|
# wrap/buffer in a proper file object interface.
|
|
64
104
|
tf.addfile(ti, f)
|
|
@@ -12,34 +12,40 @@ from taskgraph.actions import registry
|
|
|
12
12
|
("non-existing-action", {}, [], pytest.raises(ValueError)),
|
|
13
13
|
(
|
|
14
14
|
"retrigger",
|
|
15
|
-
{"
|
|
15
|
+
{"base_repository": "https://some.git.repo"},
|
|
16
16
|
[],
|
|
17
17
|
pytest.raises(InvalidRepoUrlError),
|
|
18
18
|
),
|
|
19
19
|
(
|
|
20
20
|
"retrigger",
|
|
21
|
-
{"
|
|
21
|
+
{"base_repository": "https://hg.mozilla.org/try"},
|
|
22
22
|
["unrelated:scope"],
|
|
23
23
|
pytest.raises(ValueError),
|
|
24
24
|
),
|
|
25
25
|
(
|
|
26
26
|
"retrigger",
|
|
27
|
-
{"
|
|
27
|
+
{"base_repository": "https://hg.mozilla.org/mozilla-central"},
|
|
28
28
|
["assume:repo:hg.mozilla.org/mozilla-central:action:generic"],
|
|
29
29
|
does_not_raise(),
|
|
30
30
|
),
|
|
31
31
|
(
|
|
32
32
|
"retrigger",
|
|
33
|
-
{"
|
|
33
|
+
{"base_repository": "https://github.com/taskcluster/taskgraph"},
|
|
34
34
|
["assume:repo:github.com/taskcluster/taskgraph:action:generic"],
|
|
35
35
|
does_not_raise(),
|
|
36
36
|
),
|
|
37
37
|
(
|
|
38
38
|
"retrigger",
|
|
39
|
-
{"
|
|
39
|
+
{"base_repository": "git@github.com:mozilla-mobile/firefox-android.git"},
|
|
40
40
|
["assume:repo:github.com/mozilla-mobile/firefox-android:action:generic"],
|
|
41
41
|
does_not_raise(),
|
|
42
42
|
),
|
|
43
|
+
(
|
|
44
|
+
"retrigger",
|
|
45
|
+
{"base_repository": "git@github.com:mozilla-mobile/firefox-android.git"},
|
|
46
|
+
["assume:repo:github.com/mozilla-mobile/firefox-android:pr-action:generic"],
|
|
47
|
+
does_not_raise(),
|
|
48
|
+
),
|
|
43
49
|
),
|
|
44
50
|
)
|
|
45
51
|
def test_sanity_check_task_scope(
|