taskcluster-taskgraph 16.2.0__tar.gz → 16.2.1__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-16.2.0 → taskcluster_taskgraph-16.2.1}/CHANGELOG.md +9 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/PKG-INFO +2 -2
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/pyproject.toml +2 -2
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/run-task/run-task +21 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/taskcluster.py +2 -3
- taskcluster_taskgraph-16.2.1/test/test_util_archive.py +181 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_taskcluster.py +19 -4
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/uv.lock +7 -7
- taskcluster_taskgraph-16.2.0/test/test_util_archive.py +0 -174
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.codespell-ignore-words.txt +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/CODEOWNERS +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/dependabot.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/workflows/codeql-analysis.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/workflows/pre-commit-autoupdate.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/workflows/pre-commit.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/workflows/pypi-publish.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.gitignore +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.pre-commit-config.yaml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.readthedocs.yaml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.taskcluster.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.yamllint +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/CODE_OF_CONDUCT.md +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/CONTRIBUTING.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/LICENSE +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/Makefile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/README.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/index.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/kind.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/loading.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/optimization.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/overview.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/scopes.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/task-graphs.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/transforms.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/conf.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/contributing.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/glossary.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/bootstrap-taskgraph.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/create-actions.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/create-tasks.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/debugging.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/docker.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/index.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/load-task-locally.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/resolve-keyed-by.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/run-locally.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/send-notifications.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/use-fetches.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/index.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/cli.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/index.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/migrations.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/optimization-strategies.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/parameters.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/modules.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/taskgraph.actions.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/taskgraph.loader.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/taskgraph.optimize.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/taskgraph.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/taskgraph.transforms.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/taskgraph.transforms.run.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/source/taskgraph.util.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/transforms/chunking.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/transforms/from_deps.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/transforms/index.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/transforms/matrix.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/reference/transforms/task_context.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/tutorials/connecting-taskcluster.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/tutorials/creating-a-task-graph.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/tutorials/example-taskcluster.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/tutorials/getting-started.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/tutorials/index.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/make.bat +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/pytest-taskgraph/README.md +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/pytest-taskgraph/pyproject.toml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/pytest-taskgraph/src/pytest_taskgraph/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/pytest-taskgraph/src/pytest_taskgraph/fixtures/gen.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/pytest-taskgraph/src/pytest_taskgraph/fixtures/vcs.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/sphinx-taskgraph/README.md +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/sphinx-taskgraph/pyproject.toml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/sphinx-taskgraph/src/sphinx_taskgraph/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/packages/sphinx-taskgraph/src/sphinx_taskgraph/autoschema.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/add_new_jobs.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/cancel.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/cancel_all.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/rebuild_cached_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/registry.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/retrigger.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/actions/util.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/config.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/create.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/decision.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/docker.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/filter_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/generator.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/graph.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/loader/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/loader/default.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/loader/transform.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/main.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/morph.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/optimize/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/optimize/base.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/optimize/strategies.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/parameters.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/run-task/fetch-content +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/run-task/hgrc +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/run-task/robustcheckout.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/target_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/task.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/taskgraph.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/base.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/cached_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/chunking.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/code_review.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/docker_image.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/fetch.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/from_deps.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/matrix.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/notify.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/run/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/run/common.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/run/index_search.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/run/run_task.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/run/toolchain.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/task.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/transforms/task_context.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/archive.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/attributes.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/cached_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/caches.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/copy.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/dependencies.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/docker.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/hash.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/json.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/keyed_by.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/parameterization.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/path.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/python_path.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/readonlydict.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/schema.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/set_name.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/shell.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/taskgraph.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/templates.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/time.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/treeherder.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/vcs.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/verify.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/workertypes.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/yaml.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/config.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/REGISTRY +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/decision/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/decision/HASH +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/decision/README.md +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/decision/VERSION +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/decision/system-setup.sh +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/fetch/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/image_builder/README.rst +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/index-task/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/index-task/README +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/index-task/insert-indexes.js +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/index-task/package.json +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/index-task/yarn.lock +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/python/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/run-task/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/run-task/system-setup.sh +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/skopeo/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/skopeo/policy.json +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/docker/skopeo/push_image.sh +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/check/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/codecov/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/complete/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/doc/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/docker-image/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/fetch/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/push-image/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/kinds/test/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/scripts/codecov-upload.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/scripts/external_tools/tooltool.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/self_taskgraph/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/self_taskgraph/custom_parameters.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/self_taskgraph/custom_target_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/self_taskgraph/transforms/add_pr_route.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/self_taskgraph/transforms/push_image.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/test/params/main-repo-pull-request-untrusted.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/test/params/main-repo-pull-request.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/test/params/main-repo-push.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/test/params/main-repo-release-pytest-taskgraph.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/taskcluster/test/params/main-repo-release-taskcluster-taskgraph.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/cookiecutter.json +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/hooks/post_gen_project.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/{{cookiecutter.project_name}}/taskcluster/config.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/{{cookiecutter.project_name}}/taskcluster/docker/linux/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/{{cookiecutter.project_name}}/taskcluster/kinds/docker-image/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/{{cookiecutter.project_name}}/taskcluster/kinds/hello/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/{{cookiecutter.project_name}}/taskcluster/{{cookiecutter.project_slug}}_taskgraph/transforms/hello.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/template/{{cookiecutter.project_name}}/taskcluster.github.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/__init__.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/automationrelevance.json +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/conftest.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/task_context.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/config.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/docker/hello-world/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/docker/hello-world-tag/Dockerfile +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/docker/hello-world-tag/REGISTRY +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/docker/hello-world-tag/VERSION +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/kinds/docker-image/kind.yml +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/scripts/toolchain/run.ps1 +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/scripts/toolchain/run.sh +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/taskcluster/test_taskgraph/transforms/foo.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/data/testmod/thing.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/mockedopen.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_actions_rebuild_cached_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_actions_registry.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_config.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_create.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_decision.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_docker.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_generator.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_graph.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_main.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_morph.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_optimize.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_optimize_strategies.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_parameters.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_scripts_fetch_content.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_scripts_run_task.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_target_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_taskgraph.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transform_chunking.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transform_docker_image.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transform_task_context.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_base.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_cached_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_fetch.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_from_deps.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_matrix.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_notify.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_run.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_run_run_task.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_run_toolchain.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_transforms_task.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_attributes.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_cached_tasks.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_copy.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_dependencies.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_docker.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_json.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_keyed_by.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_parameterization.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_path.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_python_path.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_readonlydict.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_schema.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_templates.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_time.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_treeherder.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_vcs.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_verify.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_workertypes.py +0 -0
- {taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/test/test_util_yaml.py +0 -0
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
# Change Log
|
|
2
|
+
|
|
3
|
+
## [16.2.1] - 2025-10-14
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- `run-task` script now cleans up zombie processes
|
|
8
|
+
- Fixed regression to `taskgraph.util.taskcluster.list_artifacts`
|
|
9
|
+
- Fixed regression to `taskgraph.util.taskcluster.get_artifact`
|
|
10
|
+
|
|
2
11
|
## [16.2.0] - 2025-09-26
|
|
3
12
|
|
|
4
13
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: taskcluster-taskgraph
|
|
3
|
-
Version: 16.2.
|
|
3
|
+
Version: 16.2.1
|
|
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
|
|
@@ -26,7 +26,7 @@ Requires-Dist: redo>=2.0
|
|
|
26
26
|
Requires-Dist: requests>=2.25
|
|
27
27
|
Requires-Dist: slugid>=2.0
|
|
28
28
|
Requires-Dist: taskcluster-urls>=11.0
|
|
29
|
-
Requires-Dist: taskcluster>=
|
|
29
|
+
Requires-Dist: taskcluster>=91.0
|
|
30
30
|
Requires-Dist: voluptuous>=0.12.1
|
|
31
31
|
Provides-Extra: load-image
|
|
32
32
|
Requires-Dist: zstandard; extra == 'load-image'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
### Project
|
|
2
2
|
[project]
|
|
3
3
|
name = "taskcluster-taskgraph"
|
|
4
|
-
version = "16.2.
|
|
4
|
+
version = "16.2.1"
|
|
5
5
|
description = "Build taskcluster taskgraphs"
|
|
6
6
|
readme = "README.rst"
|
|
7
7
|
authors = [
|
|
@@ -29,7 +29,7 @@ dependencies = [
|
|
|
29
29
|
"redo>=2.0",
|
|
30
30
|
"requests>=2.25",
|
|
31
31
|
"slugid>=2.0",
|
|
32
|
-
"taskcluster>=
|
|
32
|
+
"taskcluster>=91.0",
|
|
33
33
|
"taskcluster-urls>=11.0",
|
|
34
34
|
"voluptuous>=0.12.1",
|
|
35
35
|
]
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/run-task/run-task
RENAMED
|
@@ -28,6 +28,7 @@ import socket
|
|
|
28
28
|
import stat
|
|
29
29
|
import subprocess
|
|
30
30
|
import sys
|
|
31
|
+
import threading
|
|
31
32
|
import time
|
|
32
33
|
import urllib.error
|
|
33
34
|
import urllib.request
|
|
@@ -121,6 +122,17 @@ def print_line(prefix, m):
|
|
|
121
122
|
sys.stdout.buffer.flush()
|
|
122
123
|
|
|
123
124
|
|
|
125
|
+
def reap_zombies(main_subprocess):
|
|
126
|
+
"""Wait for main_subprocess to exit, while awaiting any other child processes"""
|
|
127
|
+
while main_subprocess.poll() is None:
|
|
128
|
+
with main_subprocess._waitpid_lock:
|
|
129
|
+
if main_subprocess.returncode is not None:
|
|
130
|
+
return
|
|
131
|
+
pid, status = os.wait()
|
|
132
|
+
if pid == main_subprocess.pid:
|
|
133
|
+
main_subprocess._handle_exitstatus(status)
|
|
134
|
+
|
|
135
|
+
|
|
124
136
|
def _call_windows_retry(func, args=(), retry_max=5, retry_delay=0.5):
|
|
125
137
|
"""
|
|
126
138
|
It's possible to see spurious errors on Windows due to various things
|
|
@@ -278,6 +290,13 @@ def run_command(prefix, args, *, extra_env=None, cwd=None):
|
|
|
278
290
|
|
|
279
291
|
stdout = io.TextIOWrapper(p.stdout, encoding="latin1")
|
|
280
292
|
|
|
293
|
+
if os.getpid() == 1:
|
|
294
|
+
# in docker we're init, so we get to adopt unawaited zombies
|
|
295
|
+
reaper_thread = threading.Thread(target=reap_zombies, args=(p,))
|
|
296
|
+
reaper_thread.start()
|
|
297
|
+
else:
|
|
298
|
+
reaper_thread = None
|
|
299
|
+
|
|
281
300
|
while True:
|
|
282
301
|
data = stdout.readline().encode("latin1")
|
|
283
302
|
|
|
@@ -286,6 +305,8 @@ def run_command(prefix, args, *, extra_env=None, cwd=None):
|
|
|
286
305
|
|
|
287
306
|
print_line(prefix, data)
|
|
288
307
|
|
|
308
|
+
if reaper_thread:
|
|
309
|
+
reaper_thread.join()
|
|
289
310
|
return p.wait()
|
|
290
311
|
|
|
291
312
|
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/src/taskgraph/util/taskcluster.py
RENAMED
|
@@ -175,9 +175,8 @@ def get_artifact(task_id, path):
|
|
|
175
175
|
|
|
176
176
|
def list_artifacts(task_id):
|
|
177
177
|
queue = get_taskcluster_client("queue")
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
return task["artifacts"]
|
|
178
|
+
response = queue.listLatestArtifacts(task_id)
|
|
179
|
+
return response["artifacts"]
|
|
181
180
|
|
|
182
181
|
|
|
183
182
|
def get_artifact_prefix(task):
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import io
|
|
7
|
+
import stat
|
|
8
|
+
import tarfile
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from taskgraph.util.archive import (
|
|
13
|
+
DEFAULT_MTIME,
|
|
14
|
+
create_tar_from_files,
|
|
15
|
+
create_tar_gz_from_files,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
MODE_STANDARD = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def file_hash(path):
|
|
22
|
+
h = hashlib.sha1()
|
|
23
|
+
with open(path, "rb") as fh:
|
|
24
|
+
while True:
|
|
25
|
+
data = fh.read(8192)
|
|
26
|
+
if not data:
|
|
27
|
+
break
|
|
28
|
+
h.update(data)
|
|
29
|
+
|
|
30
|
+
return h.hexdigest()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@pytest.fixture
|
|
34
|
+
def create_files(tmp_path):
|
|
35
|
+
def inner():
|
|
36
|
+
files = {}
|
|
37
|
+
for i in range(10):
|
|
38
|
+
p = tmp_path / f"file{i:02d}"
|
|
39
|
+
p.write_bytes(b"file%02d" % i)
|
|
40
|
+
# Need to set permissions or umask may influence testing.
|
|
41
|
+
p.chmod(MODE_STANDARD)
|
|
42
|
+
files[f"file{i:02d}"] = str(p)
|
|
43
|
+
|
|
44
|
+
for i in range(10):
|
|
45
|
+
files[f"file{i + 10:02d}"] = io.BytesIO(b"file%02d" % (i + 10))
|
|
46
|
+
|
|
47
|
+
return files
|
|
48
|
+
|
|
49
|
+
return inner
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def verify_basic_tarfile(tf):
|
|
53
|
+
assert len(tf.getmembers()) == 20
|
|
54
|
+
|
|
55
|
+
names = [f"file{i:02d}" for i in range(20)]
|
|
56
|
+
assert tf.getnames() == names
|
|
57
|
+
|
|
58
|
+
for ti in tf.getmembers():
|
|
59
|
+
assert ti.uid == 0
|
|
60
|
+
assert ti.gid == 0
|
|
61
|
+
assert ti.uname == ""
|
|
62
|
+
assert ti.gname == ""
|
|
63
|
+
assert ti.mode == MODE_STANDARD
|
|
64
|
+
assert ti.mtime == DEFAULT_MTIME
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@pytest.mark.xfail(reason="ValueError is not thrown despite being provided directory.")
|
|
68
|
+
def test_dirs_refused(tmp_path):
|
|
69
|
+
tp = tmp_path / "test.tar"
|
|
70
|
+
with open(tp, "wb") as fh:
|
|
71
|
+
with pytest.raises(ValueError, match="not a regular"):
|
|
72
|
+
create_tar_from_files(fh, {"test": str(tmp_path)})
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_setuid_setgid_refused(tmp_path):
|
|
76
|
+
uid = tmp_path / "setuid"
|
|
77
|
+
uid.touch()
|
|
78
|
+
uid.chmod(MODE_STANDARD | stat.S_ISUID)
|
|
79
|
+
|
|
80
|
+
gid = tmp_path / "setgid"
|
|
81
|
+
gid.touch()
|
|
82
|
+
gid.chmod(MODE_STANDARD | stat.S_ISGID)
|
|
83
|
+
|
|
84
|
+
tp = tmp_path / "test.tar"
|
|
85
|
+
with open(tp, "wb") as fh:
|
|
86
|
+
with pytest.raises(ValueError, match="cannot add file with setuid"):
|
|
87
|
+
create_tar_from_files(fh, {"test": str(uid)})
|
|
88
|
+
with pytest.raises(ValueError, match="cannot add file with setuid"):
|
|
89
|
+
create_tar_from_files(fh, {"test": str(gid)})
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_create_tar_basic(tmp_path, create_files):
|
|
93
|
+
files = create_files()
|
|
94
|
+
|
|
95
|
+
tp = tmp_path / "test.tar"
|
|
96
|
+
with open(tp, "wb") as fh:
|
|
97
|
+
create_tar_from_files(fh, files)
|
|
98
|
+
|
|
99
|
+
# Output should be deterministic.
|
|
100
|
+
assert file_hash(tp) == "01cd314e277f060e98c7de6c8ea57f96b3a2065c"
|
|
101
|
+
|
|
102
|
+
with tarfile.open(tp, "r") as tf:
|
|
103
|
+
verify_basic_tarfile(tf)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_executable_preserved(tmp_path):
|
|
107
|
+
p = tmp_path / "exec"
|
|
108
|
+
p.write_bytes(b"#!/bin/bash\n")
|
|
109
|
+
p.chmod(MODE_STANDARD | stat.S_IXUSR)
|
|
110
|
+
|
|
111
|
+
tp = tmp_path / "test.tar"
|
|
112
|
+
with open(tp, "wb") as fh:
|
|
113
|
+
create_tar_from_files(fh, {"exec": str(p)})
|
|
114
|
+
|
|
115
|
+
# Test determinism by creating the same file again
|
|
116
|
+
tp2 = tmp_path / "test2.tar"
|
|
117
|
+
with open(tp2, "wb") as fh:
|
|
118
|
+
create_tar_from_files(fh, {"exec": str(p)})
|
|
119
|
+
|
|
120
|
+
assert file_hash(str(tp)) == file_hash(str(tp2))
|
|
121
|
+
|
|
122
|
+
# Verify executable permissions are preserved in tar
|
|
123
|
+
with tarfile.open(tp, "r") as tf:
|
|
124
|
+
m = tf.getmember("exec")
|
|
125
|
+
assert m.mode == MODE_STANDARD | stat.S_IXUSR
|
|
126
|
+
|
|
127
|
+
# Verify file content is correct
|
|
128
|
+
extracted_content = tf.extractfile(m).read()
|
|
129
|
+
assert extracted_content == b"#!/bin/bash\n"
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_create_tar_gz_basic(tmp_path, create_files):
|
|
133
|
+
gp = tmp_path / "test.tar.gz"
|
|
134
|
+
with open(gp, "wb") as fh:
|
|
135
|
+
create_tar_gz_from_files(fh, create_files())
|
|
136
|
+
|
|
137
|
+
# Test determinism by creating the same file again with fresh BytesIO objects
|
|
138
|
+
gp2 = tmp_path / "test2.tar.gz"
|
|
139
|
+
with open(gp2, "wb") as fh:
|
|
140
|
+
create_tar_gz_from_files(fh, create_files())
|
|
141
|
+
|
|
142
|
+
assert file_hash(str(gp)) == file_hash(str(gp2))
|
|
143
|
+
|
|
144
|
+
# Create uncompressed version for size comparison
|
|
145
|
+
tp = tmp_path / "test.tar"
|
|
146
|
+
with open(tp, "wb") as fh:
|
|
147
|
+
create_tar_from_files(fh, create_files())
|
|
148
|
+
uncompressed_size = tp.stat().st_size
|
|
149
|
+
compressed_size = gp.stat().st_size
|
|
150
|
+
|
|
151
|
+
# Compressed should be smaller than uncompressed
|
|
152
|
+
assert compressed_size < uncompressed_size
|
|
153
|
+
|
|
154
|
+
# Verify the contents are correct
|
|
155
|
+
with tarfile.open(gp, "r:gz") as tf:
|
|
156
|
+
verify_basic_tarfile(tf)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def test_tar_gz_name(tmp_path, create_files):
|
|
160
|
+
gp = tmp_path / "test.tar.gz"
|
|
161
|
+
with open(gp, "wb") as fh:
|
|
162
|
+
create_tar_gz_from_files(fh, create_files(), filename="foobar")
|
|
163
|
+
|
|
164
|
+
# Test determinism by creating the same file again with fresh BytesIO objects
|
|
165
|
+
gp2 = tmp_path / "test2.tar.gz"
|
|
166
|
+
with open(gp2, "wb") as fh:
|
|
167
|
+
create_tar_gz_from_files(fh, create_files(), filename="foobar")
|
|
168
|
+
|
|
169
|
+
assert file_hash(str(gp)) == file_hash(str(gp2))
|
|
170
|
+
|
|
171
|
+
# Create version without filename for comparison
|
|
172
|
+
gp_no_name = tmp_path / "test_no_name.tar.gz"
|
|
173
|
+
with open(gp_no_name, "wb") as fh:
|
|
174
|
+
create_tar_gz_from_files(fh, create_files())
|
|
175
|
+
|
|
176
|
+
# Files should be different (different filename in gzip header)
|
|
177
|
+
assert file_hash(str(gp)) != file_hash(str(gp_no_name))
|
|
178
|
+
|
|
179
|
+
# Verify the contents are correct
|
|
180
|
+
with tarfile.open(gp, "r:gz") as tf:
|
|
181
|
+
verify_basic_tarfile(tf)
|
|
@@ -110,16 +110,25 @@ def test_get_artifact(responses, root_url):
|
|
|
110
110
|
|
|
111
111
|
# Test text artifact
|
|
112
112
|
responses.get(
|
|
113
|
-
|
|
113
|
+
"http://foo.bar/artifact.txt",
|
|
114
114
|
body=b"foobar",
|
|
115
115
|
)
|
|
116
|
+
responses.get(
|
|
117
|
+
f"{root_url}/api/queue/v1/task/{tid}/artifacts/artifact.txt",
|
|
118
|
+
body=b'{"type": "s3", "url": "http://foo.bar/artifact.txt"}',
|
|
119
|
+
status=303,
|
|
120
|
+
headers={"Location": "http://foo.bar/artifact.txt"},
|
|
121
|
+
)
|
|
116
122
|
raw = tc.get_artifact(tid, "artifact.txt")
|
|
117
123
|
assert raw.read() == b"foobar"
|
|
118
124
|
|
|
119
125
|
# Test JSON artifact
|
|
126
|
+
responses.get("http://foo.bar/artifact.json", json={"foo": "bar"})
|
|
120
127
|
responses.get(
|
|
121
128
|
f"{root_url}/api/queue/v1/task/{tid}/artifacts/artifact.json",
|
|
122
|
-
|
|
129
|
+
body=b'{"type": "s3", "url": "http://foo.bar/artifact.json"}',
|
|
130
|
+
status=303,
|
|
131
|
+
headers={"Location": "http://foo.bar/artifact.json"},
|
|
123
132
|
)
|
|
124
133
|
result = tc.get_artifact(tid, "artifact.json")
|
|
125
134
|
assert result == {"foo": "bar"}
|
|
@@ -127,9 +136,15 @@ def test_get_artifact(responses, root_url):
|
|
|
127
136
|
# Test YAML artifact
|
|
128
137
|
expected_result = {"foo": b"\xe2\x81\x83".decode()}
|
|
129
138
|
responses.get(
|
|
130
|
-
|
|
139
|
+
"http://foo.bar/artifact.yml",
|
|
131
140
|
body=b'foo: "\xe2\x81\x83"',
|
|
132
141
|
)
|
|
142
|
+
responses.get(
|
|
143
|
+
f"{root_url}/api/queue/v1/task/{tid}/artifacts/artifact.yml",
|
|
144
|
+
body=b'{"type": "s3", "url": "http://foo.bar/artifact.yml"}',
|
|
145
|
+
status=303,
|
|
146
|
+
headers={"Location": "http://foo.bar/artifact.yml"},
|
|
147
|
+
)
|
|
133
148
|
result = tc.get_artifact(tid, "artifact.yml")
|
|
134
149
|
assert result == expected_result
|
|
135
150
|
|
|
@@ -139,7 +154,7 @@ def test_list_artifact(responses, root_url):
|
|
|
139
154
|
tc.get_taskcluster_client.cache_clear()
|
|
140
155
|
|
|
141
156
|
responses.get(
|
|
142
|
-
f"{root_url}/api/queue/v1/task/{tid}",
|
|
157
|
+
f"{root_url}/api/queue/v1/task/{tid}/artifacts",
|
|
143
158
|
json={"artifacts": ["file1.txt", "file2.json"]},
|
|
144
159
|
)
|
|
145
160
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
version = 1
|
|
2
|
-
revision =
|
|
2
|
+
revision = 3
|
|
3
3
|
requires-python = ">=3.8"
|
|
4
4
|
resolution-markers = [
|
|
5
5
|
"python_full_version >= '3.11'",
|
|
@@ -998,7 +998,7 @@ version = "1.3.0"
|
|
|
998
998
|
source = { registry = "https://pypi.org/simple" }
|
|
999
999
|
dependencies = [
|
|
1000
1000
|
{ name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
1001
|
-
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.
|
|
1001
|
+
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" },
|
|
1002
1002
|
]
|
|
1003
1003
|
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" }
|
|
1004
1004
|
wheels = [
|
|
@@ -3320,7 +3320,7 @@ wheels = [
|
|
|
3320
3320
|
|
|
3321
3321
|
[[package]]
|
|
3322
3322
|
name = "taskcluster"
|
|
3323
|
-
version = "
|
|
3323
|
+
version = "91.0.0"
|
|
3324
3324
|
source = { registry = "https://pypi.org/simple" }
|
|
3325
3325
|
dependencies = [
|
|
3326
3326
|
{ name = "aiohttp", version = "3.10.11", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
@@ -3333,14 +3333,14 @@ dependencies = [
|
|
|
3333
3333
|
{ name = "slugid" },
|
|
3334
3334
|
{ name = "taskcluster-urls" },
|
|
3335
3335
|
]
|
|
3336
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
3336
|
+
sdist = { url = "https://files.pythonhosted.org/packages/64/b9/96fc43251b42348b2e422a45bd7c6795311e32e322b141e97be83ba28e64/taskcluster-91.0.0.tar.gz", hash = "sha256:2e21feac068750503a32f4ca4273c904d8455d6b1db8e7295c3aa119af65abf4", size = 129244, upload-time = "2025-10-14T17:13:33.602Z" }
|
|
3337
3337
|
wheels = [
|
|
3338
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
3338
|
+
{ url = "https://files.pythonhosted.org/packages/2c/16/92be916f30d90ae41ee406a843f42bbedbe95109d61cb188187ab72bad75/taskcluster-91.0.0-py3-none-any.whl", hash = "sha256:c6301a5f730bb65feb2811b1190bef8124af0aeddd931eb877e066202348f5bd", size = 147340, upload-time = "2025-10-14T17:13:31.658Z" },
|
|
3339
3339
|
]
|
|
3340
3340
|
|
|
3341
3341
|
[[package]]
|
|
3342
3342
|
name = "taskcluster-taskgraph"
|
|
3343
|
-
version = "16.2"
|
|
3343
|
+
version = "16.2.1"
|
|
3344
3344
|
source = { editable = "." }
|
|
3345
3345
|
dependencies = [
|
|
3346
3346
|
{ name = "appdirs" },
|
|
@@ -3411,7 +3411,7 @@ requires-dist = [
|
|
|
3411
3411
|
{ name = "redo", specifier = ">=2.0" },
|
|
3412
3412
|
{ name = "requests", specifier = ">=2.25" },
|
|
3413
3413
|
{ name = "slugid", specifier = ">=2.0" },
|
|
3414
|
-
{ name = "taskcluster", specifier = ">=
|
|
3414
|
+
{ name = "taskcluster", specifier = ">=91.0" },
|
|
3415
3415
|
{ name = "taskcluster-urls", specifier = ">=11.0" },
|
|
3416
3416
|
{ name = "voluptuous", specifier = ">=0.12.1" },
|
|
3417
3417
|
{ name = "zstandard", marker = "extra == 'load-image'" },
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
-
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
-
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
4
|
-
|
|
5
|
-
import hashlib
|
|
6
|
-
import io
|
|
7
|
-
import os
|
|
8
|
-
import shutil
|
|
9
|
-
import stat
|
|
10
|
-
import tarfile
|
|
11
|
-
import tempfile
|
|
12
|
-
import unittest
|
|
13
|
-
|
|
14
|
-
import pytest
|
|
15
|
-
|
|
16
|
-
from taskgraph.util.archive import (
|
|
17
|
-
DEFAULT_MTIME,
|
|
18
|
-
create_tar_from_files,
|
|
19
|
-
create_tar_gz_from_files,
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
MODE_STANDARD = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def file_hash(path):
|
|
26
|
-
h = hashlib.sha1()
|
|
27
|
-
with open(path, "rb") as fh:
|
|
28
|
-
while True:
|
|
29
|
-
data = fh.read(8192)
|
|
30
|
-
if not data:
|
|
31
|
-
break
|
|
32
|
-
h.update(data)
|
|
33
|
-
|
|
34
|
-
return h.hexdigest()
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class TestArchive(unittest.TestCase):
|
|
38
|
-
def _create_files(self, root):
|
|
39
|
-
files = {}
|
|
40
|
-
for i in range(10):
|
|
41
|
-
p = os.path.join(root, f"file{i:02d}")
|
|
42
|
-
with open(p, "wb") as fh:
|
|
43
|
-
fh.write(b"file%02d" % i)
|
|
44
|
-
# Need to set permissions or umask may influence testing.
|
|
45
|
-
os.chmod(p, MODE_STANDARD)
|
|
46
|
-
files[f"file{i:02d}"] = p
|
|
47
|
-
|
|
48
|
-
for i in range(10):
|
|
49
|
-
files[f"file{i + 10:02d}"] = io.BytesIO(b"file%02d" % (i + 10))
|
|
50
|
-
|
|
51
|
-
return files
|
|
52
|
-
|
|
53
|
-
def _verify_basic_tarfile(self, tf):
|
|
54
|
-
self.assertEqual(len(tf.getmembers()), 20)
|
|
55
|
-
|
|
56
|
-
names = [f"file{i:02d}" for i in range(20)]
|
|
57
|
-
self.assertEqual(tf.getnames(), names)
|
|
58
|
-
|
|
59
|
-
for ti in tf.getmembers():
|
|
60
|
-
self.assertEqual(ti.uid, 0)
|
|
61
|
-
self.assertEqual(ti.gid, 0)
|
|
62
|
-
self.assertEqual(ti.uname, "")
|
|
63
|
-
self.assertEqual(ti.gname, "")
|
|
64
|
-
self.assertEqual(ti.mode, MODE_STANDARD)
|
|
65
|
-
self.assertEqual(ti.mtime, DEFAULT_MTIME)
|
|
66
|
-
|
|
67
|
-
@pytest.mark.xfail(
|
|
68
|
-
reason="ValueError is not thrown despite being provided directory."
|
|
69
|
-
)
|
|
70
|
-
def test_dirs_refused(self):
|
|
71
|
-
d = tempfile.mkdtemp()
|
|
72
|
-
try:
|
|
73
|
-
tp = os.path.join(d, "test.tar")
|
|
74
|
-
with open(tp, "wb") as fh:
|
|
75
|
-
with self.assertRaisesRegex(ValueError, "not a regular"):
|
|
76
|
-
create_tar_from_files(fh, {"test": d})
|
|
77
|
-
finally:
|
|
78
|
-
shutil.rmtree(d)
|
|
79
|
-
|
|
80
|
-
def test_setuid_setgid_refused(self):
|
|
81
|
-
d = tempfile.mkdtemp()
|
|
82
|
-
try:
|
|
83
|
-
uid = os.path.join(d, "setuid")
|
|
84
|
-
gid = os.path.join(d, "setgid")
|
|
85
|
-
with open(uid, "a"):
|
|
86
|
-
pass
|
|
87
|
-
with open(gid, "a"):
|
|
88
|
-
pass
|
|
89
|
-
|
|
90
|
-
os.chmod(uid, MODE_STANDARD | stat.S_ISUID)
|
|
91
|
-
os.chmod(gid, MODE_STANDARD | stat.S_ISGID)
|
|
92
|
-
|
|
93
|
-
tp = os.path.join(d, "test.tar")
|
|
94
|
-
with open(tp, "wb") as fh:
|
|
95
|
-
with self.assertRaisesRegex(ValueError, "cannot add file with setuid"):
|
|
96
|
-
create_tar_from_files(fh, {"test": uid})
|
|
97
|
-
with self.assertRaisesRegex(ValueError, "cannot add file with setuid"):
|
|
98
|
-
create_tar_from_files(fh, {"test": gid})
|
|
99
|
-
finally:
|
|
100
|
-
shutil.rmtree(d)
|
|
101
|
-
|
|
102
|
-
def test_create_tar_basic(self):
|
|
103
|
-
d = tempfile.mkdtemp()
|
|
104
|
-
try:
|
|
105
|
-
files = self._create_files(d)
|
|
106
|
-
|
|
107
|
-
tp = os.path.join(d, "test.tar")
|
|
108
|
-
with open(tp, "wb") as fh:
|
|
109
|
-
create_tar_from_files(fh, files)
|
|
110
|
-
|
|
111
|
-
# Output should be deterministic.
|
|
112
|
-
self.assertEqual(file_hash(tp), "01cd314e277f060e98c7de6c8ea57f96b3a2065c")
|
|
113
|
-
|
|
114
|
-
with tarfile.open(tp, "r") as tf:
|
|
115
|
-
self._verify_basic_tarfile(tf)
|
|
116
|
-
|
|
117
|
-
finally:
|
|
118
|
-
shutil.rmtree(d)
|
|
119
|
-
|
|
120
|
-
@pytest.mark.xfail(reason="hash mismatch")
|
|
121
|
-
def test_executable_preserved(self):
|
|
122
|
-
d = tempfile.mkdtemp()
|
|
123
|
-
try:
|
|
124
|
-
p = os.path.join(d, "exec")
|
|
125
|
-
with open(p, "wb") as fh:
|
|
126
|
-
fh.write("#!/bin/bash\n")
|
|
127
|
-
os.chmod(p, MODE_STANDARD | stat.S_IXUSR)
|
|
128
|
-
|
|
129
|
-
tp = os.path.join(d, "test.tar")
|
|
130
|
-
with open(tp, "wb") as fh:
|
|
131
|
-
create_tar_from_files(fh, {"exec": p})
|
|
132
|
-
|
|
133
|
-
self.assertEqual(file_hash(tp), "357e1b81c0b6cfdfa5d2d118d420025c3c76ee93")
|
|
134
|
-
|
|
135
|
-
with tarfile.open(tp, "r") as tf:
|
|
136
|
-
m = tf.getmember("exec")
|
|
137
|
-
self.assertEqual(m.mode, MODE_STANDARD | stat.S_IXUSR)
|
|
138
|
-
|
|
139
|
-
finally:
|
|
140
|
-
shutil.rmtree(d)
|
|
141
|
-
|
|
142
|
-
def test_create_tar_gz_basic(self):
|
|
143
|
-
d = tempfile.mkdtemp()
|
|
144
|
-
try:
|
|
145
|
-
files = self._create_files(d)
|
|
146
|
-
|
|
147
|
-
gp = os.path.join(d, "test.tar.gz")
|
|
148
|
-
with open(gp, "wb") as fh:
|
|
149
|
-
create_tar_gz_from_files(fh, files)
|
|
150
|
-
|
|
151
|
-
self.assertEqual(file_hash(gp), "7c4da5adc5088cdf00911d5daf9a67b15de714b7")
|
|
152
|
-
|
|
153
|
-
with tarfile.open(gp, "r:gz") as tf:
|
|
154
|
-
self._verify_basic_tarfile(tf)
|
|
155
|
-
|
|
156
|
-
finally:
|
|
157
|
-
shutil.rmtree(d)
|
|
158
|
-
|
|
159
|
-
def test_tar_gz_name(self):
|
|
160
|
-
d = tempfile.mkdtemp()
|
|
161
|
-
try:
|
|
162
|
-
files = self._create_files(d)
|
|
163
|
-
|
|
164
|
-
gp = os.path.join(d, "test.tar.gz")
|
|
165
|
-
with open(gp, "wb") as fh:
|
|
166
|
-
create_tar_gz_from_files(fh, files, filename="foobar")
|
|
167
|
-
|
|
168
|
-
self.assertEqual(file_hash(gp), "721e00083c17d16df2edbddf40136298c06d0c49")
|
|
169
|
-
|
|
170
|
-
with tarfile.open(gp, "r:gz") as tf:
|
|
171
|
-
self._verify_basic_tarfile(tf)
|
|
172
|
-
|
|
173
|
-
finally:
|
|
174
|
-
shutil.rmtree(d)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/workflows/codeql-analysis.yml
RENAMED
|
File without changes
|
|
File without changes
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/workflows/pre-commit.yml
RENAMED
|
File without changes
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/.github/workflows/pypi-publish.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/concepts/optimization.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/bootstrap-taskgraph.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/load-task-locally.rst
RENAMED
|
File without changes
|
{taskcluster_taskgraph-16.2.0 → taskcluster_taskgraph-16.2.1}/docs/howto/resolve-keyed-by.rst
RENAMED
|
File without changes
|
|
File without changes
|