Skip to content

Commit

Permalink
Add a wpt docker-push command (#23742)
Browse files Browse the repository at this point in the history
Co-authored-by: Robert Ma <[email protected]>
  • Loading branch information
jgraham and Hexcles authored Jun 1, 2020
1 parent f5dbcc5 commit e2580a2
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 17 deletions.
18 changes: 8 additions & 10 deletions tools/docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ images must be updated as well. Doing this requires you be part of the
'webplatformtests' organization on Docker Hub; ping @Hexcles or @stephenmcgruer
if you are not a member.

In this directory, run the following, where `<tag>` is of the form
`webplatformtests/wpt:{current-version + 0.01}`:
The tag for a new docker image is of the form
`webplatformtests/wpt:{current-version + 0.01}`

```sh
# --pull forces Docker to get the newest base image.
docker build --pull -t <tag> .
docker push <tag>
```
To update the docker image:

Then update the following Taskcluster configurations to use the new image:
* `.taskcluster.yml` (the decision task)
* `tools/ci/tc/tasks/test.yml` (all the other tasks)
* Update the following Taskcluster configurations to use the new image:
- `.taskcluster.yml` (the decision task)
- `tools/ci/tc/tasks/test.yml` (all the other tasks)

* Run `wpt docker-push`
28 changes: 24 additions & 4 deletions tools/docker/commands.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
{
"docker-run": {"path": "frontend.py", "script": "run", "parser": "parser_run", "help": "Run wpt docker image",
"virtualenv": false},
"docker-build": {"path": "frontend.py", "script": "build", "help": "Build wpt docker image",
"virtualenv": false}
"docker-run": {
"path": "frontend.py",
"script": "run",
"parser": "parser_run",
"help": "Run wpt docker image",
"virtualenv": false
},
"docker-build": {
"path": "frontend.py",
"script": "build",
"help": "Build wpt docker image",
"virtualenv": false
},
"docker-push": {
"path": "frontend.py",
"script": "push",
"parser": "parser_push",
"help": "Build and push wpt docker image",
"virtualenv": true,
"install": [
"requests",
"pyyaml"
]
}
}
99 changes: 96 additions & 3 deletions tools/docker/frontend.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,111 @@
import argparse
import subprocess
import logging
import os
import re
import subprocess
import sys

from six import iteritems

here = os.path.abspath(os.path.dirname(__file__))
wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir))

def build(*args, **kwargs):
logger = logging.getLogger()


def build(tag="wpt:local", *args, **kwargs):
subprocess.check_call(["docker",
"build",
"--pull",
"--tag", "wpt:local",
"--tag", tag,
here])


def parser_push():
parser = argparse.ArgumentParser()
parser.add_argument("--tag", action="store",
help="Tag to use (default is taken from .taskcluster.yml)")
parser.add_argument("--force", action="store_true",
help="Ignore warnings and push anyway")
return parser


def walk_yaml(root, target):
rv = []
if isinstance(root, list):
for value in root:
if isinstance(value, (dict, list)):
rv.extend(walk_yaml(value, target))
elif isinstance(root, dict):
for key, value in iteritems(root):
if isinstance(value, (dict, list)):
rv.extend(walk_yaml(value, target))
elif key == target:
rv.append(value)
return rv


def read_image_name():
import yaml
with open(os.path.join(wpt_root, ".taskcluster.yml")) as f:
taskcluster_data = yaml.safe_load(f)
taskcluster_values = set(walk_yaml(taskcluster_data, "image"))
with open(os.path.join(wpt_root, "tools", "ci", "tc", "tasks", "test.yml")) as f:
test_data = yaml.safe_load(f)
tests_value = test_data["components"]["wpt-base"]["image"]
return taskcluster_values, tests_value


def lookup_tag(tag):
import requests
org, repo_version = tag.split("/", 1)
repo, version = repo_version.rsplit(":", 1)
resp = requests.get("https://hub.docker.com/v2/repositories/%s/%s/tags/%s" %
(org, repo, version))
if resp.status_code == 200:
return True
if resp.status_code == 404:
return False
resp.raise_for_status()


def push(venv, tag=None, force=False, *args, **kwargs):
taskcluster_tags, tests_tag = read_image_name()

taskcluster_tag = taskcluster_tags.pop()

error_log = logger.warning if force else logger.error
if len(taskcluster_tags) != 0 or tests_tag != taskcluster_tag:
error_log("Image names in .taskcluster.yml and tools/ci/tc/tasks/test.yml "
"don't match.")
if not force:
sys.exit(1)
if tag is not None and tag != taskcluster_tag:
error_log("Supplied tag doesn't match .taskcluster.yml or "
"tools/ci/tc/tasks/test.yml; remember to update before pushing")
if not force:
sys.exit(1)
if tag is None:
logger.info("Using tag %s from .taskcluster.yml" % taskcluster_tag)
tag = taskcluster_tag

tag_re = re.compile(r"webplatformtests/wpt:\d\.\d+")
if not tag_re.match(tag):
error_log("Tag doesn't match expected format webplatformtests/wpt:0.x")
if not force:
sys.exit(1)

if lookup_tag(tag):
# No override for this case
logger.critical("Tag %s already exists" % tag)
sys.exit(1)

build(tag)
subprocess.check_call(["docker",
"push",
tag])


def parser_run():
parser = argparse.ArgumentParser()
parser.add_argument("--rebuild", action="store_true", help="Force rebuild of image")
Expand Down

0 comments on commit e2580a2

Please sign in to comment.