Reorganize Servo's WPT Python scripts

This change moves all of Servo's WPT Python support scripts into one
directory as they were previously scattered throughout the directory
structure. This should allow more code reuse and make it easier to
understand how everything fits together.

The changes:

- `tests/wpt/update` → `python/wpt/importer`
- `etc/ci/upstream-wpt-changes/wptupstreamer` → `python/wpt/exporter`
- `etc/ci/upstream-wpt-changes/test.py` → `python/wpt/test.py`
- `etc/ci/upstream-wpt-changes/tests` → `python/wpt/tests`
- `tests/wpt/servowpt.py` →
    - `python/wpt/update.py`
    - `python/wpt/run.py`
- `tests/wpt/manifestupdate.py` → `python/wpt/manifestupdate.py`

This change also removes
 - The ability to run the `update-wpt` and `test-wpt` commands without
   using `mach`. These didn't work very well, because it was difficult
   to get all of the wptrunner and mach dependencies installed outside
   of the Python virtualenv. It's simpler if they are always run through
   `mach`.
- The old WPT change upstreaming script that was no longer used.
This commit is contained in:
Martin Robinson 2023-04-16 11:33:02 +02:00
parent 9acb9cc5cf
commit e2cf3e8d1a
52 changed files with 237 additions and 888 deletions

View file

@ -10,3 +10,8 @@ is the canonical repository for this code.
servo-tidy is used to check licenses, line lengths, whitespace, flake8 on
Python files, lock file versions, and more.
# `wpt`
servo-wpt is a module with support scripts for running, importing,
exporting, updating manifests, and updating expectations for WPT
tests.

View file

