diff options
Diffstat (limited to 'testing/web-platform/tests/docs/frontend.py')
-rw-r--r-- | testing/web-platform/tests/docs/frontend.py | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/testing/web-platform/tests/docs/frontend.py b/testing/web-platform/tests/docs/frontend.py new file mode 100644 index 0000000000..c8d114b39f --- /dev/null +++ b/testing/web-platform/tests/docs/frontend.py @@ -0,0 +1,127 @@ +import argparse +import logging +import os +import subprocess +import sys + +here = os.path.dirname(__file__) +wpt_root = os.path.abspath(os.path.join(here, "..")) + +# Directories relative to the wpt root that we want to include in the docs +# Sphinx doesn't support including files outside of docs/ so we temporarily symlink +# these directories under docs/ whilst running the build. +link_dirs = [ + "tools/wptserve", + "tools/certs", + "tools/wptrunner", + "tools/webtransport", + "tools/third_party/pywebsocket3", +] + +logger = logging.getLogger() + + +def link_source_dirs(): + created = set() + failed = [] + for rel_path in link_dirs: + rel_path = rel_path.replace("/", os.path.sep) + src = os.path.join(wpt_root, rel_path) + dest = os.path.join(here, rel_path) + try: + dest_dir = os.path.dirname(dest) + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + created.add(dest_dir) + if not os.path.exists(dest): + os.symlink(src, dest, target_is_directory=True) + else: + if (not os.path.islink(dest) or + os.path.join(os.path.dirname(dest), os.readlink(dest)) != src): + # The file exists but it isn't a link or points at the wrong target + raise OSError("File exists") + except Exception as e: + failed.append((dest, e)) + else: + created.add(dest) + return created, failed + + +def unlink_source_dirs(created): + # Sort backwards in length to remove all files before getting to directory + for path in sorted(created, key=lambda x: -len(x)): + # This will also remove empty parent directories + if not os.path.islink(path) and os.path.isdir(path): + os.removedirs(path) + else: + os.unlink(path) + + +def get_parser(): + p = argparse.ArgumentParser() + p.add_argument("--type", default="html", help="Output type (default: html)") + p.add_argument("--docker", action="store_true", help="Run inside the docs docker image") + p.add_argument("--serve", default=None, nargs="?", const=8000, + type=int, help="Run a server on the specified port (default: 8000)") + return p + + +def docker_build(tag="wpt:docs"): + subprocess.check_call(["docker", + "build", + "--pull", + "--tag", tag, + here]) + +def docker_run(**kwargs): + cmd = ["docker", "run"] + cmd.extend(["--mount", + "type=bind,source=%s,target=/app/web-platform-tests" % wpt_root]) + if kwargs["serve"] is not None: + serve = str(kwargs["serve"]) + cmd.extend(["--expose", serve, "--publish", f"{serve}:{serve}"]) + cmd.extend(["-w", "/app/web-platform-tests"]) + if os.isatty(os.isatty(sys.stdout.fileno())): + cmd.append("-it") + cmd.extend(["wpt:docs", "./wpt"]) + # /app/venv is created during docker build and is always active inside the + # container. + cmd.extend(["--venv", "/app/venv", "--skip-venv-setup"]) + cmd.extend(["build-docs", "--type", kwargs["type"]]) + if kwargs["serve"] is not None: + cmd.extend(["--serve", str(kwargs["serve"])]) + logger.debug(" ".join(cmd)) + return subprocess.call(cmd) + + +def build(_venv, **kwargs): + if kwargs["docker"]: + docker_build() + return docker_run(**kwargs) + + out_dir = os.path.join(here, "_build") + try: + created, failed = link_source_dirs() + if failed: + failure_msg = "\n".join(f"{dest}: {err}" for (dest, err) in failed) + logger.error(f"Failed to create source symlinks:\n{failure_msg}") + sys.exit(1) + if kwargs["serve"] is not None: + executable = "sphinx-autobuild" + extras = ["--port", str(kwargs["serve"]), + "--host", "0.0.0.0", + "--watch", os.path.abspath(os.path.join(here, os.pardir, "resources")), + # Ignore changes to files specified with glob pattern + "--ignore", "**/flycheck_*", + "--ignore", "**/.*", + "--ignore", "**/#*", + "--ignore", "docs/frontend.py", + "--ignore", "docs/Dockerfile"] + else: + executable = "sphinx-build" + extras = [] + cmd = [executable, "-n", "-v", "-b", kwargs["type"], "-j", "auto"] + extras + [here, out_dir] + logger.debug(" ".join(cmd)) + subprocess.check_call(cmd) + finally: + unlink_source_dirs(created) |