From c33f5cc3a9f8712dc3aceee70f76e59c7df0d627 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 25 Sep 2018 09:25:30 +0200 Subject: [PATCH] Docstrings for decisionlib --- etc/ci/taskcluster/decisionlib.py | 46 ++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/etc/ci/taskcluster/decisionlib.py b/etc/ci/taskcluster/decisionlib.py index 5650131ad3e..53778221b07 100644 --- a/etc/ci/taskcluster/decisionlib.py +++ b/etc/ci/taskcluster/decisionlib.py @@ -23,20 +23,26 @@ import taskcluster class DecisionTask: + """ + Holds some project-specific configuration and provides higher-level functionality + on top of the `taskcluster` package a.k.a. `taskcluster-client.py`. + """ + DOCKER_IMAGE_ARTIFACT_FILENAME = "image.tar.lz4" # https://github.com/servo/taskcluster-bootstrap-docker-images#image-builder DOCKER_IMAGE_BUILDER_IMAGE = "servobrowser/taskcluster-bootstrap:image-builder@sha256:" \ "0a7d012ce444d62ffb9e7f06f0c52fedc24b68c2060711b313263367f7272d9d" - def __init__(self, *, index_prefix, task_name_template="%s", - worker_type="github-worker", docker_image_cache_expiry="1 year"): + def __init__(self, *, index_prefix="garbage.servo-decisionlib", task_name_template="%s", + worker_type="github-worker", docker_image_cache_expiry="1 year", + routes_for_all_subtasks=None, scopes_for_all_subtasks=None): self.task_name_template = task_name_template self.index_prefix = index_prefix self.worker_type = worker_type self.docker_image_cache_expiry = docker_image_cache_expiry - self.routes_for_all_subtasks = [] - self.scopes_for_all_subtasks = [] + self.routes_for_all_subtasks = routes_for_all_subtasks or [] + self.scopes_for_all_subtasks = scopes_for_all_subtasks or [] # https://docs.taskcluster.net/docs/reference/workers/docker-worker/docs/features#feature-taskclusterproxy self.queue_service = taskcluster.Queue(options={"baseUrl": "http://taskcluster/queue/v1/"}) @@ -46,9 +52,18 @@ class DecisionTask: self.found_or_created_indices = {} def from_now_json(self, offset): + """ + Same as `taskcluster.fromNowJSON`, but uses the creation time of `self` for “now”. + """ return taskcluster.stringDate(taskcluster.fromNow(offset, dateObj=self.now)) def find_or_create_task(self, *, index_bucket, index_key, index_expiry, artifacts, **kwargs): + """ + Find a task indexed in the given bucket (kind, category, …) and cache key, + on schedule a new one if there isn’t one yet. + + Returns the task ID. + """ index_path = "%s.%s.%s" % (self.index_prefix, index_bucket, index_key) task_id = self.found_or_created_indices.get(index_path) @@ -82,6 +97,12 @@ class DecisionTask: return task_id def find_or_build_docker_image(self, dockerfile): + """ + Find a task that built a Docker image based on this `dockerfile`, + or schedule a new image-building task if needed. + + Returns the task ID. + """ dockerfile_contents = expand_dockerfile(dockerfile) digest = hashlib.sha256(dockerfile_contents).hexdigest() @@ -114,6 +135,16 @@ class DecisionTask: artifacts=None, dependencies=None, env=None, cache=None, scopes=None, routes=None, extra=None, features=None, with_repo=True): + """ + Schedule a new task. Only supports `docker-worker` for now. + + Returns the new task ID. + + One of `docker_image` or `dockerfile` (but not both) must be given. + If `dockerfile` is given, the corresponding Docker image is built as needed and cached. + + `with_repo` indicates whether `script` should start in a clone of the git repository. + """ if docker_image and dockerfile: raise TypeError("cannot use both `docker_image` or `dockerfile`") if not docker_image and not dockerfile: @@ -201,6 +232,9 @@ class DecisionTask: def image_name(dockerfile): + """ + Guess a short name based on the path `dockerfile`. + """ basename = os.path.basename(dockerfile) suffix = ".dockerfile" if basename == "Dockerfile": @@ -212,6 +246,10 @@ def image_name(dockerfile): def expand_dockerfile(dockerfile): + """ + Read the file at path `dockerfile`, + and transitively expand the non-standard `% include` header if it is present. + """ with open(dockerfile, "rb") as f: dockerfile_contents = f.read()