@ -22,6 +22,11 @@ import subprocess
from xml.etree.ElementTree import XML
from six import iteritems
import wpt
import wpt.manifestupdate
import wpt.run
import wpt.update
from mach.registrar import Registrar
from mach.decorators import (
CommandArgument,
@ -29,25 +34,19 @@ from mach.decorators import (
Command,
)
from servo_tidy import tidy
from servo.command_base import (
CommandBase,
call, check_call, check_output,
)
from servo.util import host_triple
from wptrunner import wptcommandline
from update import updatecommandline
from servo_tidy import tidy
from servo_tidy_tests import test_tidy
from servo.util import host_triple
SCRIPT_PATH = os.path.split(__file__)[0]
PROJECT_TOPLEVEL_PATH = os.path.abspath(os.path.join(SCRIPT_PATH, "..", ".."))
WEB_PLATFORM_TESTS_PATH = os.path.join("tests", "wpt", "web-platform-tests")
SERVO_TESTS_PATH = os.path.join("tests", "wpt", "mozilla", "tests")
sys.path.insert(0, os.path.join(PROJECT_TOPLEVEL_PATH, 'tests', 'wpt'))
import servowpt # noqa: E402
CLANGFMT_CPP_DIRS = ["support/hololens/"]
CLANGFMT_VERSION = "15"
@ -67,45 +66,6 @@ TEST_SUITES = OrderedDict([
TEST_SUITES_BY_PREFIX = {path: k for k, v in iteritems(TEST_SUITES) if "paths" in v for path in v["paths"]}
def create_parser_wpt():
import mozlog.commandline
parser = wptcommandline.create_parser()
parser.add_argument('--release', default=False, action="store_true",
help="Run with a release build of servo")
parser.add_argument('--rr-chaos', default=False, action="store_true",
help="Run under chaos mode in rr until a failure is captured")
parser.add_argument('--pref', default=[], action="append", dest="prefs",
help="Pass preferences to servo")
parser.add_argument('--layout-2020', '--with-layout-2020', default=False,
action="store_true", help="Use expected results for the 2020 layout engine")
parser.add_argument('--log-servojson', action="append", type=mozlog.commandline.log_file,
help="Servo's JSON logger of unexpected results")
parser.add_argument('--always-succeed', default=False, action="store_true",
help="Always yield exit code of zero")
parser.add_argument('--no-default-test-types', default=False, action="store_true",
help="Run all of the test types provided by wptrunner or specified explicitly by --test-types")
parser.add_argument('--filter-intermittents', default=None, action="store",
help="Filter intermittents against known intermittents "
"and save the filtered output to the given file.")
parser.add_argument('--log-raw-unexpected', default=None, action="store",
help="Raw structured log messages for unexpected results."
" '--log-raw' Must also be passed in order to use this.")
return parser
def create_parser_manifest_update():
import manifestupdate
return manifestupdate.create_parser()
def run_update(topdir, check_clean=False, rebuild=False, **kwargs):
import manifestupdate
from wptrunner import wptlogging
logger = wptlogging.setup(kwargs, {"mach": sys.stdout})
wpt_dir = os.path.abspath(os.path.join(topdir, 'tests', 'wpt'))
return manifestupdate.update(logger, wpt_dir, check_clean, rebuild)
@CommandProvider
class MachCommands(CommandBase):
DEFAULT_RENDER_MODE = "cpu"
@ -353,7 +313,7 @@ class MachCommands(CommandBase):
if no_wpt:
manifest_dirty = False
else:
manifest_dirty = run_update(self.context.topdir, check_clean=True)
manifest_dirty = wpt.manifestupdate.update(check_clean=True)
tidy_failed = tidy.scan(not all_files, not no_progress, stylo=stylo, no_wpt=no_wpt)
self.install_rustfmt()
rustfmt_failed = self.call_rustup_run(["cargo", "fmt", "--", "--check"])
@ -399,7 +359,7 @@ class MachCommands(CommandBase):
@Command('test-wpt-failure',
description='Run the tests harness that verifies that the test failures are reported correctly',
category='testing',
parser=create_parser_wpt)
parser=wpt.create_parser)
def test_wpt_failure(self, **kwargs):
kwargs["pause_after_test"] = False
kwargs["include"] = ["infrastructure/failing-test.html"]
@ -408,7 +368,7 @@ class MachCommands(CommandBase):
@Command('test-wpt',
description='Run the regular web platform test suite',
category='testing',
parser=create_parser_wpt)
parser=wpt.create_parser)
def test_wpt(self, **kwargs):
ret = self.run_test_list_or_dispatch(kwargs["test_list"], "wpt", self._test_wpt, **kwargs)
if kwargs["always_succeed"]:
@ -419,7 +379,7 @@ class MachCommands(CommandBase):
@Command('test-wpt-android',
description='Run the web platform test suite in an Android emulator',
category='testing',
parser=create_parser_wpt)
parser=wpt.create_parser)
def test_wpt_android(self, release=False, dev=False, binary_args=None, **kwargs):
kwargs.update(
release=release,
@ -433,7 +393,7 @@ class MachCommands(CommandBase):
def _test_wpt(self, android=False, **kwargs):
self.set_run_env(android)
return servowpt.run_tests(**kwargs)
return wpt.run.run_tests(**kwargs)
# Helper to ensure all specified paths are handled, otherwise dispatch to appropriate test suite.
def run_test_list_or_dispatch(self, requested_paths, correct_suite, correct_function, **kwargs):
@ -454,9 +414,9 @@ class MachCommands(CommandBase):
@Command('update-manifest',
description='Run test-wpt --manifest-update SKIP_TESTS to regenerate MANIFEST.json',
category='testing',
parser=create_parser_manifest_update)
parser=wpt.manifestupdate.create_parser)
def update_manifest(self, **kwargs):
return run_update(self.context.topdir, **kwargs)
return wpt.manifestupdate.update(check_clean=False)
@Command('fmt',
description='Format the Rust and CPP source files with rustfmt and clang-format',
@ -474,13 +434,13 @@ class MachCommands(CommandBase):
@Command('update-wpt',
description='Update the web platform tests',
category='testing',
parser=updatecommandline.create_parser())
parser=wpt.update.create_parser)
def update_wpt(self, **kwargs):
patch = kwargs.get("patch", False)
if not patch and kwargs["sync"]:
print("Are you sure you don't want a patch?")
return 1
return servowpt.update_tests(**kwargs)
return wpt.update.update_tests(**kwargs)
@Command('test-android-startup',
description='Extremely minimal testing of Servo for Android',
@ -826,7 +786,7 @@ testing/web-platform/mozilla/tests for Servo-only tests""" % reference_path)
proc = subprocess.Popen("%s %s" % (editor, test_path), shell=True)
if not kwargs["no_run"]:
p = create_parser_wpt()
p = wpt.create_parser()
args = []
if kwargs["release"]:
args.append("--release")

61
python/wpt/__init__.py Normal file
View file

@ -0,0 +1,61 @@
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
import os
import sys
import mozlog.commandline
SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__))
SERVO_ROOT = os.path.abspath(os.path.join(SCRIPT_PATH, "..", ".."))
WPT_PATH = os.path.join(SERVO_ROOT, "tests", "wpt")
WPT_TOOLS_PATH = os.path.join(WPT_PATH, "web-platform-tests", "tools")
CERTS_PATH = os.path.join(WPT_TOOLS_PATH, "certs")
sys.path.insert(0, WPT_TOOLS_PATH)
import localpaths # noqa: F401,E402
import wptrunner.wptcommandline # noqa: E402
def create_parser():
parser = wptrunner.wptcommandline.create_parser()
parser.add_argument('--release', default=False, action="store_true",
help="Run with a release build of servo")
parser.add_argument('--rr-chaos', default=False, action="store_true",
help="Run under chaos mode in rr until a failure is captured")
parser.add_argument('--pref', default=[], action="append", dest="prefs",
help="Pass preferences to servo")
parser.add_argument('--layout-2020', '--with-layout-2020', default=False,
action="store_true", help="Use expected results for the 2020 layout engine")
parser.add_argument('--log-servojson', action="append", type=mozlog.commandline.log_file,
help="Servo's JSON logger of unexpected results")
parser.add_argument('--always-succeed', default=False, action="store_true",
help="Always yield exit code of zero")
parser.add_argument('--no-default-test-types', default=False, action="store_true",
help="Run all of the test types provided by wptrunner or specified explicitly by --test-types")
parser.add_argument('--filter-intermittents', default=None, action="store",
help="Filter intermittents against known intermittents "
"and save the filtered output to the given file.")
parser.add_argument('--log-raw-unexpected', default=None, action="store",
help="Raw structured log messages for unexpected results."
" '--log-raw' Must also be passed in order to use this.")
return parser
def update_args_for_layout_2020(kwargs: dict):
if kwargs.pop("layout_2020"):
kwargs["test_paths"]["/"]["metadata_path"] = os.path.join(
WPT_PATH, "metadata-layout-2020"
)
kwargs["test_paths"]["/_mozilla/"]["metadata_path"] = os.path.join(
WPT_PATH, "mozilla", "meta-layout-2020"
)
kwargs["include_manifest"] = os.path.join(
WPT_PATH, "include-layout-2020.ini"
)

43
python/wpt/export.py Executable file
View file

@ -0,0 +1,43 @@
#!/usr/bin/env python
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# pylint: disable=missing-docstring
# pylint: disable=invalid-name
import json
import logging
import os
import sys
from exporter import WPTSync
def main() -> int:
context = json.loads(os.environ['GITHUB_CONTEXT'])
logging.getLogger().level = logging.INFO
success = WPTSync(
servo_repo='servo/servo',
wpt_repo='web-platform-tests/wpt',
downstream_wpt_repo='servo-wpt-sync/web-platform-tests',
servo_path='./servo',
wpt_path='./wpt',
github_api_token=os.environ['WPT_SYNC_TOKEN'],
github_api_url='https://api.github.com/',
github_username='servo-wpt-sync',
github_email='josh+wptsync@joshmatthews.net',
github_name='Servo WPT Sync',
).run(context["event"])
return 0 if success else 1
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,285 @@
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# pylint: disable=broad-except
# pylint: disable=dangerous-default-value
# pylint: disable=fixme
# pylint: disable=missing-docstring
# This allows using types that are defined later in the file.
from __future__ import annotations
import dataclasses
import json
import logging
import re
import subprocess
from typing import Callable, Optional
from .common import \
CLOSING_EXISTING_UPSTREAM_PR, \
NO_SYNC_SIGNAL, \
NO_UPSTREAMBLE_CHANGES_COMMENT, \
OPENED_NEW_UPSTREAM_PR, \
UPDATED_EXISTING_UPSTREAM_PR, \
UPDATED_TITLE_IN_EXISTING_UPSTREAM_PR, \
UPSTREAMABLE_PATH, \
wpt_branch_name_from_servo_pr_number
from .github import GithubRepository, PullRequest
from .step import \
AsyncValue, \
ChangePRStep, \
CommentStep, \
CreateOrUpdateBranchForPRStep, \
MergePRStep, \
OpenPRStep, \
RemoveBranchForPRStep, \
Step
class LocalGitRepo:
def __init__(self, path: str, sync: WPTSync):
self.path = path
self.sync = sync
def run_without_encoding(self, *args, env: dict = {}):
command_line = ["git"] + list(args)
logging.info(" → Execution (cwd='%s'): %s",
self.path, " ".join(command_line))
env.setdefault("GIT_AUTHOR_EMAIL", self.sync.github_email)
env.setdefault("GIT_COMMITTER_EMAIL", self.sync.github_email)
env.setdefault("GIT_AUTHOR_NAME", self.sync.github_name)
env.setdefault("GIT_COMMITTER_NAME", self.sync.github_name)
try:
return subprocess.check_output(
command_line, cwd=self.path, env=env, stderr=subprocess.STDOUT
)
except subprocess.CalledProcessError as exception:
logging.warning("Process execution failed with output:\n%s",
exception.output.decode("utf-8", errors="surrogateescape"))
raise exception
def run(self, *args, env: dict = {}):
return (
self
.run_without_encoding(*args, env=env)
.decode("utf-8", errors="surrogateescape")
)
@dataclasses.dataclass()
class SyncRun:
sync: WPTSync
servo_pr: PullRequest
upstream_pr: AsyncValue[PullRequest]
step_callback: Optional[Callable[[Step], None]]
steps: list[Step] = dataclasses.field(default_factory=list)
def make_comment(self, template: str) -> str:
upstream_pr = self.upstream_pr.value() if self.upstream_pr.has_value() else ""
return template.format(
upstream_pr=upstream_pr,
servo_pr=self.servo_pr,
)
def add_step(self, step) -> Optional[AsyncValue]:
self.steps.append(step)
return step.provides()
def run(self):
# This loop always removes the first step and runs it, because
# individual steps can modify the list of steps. For instance, if a
# step fails, it might clear the remaining steps and replace them with
# steps that report the error to GitHub.
while self.steps:
step = self.steps.pop(0)
step.run(self)
if self.step_callback:
self.step_callback(step)
@staticmethod
def clean_up_body_text(body: str) -> str:
# Turn all bare or relative issue references into unlinked ones, so that
# the PR doesn't inadvertently close or link to issues in the upstream
# repository.
return (
re.sub(
r"(^|\s)(\w*)#([1-9]\d*)",
r"\g<1>\g<2>#<!-- nolink -->\g<3>",
body,
flags=re.MULTILINE,
)
.split("\n---")[0]
.split("<!-- Thank you for")[0]
)
def prepare_body_text(self, body: str) -> str:
return SyncRun.clean_up_body_text(body) + f"\nReviewed in {self.servo_pr}"
@dataclasses.dataclass(kw_only=True)
class WPTSync:
servo_repo: str
wpt_repo: str
downstream_wpt_repo: str
servo_path: str
wpt_path: str
github_api_token: str
github_api_url: str
github_username: str
github_email: str
github_name: str
suppress_force_push: bool = False
def __post_init__(self):
self.servo = GithubRepository(self, self.servo_repo)
self.wpt = GithubRepository(self, self.wpt_repo)
self.downstream_wpt = GithubRepository(self, self.downstream_wpt_repo)
self.local_servo_repo = LocalGitRepo(self.servo_path, self)
self.local_wpt_repo = LocalGitRepo(self.wpt_path, self)
def run(self, payload: dict, step_callback=None) -> bool:
if "pull_request" not in payload:
return True
pull_data = payload["pull_request"]
if NO_SYNC_SIGNAL in pull_data.get("body", ""):
return True
# Only look for an existing remote PR if the action is appropriate.
logging.info("Processing '%s' action...", payload["action"])
action = payload["action"]
if action not in ["opened", "synchronize", "reopened", "edited", "closed"]:
return True
if (
action == "edited"
and "title" not in payload["changes"]
and "body" not in payload["changes"]
):
return True
try:
servo_pr = self.servo.get_pull_request(pull_data["number"])
downstream_wpt_branch = self.downstream_wpt.get_branch(
wpt_branch_name_from_servo_pr_number(servo_pr.number)
)
upstream_pr = self.wpt.get_open_pull_request_for_branch(
downstream_wpt_branch
)
if upstream_pr:
logging.info(
" → Detected existing upstream PR %s", upstream_pr)
run = SyncRun(self, servo_pr, AsyncValue(
upstream_pr), step_callback)
pull_data = payload["pull_request"]
if payload["action"] in ["opened", "synchronize", "reopened"]:
self.handle_new_pull_request_contents(run, pull_data)
elif payload["action"] == "edited":
self.handle_edited_pull_request(run, pull_data)
elif payload["action"] == "closed":
self.handle_closed_pull_request(run, pull_data)
run.run()
return True
except Exception as exception:
if isinstance(exception, subprocess.CalledProcessError):
logging.error(exception.output)
logging.error(json.dumps(payload))
logging.error(exception, exc_info=True)
return False
def handle_new_pull_request_contents(self, run: SyncRun, pull_data: dict):
num_commits = pull_data["commits"]
head_sha = pull_data["head"]["sha"]
is_upstreamable = (
len(
self.local_servo_repo.run(
"diff", head_sha, f"{head_sha}~{num_commits}", "--", UPSTREAMABLE_PATH
)
)
> 0
)
logging.info(" → PR is upstreamable: '%s'", is_upstreamable)
title = pull_data['title']
body = pull_data['body']
if run.upstream_pr.has_value():
if is_upstreamable:
# In case this is adding new upstreamable changes to a PR that was closed
# due to a lack of upstreamable changes, force it to be reopened.
# Github refuses to reopen a PR that had a branch force pushed, so be sure
# to do this first.
run.add_step(ChangePRStep(
run.upstream_pr.value(), "opened", title, body))
# Push the relevant changes to the upstream branch.
run.add_step(CreateOrUpdateBranchForPRStep(
pull_data, run.servo_pr))
run.add_step(CommentStep(
run.servo_pr, UPDATED_EXISTING_UPSTREAM_PR))
else:
# Close the upstream PR, since would contain no changes otherwise.
run.add_step(CommentStep(run.upstream_pr.value(),
NO_UPSTREAMBLE_CHANGES_COMMENT))
run.add_step(ChangePRStep(run.upstream_pr.value(), "closed"))
run.add_step(RemoveBranchForPRStep(pull_data))
run.add_step(CommentStep(
run.servo_pr, CLOSING_EXISTING_UPSTREAM_PR))
elif is_upstreamable:
# Push the relevant changes to a new upstream branch.
branch = run.add_step(
CreateOrUpdateBranchForPRStep(pull_data, run.servo_pr))
# Create a pull request against the upstream repository for the new branch.
assert branch
upstream_pr = run.add_step(OpenPRStep(
branch, self.wpt, title, body,
["servo-export", "do not merge yet"],
))
assert upstream_pr
run.upstream_pr = upstream_pr
# Leave a comment to the new pull request in the original pull request.
run.add_step(CommentStep(run.servo_pr, OPENED_NEW_UPSTREAM_PR))
def handle_edited_pull_request(self, run: SyncRun, pull_data: dict):
logging.info("Changing upstream PR title")
if run.upstream_pr.has_value():
run.add_step(ChangePRStep(
run.upstream_pr.value(
), "open", pull_data["title"], pull_data["body"]
))
run.add_step(CommentStep(
run.servo_pr, UPDATED_TITLE_IN_EXISTING_UPSTREAM_PR))
def handle_closed_pull_request(self, run: SyncRun, pull_data: dict):
logging.info("Processing closed PR")
if not run.upstream_pr.has_value():
# If we don't recognize this PR, it never contained upstreamable changes.
return
if pull_data["merged"]:
# Since the upstreamable changes have now been merged locally, merge the
# corresponding upstream PR.
run.add_step(MergePRStep(
run.upstream_pr.value(), ["do not merge yet"]))
else:
# If a PR with upstreamable changes is closed without being merged, we
# don't want to merge the changes upstream either.
run.add_step(ChangePRStep(run.upstream_pr.value(), "closed"))
# Always clean up our remote branch.
run.add_step(RemoveBranchForPRStep(pull_data))

View file

@ -0,0 +1,53 @@
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# pylint: disable=missing-docstring
UPSTREAMABLE_PATH = "tests/wpt/web-platform-tests/"
NO_SYNC_SIGNAL = "[no-wpt-sync]"
OPENED_NEW_UPSTREAM_PR = (
"🤖 Opened new upstream WPT pull request ({upstream_pr}) "
"with upstreamable changes."
)
UPDATED_EXISTING_UPSTREAM_PR = (
"📝 Transplanted new upstreamable changes to existing "
"upstream WPT pull request ({upstream_pr})."
)
UPDATED_TITLE_IN_EXISTING_UPSTREAM_PR = (
"✍ Updated existing upstream WPT pull request ({upstream_pr}) title and body."
)
CLOSING_EXISTING_UPSTREAM_PR = (
"🤖 This change no longer contains upstreamable changes to WPT; closed existing "
"upstream pull request ({upstream_pr})."
)
NO_UPSTREAMBLE_CHANGES_COMMENT = (
"👋 Downstream pull request ({servo_pr}) no longer contains any upstreamable "
"changes. Closing pull request without merging."
)
COULD_NOT_APPLY_CHANGES_DOWNSTREAM_COMMENT = (
"🛠 These changes could not be applied onto the latest upstream WPT. "
"Servo's copy of the Web Platform Tests may be out of sync."
)
COULD_NOT_APPLY_CHANGES_UPSTREAM_COMMENT = (
"🛠 Changes from the source pull request ({servo_pr}) can no longer be "
"cleanly applied. Waiting for a new version of these changes downstream."
)
COULD_NOT_MERGE_CHANGES_DOWNSTREAM_COMMENT = (
"⛔ Failed to properly merge the upstream pull request ({upstream_pr}). "
"Please address any CI issues and try to merge manually."
)
COULD_NOT_MERGE_CHANGES_UPSTREAM_COMMENT = (
"⛔ The downstream PR has merged ({servo_pr}), but these changes could not "
"be merged properly. Please address any CI issues and try to merge manually."
)
def wpt_branch_name_from_servo_pr_number(servo_pr_number):
return f"servo_export_{servo_pr_number}"

View file

@ -0,0 +1,178 @@
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# pylint: disable=missing-docstring
"""This modules contains some abstractions of GitHub repositories. It could one
day be entirely replaced with something like PyGithub."""
# This allows using types that are defined later in the file.
from __future__ import annotations
import logging
import urllib
from typing import Optional, TYPE_CHECKING
import requests
if TYPE_CHECKING:
from . import WPTSync
USER_AGENT = "Servo web-platform-test sync service"
TIMEOUT = 30 # 30 seconds
def authenticated(sync: WPTSync, method, url, json=None) -> requests.Response:
logging.info(" → Request: %s %s", method, url)
if json:
logging.info(" → Request JSON: %s", json)
headers = {
"Authorization": f"Bearer {sync.github_api_token}",
"User-Agent": USER_AGENT,
}
url = urllib.parse.urljoin(sync.github_api_url, url)
response = requests.request(
method, url, headers=headers, json=json, timeout=TIMEOUT
)
if int(response.status_code / 100) != 2:
raise ValueError(
f"Got unexpected {response.status_code} response: {response.text}"
)
return response
class GithubRepository:
"""
This class allows interacting with a single GitHub repository.
"""
def __init__(self, sync: WPTSync, repo: str):
self.sync = sync
self.repo = repo
self.org = repo.split("/")[0]
self.pulls_url = f"repos/{self.repo}/pulls"
def __str__(self):
return self.repo
def get_pull_request(self, number: int) -> PullRequest:
return PullRequest(self, number)
def get_branch(self, name: str) -> GithubBranch:
return GithubBranch(self, name)
def get_open_pull_request_for_branch(
self, branch: GithubBranch
) -> Optional[PullRequest]:
"""If this repository has an open pull request with the
given source head reference targeting the master branch,
return the first matching pull request, otherwise return None."""
params = "+".join([
"is:pr",
"state:open",
f"repo:{self.repo}",
f"author:{branch.repo.org}",
f"head:{branch.name}",
])
response = authenticated(self.sync, "GET", f"search/issues?q={params}")
if int(response.status_code / 100) != 2:
return None
json = response.json()
if not isinstance(json, dict) or \
"total_count" not in json or \
"items" not in json:
raise ValueError(
f"Got unexpected response from GitHub search: {response.text}"
)
if json["total_count"] < 1:
return None
return self.get_pull_request(json["items"][0]["number"])
def open_pull_request(self, branch: GithubBranch, title: str, body: str):
data = {
"title": title,
"head": branch.get_pr_head_reference_for_repo(self),
"base": "master",
"body": body,
"maintainer_can_modify": False,
}
response = authenticated(self.sync, "POST", self.pulls_url, json=data)
return self.get_pull_request(response.json()["number"])
class GithubBranch:
def __init__(self, repo: GithubRepository, branch_name: str):
self.repo = repo
self.name = branch_name
def __str__(self):
return f"{self.repo}/{self.name}"
def get_pr_head_reference_for_repo(self, other_repo: GithubRepository) -> str:
"""Get the head reference to use in pull requests for the given repository.
If the organization is the same this is just `<branch>` otherwise
it will be `<org>:<branch>`."""
if self.repo.org == other_repo.org:
return self.name
return f"{self.repo.org}:{self.name}"
class PullRequest:
"""
This class allows interacting with a single pull request on GitHub.
"""
def __init__(self, repo: GithubRepository, number: int):
self.repo = repo
self.context = repo.sync
self.number = number
self.base_url = f"repos/{self.repo.repo}/pulls/{self.number}"
self.base_issues_url = f"repos/{self.repo.repo}/issues/{self.number}"
def __str__(self):
return f"{self.repo}#{self.number}"
def api(self, *args, **kwargs) -> requests.Response:
return authenticated(self.context, *args, **kwargs)
def leave_comment(self, comment: str):
return self.api(
"POST", f"{self.base_issues_url}/comments", json={"body": comment}
)
def change(
self,
state: Optional[str] = None,
title: Optional[str] = None,
body: Optional[str] = None,
):
data = {}
if title:
data["title"] = title
if body:
data["body"] = body
if state:
data["state"] = state
return self.api("PATCH", self.base_url, json=data)
def remove_label(self, label: str):
self.api("DELETE", f"{self.base_issues_url}/labels/{label}")
def add_labels(self, labels: list[str]):
self.api("POST", f"{self.base_issues_url}/labels", json=labels)
def merge(self):
self.api("PUT", f"{self.base_url}/merge", json={"merge_method": "rebase"})

313
python/wpt/exporter/step.py Normal file
View file

@ -0,0 +1,313 @@
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# pylint: disable=broad-except
# pylint: disable=dangerous-default-value
# pylint: disable=fixme
# pylint: disable=missing-docstring
# This allows using types that are defined later in the file.
from __future__ import annotations
import logging
import os
import textwrap
from typing import TYPE_CHECKING, Generic, Optional, TypeVar
from .common import COULD_NOT_APPLY_CHANGES_DOWNSTREAM_COMMENT
from .common import COULD_NOT_APPLY_CHANGES_UPSTREAM_COMMENT
from .common import COULD_NOT_MERGE_CHANGES_DOWNSTREAM_COMMENT
from .common import COULD_NOT_MERGE_CHANGES_UPSTREAM_COMMENT
from .common import UPSTREAMABLE_PATH
from .common import wpt_branch_name_from_servo_pr_number
from .github import GithubBranch, GithubRepository, PullRequest
if TYPE_CHECKING:
from . import SyncRun, WPTSync
PATCH_FILE_NAME = "tmp.patch"
class Step:
def __init__(self, name):
self.name = name
def provides(self) -> Optional[AsyncValue]:
return None
def run(self, _: SyncRun):
return
T = TypeVar('T')
class AsyncValue(Generic[T]):
def __init__(self, value: Optional[T] = None):
self._value = value
def resolve(self, value: T):
self._value = value
def value(self) -> T:
assert self._value is not None
return self._value
def has_value(self):
return self._value is not None
class CreateOrUpdateBranchForPRStep(Step):
def __init__(self, pull_data: dict, pull_request: PullRequest):
Step.__init__(self, "CreateOrUpdateBranchForPRStep")
self.pull_data = pull_data
self.pull_request = pull_request
self.branch: AsyncValue[GithubBranch] = AsyncValue()
def provides(self):
return self.branch
def run(self, run: SyncRun):
try:
commits = self._get_upstreamable_commits_from_local_servo_repo(
run.sync)
branch_name = self._create_or_update_branch_for_pr(run, commits)
branch = run.sync.downstream_wpt.get_branch(branch_name)
self.branch.resolve(branch)
self.name += f":{len(commits)}:{branch}"
except Exception as exception:
logging.info("Could not apply changes to upstream WPT repository.")
logging.info(exception, exc_info=True)
run.steps = []
run.add_step(CommentStep(
self.pull_request, COULD_NOT_APPLY_CHANGES_DOWNSTREAM_COMMENT
))
if run.upstream_pr.has_value():
run.add_step(CommentStep(
run.upstream_pr.value(), COULD_NOT_APPLY_CHANGES_UPSTREAM_COMMENT
))
def _get_upstreamable_commits_from_local_servo_repo(self, sync: WPTSync):
local_servo_repo = sync.local_servo_repo
number_of_commits = self.pull_data["commits"]
pr_head = self.pull_data["head"]["sha"]
commit_shas = local_servo_repo.run(
"log", "--pretty=%H", pr_head, f"-{number_of_commits}"
).splitlines()
filtered_commits = []
for sha in commit_shas:
# Specifying the path here does a few things. First, it excludes any
# changes that do not touch WPT files at all. Secondly, when a file is
# moved in or out of the WPT directory the filename which is outside the
# directory becomes /dev/null and the change becomes an addition or
# deletion. This makes the patch usable on the WPT repository itself.
# TODO: If we could cleverly parse and manipulate the full commit diff
# we could avoid cloning the servo repository altogether and only
# have to fetch the commit diffs from GitHub.
# NB: The output of git show might include binary files or non-UTF8 text,
# so store the content of the diff as a `bytes`.
diff = local_servo_repo.run_without_encoding(
"show", "--binary", "--format=%b", sha, "--", UPSTREAMABLE_PATH
)
# Retrieve the diff of any changes to files that are relevant
if diff:
# Create an object that contains everything necessary to transplant this
# commit to another repository.
filtered_commits += [
{
"author": local_servo_repo.run(
"show", "-s", "--pretty=%an <%ae>", sha
),
"message": local_servo_repo.run(
"show", "-s", "--pretty=%B", sha
),
"diff": diff,
}
]
return filtered_commits
def _apply_filtered_servo_commit_to_wpt(self, run: SyncRun, commit: dict):
patch_path = os.path.join(run.sync.wpt_path, PATCH_FILE_NAME)
strip_count = UPSTREAMABLE_PATH.count("/") + 1
try:
with open(patch_path, "wb") as file:
file.write(commit["diff"])
run.sync.local_wpt_repo.run(
"apply", PATCH_FILE_NAME, "-p", str(strip_count)
)
finally:
# Ensure the patch file is not added with the other changes.
os.remove(patch_path)
run.sync.local_wpt_repo.run("add", "--all")
run.sync.local_wpt_repo.run(
"commit", "--message", commit["message"], "--author", commit["author"]
)
def _create_or_update_branch_for_pr(
self, run: SyncRun, commits: list[dict], pre_commit_callback=None
):
branch_name = wpt_branch_name_from_servo_pr_number(
self.pull_data["number"])
try:
# Create a new branch with a unique name that is consistent between
# updates of the same PR.
run.sync.local_wpt_repo.run("checkout", "-b", branch_name)
for commit in commits:
self._apply_filtered_servo_commit_to_wpt(run, commit)
if pre_commit_callback:
pre_commit_callback()
# Push the branch upstream (forcing to overwrite any existing changes).
if not run.sync.suppress_force_push:
# In order to push to our downstream branch we need to ensure that
# the local repository isn't a shallow clone. Shallow clones are
# commonly created by GitHub actions.
run.sync.local_wpt_repo.run("fetch", "--unshallow", "origin")
user = run.sync.github_username
token = run.sync.github_api_token
repo = run.sync.downstream_wpt_repo
remote_url = f"https://{user}:{token}@github.com/{repo}.git"
run.sync.local_wpt_repo.run(
"push", "-f", remote_url, branch_name)
return branch_name
finally:
try:
run.sync.local_wpt_repo.run("checkout", "master")
run.sync.local_wpt_repo.run("branch", "-D", branch_name)
except Exception:
pass
class RemoveBranchForPRStep(Step):
def __init__(self, pull_request):
Step.__init__(self, "RemoveBranchForPRStep")
self.branch_name = wpt_branch_name_from_servo_pr_number(
pull_request["number"])
def run(self, run: SyncRun):
self.name += f":{run.sync.downstream_wpt.get_branch(self.branch_name)}"
logging.info(" -> Removing branch used for upstream PR")
if not run.sync.suppress_force_push:
user = run.sync.github_username
token = run.sync.github_api_token
repo = run.sync.downstream_wpt_repo
remote_url = f"https://{user}:{token}@github.com/{repo}.git"
run.sync.local_wpt_repo.run("push", remote_url, "--delete",
self.branch_name)
class ChangePRStep(Step):
def __init__(
self,
pull_request: PullRequest,
state: str,
title: Optional[str] = None,
body: Optional[str] = None,
):
name = f"ChangePRStep:{pull_request}:{state}"
if title:
name += f":{title}"
Step.__init__(self, name)
self.pull_request = pull_request
self.state = state
self.title = title
self.body = body
def run(self, run: SyncRun):
body = self.body
if body:
body = run.prepare_body_text(body)
self.name += (
f':{textwrap.shorten(body, width=20, placeholder="...")}[{len(body)}]'
)
self.pull_request.change(state=self.state, title=self.title, body=body)
class MergePRStep(Step):
def __init__(self, pull_request: PullRequest, labels_to_remove: list[str] = []):
Step.__init__(self, f"MergePRStep:{pull_request}")
self.pull_request = pull_request
self.labels_to_remove = labels_to_remove
def run(self, run: SyncRun):
for label in self.labels_to_remove:
self.pull_request.remove_label(label)
try:
self.pull_request.merge()
except Exception as exception:
logging.warning("Could not merge PR (%s).", self.pull_request)
logging.warning(exception, exc_info=True)
run.steps = []
run.add_step(CommentStep(
self.pull_request, COULD_NOT_MERGE_CHANGES_UPSTREAM_COMMENT
))
run.add_step(CommentStep(
run.servo_pr, COULD_NOT_MERGE_CHANGES_DOWNSTREAM_COMMENT
))
self.pull_request.add_labels(["stale-servo-export"])
class OpenPRStep(Step):
def __init__(
self,
source_branch: AsyncValue[GithubBranch],
target_repo: GithubRepository,
title: str,
body: str,
labels: list[str],
):
Step.__init__(self, "OpenPRStep")
self.title = title
self.body = body
self.source_branch = source_branch
self.target_repo = target_repo
self.new_pr: AsyncValue[PullRequest] = AsyncValue()
self.labels = labels
def provides(self):
return self.new_pr
def run(self, run: SyncRun):
pull_request = self.target_repo.open_pull_request(
self.source_branch.value(), self.title, run.prepare_body_text(self.body)
)
if self.labels:
pull_request.add_labels(self.labels)
self.new_pr.resolve(pull_request)
self.name += f":{self.source_branch.value()}{self.new_pr.value()}"
class CommentStep(Step):
def __init__(self, pull_request: PullRequest, comment_template: str):
Step.__init__(self, "CommentStep")
self.pull_request = pull_request
self.comment_template = comment_template
def run(self, run: SyncRun):
comment = run.make_comment(self.comment_template)
self.name += f":{self.pull_request}:{comment}"
self.pull_request.leave_comment(comment)

View file

@ -0,0 +1,367 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# This allows using types that are defined later in the file.
from __future__ import annotations
import collections
import os
import sys
import mozlog
import mozlog.formatters.base
import mozlog.reader
from dataclasses import dataclass, field
from typing import Dict, List, Optional, Any
from six import itervalues
DEFAULT_MOVE_UP_CODE = u"\x1b[A"
DEFAULT_CLEAR_EOL_CODE = u"\x1b[K"
@dataclass
class UnexpectedSubtestResult():
path: str
subtest: str
actual: str
expected: str
message: str
time: int
stack: Optional[str]
@dataclass
class UnexpectedResult():
path: str
actual: str
expected: str
message: str
time: int
stack: Optional[str]
unexpected_subtest_results: list[UnexpectedSubtestResult] = field(
default_factory=list)
issues: list[str] = field(default_factory=list)
flaky: bool = False
def __str__(self):
output = UnexpectedResult.to_lines(self)
if self.unexpected_subtest_results:
def make_subtests_failure(subtest_results):
# Test names sometimes contain control characters, which we want
# to be printed in their raw form, and not their interpreted form.
lines = []
for subtest in subtest_results[:-1]:
lines += UnexpectedResult.to_lines(
subtest, print_stack=False)
lines += UnexpectedResult.to_lines(subtest_results[-1])
return self.wrap_and_indent_lines(lines, " ").splitlines()
# Organize the failures by stack trace so we don't print the same stack trace
# more than once. They are really tall and we don't want to flood the screen
# with duplicate information.
results_by_stack = collections.defaultdict(list)
for subtest_result in self.unexpected_subtest_results:
results_by_stack[subtest_result.stack].append(subtest_result)
# Print stackless results first. They are all separate.
if None in results_by_stack:
output += make_subtests_failure(results_by_stack.pop(None))
for subtest_results in results_by_stack.values():
output += make_subtests_failure(subtest_results)
return UnexpectedResult.wrap_and_indent_lines(output, " ")
@staticmethod
def wrap_and_indent_lines(lines, indent):
if not lines:
return ""
output = indent + u"\u25B6 %s\n" % lines[0]
for line in lines[1:-1]:
output += indent + u"\u2502 %s\n" % line
if len(lines) > 1:
output += indent + u"\u2514 %s\n" % lines[-1]
return output
@staticmethod
def to_lines(result: Any[UnexpectedSubtestResult, UnexpectedResult], print_stack=True):
first_line = result.actual
if result.expected != result.actual:
first_line += f" [expected {result.expected}]"
# Test names sometimes contain control characters, which we want
# to be printed in their raw form, and not their interpreted form.
first_line += f" {result.path.encode('unicode-escape').decode('utf-8')}"
if isinstance(result, UnexpectedResult) and result.issues:
first_line += f" ({', '.join([f'#{bug}' for bug in result.issues])})"
lines = [first_line]
if result.message:
for message_line in result.message.splitlines():
lines.append(f" \u2192 {message_line}")
if print_stack and result.stack:
lines.append("")
lines.extend(result.stack.splitlines())
return lines
class ServoHandler(mozlog.reader.LogHandler):
"""LogHandler designed to collect unexpected results for use by
script or by the ServoFormatter output formatter."""
def __init__(self):
self.reset_state()
def reset_state(self):
self.number_of_tests = 0
self.completed_tests = 0
self.need_to_erase_last_line = False
self.running_tests: Dict[str, str] = {}
self.test_output = collections.defaultdict(str)
self.subtest_failures = collections.defaultdict(list)
self.tests_with_failing_subtests = []
self.unexpected_results: List[UnexpectedResult] = []
self.expected = {
'OK': 0,
'PASS': 0,
'FAIL': 0,
'ERROR': 0,
'TIMEOUT': 0,
'SKIP': 0,
'CRASH': 0,
'PRECONDITION_FAILED': 0,
}
self.unexpected_tests = {
'OK': [],
'PASS': [],
'FAIL': [],
'ERROR': [],
'TIMEOUT': [],
'CRASH': [],
'PRECONDITION_FAILED': [],
}
def suite_start(self, data):
self.reset_state()
self.number_of_tests = sum(len(tests) for tests in itervalues(data["tests"]))
self.suite_start_time = data["time"]
def suite_end(self, _):
pass
def test_start(self, data):
self.running_tests[data['thread']] = data['test']
@staticmethod
def data_was_for_expected_result(data):
if "expected" not in data:
return True
return "known_intermittent" in data \
and data["status"] in data["known_intermittent"]
def test_end(self, data: dict) -> Optional[UnexpectedResult]:
self.completed_tests += 1
test_status = data["status"]
test_path = data["test"]
del self.running_tests[data['thread']]
had_expected_test_result = self.data_was_for_expected_result(data)
subtest_failures = self.subtest_failures.pop(test_path, [])
if had_expected_test_result and not subtest_failures:
self.expected[test_status] += 1
return None
# If the test crashed or timed out, we also include any process output,
# because there is a good chance that the test produced a stack trace
# or other error messages.
stack = data.get("stack", None)
if test_status in ("CRASH", "TIMEOUT"):
stack = f"\n{stack}" if stack else ""
stack = f"{self.test_output[test_path]}{stack}"
result = UnexpectedResult(
test_path,
test_status,
data.get("expected", test_status),
data.get("message", ""),
data["time"],
stack,
subtest_failures
)
if not had_expected_test_result:
self.unexpected_tests[result.actual].append(data)
if subtest_failures:
self.tests_with_failing_subtests.append(data)
self.unexpected_results.append(result)
return result
def test_status(self, data: dict):
if self.data_was_for_expected_result(data):
return
self.subtest_failures[data["test"]].append(UnexpectedSubtestResult(
data["test"],
data["subtest"],
data["status"],
data["expected"],
data.get("message", ""),
data["time"],
data.get('stack', None),
))
def process_output(self, data):
if data['thread'] not in self.running_tests:
return
test_name = self.running_tests[data['thread']]
self.test_output[test_name] += data['data'] + "\n"
def log(self, _):
pass
class ServoFormatter(mozlog.formatters.base.BaseFormatter, ServoHandler):
"""Formatter designed to produce unexpected test results grouped
together in a readable format."""
def __init__(self):
ServoHandler.__init__(self)
self.current_display = ""
self.interactive = os.isatty(sys.stdout.fileno())
if self.interactive:
self.line_width = os.get_terminal_size().columns
self.move_up = DEFAULT_MOVE_UP_CODE
self.clear_eol = DEFAULT_CLEAR_EOL_CODE
try:
import blessings
self.terminal = blessings.Terminal()
self.move_up = self.terminal.move_up
self.clear_eol = self.terminal.clear_eol
except Exception as exception:
sys.stderr.write("GroupingFormatter: Could not get terminal "
"control characters: %s\n" % exception)
def text_to_erase_display(self):
if not self.interactive or not self.current_display:
return ""
return ((self.move_up + self.clear_eol)
* self.current_display.count('\n'))
def generate_output(self, text=None, new_display=None):
if not self.interactive:
return text
output = self.text_to_erase_display()
if text:
output += text
if new_display is not None:
self.current_display = new_display
return output + self.current_display
def test_counter(self):
if self.number_of_tests == 0:
return " [%i] " % self.completed_tests
else:
return " [%i/%i] " % (self.completed_tests, self.number_of_tests)
def build_status_line(self):
new_display = self.test_counter()
if self.running_tests:
indent = " " * len(new_display)
if self.interactive:
max_width = self.line_width - len(new_display)
else:
max_width = sys.maxsize
return new_display + ("\n%s" % indent).join(
val[:max_width] for val in self.running_tests.values()) + "\n"
else:
return new_display + "No tests running.\n"
def suite_start(self, data):
ServoHandler.suite_start(self, data)
if self.number_of_tests == 0:
return "Running tests in %s\n\n" % data[u'source']
else:
return "Running %i tests in %s\n\n" % (self.number_of_tests, data[u'source'])
def test_start(self, data):
ServoHandler.test_start(self, data)
if self.interactive:
return self.generate_output(new_display=self.build_status_line())
def test_end(self, data):
unexpected_result = ServoHandler.test_end(self, data)
if not unexpected_result:
if self.interactive:
return self.generate_output(new_display=self.build_status_line())
else:
return self.generate_output(text="%s%s\n" % (self.test_counter(), data["test"]))
# Surround test output by newlines so that it is easier to read.
output_for_unexpected_test = f"{unexpected_result}\n"
return self.generate_output(text=output_for_unexpected_test,
new_display=self.build_status_line())
def test_status(self, data):
ServoHandler.test_status(self, data)
def suite_end(self, data):
ServoHandler.suite_end(self, data)
if not self.interactive:
output = u"\n"
else:
output = ""
output += u"Ran %i tests finished in %.1f seconds.\n" % (
self.completed_tests, (data["time"] - self.suite_start_time) / 1000)
output += u" \u2022 %i ran as expected. %i tests skipped.\n" % (
sum(self.expected.values()), self.expected['SKIP'])
def text_for_unexpected_list(text, section):
tests = self.unexpected_tests[section]
if not tests:
return u""
return u" \u2022 %i tests %s\n" % (len(tests), text)
output += text_for_unexpected_list(u"crashed unexpectedly", 'CRASH')
output += text_for_unexpected_list(u"had errors unexpectedly", 'ERROR')
output += text_for_unexpected_list(u"failed unexpectedly", 'FAIL')
output += text_for_unexpected_list(u"precondition failed unexpectedly", 'PRECONDITION_FAILED')
output += text_for_unexpected_list(u"timed out unexpectedly", 'TIMEOUT')
output += text_for_unexpected_list(u"passed unexpectedly", 'PASS')
output += text_for_unexpected_list(u"unexpectedly okay", 'OK')
num_with_failing_subtests = len(self.tests_with_failing_subtests)
if num_with_failing_subtests:
output += (u" \u2022 %i tests had unexpected subtest results\n"
% num_with_failing_subtests)
output += "\n"
# Repeat failing test output, so that it is easier to find, since the
# non-interactive version prints all the test names.
if not self.interactive and self.unexpected_results:
output += u"Tests with unexpected results:\n"
output += "".join([str(result)
for result in self.unexpected_results])
return self.generate_output(text=output, new_display="")
def process_output(self, data):
ServoHandler.process_output(self, data)
def log(self, data):
ServoHandler.log(self, data)
# We are logging messages that begin with STDERR, because that is how exceptions
# in this formatter are indicated.
if data['message'].startswith('STDERR'):
return self.generate_output(text=data['message'] + "\n")
if data['level'] in ('CRITICAL', 'ERROR'):
return self.generate_output(text=data['message'] + "\n")

View file

@ -0,0 +1,57 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
import os
import sys
from .tree import GitTree, GeckoCommit
from wptrunner.update import setup_logging, WPTUpdate # noqa: F401
from wptrunner.update.base import Step, StepRunner, exit_unclean # noqa: F401
from wptrunner.update.update import LoadConfig, SyncFromUpstream, UpdateMetadata # noqa: F401
from wptrunner import wptcommandline # noqa: F401
class LoadTrees(Step):
"""Load gecko tree and sync tree containing web-platform-tests"""
provides = ["local_tree", "sync_tree"]
def create(self, state):
if os.path.exists(state.sync["path"]):
sync_tree = GitTree(root=state.sync["path"])
else:
sync_tree = None
assert GitTree.is_type()
state.update({"local_tree": GitTree(commit_cls=GeckoCommit),
"sync_tree": sync_tree})
class UpdateRunner(StepRunner):
"""Overall runner for updating web-platform-tests in Gecko."""
steps = [LoadConfig,
LoadTrees,
SyncFromUpstream,
UpdateMetadata]
def run_update(**kwargs):
logger = setup_logging(kwargs, {"mach": sys.stdout})
updater = WPTUpdate(logger, runner_cls=UpdateRunner, **kwargs)
return updater.run() != exit_unclean
def create_parser():
parser = wptcommandline.create_parser_update()
parser.add_argument("--layout-2020", "--with-layout-2020", default=False, action="store_true",
help="Use expected results for the 2020 layout engine")
return parser
def check_args(kwargs):
wptcommandline.set_from_config(kwargs)
if hasattr(wptcommandline, 'check_paths'):
wptcommandline.check_paths(kwargs)
return kwargs

201
python/wpt/importer/tree.py Normal file
View file

@ -0,0 +1,201 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
from distutils.spawn import find_executable
import re
import subprocess
import sys
import tempfile
from wptrunner import update as wptupdate
from wptrunner.update.tree import Commit, CommitMessage, get_unique_name
class GitTree(wptupdate.tree.GitTree):
def __init__(self, *args, **kwargs):
"""Extension of the basic GitTree with extra methods for
transfering patches"""
commit_cls = kwargs.pop("commit_cls", Commit)
wptupdate.tree.GitTree.__init__(self, *args, **kwargs)
self.commit_cls = commit_cls
def create_branch(self, name, ref=None):
"""Create a named branch,
:param name: String representing the branch name.
:param ref: None to use current HEAD or rev that the branch should point to"""
args = []
if ref is not None:
if hasattr(ref, "sha1"):
ref = ref.sha1
args.append(ref)
self.git("branch", name, *args)
def commits_by_message(self, message, path=None):
"""List of commits with messages containing a given string.
:param message: The string that must be contained in the message.
:param path: Path to a file or directory the commit touches
"""
args = ["--pretty=format:%H", "--reverse", "-z", "--grep=%s" % message]
if path is not None:
args.append("--")
args.append(path)
data = self.git("log", *args)
return [self.commit_cls(self, sha1) for sha1 in data.split("\0")]
def log(self, base_commit=None, path=None):
"""List commits touching a certian path from a given base commit.
:base_param commit: Commit object for the base commit from which to log
:param path: Path that the commits must touch
"""
args = ["--pretty=format:%H", "--reverse", "-z", "--no-merges"]
if base_commit is not None:
args.append("%s.." % base_commit.sha1)
if path is not None:
args.append("--")
args.append(path)
data = self.git("log", *args)
return [self.commit_cls(self, sha1) for sha1 in data.split("\0") if sha1]
def import_patch(self, patch, strip_count):
"""Import a patch file into the tree and commit it
:param patch: a Patch object containing the patch to import
"""
with tempfile.NamedTemporaryFile() as f:
f.write(patch.diff)
f.flush()
f.seek(0)
self.git("apply", "--index", f.name, "-p", str(strip_count))
self.git("commit", "-m", patch.message.text, "--author=%s" % patch.full_author)
def rebase(self, ref, continue_rebase=False):
"""Rebase the current branch onto another commit.
:param ref: A Commit object for the commit to rebase onto
:param continue_rebase: Continue an in-progress rebase"""
if continue_rebase:
args = ["--continue"]
else:
if hasattr(ref, "sha1"):
ref = ref.sha1
args = [ref]
self.git("rebase", *args)
def push(self, remote, local_ref, remote_ref, force=False):
"""Push local changes to a remote.
:param remote: URL of the remote to push to
:param local_ref: Local branch to push
:param remote_ref: Name of the remote branch to push to
:param force: Do a force push
"""
args = []
if force:
args.append("-f")
args.extend([remote, "%s:%s" % (local_ref, remote_ref)])
self.git("push", *args)
def unique_branch_name(self, prefix):
"""Get an unused branch name in the local tree
:param prefix: Prefix to use at the start of the branch name"""
branches = [ref[len("refs/heads/"):] for sha1, ref in self.list_refs()
if ref.startswith("refs/heads/")]
return get_unique_name(branches, prefix)
class Patch(object):
def __init__(self, author, email, message, merge_message, diff):
self.author = author
self.email = email
self.merge_message = merge_message
if isinstance(message, CommitMessage):
self.message = message
else:
self.message = GeckoCommitMessage(message)
self.diff = diff
def __repr__(self):
return "<Patch (%s)>" % self.message.full_summary
@property
def full_author(self):
return "%s <%s>" % (self.author, self.email)
@property
def empty(self):
return bool(self.diff.strip())
class GeckoCommitMessage(CommitMessage):
"""Commit message following the Gecko conventions for identifying bug number
and reviewer"""
# c.f. http://hg.mozilla.org/hgcustom/version-control-tools/file/tip/hghooks/mozhghooks/commit-message.py
# which has the regexps that are actually enforced by the VCS hooks. These are
# slightly different because we need to parse out specific parts of the message rather
# than just enforce a general pattern.
_bug_re = re.compile(r"^Bug (\d+)[^\w]*(?:Part \d+[^\w]*)?(.*?)\s*(?:r=(\w*))?$",
re.IGNORECASE)
_merge_re = re.compile(r"^Auto merge of #(\d+) - [^:]+:[^,]+, r=(.+)$", re.IGNORECASE)
_backout_re = re.compile(r"^(?:Back(?:ing|ed)\s+out)|Backout|(?:Revert|(?:ed|ing))",
re.IGNORECASE)
_backout_sha1_re = re.compile(r"(?:\s|\:)(0-9a-f){12}")
def _parse_message(self):
CommitMessage._parse_message(self)
if self._backout_re.match(self.full_summary):
self.backouts = self._backout_re.findall(self.full_summary)
else:
self.backouts = []
m = self._merge_re.match(self.full_summary)
if m is not None:
self.bug, self.reviewer = m.groups()
self.summary = self.full_summary
else:
m = self._bug_re.match(self.full_summary)
if m is not None:
self.bug, self.summary, self.reviewer = m.groups()
else:
self.bug, self.summary, self.reviewer = None, self.full_summary, None
class GeckoCommit(Commit):
msg_cls = GeckoCommitMessage
def __init__(self, tree, sha1, is_merge=False):
Commit.__init__(self, tree, sha1)
if not is_merge:
args = ["-c", sha1]
try:
merge_rev = self.git("when-merged", *args).strip()
except subprocess.CalledProcessError as exn:
if not find_executable('git-when-merged'):
print('Please add the `when-merged` git command to your PATH '
'(https://github.com/mhagger/git-when-merged/).')
sys.exit(1)
raise exn
self.merge = GeckoCommit(tree, merge_rev, True)
def export_patch(self, path=None):
"""Convert a commit in the tree to a Patch with the bug number and
reviewer stripped from the message"""
args = ["--binary", self.sha1]
if path is not None:
args.append("--")
args.append(path)
diff = self.git("show", *args)
merge_message = self.merge.message if self.merge else None
return Patch(self.author, self.email, self.message, merge_message, diff)

View file

@ -0,0 +1,173 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
import argparse
import os
import sys
import tempfile
from collections import defaultdict
from six import iterkeys, iteritems
from . import SERVO_ROOT, WPT_PATH
from mozlog.structured import commandline
# This must happen after importing from "." since it adds WPT
# tools to the Python system path.
import manifest as wptmanifest
from wptrunner.wptcommandline import get_test_paths, set_from_config
from wptrunner import wptlogging
def create_parser():
p = argparse.ArgumentParser()
p.add_argument("--check-clean", action="store_true",
help="Check that updating the manifest doesn't lead to any changes")
p.add_argument("--rebuild", action="store_true",
help="Rebuild the manifest from scratch")
commandline.add_logging_group(p)
return p
def update(check_clean=True, rebuild=False, **kwargs):
logger = wptlogging.setup(kwargs, {"mach": sys.stdout})
kwargs = {"config": os.path.join(WPT_PATH, "config.ini"),
"manifest_path": os.path.join(WPT_PATH, "metadata"),
"tests_root": None,
"metadata_root": None}
set_from_config(kwargs)
config = kwargs["config"]
test_paths = get_test_paths(config)
if check_clean:
return _check_clean(logger, test_paths)
return _update(logger, test_paths, rebuild)
def _update(logger, test_paths, rebuild):
for url_base, paths in iteritems(test_paths):
manifest_path = os.path.join(paths["metadata_path"], "MANIFEST.json")
cache_subdir = os.path.relpath(os.path.dirname(manifest_path),
os.path.dirname(__file__))
wptmanifest.manifest.load_and_update(paths["tests_path"],
manifest_path,
url_base,
working_copy=True,
rebuild=rebuild,
cache_root=os.path.join(SERVO_ROOT, ".wpt",
cache_subdir))
return 0
def _check_clean(logger, test_paths):
manifests_by_path = {}
rv = 0
for url_base, paths in iteritems(test_paths):
tests_path = paths["tests_path"]
manifest_path = os.path.join(paths["metadata_path"], "MANIFEST.json")
old_manifest = wptmanifest.manifest.load_and_update(tests_path,
manifest_path,
url_base,
working_copy=False,
update=False,
write_manifest=False)
# Even if no cache is specified, one will be used automatically by the
# VCS integration. Create a brand new cache every time to ensure that
# the VCS integration always thinks that any file modifications in the
# working directory are new and interesting.
cache_root = tempfile.mkdtemp()
new_manifest = wptmanifest.manifest.load_and_update(tests_path,
manifest_path,
url_base,
working_copy=True,
update=True,
cache_root=cache_root,
write_manifest=False,
allow_cached=False)
manifests_by_path[manifest_path] = (old_manifest, new_manifest)
for manifest_path, (old_manifest, new_manifest) in iteritems(manifests_by_path):
if not diff_manifests(logger, manifest_path, old_manifest, new_manifest):
logger.error("Manifest %s is outdated, use |./mach update-manifest| to fix." % manifest_path)
rv = 1
return rv
def diff_manifests(logger, manifest_path, old_manifest, new_manifest):
"""Lint the differences between old and new versions of a
manifest. Differences are considered significant (and so produce
lint errors) if they produce a meaningful difference in the actual
tests run.
:param logger: mozlog logger to use for output
:param manifest_path: Path to the manifest being linted
:param old_manifest: Manifest object representing the initial manifest
:param new_manifest: Manifest object representing the updated manifest
"""
logger.info("Diffing old and new manifests %s" % manifest_path)
old_items, new_items = defaultdict(set), defaultdict(set)
for manifest, items in [(old_manifest, old_items),
(new_manifest, new_items)]:
for test_type, path, tests in manifest:
for test in tests:
test_id = [test.id]
if hasattr(test, "script_metadata"):
if test.script_metadata is not None:
test_id.extend(tuple(item) for item in test.script_metadata)
if hasattr(test, "references"):
test_id.extend(tuple(item) for item in test.references)
test_id = tuple(test_id)
items[path].add((test_type, test_id))
old_paths = set(iterkeys(old_items))
new_paths = set(iterkeys(new_items))
added_paths = new_paths - old_paths
deleted_paths = old_paths - new_paths
common_paths = new_paths & old_paths
clean = True
for path in added_paths:
clean = False
log_error(logger, manifest_path, "%s in source but not in manifest." % path)
for path in deleted_paths:
clean = False
log_error(logger, manifest_path, "%s in manifest but removed from source." % path)
for path in common_paths:
old_tests = old_items[path]
new_tests = new_items[path]
added_tests = new_tests - old_tests
removed_tests = old_tests - new_tests
if added_tests or removed_tests:
clean = False
log_error(logger, manifest_path, "%s changed test types or metadata" % path)
if clean:
# Manifest currently has some list vs tuple inconsistencies that break
# a simple equality comparison.
old_paths = old_manifest.to_json()['items']
new_paths = new_manifest.to_json()['items']
if old_paths != new_paths:
logger.warning("Manifest %s contains correct tests but file hashes changed." % manifest_path) # noqa
clean = False
return clean
def log_error(logger, manifest_path, msg):
logger.lint_error(path=manifest_path,
message=msg,
lineno=0,
source="",
linter="wpt-manifest")

View file

@ -0,0 +1,4 @@
-r requirements.txt
flask
types-requests

View file

@ -0,0 +1 @@
requests

326
python/wpt/run.py Normal file
View file

@ -0,0 +1,326 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# pylint: disable=missing-docstring
import dataclasses
import json
import multiprocessing
import os
import re
import sys
import urllib.error
import urllib.parse
import urllib.request
from typing import List, NamedTuple, Optional, Union
import mozlog
import mozlog.formatters
from . import SERVO_ROOT, WPT_PATH, WPT_TOOLS_PATH, update_args_for_layout_2020
from .grouping_formatter import (
ServoFormatter, ServoHandler,
UnexpectedResult, UnexpectedSubtestResult
)
from wptrunner import wptcommandline
from wptrunner import wptrunner
CERTS_PATH = os.path.join(WPT_TOOLS_PATH, "certs")
TRACKER_API = "https://build.servo.org/intermittent-tracker"
TRACKER_API_ENV_VAR = "INTERMITTENT_TRACKER_API"
TRACKER_DASHBOARD_SECRET_ENV_VAR = "INTERMITTENT_TRACKER_DASHBOARD_SECRET"
def determine_build_type(kwargs: dict, target_dir: str):
if kwargs["release"]:
return "release"
elif kwargs["debug"]:
return "debug"
elif os.path.exists(os.path.join(target_dir, "debug")):
return "debug"
elif os.path.exists(os.path.join(target_dir, "release")):
return "release"
return "debug"
def set_if_none(args: dict, key: str, value):
if key not in args or args[key] is None:
args[key] = value
def run_tests(**kwargs):
# By default, Rayon selects the number of worker threads based on the
# available CPU count. This doesn't work very well when running tests on CI,
# since we run so many Servo processes in parallel. The result is a lot of
# extra timeouts. Instead, force Rayon to assume we are running on a 2 CPU
# environment.
os.environ["RAYON_RS_NUM_CPUS"] = "2"
os.environ["RUST_BACKTRACE"] = "1"
os.environ["HOST_FILE"] = os.path.join(SERVO_ROOT, "tests", "wpt", "hosts")
set_if_none(kwargs, "product", "servo")
set_if_none(kwargs, "config", os.path.join(WPT_PATH, "config.ini"))
set_if_none(kwargs, "include_manifest", os.path.join(WPT_PATH, "include.ini"))
set_if_none(kwargs, "manifest_update", False)
set_if_none(kwargs, "processes", multiprocessing.cpu_count())
set_if_none(kwargs, "ca_cert_path", os.path.join(CERTS_PATH, "cacert.pem"))
set_if_none(
kwargs, "host_key_path", os.path.join(CERTS_PATH, "web-platform.test.key")
)
set_if_none(
kwargs, "host_cert_path", os.path.join(CERTS_PATH, "web-platform.test.pem")
)
kwargs["user_stylesheets"].append(os.path.join(SERVO_ROOT, "resources", "ahem.css"))
if "CARGO_TARGET_DIR" in os.environ:
target_dir = os.path.join(os.environ["CARGO_TARGET_DIR"])
else:
target_dir = os.path.join(SERVO_ROOT, "target")
default_binary_path = os.path.join(
target_dir, determine_build_type(kwargs, target_dir), "servo"
)
if sys.platform == "win32":
target_dir += ".exe"
set_if_none(kwargs, "binary", default_binary_path)
set_if_none(kwargs, "webdriver_binary", default_binary_path)
if kwargs.pop("rr_chaos"):
kwargs["debugger"] = "rr"
kwargs["debugger_args"] = "record --chaos"
kwargs["repeat_until_unexpected"] = True
# TODO: Delete rr traces from green test runs?
prefs = kwargs.pop("prefs")
if prefs:
kwargs["binary_args"] = ["--pref=" + pref for pref in prefs]
if not kwargs.get("no_default_test_types"):
test_types = {
"servo": ["testharness", "reftest", "wdspec"],
"servodriver": ["testharness", "reftest"],
}
product = kwargs.get("product") or "servo"
kwargs["test_types"] = test_types[product]
filter_intermittents_output = kwargs.pop("filter_intermittents", None)
unexpected_raw_log_output_file = kwargs.pop("log_raw_unexpected", None)
raw_log_outputs = kwargs.get("log_raw", [])
wptcommandline.check_args(kwargs)
update_args_for_layout_2020(kwargs)
mozlog.commandline.log_formatters["servo"] = (
ServoFormatter,
"Servo's grouping output formatter",
)
use_mach_logging = False
if len(kwargs["test_list"]) == 1:
file_ext = os.path.splitext(kwargs["test_list"][0])[1].lower()
if file_ext in [".htm", ".html", ".js", ".xhtml", ".xht", ".py"]:
use_mach_logging = True
if use_mach_logging:
logger = wptrunner.setup_logging(kwargs, {"mach": sys.stdout})
else:
logger = wptrunner.setup_logging(kwargs, {"servo": sys.stdout})
handler = ServoHandler()
logger.add_handler(handler)
wptrunner.run_tests(**kwargs)
return_value = 0 if not handler.unexpected_results else 1
# Filter intermittents if that was specified on the command-line.
if handler.unexpected_results and filter_intermittents_output:
# Copy the list of unexpected results from the first run, so that we
# can access them after the tests are rerun (which changes
# `handler.unexpected_results`). After rerunning some tests will be
# marked as flaky but otherwise the contents of this original list
# won't change.
unexpected_results = list(handler.unexpected_results)
# This isn't strictly necessary since `handler.suite_start()` clears
# the state, but make sure that we are starting with a fresh handler.
handler.reset_state()
print(80 * "=")
print(f"Rerunning {len(unexpected_results)} tests "
"with unexpected results to detect flaky tests.")
unexpected_results_tests = [result.path for result in unexpected_results]
kwargs["test_list"] = unexpected_results_tests
kwargs["include"] = unexpected_results_tests
kwargs["pause_after_test"] = False
wptrunner.run_tests(**kwargs)
# Use the second run to mark tests from the first run as flaky, but
# discard the results otherwise.
# TODO: It might be a good idea to send the new results to the
# dashboard if they were also unexpected.
stable_tests = [result.path for result in handler.unexpected_results]
for result in unexpected_results:
result.flaky = result.path not in stable_tests
all_filtered = filter_intermittents(unexpected_results,
filter_intermittents_output)
return_value = 0 if all_filtered else 1
# Write the unexpected-only raw log if that was specified on the command-line.
if unexpected_raw_log_output_file:
if not raw_log_outputs:
print("'--log-raw-unexpected' not written without '--log-raw'.")
else:
write_unexpected_only_raw_log(
handler.unexpected_results,
raw_log_outputs[0].name,
unexpected_raw_log_output_file
)
return return_value
class GithubContextInformation(NamedTuple):
build_url: Optional[str]
pull_url: Optional[str]
branch_name: Optional[str]
class TrackerDashboardFilter():
def __init__(self):
base_url = os.environ.get(TRACKER_API_ENV_VAR, TRACKER_API)
self.headers = {
"Content-Type": "application/json"
}
if TRACKER_DASHBOARD_SECRET_ENV_VAR in os.environ and os.environ[TRACKER_DASHBOARD_SECRET_ENV_VAR]:
self.url = f"{base_url}/dashboard/attempts"
secret = os.environ[TRACKER_DASHBOARD_SECRET_ENV_VAR]
self.headers["Authorization"] = f"Bearer {secret}"
else:
self.url = f"{base_url}/dashboard/query"
@staticmethod
def get_github_context_information() -> GithubContextInformation:
github_context = json.loads(os.environ.get("GITHUB_CONTEXT", "{}"))
if not github_context:
return GithubContextInformation(None, None, None)
repository = github_context['repository']
repo_url = f"https://github.com/{repository}"
run_id = github_context['run_id']
build_url = f"{repo_url}/actions/runs/{run_id}"
commit_title = github_context["event"]["head_commit"]["message"]
match = re.match(r"^Auto merge of #(\d+)", commit_title)
pr_url = f"{repo_url}/pull/{match.group(1)}" if match else None
return GithubContextInformation(
build_url,
pr_url,
github_context["ref_name"]
)
def make_data_from_result(
self,
result: Union[UnexpectedResult, UnexpectedSubtestResult],
) -> dict:
data = {
'path': result.path,
'subtest': None,
'expected': result.expected,
'actual': result.actual,
'time': result.time // 1000,
'message': result.message,
'stack': result.stack,
}
if isinstance(result, UnexpectedSubtestResult):
data["subtest"] = result.subtest
return data
def report_failures(self, unexpected_results: List[UnexpectedResult]):
attempts = []
for result in unexpected_results:
attempts.append(self.make_data_from_result(result))
for subtest_result in result.unexpected_subtest_results:
attempts.append(self.make_data_from_result(subtest_result))
context = self.get_github_context_information()
try:
request = urllib.request.Request(
url=self.url,
method='POST',
data=json.dumps({
'branch': context.branch_name,
'build_url': context.build_url,
'pull_url': context.pull_url,
'attempts': attempts
}).encode('utf-8'),
headers=self.headers)
known_intermittents = dict()
with urllib.request.urlopen(request) as response:
for test in json.load(response)["known"]:
known_intermittents[test["path"]] = \
[issue["number"] for issue in test["issues"]]
except urllib.error.HTTPError as e:
print(e)
print(e.readlines())
raise(e)
for result in unexpected_results:
result.issues = known_intermittents.get(result.path, [])
def filter_intermittents(
unexpected_results: List[UnexpectedResult],
output_path: str
) -> bool:
print(f"Filtering {len(unexpected_results)} "
"unexpected results for known intermittents")
dashboard = TrackerDashboardFilter()
dashboard.report_failures(unexpected_results)
def add_result(output, text, results: List[UnexpectedResult], filter_func) -> None:
filtered = [str(result) for result in filter(filter_func, results)]
if filtered:
output += [f"{text} ({len(results)}): ", *filtered]
def is_stable_and_unexpected(result):
return not result.flaky and not result.issues
output: List[str] = []
add_result(output, "Flaky unexpected results", unexpected_results,
lambda result: result.flaky)
add_result(output, "Stable unexpected results that are known-intermittent",
unexpected_results, lambda result: not result.flaky and result.issues)
add_result(output, "Stable unexpected results",
unexpected_results, is_stable_and_unexpected)
print("\n".join(output))
with open(output_path, "w", encoding="utf-8") as file:
json.dump([dataclasses.asdict(result) for result in unexpected_results], file)
return not any([is_stable_and_unexpected(result) for result in unexpected_results])
def write_unexpected_only_raw_log(
unexpected_results: List[UnexpectedResult],
raw_log_file: str,
filtered_raw_log_file: str
):
tests = [result.path for result in unexpected_results]
print(f"Writing unexpected-only raw log to {filtered_raw_log_file}")
with open(filtered_raw_log_file, "w", encoding="utf-8") as output:
with open(raw_log_file) as input:
for line in input.readlines():
data = json.loads(line)
if data["action"] in ["suite_start", "suite_end"] or \
("test" in data and data["test"] in tests):
output.write(line)

673
python/wpt/test.py Normal file
View file

@ -0,0 +1,673 @@
#!/usr/bin/env python
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
# pylint: disable=broad-except
# pylint: disable=dangerous-default-value
# pylint: disable=global-statement
# pylint: disable=line-too-long
# pylint: disable=missing-docstring
# pylint: disable=protected-access
# This allows using types that are defined later in the file.
from __future__ import annotations
import dataclasses
import json
import locale
import logging
import os
import shutil
import subprocess
import sys
import tempfile
import threading
import time
import unittest
from functools import partial
from typing import Any, Optional, Tuple
from wsgiref.simple_server import WSGIRequestHandler, make_server
import flask
import flask.cli
import requests
from exporter import SyncRun, WPTSync
from exporter.step import CreateOrUpdateBranchForPRStep
TESTS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tests")
SYNC: Optional[WPTSync] = None
TMP_DIR: Optional[str] = None
PORT = 9000
if "-v" in sys.argv or "--verbose" in sys.argv:
logging.getLogger().level = logging.DEBUG
@dataclasses.dataclass
class MockPullRequest():
head: str
number: int
state: str = "open"
class MockGitHubAPIServer():
def __init__(self, port: int):
self.port = port
self.disable_logging()
self.app = flask.Flask(__name__)
self.pulls: list[MockPullRequest] = []
class NoLoggingHandler(WSGIRequestHandler):
def log_message(self, *args):
pass
if logging.getLogger().level == logging.DEBUG:
handler = WSGIRequestHandler
else:
handler = NoLoggingHandler
self.server = make_server('localhost', self.port, self.app, handler_class=handler)
self.start_server_thread()
def disable_logging(self):
flask.cli.show_server_banner = lambda *args: None
logging.getLogger("werkzeug").disabled = True
logging.getLogger('werkzeug').setLevel(logging.CRITICAL)
def start(self):
self.thread.start()
# Wait for the server to be started.
while True:
try:
response = requests.get(f'http://localhost:{self.port}/ping', timeout=1)
assert response.status_code == 200
assert response.text == 'pong'
break
except Exception:
time.sleep(0.1)
def reset_server_state_with_pull_requests(self, pulls: list[MockPullRequest]):
response = requests.get(
f'http://localhost:{self.port}/reset-mock-github',
json=[dataclasses.asdict(pull_request) for pull_request in pulls],
timeout=1
)
assert response.status_code == 200
assert response.text == '👍'
def shutdown(self):
self.server.shutdown()
self.thread.join()
def start_server_thread(self):
# pylint: disable=unused-argument
self.thread = threading.Thread(target=self.server.serve_forever, daemon=True)
self.thread.start()
@self.app.route("/ping")
def ping():
return ('pong', 200)
@self.app.route("/reset-mock-github")
def reset_server():
self.pulls = [
MockPullRequest(pull_request['head'],
pull_request['number'],
pull_request['state'])
for pull_request in flask.request.json]
return ('👍', 200)
@self.app.route("/repos/<org>/<repo>/pulls/<int:number>/merge", methods=['PUT'])
def merge_pull_request(org, repo, number):
for pull_request in self.pulls:
if pull_request.number == number:
pull_request.state = 'closed'
return ('', 204)
return ('', 404)
@self.app.route("/search/issues", methods=['GET'])
def search():
params = {}
param_strings = flask.request.args.get("q", "").split(" ")
for string in param_strings:
parts = string.split(":")
params[parts[0]] = parts[1]
assert params["is"] == "pr"
assert params["state"] == "open"
assert "author" in params
assert "head" in params
head_ref = f"{params['author']}:{params['head']}"
for pull_request in self.pulls:
if pull_request.head == head_ref:
return json.dumps({
"total_count": 1,
"items": [{
"number": pull_request.number
}]
})
return json.dumps({"total_count": 0, "items": []})
@self.app.route("/repos/<org>/<repo>/pulls", methods=['POST'])
def create_pull_request(org, repo):
new_pr_number = len(self.pulls) + 1
self.pulls.append(MockPullRequest(
flask.request.json["head"],
new_pr_number,
"open"
))
return {"number": new_pr_number}
@self.app.route("/repos/<org>/<repo>/pulls/<int:number>", methods=['PATCH'])
def update_pull_request(org, repo, number):
for pull_request in self.pulls:
if pull_request.number == number:
if 'state' in flask.request.json:
pull_request.state = flask.request.json['state']
return ('', 204)
return ('', 404)
@self.app.route("/repos/<org>/<repo>/issues/<number>/labels", methods=['GET', 'POST'])
@self.app.route("/repos/<org>/<repo>/issues/<number>/labels/<label>", methods=['DELETE'])
@self.app.route("/repos/<org>/<repo>/issues/<issue>/comments", methods=['GET', 'POST'])
def other_requests(*args, **kwargs):
return ('', 204)
class TestCleanUpBodyText(unittest.TestCase):
"""Tests that SyncRun.clean_up_body_text properly prepares the
body text for an upstream pull request."""
def test_prepare_body(self):
text = "Simple body text"
self.assertEqual(text, SyncRun.clean_up_body_text(text))
self.assertEqual(
"With reference: #<!-- nolink -->3",
SyncRun.clean_up_body_text("With reference: #3"),
)
self.assertEqual(
"Multi reference: #<!-- nolink -->3 and #<!-- nolink -->1020",
SyncRun.clean_up_body_text("Multi reference: #3 and #1020"),
)
self.assertEqual(
"Subject\n\nBody text #<!-- nolink -->1",
SyncRun.clean_up_body_text(
"Subject\n\nBody text #1\n---<!-- Thank you for contributing"
),
)
self.assertEqual(
"Subject\n\nNo dashes",
SyncRun.clean_up_body_text(
"Subject\n\nNo dashes<!-- Thank you for contributing"
),
)
self.assertEqual(
"Subject\n\nNo --- comment",
SyncRun.clean_up_body_text(
"Subject\n\nNo --- comment\n---Other stuff that"
),
)
self.assertEqual(
"Subject\n\n#<!-- nolink -->3 servo#<!-- nolink -->3 servo/servo#3",
SyncRun.clean_up_body_text(
"Subject\n\n#3 servo#3 servo/servo#3",
),
"Only relative and bare issue reference links should be escaped."
)
class TestApplyCommitsToWPT(unittest.TestCase):
"""Tests that commits are properly applied to WPT by
CreateOrUpdateBranchForPRStep._create_or_update_branch_for_pr."""
def run_test(self, pr_number: int, commit_data: dict):
def make_commit(data):
with open(os.path.join(TESTS_DIR, data[2]), "rb") as file:
return {"author": data[0], "message": data[1], "diff": file.read()}
commits = [make_commit(data) for data in commit_data]
assert SYNC is not None
pull_request = SYNC.servo.get_pull_request(pr_number)
step = CreateOrUpdateBranchForPRStep({"number": pr_number}, pull_request)
def get_applied_commits(
num_commits: int, applied_commits: list[Tuple[str, str]]
):
assert SYNC is not None
repo = SYNC.local_wpt_repo
log = ["log", "--oneline", f"-{num_commits}"]
applied_commits += list(
zip(
repo.run(*log, "--format=%aN <%ae>").splitlines(),
repo.run(*log, "--format=%s").splitlines(),
)
)
applied_commits.reverse()
applied_commits: list[Any] = []
callback = partial(get_applied_commits, len(commits), applied_commits)
step._create_or_update_branch_for_pr(
SyncRun(SYNC, pull_request, None, None), commits, callback
)
expected_commits = [(commit["author"], commit["message"]) for commit in commits]
self.assertListEqual(applied_commits, expected_commits)
def test_simple_commit(self):
self.run_test(
45, [["test author <test@author>", "test commit message", "18746.diff"]]
)
def test_two_commits(self):
self.run_test(
100,
[
["test author <test@author>", "test commit message", "18746.diff"],
["another person <two@author>", "a different message", "wpt.diff"],
["another person <two@author>", "adding some non-utf8 chaos", "add-non-utf8-file.diff"],
],
)
def test_non_utf8_commit(self):
self.run_test(
100,
[
["test author <nonutf8@author>", "adding some non-utf8 chaos", "add-non-utf8-file.diff"],
],
)
class TestFullSyncRun(unittest.TestCase):
server: Optional[MockGitHubAPIServer] = None
@classmethod
def setUpClass(cls):
cls.server = MockGitHubAPIServer(PORT)
@classmethod
def tearDownClass(cls):
assert cls.server is not None
cls.server.shutdown()
def tearDown(self):
assert SYNC is not None
# Clean up any old files.
first_commit_hash = SYNC.local_servo_repo.run("rev-list", "HEAD").splitlines()[
-1
]
SYNC.local_servo_repo.run("reset", "--hard", first_commit_hash)
SYNC.local_servo_repo.run("clean", "-fxd")
def mock_servo_repository_state(self, diffs: list):
assert SYNC is not None
def make_commit_data(diff):
if not isinstance(diff, list):
return [diff, "tmp author", "tmp@tmp.com", "tmp commit message"]
return diff
# Apply each commit to the repository.
orig_sha = SYNC.local_servo_repo.run("rev-parse", "HEAD").strip()
commits = [make_commit_data(diff) for diff in diffs]
for commit in commits:
patch_file, author, email, message = commit
SYNC.local_servo_repo.run("apply", os.path.join(TESTS_DIR, patch_file))
SYNC.local_servo_repo.run("add", ".")
SYNC.local_servo_repo.run(
"commit",
"-a",
"--author",
f"{author} <{email}>",
"-m",
message,
env={
"GIT_COMMITTER_NAME": author.encode(locale.getpreferredencoding()),
"GIT_COMMITTER_EMAIL": email,
},
)
# Reset the repository to the original hash, but the commits are still
# available until the next `git gc`.
last_commit_sha = SYNC.local_servo_repo.run("rev-parse", "HEAD").strip()
SYNC.local_servo_repo.run("reset", "--hard", orig_sha)
return last_commit_sha
def run_test(
self, payload_file: str, diffs: list, existing_prs: list[MockPullRequest] = []
):
with open(os.path.join(TESTS_DIR, payload_file), encoding="utf-8") as file:
payload = json.loads(file.read())
logging.info("Mocking application of PR to servo.")
last_commit_sha = self.mock_servo_repository_state(diffs)
payload["pull_request"]["head"]["sha"] = last_commit_sha
logging.info("Resetting server state")
assert self.server is not None
self.server.reset_server_state_with_pull_requests(existing_prs)
actual_steps = []
assert SYNC is not None
SYNC.run(payload, step_callback=lambda step: actual_steps.append(step.name))
return actual_steps
def test_opened_upstreamable_pr(self):
self.assertListEqual(
self.run_test("opened.json", ["18746.diff"]),
[
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_18746",
"OpenPRStep:servo-wpt-sync/wpt/servo_export_18746→wpt/wpt#1",
"CommentStep:servo/servo#18746:🤖 Opened new upstream WPT pull request "
"(wpt/wpt#1) with upstreamable changes.",
],
)
def test_opened_upstreamable_pr_with_move_into_wpt(self):
self.assertListEqual(
self.run_test("opened.json", ["move-into-wpt.diff"]),
[
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_18746",
"OpenPRStep:servo-wpt-sync/wpt/servo_export_18746→wpt/wpt#1",
"CommentStep:servo/servo#18746:🤖 Opened new upstream WPT pull request "
"(wpt/wpt#1) with upstreamable changes.",
],
)
def test_opened_upstreamble_pr_with_move_into_wpt_and_non_ascii_author(self):
self.assertListEqual(
self.run_test(
"opened.json",
[
[
"move-into-wpt.diff",
"Fernando Jiménez Moreno",
"foo@bar.com",
"ééééé",
]
],
),
[
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_18746",
"OpenPRStep:servo-wpt-sync/wpt/servo_export_18746→wpt/wpt#1",
"CommentStep:servo/servo#18746:🤖 Opened new upstream WPT pull request "
"(wpt/wpt#1) with upstreamable changes.",
],
)
def test_opened_upstreamable_pr_with_move_out_of_wpt(self):
self.assertListEqual(
self.run_test("opened.json", ["move-out-of-wpt.diff"]),
[
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_18746",
"OpenPRStep:servo-wpt-sync/wpt/servo_export_18746→wpt/wpt#1",
"CommentStep:servo/servo#18746:🤖 Opened new upstream WPT pull request "
"(wpt/wpt#1) with upstreamable changes.",
],
)
def test_opened_new_mr_with_no_sync_signal(self):
self.assertListEqual(
self.run_test("opened-with-no-sync-signal.json", ["18746.diff"]), []
)
self.assertListEqual(
self.run_test("opened-with-no-sync-signal.json", ["non-wpt.diff"]), []
)
def test_opened_upstreamable_pr_not_applying_cleanly_to_upstream(self):
self.assertListEqual(
self.run_test("opened.json", ["does-not-apply-cleanly.diff"]),
[
"CreateOrUpdateBranchForPRStep",
"CommentStep:servo/servo#18746:🛠 These changes could not be applied "
"onto the latest upstream WPT. Servo's copy of the Web Platform Tests may be out of sync.",
],
)
def test_open_new_upstreamable_pr_with_preexisting_upstream_pr(self):
self.assertListEqual(
self.run_test(
"opened.json",
["18746.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_18746", 1)],
),
[
"ChangePRStep:wpt/wpt#1:opened:This is a test:<!-- Please...[95]",
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_18746",
"CommentStep:servo/servo#18746:📝 Transplanted new upstreamable changes to "
"existing upstream WPT pull request (wpt/wpt#1).",
],
)
def test_open_new_non_upstreamable_pr_with_preexisting_upstream_pr(self):
self.assertListEqual(
self.run_test(
"opened.json",
["non-wpt.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_18746", 1)],
),
[
"CommentStep:wpt/wpt#1:👋 Downstream pull request (servo/servo#18746) no longer "
"contains any upstreamable changes. Closing pull request without merging.",
"ChangePRStep:wpt/wpt#1:closed",
"RemoveBranchForPRStep:servo-wpt-sync/wpt/servo_export_18746",
"CommentStep:servo/servo#18746:🤖 This change no longer contains upstreamable changes "
"to WPT; closed existing upstream pull request (wpt/wpt#1).",
]
)
def test_opened_upstreamable_pr_with_non_utf8_file_contents(self):
self.assertListEqual(
self.run_test("opened.json", ["add-non-utf8-file.diff"]),
[
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_18746",
"OpenPRStep:servo-wpt-sync/wpt/servo_export_18746→wpt/wpt#1",
"CommentStep:servo/servo#18746:🤖 Opened new upstream WPT pull request "
"(wpt/wpt#1) with upstreamable changes.",
],
)
def test_open_new_upstreamable_pr_with_preexisting_upstream_pr_not_apply_cleanly_to_upstream(
self,
):
self.assertListEqual(
self.run_test(
"opened.json",
["does-not-apply-cleanly.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_18746", 1)],
),
[
"ChangePRStep:wpt/wpt#1:opened:This is a test:<!-- Please...[95]",
"CreateOrUpdateBranchForPRStep",
"CommentStep:servo/servo#18746:🛠 These changes could not be applied onto the latest "
"upstream WPT. Servo's copy of the Web Platform Tests may be out of sync.",
"CommentStep:wpt/wpt#1:🛠 Changes from the source pull request (servo/servo#18746) can "
"no longer be cleanly applied. Waiting for a new version of these changes downstream.",
],
)
def test_closed_pr_no_upstream_pr(self):
self.assertListEqual(self.run_test("closed.json", ["18746.diff"]), [])
def test_closed_pr_with_preexisting_upstream_pr(self):
self.assertListEqual(
self.run_test(
"closed.json",
["18746.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_18746", 10)],
),
[
"ChangePRStep:wpt/wpt#10:closed",
"RemoveBranchForPRStep:servo-wpt-sync/wpt/servo_export_18746"
]
)
def test_synchronize_move_new_changes_to_preexisting_upstream_pr(self):
self.assertListEqual(
self.run_test(
"synchronize.json",
["18746.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_19612", 10)],
),
[
"ChangePRStep:wpt/wpt#10:opened:deny warnings:<!-- Please...[142]",
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_19612",
"CommentStep:servo/servo#19612:📝 Transplanted new upstreamable changes to existing "
"upstream WPT pull request (wpt/wpt#10).",
]
)
def test_synchronize_close_upstream_pr_after_new_changes_do_not_include_wpt(self):
self.assertListEqual(
self.run_test(
"synchronize.json",
["non-wpt.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_19612", 11)],
),
[
"CommentStep:wpt/wpt#11:👋 Downstream pull request (servo/servo#19612) no longer contains any "
"upstreamable changes. Closing pull request without merging.",
"ChangePRStep:wpt/wpt#11:closed",
"RemoveBranchForPRStep:servo-wpt-sync/wpt/servo_export_19612",
"CommentStep:servo/servo#19612:🤖 This change no longer contains upstreamable changes to WPT; "
"closed existing upstream pull request (wpt/wpt#11).",
]
)
def test_synchronize_open_upstream_pr_after_new_changes_include_wpt(self):
self.assertListEqual(
self.run_test("synchronize.json", ["18746.diff"]),
[
"CreateOrUpdateBranchForPRStep:1:servo-wpt-sync/wpt/servo_export_19612",
"OpenPRStep:servo-wpt-sync/wpt/servo_export_19612→wpt/wpt#1",
"CommentStep:servo/servo#19612:🤖 Opened new upstream WPT pull request "
"(wpt/wpt#1) with upstreamable changes.",
]
)
def test_synchronize_fail_to_update_preexisting_pr_after_new_changes_do_not_apply(
self,
):
self.assertListEqual(
self.run_test(
"synchronize.json",
["does-not-apply-cleanly.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_19612", 11)],
),
[
"ChangePRStep:wpt/wpt#11:opened:deny warnings:<!-- Please...[142]",
"CreateOrUpdateBranchForPRStep",
"CommentStep:servo/servo#19612:🛠 These changes could not be applied onto the "
"latest upstream WPT. Servo's copy of the Web Platform Tests may be out of sync.",
"CommentStep:wpt/wpt#11:🛠 Changes from the source pull request (servo/servo#19612) can "
"no longer be cleanly applied. Waiting for a new version of these changes downstream.",
]
)
def test_edited_with_upstream_pr(self):
self.assertListEqual(
self.run_test(
"edited.json", ["wpt.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_19620", 10)]
),
[
"ChangePRStep:wpt/wpt#10:open:A cool new title:Reference #<!--...[136]",
"CommentStep:servo/servo#19620:✍ Updated existing upstream WPT pull "
"request (wpt/wpt#10) title and body."
]
)
def test_edited_with_no_upstream_pr(self):
self.assertListEqual(self.run_test("edited.json", ["wpt.diff"], []), [])
def test_synchronize_move_new_changes_to_preexisting_upstream_pr_with_multiple_commits(
self,
):
self.assertListEqual(
self.run_test(
"synchronize-multiple.json", ["18746.diff", "non-wpt.diff", "wpt.diff"]
),
[
"CreateOrUpdateBranchForPRStep:2:servo-wpt-sync/wpt/servo_export_19612",
"OpenPRStep:servo-wpt-sync/wpt/servo_export_19612→wpt/wpt#1",
"CommentStep:servo/servo#19612:"
"🤖 Opened new upstream WPT pull request (wpt/wpt#1) with upstreamable changes.",
]
)
def test_synchronize_with_non_upstreamable_changes(self):
self.assertListEqual(self.run_test("synchronize.json", ["non-wpt.diff"]), [])
def test_merge_upstream_pr_after_merge(self):
self.assertListEqual(
self.run_test(
"merged.json",
["18746.diff"],
[MockPullRequest("servo-wpt-sync:servo_export_19620", 100)]
),
[
"MergePRStep:wpt/wpt#100",
"RemoveBranchForPRStep:servo-wpt-sync/wpt/servo_export_19620"
]
)
def test_pr_merged_no_upstream_pr(self):
self.assertListEqual(self.run_test("merged.json", ["18746.diff"]), [])
def test_merge_of_non_upstreamble_pr(self):
self.assertListEqual(self.run_test("merged.json", ["non-wpt.diff"]), [])
def setUpModule():
# pylint: disable=invalid-name
global TMP_DIR, SYNC
TMP_DIR = tempfile.mkdtemp()
SYNC = WPTSync(
servo_repo="servo/servo",
wpt_repo="wpt/wpt",
downstream_wpt_repo="servo-wpt-sync/wpt",
servo_path=os.path.join(TMP_DIR, "servo-mock"),
wpt_path=os.path.join(TMP_DIR, "wpt-mock"),
github_api_token="",
github_api_url=f"http://localhost:{PORT}",
github_username="servo-wpt-sync",
github_email="servo-wpt-sync",
github_name="servo-wpt-sync@servo.org",
suppress_force_push=True,
)
def setup_mock_repo(repo_name, local_repo):
subprocess.check_output(
["cp", "-R", "-p", os.path.join(TESTS_DIR, repo_name), local_repo.path])
local_repo.run("init", "-b", "master")
local_repo.run("add", ".")
local_repo.run("commit", "-a", "-m", "Initial commit")
logging.info("=" * 80)
logging.info("Setting up mock repositories")
setup_mock_repo("servo-mock", SYNC.local_servo_repo)
setup_mock_repo("wpt-mock", SYNC.local_wpt_repo)
logging.info("=" * 80)
def tearDownModule():
# pylint: disable=invalid-name
shutil.rmtree(TMP_DIR)
if __name__ == "__main__":
# Uncomment this line to enable verbose logging.
# logging.getLogger().setLevel(logging.INFO)
unittest.main()

View file

@ -0,0 +1,10 @@
diff --git a/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-location.html b/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-location.html
index ac35dea54c47..135ad21d15ab 100644
--- a/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-location.html
+++ b/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-location.html
@@ -13,4 +13,5 @@
<script src="redirect-location.js"></script>
</body>
</html>
+test commit

View file

@ -0,0 +1,7 @@
diff --git a/tests/wpt/web-platform-tests/non-utf8-file.txt b/tests/wpt/web-platform-tests/non-utf8-file.txt
new file mode 100644
index 0000000..5a992e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/non-utf8-file.txt
@@ -0,0 +1 @@
+foo bér ÿ "

View file

@ -0,0 +1,476 @@
{
"action": "closed",
"number": 18746,
"pull_request": {
"url": "https://api.github.com/repos/servo/servo/pulls/18746",
"id": 144666315,
"html_url": "https://github.com/servo/servo/pull/18746",
"diff_url": "https://github.com/servo/servo/pull/18746.diff",
"patch_url": "https://github.com/servo/servo/pull/18746.patch",
"issue_url": "https://api.github.com/repos/servo/servo/issues/18746",
"number": 18746,
"state": "closed",
"locked": false,
"title": "This is a test",
"user": {
"login": "jdm",
"id": 27658,
"avatar_url": "https://avatars1.githubusercontent.com/u/27658?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jdm",
"html_url": "https://github.com/jdm",
"followers_url": "https://api.github.com/users/jdm/followers",
"following_url": "https://api.github.com/users/jdm/following{/other_user}",
"gists_url": "https://api.github.com/users/jdm/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jdm/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jdm/subscriptions",
"organizations_url": "https://api.github.com/users/jdm/orgs",
"repos_url": "https://api.github.com/users/jdm/repos",
"events_url": "https://api.github.com/users/jdm/events{/privacy}",
"received_events_url": "https://api.github.com/users/jdm/received_events",
"type": "User",
"site_admin": false
},
"body": "<!-- Please describe your changes on the following line: -->\r\n\r\n\r\n---\r\n<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->\r\n- [ ] `./mach build -d` does not report any errors\r\n- [ ] `./mach test-tidy` does not report any errors\r\n- [ ] These changes fix #__ (github issue number if applicable).\r\n\r\n<!-- Either: -->\r\n- [ ] There are tests for these changes OR\r\n- [ ] These changes do not require tests because _____\r\n\r\n<!-- Also, please make sure that \"Allow edits from maintainers\" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->\r\n\r\n<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->\r\n",
"created_at": "2017-10-04T13:16:26Z",
"updated_at": "2017-10-04T13:16:30Z",
"closed_at": "2017-10-04T13:16:30Z",
"merged_at": null,
"merge_commit_sha": "04b78ff84073a6b6e2126fea39c8878f3f7af72b",
"assignee": {
"login": "emilio",
"id": 1323194,
"avatar_url": "https://avatars1.githubusercontent.com/u/1323194?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/emilio",
"html_url": "https://github.com/emilio",
"followers_url": "https://api.github.com/users/emilio/followers",
"following_url": "https://api.github.com/users/emilio/following{/other_user}",
"gists_url": "https://api.github.com/users/emilio/gists{/gist_id}",
"starred_url": "https://api.github.com/users/emilio/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/emilio/subscriptions",
"organizations_url": "https://api.github.com/users/emilio/orgs",
"repos_url": "https://api.github.com/users/emilio/repos",
"events_url": "https://api.github.com/users/emilio/events{/privacy}",
"received_events_url": "https://api.github.com/users/emilio/received_events",
"type": "User",
"site_admin": false
},
"assignees": [
{
"login": "emilio",
"id": 1323194,
"avatar_url": "https://avatars1.githubusercontent.com/u/1323194?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/emilio",
"html_url": "https://github.com/emilio",
"followers_url": "https://api.github.com/users/emilio/followers",
"following_url": "https://api.github.com/users/emilio/following{/other_user}",
"gists_url": "https://api.github.com/users/emilio/gists{/gist_id}",
"starred_url": "https://api.github.com/users/emilio/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/emilio/subscriptions",
"organizations_url": "https://api.github.com/users/emilio/orgs",
"repos_url": "https://api.github.com/users/emilio/repos",
"events_url": "https://api.github.com/users/emilio/events{/privacy}",
"received_events_url": "https://api.github.com/users/emilio/received_events",
"type": "User",
"site_admin": false
}
],
"requested_reviewers": [
],
"milestone": null,
"commits_url": "https://api.github.com/repos/servo/servo/pulls/18746/commits",
"review_comments_url": "https://api.github.com/repos/servo/servo/pulls/18746/comments",
"review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}",
"comments_url": "https://api.github.com/repos/servo/servo/issues/18746/comments",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f",
"head": {
"label": "servo:jdm-patch-1",
"ref": "jdm-patch-1",
"sha": "1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:26Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2072,
"forks": 1731,
"open_issues": 2072,
"watchers": 10131,
"default_branch": "master"
}
},
"base": {
"label": "servo:master",
"ref": "master",
"sha": "3b7a82b8c743bcbbefb6f25defd4cc132c25c348",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:26Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2072,
"forks": 1731,
"open_issues": 2072,
"watchers": 10131,
"default_branch": "master"
}
},
"_links": {
"self": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746"
},
"html": {
"href": "https://github.com/servo/servo/pull/18746"
},
"issue": {
"href": "https://api.github.com/repos/servo/servo/issues/18746"
},
"comments": {
"href": "https://api.github.com/repos/servo/servo/issues/18746/comments"
},
"review_comments": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746/comments"
},
"review_comment": {
"href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}"
},
"commits": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746/commits"
},
"statuses": {
"href": "https://api.github.com/repos/servo/servo/statuses/1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f"
}
},
"author_association": "MEMBER",
"merged": false,
"mergeable": true,
"rebaseable": true,
"mergeable_state": "unstable",
"merged_by": null,
"comments": 0,
"review_comments": 0,
"maintainer_can_modify": false,
"commits": 1,
"additions": 2,
"deletions": 1,
"changed_files": 1
},
"repository": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:26Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2072,
"forks": 1731,
"open_issues": 2072,
"watchers": 10131,
"default_branch": "master"
},
"organization": {
"login": "servo",
"id": 2566135,
"url": "https://api.github.com/orgs/servo",
"repos_url": "https://api.github.com/orgs/servo/repos",
"events_url": "https://api.github.com/orgs/servo/events",
"hooks_url": "https://api.github.com/orgs/servo/hooks",
"issues_url": "https://api.github.com/orgs/servo/issues",
"members_url": "https://api.github.com/orgs/servo/members{/member}",
"public_members_url": "https://api.github.com/orgs/servo/public_members{/member}",
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"description": "The Servo web browser engine"
},
"sender": {
"login": "jdm",
"id": 27658,
"avatar_url": "https://avatars1.githubusercontent.com/u/27658?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jdm",
"html_url": "https://github.com/jdm",
"followers_url": "https://api.github.com/users/jdm/followers",
"following_url": "https://api.github.com/users/jdm/following{/other_user}",
"gists_url": "https://api.github.com/users/jdm/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jdm/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jdm/subscriptions",
"organizations_url": "https://api.github.com/users/jdm/orgs",
"repos_url": "https://api.github.com/users/jdm/repos",
"events_url": "https://api.github.com/users/jdm/events{/privacy}",
"received_events_url": "https://api.github.com/users/jdm/received_events",
"type": "User",
"site_admin": false
}
}

View file

@ -0,0 +1,9 @@
diff --git a/tests/wpt/web-platform-tests/css/css-test.html b/tests/wpt/web-platform-tests/css/css-test.html
index cffb6eb..6100a49 100644
--- a/tests/wpt/web-platform-tests/css/out-of-sync-test.html
+++ b/tests/wpt/web-platform-tests/css/out-of-sync-test.html
@@ -1,3 +1,3 @@
<html>
-<h1>css test!</h1>
+<h1>css test!</h1>hi
</html>

View file

@ -0,0 +1,514 @@
{
"action": "edited",
"changes": {
"body": {
"from": "Original body<!-- Please describe your changes on the following line: -->\r\n\r\n\r\n---\r\n<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->\r\n- [ ] `./mach build -d` does not report any errors\r\n- [ ] `./mach test-tidy` does not report any errors\r\n- [ ] These changes fix #___ (GitHub issue number if applicable)\r\n\r\n<!-- Either: -->\r\n- [ ] There are tests for these changes OR\r\n- [ ] These changes do not require tests because ___\r\n\r\n<!-- Also, please make sure that \"Allow edits from maintainers\" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->\r\n\r\n<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->\r\n"
},
"title": {
"from": "Original bad title"
}
},
"number": 19620,
"pull_request": {
"_links": {
"comments": {
"href": "https://api.github.com/repos/servo/servo/issues/19620/comments"
},
"commits": {
"href": "https://api.github.com/repos/servo/servo/pulls/19620/commits"
},
"html": {
"href": "https://github.com/servo/servo/pull/19620"
},
"issue": {
"href": "https://api.github.com/repos/servo/servo/issues/19620"
},
"review_comment": {
"href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}"
},
"review_comments": {
"href": "https://api.github.com/repos/servo/servo/pulls/19620/comments"
},
"self": {
"href": "https://api.github.com/repos/servo/servo/pulls/19620"
},
"statuses": {
"href": "https://api.github.com/repos/servo/servo/statuses/28ce5e1e33563e9dc2fe7bc342d313b38147df23"
}
},
"active_lock_reason": null,
"additions": 13,
"assignee": null,
"assignees": [],
"author_association": "OWNER",
"auto_merge": null,
"base": {
"label": "mrobinson:master",
"ref": "master",
"repo": {
"allow_auto_merge": false,
"allow_forking": true,
"allow_merge_commit": true,
"allow_rebase_merge": true,
"allow_squash_merge": true,
"allow_update_branch": false,
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"archived": false,
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"clone_url": "https://github.com/servo/servo.git",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"created_at": "2014-03-31T16:17:52Z",
"default_branch": "master",
"delete_branch_on_merge": false,
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"description": "The Servo Browser Engine",
"disabled": false,
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"events_url": "https://api.github.com/repos/servo/servo/events",
"fork": true,
"forks": 0,
"forks_count": 0,
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"full_name": "servo/servo",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_url": "git://github.com/servo/servo.git",
"has_discussions": false,
"has_downloads": true,
"has_issues": false,
"has_pages": false,
"has_projects": true,
"has_wiki": true,
"homepage": "",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"html_url": "https://github.com/servo/servo",
"id": 18299566,
"is_template": false,
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"language": null,
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"node_id": "MDc6TGljZW5zZTE0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"merge_commit_message": "PR_TITLE",
"merge_commit_title": "MERGE_MESSAGE",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"mirror_url": null,
"name": "servo",
"node_id": "MDEwOlJlcG9zaXRvcnkxODI5OTU2Ng==",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"open_issues": 2,
"open_issues_count": 2,
"owner": {
"avatar_url": "https://avatars.githubusercontent.com/u/13536?v=4",
"events_url": "https://api.github.com/users/mrobinson/events{/privacy}",
"followers_url": "https://api.github.com/users/mrobinson/followers",
"following_url": "https://api.github.com/users/mrobinson/following{/other_user}",
"gists_url": "https://api.github.com/users/mrobinson/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/mrobinson",
"id": 13536,
"login": "mrobinson",
"node_id": "MDQ6VXNlcjEzNTM2",
"organizations_url": "https://api.github.com/users/mrobinson/orgs",
"received_events_url": "https://api.github.com/users/mrobinson/received_events",
"repos_url": "https://api.github.com/users/mrobinson/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/mrobinson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mrobinson/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mrobinson"
},
"private": false,
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"pushed_at": "2023-01-09T08:10:35Z",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"size": 928531,
"squash_merge_commit_message": "COMMIT_MESSAGES",
"squash_merge_commit_title": "COMMIT_OR_PR_TITLE",
"ssh_url": "git@github.com:servo/servo.git",
"stargazers_count": 0,
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"svn_url": "https://github.com/servo/servo",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"topics": [],
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"updated_at": "2023-01-02T14:06:01Z",
"url": "https://api.github.com/repos/servo/servo",
"use_squash_pr_title_as_default": false,
"visibility": "public",
"watchers": 0,
"watchers_count": 0,
"web_commit_signoff_required": false
},
"sha": "35b45a8a0b6741679439de56613f3588e5cc5887",
"user": {
"avatar_url": "https://avatars.githubusercontent.com/u/13536?v=4",
"events_url": "https://api.github.com/users/mrobinson/events{/privacy}",
"followers_url": "https://api.github.com/users/mrobinson/followers",
"following_url": "https://api.github.com/users/mrobinson/following{/other_user}",
"gists_url": "https://api.github.com/users/mrobinson/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/mrobinson",
"id": 13536,
"login": "mrobinson",
"node_id": "MDQ6VXNlcjEzNTM2",
"organizations_url": "https://api.github.com/users/mrobinson/orgs",
"received_events_url": "https://api.github.com/users/mrobinson/received_events",
"repos_url": "https://api.github.com/users/mrobinson/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/mrobinson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mrobinson/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mrobinson"
}
},
"body": "Reference #3 servo/servo#3<!-- Please describe your changes on the following line: -->\r\n\r\n\r\n---\r\n<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->\r\n- [ ] `./mach build -d` does not report any errors\r\n- [ ] `./mach test-tidy` does not report any errors\r\n- [ ] These changes fix #___ (GitHub issue number if applicable)\r\n\r\n<!-- Either: -->\r\n- [ ] There are tests for these changes OR\r\n- [ ] These changes do not require tests because ___\r\n\r\n<!-- Also, please make sure that \"Allow edits from maintainers\" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->\r\n\r\n<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->\r\n",
"changed_files": 2,
"closed_at": null,
"comments": 1,
"comments_url": "https://api.github.com/repos/servo/servo/issues/19620/comments",
"commits": 2,
"commits_url": "https://api.github.com/repos/servo/servo/pulls/19620/commits",
"created_at": "2023-01-09T08:10:35Z",
"deletions": 8,
"diff_url": "https://github.com/servo/servo/pull/19620.diff",
"draft": false,
"head": {
"label": "mrobinson:more-work",
"ref": "more-work",
"repo": {
"allow_auto_merge": false,
"allow_forking": true,
"allow_merge_commit": true,
"allow_rebase_merge": true,
"allow_squash_merge": true,
"allow_update_branch": false,
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"archived": false,
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"clone_url": "https://github.com/servo/servo.git",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"created_at": "2014-03-31T16:17:52Z",
"default_branch": "master",
"delete_branch_on_merge": false,
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"description": "The Servo Browser Engine",
"disabled": false,
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"events_url": "https://api.github.com/repos/servo/servo/events",
"fork": true,
"forks": 0,
"forks_count": 0,
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"full_name": "servo/servo",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_url": "git://github.com/servo/servo.git",
"has_discussions": false,
"has_downloads": true,
"has_issues": false,
"has_pages": false,
"has_projects": true,
"has_wiki": true,
"homepage": "",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"html_url": "https://github.com/servo/servo",
"id": 18299566,
"is_template": false,
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"language": null,
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"node_id": "MDc6TGljZW5zZTE0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"merge_commit_message": "PR_TITLE",
"merge_commit_title": "MERGE_MESSAGE",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"mirror_url": null,
"name": "servo",
"node_id": "MDEwOlJlcG9zaXRvcnkxODI5OTU2Ng==",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"open_issues": 2,
"open_issues_count": 2,
"owner": {
"avatar_url": "https://avatars.githubusercontent.com/u/13536?v=4",
"events_url": "https://api.github.com/users/mrobinson/events{/privacy}",
"followers_url": "https://api.github.com/users/mrobinson/followers",
"following_url": "https://api.github.com/users/mrobinson/following{/other_user}",
"gists_url": "https://api.github.com/users/mrobinson/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/mrobinson",
"id": 13536,
"login": "mrobinson",
"node_id": "MDQ6VXNlcjEzNTM2",
"organizations_url": "https://api.github.com/users/mrobinson/orgs",
"received_events_url": "https://api.github.com/users/mrobinson/received_events",
"repos_url": "https://api.github.com/users/mrobinson/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/mrobinson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mrobinson/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mrobinson"
},
"private": false,
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"pushed_at": "2023-01-09T08:10:35Z",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"size": 928531,
"squash_merge_commit_message": "COMMIT_MESSAGES",
"squash_merge_commit_title": "COMMIT_OR_PR_TITLE",
"ssh_url": "git@github.com:servo/servo.git",
"stargazers_count": 0,
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"svn_url": "https://github.com/servo/servo",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"topics": [],
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"updated_at": "2023-01-02T14:06:01Z",
"url": "https://api.github.com/repos/servo/servo",
"use_squash_pr_title_as_default": false,
"visibility": "public",
"watchers": 0,
"watchers_count": 0,
"web_commit_signoff_required": false
},
"sha": "28ce5e1e33563e9dc2fe7bc342d313b38147df23",
"user": {
"avatar_url": "https://avatars.githubusercontent.com/u/13536?v=4",
"events_url": "https://api.github.com/users/mrobinson/events{/privacy}",
"followers_url": "https://api.github.com/users/mrobinson/followers",
"following_url": "https://api.github.com/users/mrobinson/following{/other_user}",
"gists_url": "https://api.github.com/users/mrobinson/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/mrobinson",
"id": 13536,
"login": "mrobinson",
"node_id": "MDQ6VXNlcjEzNTM2",
"organizations_url": "https://api.github.com/users/mrobinson/orgs",
"received_events_url": "https://api.github.com/users/mrobinson/received_events",
"repos_url": "https://api.github.com/users/mrobinson/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/mrobinson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mrobinson/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mrobinson"
}
},
"html_url": "https://github.com/servo/servo/pull/19620",
"id": 1190367516,
"issue_url": "https://api.github.com/repos/servo/servo/issues/19620",
"labels": [],
"locked": false,
"maintainer_can_modify": false,
"merge_commit_sha": "a5a2e2e745d1b3aaf8544cc7c6eddc519ff9f8f7",
"mergeable": true,
"mergeable_state": "clean",
"merged": false,
"merged_at": null,
"merged_by": null,
"milestone": null,
"node_id": "PR_kwDOARc6rs5G85Ec",
"number": 19620,
"patch_url": "https://github.com/servo/servo/pull/19620.patch",
"rebaseable": true,
"requested_reviewers": [],
"requested_teams": [],
"review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}",
"review_comments": 0,
"review_comments_url": "https://api.github.com/repos/servo/servo/pulls/19620/comments",
"state": "open",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/28ce5e1e33563e9dc2fe7bc342d313b38147df23",
"title": "A cool new title",
"updated_at": "2023-01-09T08:16:53Z",
"url": "https://api.github.com/repos/servo/servo/pulls/19620",
"user": {
"avatar_url": "https://avatars.githubusercontent.com/u/13536?v=4",
"events_url": "https://api.github.com/users/mrobinson/events{/privacy}",
"followers_url": "https://api.github.com/users/mrobinson/followers",
"following_url": "https://api.github.com/users/mrobinson/following{/other_user}",
"gists_url": "https://api.github.com/users/mrobinson/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/mrobinson",
"id": 13536,
"login": "mrobinson",
"node_id": "MDQ6VXNlcjEzNTM2",
"organizations_url": "https://api.github.com/users/mrobinson/orgs",
"received_events_url": "https://api.github.com/users/mrobinson/received_events",
"repos_url": "https://api.github.com/users/mrobinson/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/mrobinson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mrobinson/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mrobinson"
}
},
"repository": {
"allow_forking": true,
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"archived": false,
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"clone_url": "https://github.com/servo/servo.git",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"created_at": "2014-03-31T16:17:52Z",
"default_branch": "master",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"description": "The Servo Browser Engine",
"disabled": false,
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"events_url": "https://api.github.com/repos/servo/servo/events",
"fork": true,
"forks": 0,
"forks_count": 0,
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"full_name": "servo/servo",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_url": "git://github.com/servo/servo.git",
"has_discussions": false,
"has_downloads": true,
"has_issues": false,
"has_pages": false,
"has_projects": true,
"has_wiki": true,
"homepage": "",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"html_url": "https://github.com/servo/servo",
"id": 18299566,
"is_template": false,
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"language": null,
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"node_id": "MDc6TGljZW5zZTE0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"mirror_url": null,
"name": "servo",
"node_id": "MDEwOlJlcG9zaXRvcnkxODI5OTU2Ng==",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"open_issues": 2,
"open_issues_count": 2,
"owner": {
"avatar_url": "https://avatars.githubusercontent.com/u/13536?v=4",
"events_url": "https://api.github.com/users/mrobinson/events{/privacy}",
"followers_url": "https://api.github.com/users/mrobinson/followers",
"following_url": "https://api.github.com/users/mrobinson/following{/other_user}",
"gists_url": "https://api.github.com/users/mrobinson/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/mrobinson",
"id": 13536,
"login": "mrobinson",
"node_id": "MDQ6VXNlcjEzNTM2",
"organizations_url": "https://api.github.com/users/mrobinson/orgs",
"received_events_url": "https://api.github.com/users/mrobinson/received_events",
"repos_url": "https://api.github.com/users/mrobinson/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/mrobinson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mrobinson/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mrobinson"
},
"private": false,
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"pushed_at": "2023-01-09T08:10:35Z",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"size": 928531,
"ssh_url": "git@github.com:servo/servo.git",
"stargazers_count": 0,
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"svn_url": "https://github.com/servo/servo",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"topics": [],
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"updated_at": "2023-01-02T14:06:01Z",
"url": "https://api.github.com/repos/servo/servo",
"visibility": "public",
"watchers": 0,
"watchers_count": 0,
"web_commit_signoff_required": false
},
"sender": {
"avatar_url": "https://avatars.githubusercontent.com/u/13536?v=4",
"events_url": "https://api.github.com/users/mrobinson/events{/privacy}",
"followers_url": "https://api.github.com/users/mrobinson/followers",
"following_url": "https://api.github.com/users/mrobinson/following{/other_user}",
"gists_url": "https://api.github.com/users/mrobinson/gists{/gist_id}",
"gravatar_id": "",
"html_url": "https://github.com/mrobinson",
"id": 13536,
"login": "mrobinson",
"node_id": "MDQ6VXNlcjEzNTM2",
"organizations_url": "https://api.github.com/users/mrobinson/orgs",
"received_events_url": "https://api.github.com/users/mrobinson/received_events",
"repos_url": "https://api.github.com/users/mrobinson/repos",
"site_admin": false,
"starred_url": "https://api.github.com/users/mrobinson/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mrobinson/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mrobinson"
}
}

View file

@ -0,0 +1,515 @@
{
"action": "closed",
"number": 19620,
"pull_request": {
"url": "https://api.github.com/repos/servo/servo/pulls/19620",
"id": 159652155,
"html_url": "https://github.com/servo/servo/pull/19620",
"diff_url": "https://github.com/servo/servo/pull/19620.diff",
"patch_url": "https://github.com/servo/servo/pull/19620.patch",
"issue_url": "https://api.github.com/repos/servo/servo/issues/19620",
"number": 19620,
"state": "closed",
"locked": false,
"title": "style: Make sure to honor parse_method in transition and animation shorthands.",
"user": {
"login": "emilio",
"id": 1323194,
"avatar_url": "https://avatars1.githubusercontent.com/u/1323194?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/emilio",
"html_url": "https://github.com/emilio",
"followers_url": "https://api.github.com/users/emilio/followers",
"following_url": "https://api.github.com/users/emilio/following{/other_user}",
"gists_url": "https://api.github.com/users/emilio/gists{/gist_id}",
"starred_url": "https://api.github.com/users/emilio/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/emilio/subscriptions",
"organizations_url": "https://api.github.com/users/emilio/orgs",
"repos_url": "https://api.github.com/users/emilio/repos",
"events_url": "https://api.github.com/users/emilio/events{/privacy}",
"received_events_url": "https://api.github.com/users/emilio/received_events",
"type": "User",
"site_admin": false
},
"body": "Reviewed-by: birtles\r\nBug: 1426312\r\nMozReview-Commit-ID: HY3jtdSdaga\n\n<!-- Reviewable:start -->\n---\nThis change is[<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/servo/servo/19620)\n<!-- Reviewable:end -->\n",
"created_at": "2017-12-21T13:01:36Z",
"updated_at": "2017-12-21T14:53:35Z",
"closed_at": "2017-12-21T14:53:35Z",
"merged_at": "2017-12-21T14:53:35Z",
"merge_commit_sha": "cdb604ae6950960e46855bfb28d6c1f560b4f6e7",
"assignee": {
"login": "metajack",
"id": 28357,
"avatar_url": "https://avatars3.githubusercontent.com/u/28357?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/metajack",
"html_url": "https://github.com/metajack",
"followers_url": "https://api.github.com/users/metajack/followers",
"following_url": "https://api.github.com/users/metajack/following{/other_user}",
"gists_url": "https://api.github.com/users/metajack/gists{/gist_id}",
"starred_url": "https://api.github.com/users/metajack/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/metajack/subscriptions",
"organizations_url": "https://api.github.com/users/metajack/orgs",
"repos_url": "https://api.github.com/users/metajack/repos",
"events_url": "https://api.github.com/users/metajack/events{/privacy}",
"received_events_url": "https://api.github.com/users/metajack/received_events",
"type": "User",
"site_admin": false
},
"assignees": [
{
"login": "metajack",
"id": 28357,
"avatar_url": "https://avatars3.githubusercontent.com/u/28357?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/metajack",
"html_url": "https://github.com/metajack",
"followers_url": "https://api.github.com/users/metajack/followers",
"following_url": "https://api.github.com/users/metajack/following{/other_user}",
"gists_url": "https://api.github.com/users/metajack/gists{/gist_id}",
"starred_url": "https://api.github.com/users/metajack/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/metajack/subscriptions",
"organizations_url": "https://api.github.com/users/metajack/orgs",
"repos_url": "https://api.github.com/users/metajack/repos",
"events_url": "https://api.github.com/users/metajack/events{/privacy}",
"received_events_url": "https://api.github.com/users/metajack/received_events",
"type": "User",
"site_admin": false
}
],
"requested_reviewers": [
],
"milestone": null,
"commits_url": "https://api.github.com/repos/servo/servo/pulls/19620/commits",
"review_comments_url": "https://api.github.com/repos/servo/servo/pulls/19620/comments",
"review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}",
"comments_url": "https://api.github.com/repos/servo/servo/issues/19620/comments",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/cdb604ae6950960e46855bfb28d6c1f560b4f6e7",
"head": {
"label": "emilio:parse-transition-longhand",
"ref": "parse-transition-longhand",
"sha": "cdb604ae6950960e46855bfb28d6c1f560b4f6e7",
"user": {
"login": "emilio",
"id": 1323194,
"avatar_url": "https://avatars1.githubusercontent.com/u/1323194?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/emilio",
"html_url": "https://github.com/emilio",
"followers_url": "https://api.github.com/users/emilio/followers",
"following_url": "https://api.github.com/users/emilio/following{/other_user}",
"gists_url": "https://api.github.com/users/emilio/gists{/gist_id}",
"starred_url": "https://api.github.com/users/emilio/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/emilio/subscriptions",
"organizations_url": "https://api.github.com/users/emilio/orgs",
"repos_url": "https://api.github.com/users/emilio/repos",
"events_url": "https://api.github.com/users/emilio/events{/privacy}",
"received_events_url": "https://api.github.com/users/emilio/received_events",
"type": "User",
"site_admin": false
},
"repo": {
"id": 34808649,
"name": "servo",
"full_name": "emilio/servo",
"owner": {
"login": "emilio",
"id": 1323194,
"avatar_url": "https://avatars1.githubusercontent.com/u/1323194?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/emilio",
"html_url": "https://github.com/emilio",
"followers_url": "https://api.github.com/users/emilio/followers",
"following_url": "https://api.github.com/users/emilio/following{/other_user}",
"gists_url": "https://api.github.com/users/emilio/gists{/gist_id}",
"starred_url": "https://api.github.com/users/emilio/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/emilio/subscriptions",
"organizations_url": "https://api.github.com/users/emilio/orgs",
"repos_url": "https://api.github.com/users/emilio/repos",
"events_url": "https://api.github.com/users/emilio/events{/privacy}",
"received_events_url": "https://api.github.com/users/emilio/received_events",
"type": "User",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/emilio/servo",
"description": "The Servo Browser Engine",
"fork": true,
"url": "https://api.github.com/repos/emilio/servo",
"forks_url": "https://api.github.com/repos/emilio/servo/forks",
"keys_url": "https://api.github.com/repos/emilio/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/emilio/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/emilio/servo/teams",
"hooks_url": "https://api.github.com/repos/emilio/servo/hooks",
"issue_events_url": "https://api.github.com/repos/emilio/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/emilio/servo/events",
"assignees_url": "https://api.github.com/repos/emilio/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/emilio/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/emilio/servo/tags",
"blobs_url": "https://api.github.com/repos/emilio/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/emilio/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/emilio/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/emilio/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/emilio/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/emilio/servo/languages",
"stargazers_url": "https://api.github.com/repos/emilio/servo/stargazers",
"contributors_url": "https://api.github.com/repos/emilio/servo/contributors",
"subscribers_url": "https://api.github.com/repos/emilio/servo/subscribers",
"subscription_url": "https://api.github.com/repos/emilio/servo/subscription",
"commits_url": "https://api.github.com/repos/emilio/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/emilio/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/emilio/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/emilio/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/emilio/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/emilio/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/emilio/servo/merges",
"archive_url": "https://api.github.com/repos/emilio/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/emilio/servo/downloads",
"issues_url": "https://api.github.com/repos/emilio/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/emilio/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/emilio/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/emilio/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/emilio/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/emilio/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/emilio/servo/deployments",
"created_at": "2015-04-29T17:44:08Z",
"updated_at": "2016-01-12T15:00:17Z",
"pushed_at": "2017-12-21T12:57:32Z",
"git_url": "git://github.com/emilio/servo.git",
"ssh_url": "git@github.com:emilio/servo.git",
"clone_url": "https://github.com/emilio/servo.git",
"svn_url": "https://github.com/emilio/servo",
"homepage": "",
"size": 323504,
"stargazers_count": 0,
"watchers_count": 0,
"language": null,
"has_issues": false,
"has_projects": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 0,
"mirror_url": null,
"archived": false,
"open_issues_count": 0,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 0,
"open_issues": 0,
"watchers": 0,
"default_branch": "master"
}
},
"base": {
"label": "servo:master",
"ref": "master",
"sha": "df0f9ad7ae6f10ffeaf5d40f4a2a25abadabf9cc",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-12-21T09:43:03Z",
"pushed_at": "2017-12-21T14:53:23Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 402344,
"stargazers_count": 10867,
"watchers_count": 10867,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1810,
"mirror_url": null,
"archived": false,
"open_issues_count": 2027,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 1810,
"open_issues": 2027,
"watchers": 10867,
"default_branch": "master"
}
},
"_links": {
"self": {
"href": "https://api.github.com/repos/servo/servo/pulls/19620"
},
"html": {
"href": "https://github.com/servo/servo/pull/19620"
},
"issue": {
"href": "https://api.github.com/repos/servo/servo/issues/19620"
},
"comments": {
"href": "https://api.github.com/repos/servo/servo/issues/19620/comments"
},
"review_comments": {
"href": "https://api.github.com/repos/servo/servo/pulls/19620/comments"
},
"review_comment": {
"href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}"
},
"commits": {
"href": "https://api.github.com/repos/servo/servo/pulls/19620/commits"
},
"statuses": {
"href": "https://api.github.com/repos/servo/servo/statuses/cdb604ae6950960e46855bfb28d6c1f560b4f6e7"
}
},
"author_association": "MEMBER",
"merged": true,
"mergeable": null,
"rebaseable": null,
"mergeable_state": "unknown",
"merged_by": {
"login": "bors-servo",
"id": 4368172,
"avatar_url": "https://avatars1.githubusercontent.com/u/4368172?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/bors-servo",
"html_url": "https://github.com/bors-servo",
"followers_url": "https://api.github.com/users/bors-servo/followers",
"following_url": "https://api.github.com/users/bors-servo/following{/other_user}",
"gists_url": "https://api.github.com/users/bors-servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/bors-servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/bors-servo/subscriptions",
"organizations_url": "https://api.github.com/users/bors-servo/orgs",
"repos_url": "https://api.github.com/users/bors-servo/repos",
"events_url": "https://api.github.com/users/bors-servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/bors-servo/received_events",
"type": "User",
"site_admin": false
},
"comments": 6,
"review_comments": 0,
"maintainer_can_modify": false,
"commits": 1,
"additions": 4,
"deletions": 14,
"changed_files": 1
},
"repository": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-12-21T09:43:03Z",
"pushed_at": "2017-12-21T14:53:23Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 402344,
"stargazers_count": 10867,
"watchers_count": 10867,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1810,
"mirror_url": null,
"archived": false,
"open_issues_count": 2027,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 1810,
"open_issues": 2027,
"watchers": 10867,
"default_branch": "master"
},
"organization": {
"login": "servo",
"id": 2566135,
"url": "https://api.github.com/orgs/servo",
"repos_url": "https://api.github.com/orgs/servo/repos",
"events_url": "https://api.github.com/orgs/servo/events",
"hooks_url": "https://api.github.com/orgs/servo/hooks",
"issues_url": "https://api.github.com/orgs/servo/issues",
"members_url": "https://api.github.com/orgs/servo/members{/member}",
"public_members_url": "https://api.github.com/orgs/servo/public_members{/member}",
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"description": "The Servo web browser engine"
},
"sender": {
"login": "bors-servo",
"id": 4368172,
"avatar_url": "https://avatars1.githubusercontent.com/u/4368172?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/bors-servo",
"html_url": "https://github.com/bors-servo",
"followers_url": "https://api.github.com/users/bors-servo/followers",
"following_url": "https://api.github.com/users/bors-servo/following{/other_user}",
"gists_url": "https://api.github.com/users/bors-servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/bors-servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/bors-servo/subscriptions",
"organizations_url": "https://api.github.com/users/bors-servo/orgs",
"repos_url": "https://api.github.com/users/bors-servo/repos",
"events_url": "https://api.github.com/users/bors-servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/bors-servo/received_events",
"type": "User",
"site_admin": false
}
}

View file

@ -0,0 +1,4 @@
diff --git a/tests/wpt/mozilla/tests/mozilla/mozilla-test.html b/tests/wpt/web-platform-tests/mozilla-test.html
similarity index 100%
rename from tests/wpt/mozilla/tests/mozilla/mozilla-test.html
rename to tests/wpt/web-platform-tests/mozilla-test.html

View file

@ -0,0 +1,4 @@
diff --git a/tests/wpt/web-platform-tests/test.html b/tests/wpt/test.html
similarity index 100%
rename from tests/wpt/web-platform-tests/test.html
rename to tests/wpt/test.html

View file

@ -0,0 +1,10 @@
diff --git a/tests/wpt/something.py b/tests/wpt/something.py
index 10d52a0..92fb89d 100644
--- a/tests/wpt/something.py
+++ b/tests/wpt/something.py
@@ -8,3 +8,4 @@
# except according to those terms.
print('this is a python file')
+print('this is a change')

View file

@ -0,0 +1,440 @@
{
"action": "opened",
"number": 18746,
"pull_request": {
"url": "https://api.github.com/repos/servo/servo/pulls/18746",
"id": 144666315,
"html_url": "https://github.com/servo/servo/pull/18746",
"diff_url": "https://github.com/servo/servo/pull/18746.diff",
"patch_url": "https://github.com/servo/servo/pull/18746.patch",
"issue_url": "https://api.github.com/repos/servo/servo/issues/18746",
"number": 18746,
"state": "open",
"locked": false,
"title": "This is a test",
"user": {
"login": "jdm",
"id": 27658,
"avatar_url": "https://avatars1.githubusercontent.com/u/27658?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jdm",
"html_url": "https://github.com/jdm",
"followers_url": "https://api.github.com/users/jdm/followers",
"following_url": "https://api.github.com/users/jdm/following{/other_user}",
"gists_url": "https://api.github.com/users/jdm/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jdm/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jdm/subscriptions",
"organizations_url": "https://api.github.com/users/jdm/orgs",
"repos_url": "https://api.github.com/users/jdm/repos",
"events_url": "https://api.github.com/users/jdm/events{/privacy}",
"received_events_url": "https://api.github.com/users/jdm/received_events",
"type": "User",
"site_admin": false
},
"body": "[no-wpt-sync]<!-- Please describe your changes on the following line: -->\r\n\r\n\r\n---\r\n<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->\r\n- [ ] `./mach build -d` does not report any errors\r\n- [ ] `./mach test-tidy` does not report any errors\r\n- [ ] These changes fix #__ (github issue number if applicable).\r\n\r\n<!-- Either: -->\r\n- [ ] There are tests for these changes OR\r\n- [ ] These changes do not require tests because _____\r\n\r\n<!-- Also, please make sure that \"Allow edits from maintainers\" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->\r\n\r\n<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->\r\n",
"created_at": "2017-10-04T13:16:26Z",
"updated_at": "2017-10-04T13:16:26Z",
"closed_at": null,
"merged_at": null,
"merge_commit_sha": null,
"assignee": null,
"assignees": [
],
"requested_reviewers": [
],
"milestone": null,
"commits_url": "https://api.github.com/repos/servo/servo/pulls/18746/commits",
"review_comments_url": "https://api.github.com/repos/servo/servo/pulls/18746/comments",
"review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}",
"comments_url": "https://api.github.com/repos/servo/servo/issues/18746/comments",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f",
"head": {
"label": "servo:jdm-patch-1",
"ref": "jdm-patch-1",
"sha": "1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:20Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2073,
"forks": 1731,
"open_issues": 2073,
"watchers": 10131,
"default_branch": "master"
}
},
"base": {
"label": "servo:master",
"ref": "master",
"sha": "3b7a82b8c743bcbbefb6f25defd4cc132c25c348",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:20Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2073,
"forks": 1731,
"open_issues": 2073,
"watchers": 10131,
"default_branch": "master"
}
},
"_links": {
"self": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746"
},
"html": {
"href": "https://github.com/servo/servo/pull/18746"
},
"issue": {
"href": "https://api.github.com/repos/servo/servo/issues/18746"
},
"comments": {
"href": "https://api.github.com/repos/servo/servo/issues/18746/comments"
},
"review_comments": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746/comments"
},
"review_comment": {
"href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}"
},
"commits": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746/commits"
},
"statuses": {
"href": "https://api.github.com/repos/servo/servo/statuses/1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f"
}
},
"author_association": "MEMBER",
"merged": false,
"mergeable": null,
"rebaseable": null,
"mergeable_state": "unknown",
"merged_by": null,
"comments": 0,
"review_comments": 0,
"maintainer_can_modify": false,
"commits": 1,
"additions": 2,
"deletions": 1,
"changed_files": 1
},
"repository": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:20Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2073,
"forks": 1731,
"open_issues": 2073,
"watchers": 10131,
"default_branch": "master"
},
"organization": {
"login": "servo",
"id": 2566135,
"url": "https://api.github.com/orgs/servo",
"repos_url": "https://api.github.com/orgs/servo/repos",
"events_url": "https://api.github.com/orgs/servo/events",
"hooks_url": "https://api.github.com/orgs/servo/hooks",
"issues_url": "https://api.github.com/orgs/servo/issues",
"members_url": "https://api.github.com/orgs/servo/members{/member}",
"public_members_url": "https://api.github.com/orgs/servo/public_members{/member}",
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"description": "The Servo web browser engine"
},
"sender": {
"login": "jdm",
"id": 27658,
"avatar_url": "https://avatars1.githubusercontent.com/u/27658?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jdm",
"html_url": "https://github.com/jdm",
"followers_url": "https://api.github.com/users/jdm/followers",
"following_url": "https://api.github.com/users/jdm/following{/other_user}",
"gists_url": "https://api.github.com/users/jdm/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jdm/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jdm/subscriptions",
"organizations_url": "https://api.github.com/users/jdm/orgs",
"repos_url": "https://api.github.com/users/jdm/repos",
"events_url": "https://api.github.com/users/jdm/events{/privacy}",
"received_events_url": "https://api.github.com/users/jdm/received_events",
"type": "User",
"site_admin": false
}
}

View file

@ -0,0 +1,440 @@
{
"action": "opened",
"number": 18746,
"pull_request": {
"url": "https://api.github.com/repos/servo/servo/pulls/18746",
"id": 144666315,
"html_url": "https://github.com/servo/servo/pull/18746",
"diff_url": "https://github.com/servo/servo/pull/18746.diff",
"patch_url": "https://github.com/servo/servo/pull/18746.patch",
"issue_url": "https://api.github.com/repos/servo/servo/issues/18746",
"number": 18746,
"state": "open",
"locked": false,
"title": "This is a test",
"user": {
"login": "jdm",
"id": 27658,
"avatar_url": "https://avatars1.githubusercontent.com/u/27658?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jdm",
"html_url": "https://github.com/jdm",
"followers_url": "https://api.github.com/users/jdm/followers",
"following_url": "https://api.github.com/users/jdm/following{/other_user}",
"gists_url": "https://api.github.com/users/jdm/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jdm/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jdm/subscriptions",
"organizations_url": "https://api.github.com/users/jdm/orgs",
"repos_url": "https://api.github.com/users/jdm/repos",
"events_url": "https://api.github.com/users/jdm/events{/privacy}",
"received_events_url": "https://api.github.com/users/jdm/received_events",
"type": "User",
"site_admin": false
},
"body": "<!-- Please describe your changes on the following line: -->\r\n\r\n\r\n---\r\n<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->\r\n- [ ] `./mach build -d` does not report any errors\r\n- [ ] `./mach test-tidy` does not report any errors\r\n- [ ] These changes fix #__ (github issue number if applicable).\r\n\r\n<!-- Either: -->\r\n- [ ] There are tests for these changes OR\r\n- [ ] These changes do not require tests because _____\r\n\r\n<!-- Also, please make sure that \"Allow edits from maintainers\" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->\r\n\r\n<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->\r\n",
"created_at": "2017-10-04T13:16:26Z",
"updated_at": "2017-10-04T13:16:26Z",
"closed_at": null,
"merged_at": null,
"merge_commit_sha": null,
"assignee": null,
"assignees": [
],
"requested_reviewers": [
],
"milestone": null,
"commits_url": "https://api.github.com/repos/servo/servo/pulls/18746/commits",
"review_comments_url": "https://api.github.com/repos/servo/servo/pulls/18746/comments",
"review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}",
"comments_url": "https://api.github.com/repos/servo/servo/issues/18746/comments",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f",
"head": {
"label": "servo:jdm-patch-1",
"ref": "jdm-patch-1",
"sha": "1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:20Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2073,
"forks": 1731,
"open_issues": 2073,
"watchers": 10131,
"default_branch": "master"
}
},
"base": {
"label": "servo:master",
"ref": "master",
"sha": "3b7a82b8c743bcbbefb6f25defd4cc132c25c348",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:20Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2073,
"forks": 1731,
"open_issues": 2073,
"watchers": 10131,
"default_branch": "master"
}
},
"_links": {
"self": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746"
},
"html": {
"href": "https://github.com/servo/servo/pull/18746"
},
"issue": {
"href": "https://api.github.com/repos/servo/servo/issues/18746"
},
"comments": {
"href": "https://api.github.com/repos/servo/servo/issues/18746/comments"
},
"review_comments": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746/comments"
},
"review_comment": {
"href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}"
},
"commits": {
"href": "https://api.github.com/repos/servo/servo/pulls/18746/commits"
},
"statuses": {
"href": "https://api.github.com/repos/servo/servo/statuses/1bb1cd385c4d1928b4f60c4c15906f5318ca2f3f"
}
},
"author_association": "MEMBER",
"merged": false,
"mergeable": null,
"rebaseable": null,
"mergeable_state": "unknown",
"merged_by": null,
"comments": 0,
"review_comments": 0,
"maintainer_can_modify": false,
"commits": 1,
"additions": 2,
"deletions": 1,
"changed_files": 1
},
"repository": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-10-04T11:44:53Z",
"pushed_at": "2017-10-04T13:16:20Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 370069,
"stargazers_count": 10131,
"watchers_count": 10131,
"language": null,
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1731,
"mirror_url": null,
"open_issues_count": 2073,
"forks": 1731,
"open_issues": 2073,
"watchers": 10131,
"default_branch": "master"
},
"organization": {
"login": "servo",
"id": 2566135,
"url": "https://api.github.com/orgs/servo",
"repos_url": "https://api.github.com/orgs/servo/repos",
"events_url": "https://api.github.com/orgs/servo/events",
"hooks_url": "https://api.github.com/orgs/servo/hooks",
"issues_url": "https://api.github.com/orgs/servo/issues",
"members_url": "https://api.github.com/orgs/servo/members{/member}",
"public_members_url": "https://api.github.com/orgs/servo/public_members{/member}",
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"description": "The Servo web browser engine"
},
"sender": {
"login": "jdm",
"id": 27658,
"avatar_url": "https://avatars1.githubusercontent.com/u/27658?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/jdm",
"html_url": "https://github.com/jdm",
"followers_url": "https://api.github.com/users/jdm/followers",
"following_url": "https://api.github.com/users/jdm/following{/other_user}",
"gists_url": "https://api.github.com/users/jdm/gists{/gist_id}",
"starred_url": "https://api.github.com/users/jdm/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/jdm/subscriptions",
"organizations_url": "https://api.github.com/users/jdm/orgs",
"repos_url": "https://api.github.com/users/jdm/repos",
"events_url": "https://api.github.com/users/jdm/events{/privacy}",
"received_events_url": "https://api.github.com/users/jdm/received_events",
"type": "User",
"site_admin": false
}
}

View file

@ -0,0 +1 @@
This is a repository designed to superficially resemble the Servo repository.

View file

@ -0,0 +1,3 @@
<html>
<h1>this is a mozilla-specific test</h1>
</html>

View file

@ -0,0 +1,10 @@
# Copyright 2023 The Servo Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
print('this is a python file')

View file

@ -0,0 +1,3 @@
<html>
<h1>css test!</h1>
</html>

View file

@ -0,0 +1,3 @@
<html>
<h1>css test!</h1>
</html>

View file

@ -0,0 +1,16 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Fetch: handling Location header during redirection</title>
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<meta name="help" href="https://fetch.spec.whatwg.org/#http-network-or-cache-fetch">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script src="../resources/utils.js"></script>
<script src="redirect-location.js"></script>
</body>
</html>

View file

@ -0,0 +1,3 @@
<html>
<h1>this is a test file</h1>
</html>

View file

@ -0,0 +1,499 @@
{
"action": "synchronize",
"number": 19612,
"pull_request": {
"url": "https://api.github.com/repos/servo/servo/pulls/19612",
"id": 159474132,
"html_url": "https://github.com/servo/servo/pull/19612",
"diff_url": "https://github.com/servo/servo/pull/19612.diff",
"patch_url": "https://github.com/servo/servo/pull/19612.patch",
"issue_url": "https://api.github.com/repos/servo/servo/issues/19612",
"number": 19612,
"state": "open",
"locked": false,
"title": "deny warnings",
"user": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
},
"body": "<!-- Please describe your changes on the following line: -->\r\ndeny warnings\r\nrelated to #19573\r\n\r\n---\r\n<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->\r\n- [ ] `./mach build -d` does not report any errors\r\n- [ ] `./mach test-tidy` does not report any errors\r\n- [ ] These changes fix #19572 (github issue number if applicable).\r\n\r\n<!-- Either: -->\r\n- [ ] There are tests for these changes OR\r\n- [ ] These changes do not require tests because _____\r\n\r\n<!-- Also, please make sure that \"Allow edits from maintainers\" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->\r\n\r\n<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->\n\n<!-- Reviewable:start -->\n---\nThis change is[<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/servo/servo/19612)\n<!-- Reviewable:end -->\n",
"created_at": "2017-12-20T17:24:41Z",
"updated_at": "2017-12-21T13:34:10Z",
"closed_at": null,
"merged_at": null,
"merge_commit_sha": "b584f06079f4d4dc10fbc0e9bbef848b5aeb0d15",
"assignee": {
"login": "SimonSapin",
"id": 291359,
"avatar_url": "https://avatars0.githubusercontent.com/u/291359?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/SimonSapin",
"html_url": "https://github.com/SimonSapin",
"followers_url": "https://api.github.com/users/SimonSapin/followers",
"following_url": "https://api.github.com/users/SimonSapin/following{/other_user}",
"gists_url": "https://api.github.com/users/SimonSapin/gists{/gist_id}",
"starred_url": "https://api.github.com/users/SimonSapin/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/SimonSapin/subscriptions",
"organizations_url": "https://api.github.com/users/SimonSapin/orgs",
"repos_url": "https://api.github.com/users/SimonSapin/repos",
"events_url": "https://api.github.com/users/SimonSapin/events{/privacy}",
"received_events_url": "https://api.github.com/users/SimonSapin/received_events",
"type": "User",
"site_admin": false
},
"assignees": [
{
"login": "SimonSapin",
"id": 291359,
"avatar_url": "https://avatars0.githubusercontent.com/u/291359?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/SimonSapin",
"html_url": "https://github.com/SimonSapin",
"followers_url": "https://api.github.com/users/SimonSapin/followers",
"following_url": "https://api.github.com/users/SimonSapin/following{/other_user}",
"gists_url": "https://api.github.com/users/SimonSapin/gists{/gist_id}",
"starred_url": "https://api.github.com/users/SimonSapin/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/SimonSapin/subscriptions",
"organizations_url": "https://api.github.com/users/SimonSapin/orgs",
"repos_url": "https://api.github.com/users/SimonSapin/repos",
"events_url": "https://api.github.com/users/SimonSapin/events{/privacy}",
"received_events_url": "https://api.github.com/users/SimonSapin/received_events",
"type": "User",
"site_admin": false
}
],
"requested_reviewers": [
],
"milestone": null,
"commits_url": "https://api.github.com/repos/servo/servo/pulls/19612/commits",
"review_comments_url": "https://api.github.com/repos/servo/servo/pulls/19612/comments",
"review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}",
"comments_url": "https://api.github.com/repos/servo/servo/issues/19612/comments",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd",
"head": {
"label": "tigercosmos:o1",
"ref": "o1",
"sha": "ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd",
"user": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
},
"repo": {
"id": 100714943,
"name": "servo",
"full_name": "tigercosmos/servo",
"owner": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/tigercosmos/servo",
"description": "The Servo Browser Engine",
"fork": true,
"url": "https://api.github.com/repos/tigercosmos/servo",
"forks_url": "https://api.github.com/repos/tigercosmos/servo/forks",
"keys_url": "https://api.github.com/repos/tigercosmos/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/tigercosmos/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/tigercosmos/servo/teams",
"hooks_url": "https://api.github.com/repos/tigercosmos/servo/hooks",
"issue_events_url": "https://api.github.com/repos/tigercosmos/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/tigercosmos/servo/events",
"assignees_url": "https://api.github.com/repos/tigercosmos/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/tigercosmos/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/tigercosmos/servo/tags",
"blobs_url": "https://api.github.com/repos/tigercosmos/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/tigercosmos/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/tigercosmos/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/tigercosmos/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/tigercosmos/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/tigercosmos/servo/languages",
"stargazers_url": "https://api.github.com/repos/tigercosmos/servo/stargazers",
"contributors_url": "https://api.github.com/repos/tigercosmos/servo/contributors",
"subscribers_url": "https://api.github.com/repos/tigercosmos/servo/subscribers",
"subscription_url": "https://api.github.com/repos/tigercosmos/servo/subscription",
"commits_url": "https://api.github.com/repos/tigercosmos/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/tigercosmos/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/tigercosmos/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/tigercosmos/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/tigercosmos/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/tigercosmos/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/tigercosmos/servo/merges",
"archive_url": "https://api.github.com/repos/tigercosmos/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/tigercosmos/servo/downloads",
"issues_url": "https://api.github.com/repos/tigercosmos/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/tigercosmos/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/tigercosmos/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/tigercosmos/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/tigercosmos/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/tigercosmos/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/tigercosmos/servo/deployments",
"created_at": "2017-08-18T13:31:45Z",
"updated_at": "2017-11-05T13:18:26Z",
"pushed_at": "2017-12-21T13:34:10Z",
"git_url": "git://github.com/tigercosmos/servo.git",
"ssh_url": "git@github.com:tigercosmos/servo.git",
"clone_url": "https://github.com/tigercosmos/servo.git",
"svn_url": "https://github.com/tigercosmos/servo",
"homepage": "https://servo.org/",
"size": 321860,
"stargazers_count": 0,
"watchers_count": 0,
"language": "Rust",
"has_issues": false,
"has_projects": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 0,
"mirror_url": null,
"archived": false,
"open_issues_count": 0,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 0,
"open_issues": 0,
"watchers": 0,
"default_branch": "master"
}
},
"base": {
"label": "servo:master",
"ref": "master",
"sha": "df0f9ad7ae6f10ffeaf5d40f4a2a25abadabf9cc",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-12-21T09:43:03Z",
"pushed_at": "2017-12-21T13:12:14Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 402429,
"stargazers_count": 10867,
"watchers_count": 10867,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1810,
"mirror_url": null,
"archived": false,
"open_issues_count": 2027,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 1810,
"open_issues": 2027,
"watchers": 10867,
"default_branch": "master"
}
},
"_links": {
"self": {
"href": "https://api.github.com/repos/servo/servo/pulls/19612"
},
"html": {
"href": "https://github.com/servo/servo/pull/19612"
},
"issue": {
"href": "https://api.github.com/repos/servo/servo/issues/19612"
},
"comments": {
"href": "https://api.github.com/repos/servo/servo/issues/19612/comments"
},
"review_comments": {
"href": "https://api.github.com/repos/servo/servo/pulls/19612/comments"
},
"review_comment": {
"href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}"
},
"commits": {
"href": "https://api.github.com/repos/servo/servo/pulls/19612/commits"
},
"statuses": {
"href": "https://api.github.com/repos/servo/servo/statuses/ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd"
}
},
"author_association": "CONTRIBUTOR",
"merged": false,
"mergeable": null,
"rebaseable": null,
"mergeable_state": "unknown",
"merged_by": null,
"comments": 61,
"review_comments": 0,
"maintainer_can_modify": true,
"commits": 3,
"additions": 19,
"deletions": 20,
"changed_files": 8
},
"before": "537b653d9044d2f265d5790ba3761cea539a57f6",
"after": "ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd",
"repository": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-12-21T09:43:03Z",
"pushed_at": "2017-12-21T13:12:14Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 402429,
"stargazers_count": 10867,
"watchers_count": 10867,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1810,
"mirror_url": null,
"archived": false,
"open_issues_count": 2027,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 1810,
"open_issues": 2027,
"watchers": 10867,
"default_branch": "master"
},
"organization": {
"login": "servo",
"id": 2566135,
"url": "https://api.github.com/orgs/servo",
"repos_url": "https://api.github.com/orgs/servo/repos",
"events_url": "https://api.github.com/orgs/servo/events",
"hooks_url": "https://api.github.com/orgs/servo/hooks",
"issues_url": "https://api.github.com/orgs/servo/issues",
"members_url": "https://api.github.com/orgs/servo/members{/member}",
"public_members_url": "https://api.github.com/orgs/servo/public_members{/member}",
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"description": "The Servo web browser engine"
},
"sender": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
}
}

View file

@ -0,0 +1,499 @@
{
"action": "synchronize",
"number": 19612,
"pull_request": {
"url": "https://api.github.com/repos/servo/servo/pulls/19612",
"id": 159474132,
"html_url": "https://github.com/servo/servo/pull/19612",
"diff_url": "https://github.com/servo/servo/pull/19612.diff",
"patch_url": "https://github.com/servo/servo/pull/19612.patch",
"issue_url": "https://api.github.com/repos/servo/servo/issues/19612",
"number": 19612,
"state": "open",
"locked": false,
"title": "deny warnings",
"user": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
},
"body": "<!-- Please describe your changes on the following line: -->\r\ndeny warnings\r\nrelated to #19573\r\n\r\n---\r\n<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->\r\n- [ ] `./mach build -d` does not report any errors\r\n- [ ] `./mach test-tidy` does not report any errors\r\n- [ ] These changes fix #19572 (github issue number if applicable).\r\n\r\n<!-- Either: -->\r\n- [ ] There are tests for these changes OR\r\n- [ ] These changes do not require tests because _____\r\n\r\n<!-- Also, please make sure that \"Allow edits from maintainers\" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->\r\n\r\n<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->\n\n<!-- Reviewable:start -->\n---\nThis change is[<img src=\"https://reviewable.io/review_button.svg\" height=\"34\" align=\"absmiddle\" alt=\"Reviewable\"/>](https://reviewable.io/reviews/servo/servo/19612)\n<!-- Reviewable:end -->\n",
"created_at": "2017-12-20T17:24:41Z",
"updated_at": "2017-12-21T13:34:10Z",
"closed_at": null,
"merged_at": null,
"merge_commit_sha": "b584f06079f4d4dc10fbc0e9bbef848b5aeb0d15",
"assignee": {
"login": "SimonSapin",
"id": 291359,
"avatar_url": "https://avatars0.githubusercontent.com/u/291359?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/SimonSapin",
"html_url": "https://github.com/SimonSapin",
"followers_url": "https://api.github.com/users/SimonSapin/followers",
"following_url": "https://api.github.com/users/SimonSapin/following{/other_user}",
"gists_url": "https://api.github.com/users/SimonSapin/gists{/gist_id}",
"starred_url": "https://api.github.com/users/SimonSapin/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/SimonSapin/subscriptions",
"organizations_url": "https://api.github.com/users/SimonSapin/orgs",
"repos_url": "https://api.github.com/users/SimonSapin/repos",
"events_url": "https://api.github.com/users/SimonSapin/events{/privacy}",
"received_events_url": "https://api.github.com/users/SimonSapin/received_events",
"type": "User",
"site_admin": false
},
"assignees": [
{
"login": "SimonSapin",
"id": 291359,
"avatar_url": "https://avatars0.githubusercontent.com/u/291359?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/SimonSapin",
"html_url": "https://github.com/SimonSapin",
"followers_url": "https://api.github.com/users/SimonSapin/followers",
"following_url": "https://api.github.com/users/SimonSapin/following{/other_user}",
"gists_url": "https://api.github.com/users/SimonSapin/gists{/gist_id}",
"starred_url": "https://api.github.com/users/SimonSapin/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/SimonSapin/subscriptions",
"organizations_url": "https://api.github.com/users/SimonSapin/orgs",
"repos_url": "https://api.github.com/users/SimonSapin/repos",
"events_url": "https://api.github.com/users/SimonSapin/events{/privacy}",
"received_events_url": "https://api.github.com/users/SimonSapin/received_events",
"type": "User",
"site_admin": false
}
],
"requested_reviewers": [
],
"milestone": null,
"commits_url": "https://api.github.com/repos/servo/servo/pulls/19612/commits",
"review_comments_url": "https://api.github.com/repos/servo/servo/pulls/19612/comments",
"review_comment_url": "https://api.github.com/repos/servo/servo/pulls/comments{/number}",
"comments_url": "https://api.github.com/repos/servo/servo/issues/19612/comments",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd",
"head": {
"label": "tigercosmos:o1",
"ref": "o1",
"sha": "ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd",
"user": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
},
"repo": {
"id": 100714943,
"name": "servo",
"full_name": "tigercosmos/servo",
"owner": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/tigercosmos/servo",
"description": "The Servo Browser Engine",
"fork": true,
"url": "https://api.github.com/repos/tigercosmos/servo",
"forks_url": "https://api.github.com/repos/tigercosmos/servo/forks",
"keys_url": "https://api.github.com/repos/tigercosmos/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/tigercosmos/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/tigercosmos/servo/teams",
"hooks_url": "https://api.github.com/repos/tigercosmos/servo/hooks",
"issue_events_url": "https://api.github.com/repos/tigercosmos/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/tigercosmos/servo/events",
"assignees_url": "https://api.github.com/repos/tigercosmos/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/tigercosmos/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/tigercosmos/servo/tags",
"blobs_url": "https://api.github.com/repos/tigercosmos/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/tigercosmos/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/tigercosmos/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/tigercosmos/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/tigercosmos/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/tigercosmos/servo/languages",
"stargazers_url": "https://api.github.com/repos/tigercosmos/servo/stargazers",
"contributors_url": "https://api.github.com/repos/tigercosmos/servo/contributors",
"subscribers_url": "https://api.github.com/repos/tigercosmos/servo/subscribers",
"subscription_url": "https://api.github.com/repos/tigercosmos/servo/subscription",
"commits_url": "https://api.github.com/repos/tigercosmos/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/tigercosmos/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/tigercosmos/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/tigercosmos/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/tigercosmos/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/tigercosmos/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/tigercosmos/servo/merges",
"archive_url": "https://api.github.com/repos/tigercosmos/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/tigercosmos/servo/downloads",
"issues_url": "https://api.github.com/repos/tigercosmos/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/tigercosmos/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/tigercosmos/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/tigercosmos/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/tigercosmos/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/tigercosmos/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/tigercosmos/servo/deployments",
"created_at": "2017-08-18T13:31:45Z",
"updated_at": "2017-11-05T13:18:26Z",
"pushed_at": "2017-12-21T13:34:10Z",
"git_url": "git://github.com/tigercosmos/servo.git",
"ssh_url": "git@github.com:tigercosmos/servo.git",
"clone_url": "https://github.com/tigercosmos/servo.git",
"svn_url": "https://github.com/tigercosmos/servo",
"homepage": "https://servo.org/",
"size": 321860,
"stargazers_count": 0,
"watchers_count": 0,
"language": "Rust",
"has_issues": false,
"has_projects": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 0,
"mirror_url": null,
"archived": false,
"open_issues_count": 0,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 0,
"open_issues": 0,
"watchers": 0,
"default_branch": "master"
}
},
"base": {
"label": "servo:master",
"ref": "master",
"sha": "df0f9ad7ae6f10ffeaf5d40f4a2a25abadabf9cc",
"user": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"repo": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-12-21T09:43:03Z",
"pushed_at": "2017-12-21T13:12:14Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 402429,
"stargazers_count": 10867,
"watchers_count": 10867,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1810,
"mirror_url": null,
"archived": false,
"open_issues_count": 2027,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 1810,
"open_issues": 2027,
"watchers": 10867,
"default_branch": "master"
}
},
"_links": {
"self": {
"href": "https://api.github.com/repos/servo/servo/pulls/19612"
},
"html": {
"href": "https://github.com/servo/servo/pull/19612"
},
"issue": {
"href": "https://api.github.com/repos/servo/servo/issues/19612"
},
"comments": {
"href": "https://api.github.com/repos/servo/servo/issues/19612/comments"
},
"review_comments": {
"href": "https://api.github.com/repos/servo/servo/pulls/19612/comments"
},
"review_comment": {
"href": "https://api.github.com/repos/servo/servo/pulls/comments{/number}"
},
"commits": {
"href": "https://api.github.com/repos/servo/servo/pulls/19612/commits"
},
"statuses": {
"href": "https://api.github.com/repos/servo/servo/statuses/ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd"
}
},
"author_association": "CONTRIBUTOR",
"merged": false,
"mergeable": null,
"rebaseable": null,
"mergeable_state": "unknown",
"merged_by": null,
"comments": 61,
"review_comments": 0,
"maintainer_can_modify": true,
"commits": 1,
"additions": 19,
"deletions": 20,
"changed_files": 8
},
"before": "537b653d9044d2f265d5790ba3761cea539a57f6",
"after": "ab19bd1b6438c8e3aa0e5ab36dc3a6d5b14c12dd",
"repository": {
"id": 3390243,
"name": "servo",
"full_name": "servo/servo",
"owner": {
"login": "servo",
"id": 2566135,
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/servo",
"html_url": "https://github.com/servo",
"followers_url": "https://api.github.com/users/servo/followers",
"following_url": "https://api.github.com/users/servo/following{/other_user}",
"gists_url": "https://api.github.com/users/servo/gists{/gist_id}",
"starred_url": "https://api.github.com/users/servo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/servo/subscriptions",
"organizations_url": "https://api.github.com/users/servo/orgs",
"repos_url": "https://api.github.com/users/servo/repos",
"events_url": "https://api.github.com/users/servo/events{/privacy}",
"received_events_url": "https://api.github.com/users/servo/received_events",
"type": "Organization",
"site_admin": false
},
"private": false,
"html_url": "https://github.com/servo/servo",
"description": "The Servo Browser Engine",
"fork": false,
"url": "https://api.github.com/repos/servo/servo",
"forks_url": "https://api.github.com/repos/servo/servo/forks",
"keys_url": "https://api.github.com/repos/servo/servo/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/servo/servo/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/servo/servo/teams",
"hooks_url": "https://api.github.com/repos/servo/servo/hooks",
"issue_events_url": "https://api.github.com/repos/servo/servo/issues/events{/number}",
"events_url": "https://api.github.com/repos/servo/servo/events",
"assignees_url": "https://api.github.com/repos/servo/servo/assignees{/user}",
"branches_url": "https://api.github.com/repos/servo/servo/branches{/branch}",
"tags_url": "https://api.github.com/repos/servo/servo/tags",
"blobs_url": "https://api.github.com/repos/servo/servo/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/servo/servo/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/servo/servo/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/servo/servo/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/servo/servo/statuses/{sha}",
"languages_url": "https://api.github.com/repos/servo/servo/languages",
"stargazers_url": "https://api.github.com/repos/servo/servo/stargazers",
"contributors_url": "https://api.github.com/repos/servo/servo/contributors",
"subscribers_url": "https://api.github.com/repos/servo/servo/subscribers",
"subscription_url": "https://api.github.com/repos/servo/servo/subscription",
"commits_url": "https://api.github.com/repos/servo/servo/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/servo/servo/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/servo/servo/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/servo/servo/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/servo/servo/contents/{+path}",
"compare_url": "https://api.github.com/repos/servo/servo/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/servo/servo/merges",
"archive_url": "https://api.github.com/repos/servo/servo/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/servo/servo/downloads",
"issues_url": "https://api.github.com/repos/servo/servo/issues{/number}",
"pulls_url": "https://api.github.com/repos/servo/servo/pulls{/number}",
"milestones_url": "https://api.github.com/repos/servo/servo/milestones{/number}",
"notifications_url": "https://api.github.com/repos/servo/servo/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/servo/servo/labels{/name}",
"releases_url": "https://api.github.com/repos/servo/servo/releases{/id}",
"deployments_url": "https://api.github.com/repos/servo/servo/deployments",
"created_at": "2012-02-08T19:07:25Z",
"updated_at": "2017-12-21T09:43:03Z",
"pushed_at": "2017-12-21T13:12:14Z",
"git_url": "git://github.com/servo/servo.git",
"ssh_url": "git@github.com:servo/servo.git",
"clone_url": "https://github.com/servo/servo.git",
"svn_url": "https://github.com/servo/servo",
"homepage": "https://servo.org/",
"size": 402429,
"stargazers_count": 10867,
"watchers_count": 10867,
"language": "Rust",
"has_issues": true,
"has_projects": false,
"has_downloads": true,
"has_wiki": true,
"has_pages": false,
"forks_count": 1810,
"mirror_url": null,
"archived": false,
"open_issues_count": 2027,
"license": {
"key": "mpl-2.0",
"name": "Mozilla Public License 2.0",
"spdx_id": "MPL-2.0",
"url": "https://api.github.com/licenses/mpl-2.0"
},
"forks": 1810,
"open_issues": 2027,
"watchers": 10867,
"default_branch": "master"
},
"organization": {
"login": "servo",
"id": 2566135,
"url": "https://api.github.com/orgs/servo",
"repos_url": "https://api.github.com/orgs/servo/repos",
"events_url": "https://api.github.com/orgs/servo/events",
"hooks_url": "https://api.github.com/orgs/servo/hooks",
"issues_url": "https://api.github.com/orgs/servo/issues",
"members_url": "https://api.github.com/orgs/servo/members{/member}",
"public_members_url": "https://api.github.com/orgs/servo/public_members{/member}",
"avatar_url": "https://avatars1.githubusercontent.com/u/2566135?v=4",
"description": "The Servo web browser engine"
},
"sender": {
"login": "tigercosmos",
"id": 18013815,
"avatar_url": "https://avatars0.githubusercontent.com/u/18013815?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/tigercosmos",
"html_url": "https://github.com/tigercosmos",
"followers_url": "https://api.github.com/users/tigercosmos/followers",
"following_url": "https://api.github.com/users/tigercosmos/following{/other_user}",
"gists_url": "https://api.github.com/users/tigercosmos/gists{/gist_id}",
"starred_url": "https://api.github.com/users/tigercosmos/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/tigercosmos/subscriptions",
"organizations_url": "https://api.github.com/users/tigercosmos/orgs",
"repos_url": "https://api.github.com/users/tigercosmos/repos",
"events_url": "https://api.github.com/users/tigercosmos/events{/privacy}",
"received_events_url": "https://api.github.com/users/tigercosmos/received_events",
"type": "User",
"site_admin": false
}
}

View file

@ -0,0 +1,3 @@
<html>
<h1>css test!</h1>
</html>

View file

@ -0,0 +1,16 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Fetch: handling Location header during redirection</title>
<meta name="author" title="Canon Research France" href="https://www.crf.canon.fr">
<meta name="help" href="https://fetch.spec.whatwg.org/#http-network-or-cache-fetch">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script src="../resources/utils.js"></script>
<script src="redirect-location.js"></script>
</body>
</html>

View file

@ -0,0 +1,3 @@
<html>
<h1>this is a test file</h1>
</html>

View file

@ -0,0 +1,9 @@
diff --git a/tests/wpt/web-platform-tests/css/css-test.html b/tests/wpt/web-platform-tests/css/css-test.html
index cffb6eb..6100a49 100644
--- a/tests/wpt/web-platform-tests/css/css-test.html
+++ b/tests/wpt/web-platform-tests/css/css-test.html
@@ -1,3 +1,3 @@
<html>
-<h1>css test!</h1>
+<h1>css test!</h1>hi
</html>

29
python/wpt/update.py Normal file
View file

@ -0,0 +1,29 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# pylint: disable=missing-docstring
import os
from . import WPT_PATH, update_args_for_layout_2020
from . import importer
def set_if_none(args: dict, key: str, value):
if key not in args or args[key] is None:
args[key] = value
def update_tests(**kwargs):
set_if_none(kwargs, "product", "servo")
set_if_none(kwargs, "config", os.path.join(WPT_PATH, "config.ini"))
kwargs["store_state"] = False
importer.check_args(kwargs)
update_args_for_layout_2020(kwargs)
return 1 if not importer.run_update(**kwargs) else 0
def create_parser(**kwargs):
return importer.create_parser()