Skip to content

Commit

Permalink
github: make MockRequestNotFound easier to debug
Browse files Browse the repository at this point in the history
Summary:
Sometimes the mock key has changed and MockRequestNotFound crashed with a very
long message and a stacktrace. Make it easier to debug by diffing against all
available keys and showing the most similar key.

After:

  % lrt test-ext-github-pr-submit-overlap.t
  test-ext-github-pr-submit-overlap.t ---------------------------------------------------------
    24 $ sl pr submit --config extensions.pr_submit=$TESTDIR/github/mock_create_prs.py
       pushing 2 to https://github.com/facebook/test_github_repo.git
       created new pull request: https://github.com/facebook/test_github_repo/pull/42
       created new pull request: https://github.com/facebook/test_github_repo/pull/43
      -updated body for https://github.com/facebook/test_github_repo/pull/43
      -updated body for https://github.com/facebook/test_github_repo/pull/42
      +abort: Mock key has changed:
      +| @@ -3,8 +3,7 @@
      +|  ---
      +|  Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/test_github_repo/pull/43).
      +|  * __->__ #43
      +| -* #42
      +| -,pullRequestId=PR_id_43,query=
      +| +* #42,pullRequestId=PR_id_43,query=
      +|  mutation ($pullRequestId: ID!, $title: String!, $body: String!, $base: String!) {
      +|    updatePullRequest(
      +|      input: {pullRequestId: $pullRequestId, title: $title, body: $body, baseRefName: $base}
      +
      +[255]

Before:

  % lrt test-ext-github-pr-submit-overlap.t
  test-ext-github-pr-submit-overlap.t ---------------------------------------------------------
    24 $ sl pr submit --config extensions.pr_submit=$TESTDIR/github/mock_create_prs.py
       pushing 2 to https://github.com/facebook/test_github_repo.git
       created new pull request: https://github.com/facebook/test_github_repo/pull/42
       created new pull request: https://github.com/facebook/test_github_repo/pull/43
      -updated body for https://github.com/facebook/test_github_repo/pull/43
      -updated body for https://github.com/facebook/test_github_repo/pull/42
      +** Sapling SCM (version 4.4.2_20230221_142505_54c9ccb1b298) has crashed:
      +Traceback (most recent call last):
      +  File "eden/scm/edenscm/ext/github/mock_utils.py", line 100, in make_request
      +    return self.requests[key].get_response()
      +KeyError: 'github.com|graphql|None|base=main,body=two\n\n---\nStack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/test_github_repo/pull/43).\n* __->__ #43\n* #42,pullRequestId=PR_id_43,query=\nmutation ($pullRequestId: ID!, $title: String!, $body: String!, $base: String!) {\n  updatePullRequest(\n    input: {pullRequestId: $pullRequestId, title: $title, body: $body, baseRefName: $base}\n  ) {\n    pullRequest {\n      id\n    }\n  }\n}\n,title=two'
      +
      +During handling of the above exception, another exception occurred:
      +
      +Traceback (most recent call last):
      +  File "eden/scm/edenscm/__init__.py", line 106, in run
      +    dispatch.run(args, fin, fout, ferr, config)
      +  File "eden/scm/edenscm/dispatch.py", line 161, in run
      +    status = (dispatch(req) or 0) & 255
      +  File "eden/scm/edenscm/dispatch.py", line 499, in dispatch
      +    ret = _runcatch(req)
      +  File "eden/scm/edenscm/dispatch.py", line 687, in _runcatch
      +    return _callcatch(ui, req, _runcatchfunc)
      +  File "eden/scm/edenscm/dispatch.py", line 696, in _callcatch
      +    return scmutil.callcatch(ui, req, func)
      +  File "eden/scm/edenscm/scmutil.py", line 143, in callcatch
      +    return func()
      +  File "eden/scm/edenscm/dispatch.py", line 670, in _runcatchfunc
      +    return _dispatch(req)
      +  File "eden/scm/edenscm/dispatch.py", line 1197, in _dispatch
      +    ret = runcommand(
      +  File "eden/scm/edenscm/dispatch.py", line 886, in runcommand
      +    ret = _runcommand(ui, options, cmd, d)
      +  File "eden/scm/edenscm/dispatch.py", line 1238, in _runcommand
      +    return cmdfunc()
      +  File "eden/scm/edenscm/dispatch.py", line 1196, in <lambda>
      +    d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
      +  File "eden/scm/edenscm/util.py", line 1298, in check
      +    return func(*args, **kwargs)
      +  File "eden/scm/edenscm/ext/github/__init__.py", line 113, in submit_cmd
      +    return submit.submit(ui, repo, *args, **opts)
      +  File "eden/scm/edenscm/ext/github/submit.py", line 33, in submit
      +    return asyncio.run(
      +  File "/usr/lib64/python3.8/asyncio/runners.py", line 44, in run
      +    return loop.run_until_complete(main)
      +  File "/usr/lib64/python3.8/asyncio/base_events.py", line 616, in run_until_complete
      +    return future.result()
      +  File "eden/scm/edenscm/ext/github/submit.py", line 243, in update_commits_in_stack
      +    await asyncio.gather(*rewrite_and_archive_requests)
      +  File "eden/scm/edenscm/ext/github/submit.py", line 281, in rewrite_pull_request_body
      +    result = await gh_submit.update_pull_request(
      +  File "eden/scm/edenscm/ext/github/gh_submit.py", line 349, in update_pull_request
      +    result = await gh_cli.make_request(params, hostname=hostname)
      +  File "eden/scm/ghstack/github_gh_cli.py", line 29, in make_request
      +    return await _make_request(params, hostname, endpoint, method)
      +  File "eden/scm/edenscm/ext/github/mock_utils.py", line 102, in make_request
      +    raise MockRequestNotFound(key, self.requests)
      +edenscm.ext.github.mock_utils.MockRequestNotFound: key not found: github.com|graphql|None|base=main,body=two
      +
      +---
      +Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/test_github_repo/pull/43).
      +* __->__ #43
      +* #42,pullRequestId=PR_id_43,query=
      +mutation ($pullRequestId: ID!, $title: String!, $body: String!, $base: String!) {
      +  updatePullRequest(
      +    input: {pullRequestId: $pullRequestId, title: $title, body: $body, baseRefName: $base}
      +  ) {
      +    pullRequest {
      +      id
      +    }
      +  }
      +}
      +,title=two
      +Available keys:
      +github.com|graphql|None|name=test_github_repo,owner=facebook,query=
      +query ($owner: String!, $name: String!) {
      +  repository(name: $name, owner: $owner) {
      +    id
      +    owner {
      +      id
      +      login
      +    }
      +    name
      +    isFork
      +    defaultBranchRef {
      +      name
      +    }
      +    parent {
      +      id
      +      owner {
      +        id
      +        login
      +      }
      +      name
      +      isFork
      +      defaultBranchRef {
      +        name
      +      }
      +    }
      +  }
      +}
      +
      +
      +github.com|graphql|None|name=test_github_repo,owner=facebook,query=
      +query ($owner: String!, $name: String!) {
      +  repository(owner: $owner, name: $name) {
      +    issues(orderBy: {field: CREATED_AT, direction: ASC}, last: 1) {
      +      nodes {
      +        number
      +      }
      +    }
      +    pullRequests(orderBy: {field: CREATED_AT, direction: ASC}, last: 1) {
      +      nodes {
      +        number
      +      }
      +    }
      +  }
      +}
      +
      +
      +github.com|repos/facebook/test_github_repo/pulls|None|base=main,body=one
      +,draft=False,head=pr42,title=one
      +
      +github.com|graphql|None|name=test_github_repo,number=42,owner=facebook,query=
      +query ($owner: String!, $name: String!, $number: Int!) {
      +  repository(name: $name, owner: $owner) {
      +    pullRequest(number: $number) {
      +      id
      +      url
      +      state
      +      baseRefOid
      +      baseRefName
      +      headRefOid
      +      headRefName
      +      body
      +    }
      +  }
      +}
      +
      +
      +github.com|graphql|None|base=main,body=one
      +
      +---
      +Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/test_github_repo/pull/42).
      +* #43
      +* __->__ #42
      +,pullRequestId=PR_id_42,query=
      +mutation ($pullRequestId: ID!, $title: String!, $body: String!, $base: String!) {
      +  updatePullRequest(
      +    input: {pullRequestId: $pullRequestId, title: $title, body: $body, baseRefName: $base}
      +  ) {
      +    pullRequest {
      +      id
      +    }
      +  }
      +}
      +,title=one
      +
      +github.com|repos/facebook/test_github_repo/pulls|None|base=main,body=two
      +,draft=False,head=pr43,title=two
      +
      +github.com|graphql|None|name=test_github_repo,number=43,owner=facebook,query=
      +query ($owner: String!, $name: String!, $number: Int!) {
      +  repository(name: $name, owner: $owner) {
      +    pullRequest(number: $number) {
      +      id
      +      url
      +      state
      +      baseRefOid
      +      baseRefName
      +      headRefOid
      +      headRefName
      +      body
      +    }
      +  }
      +}
      +
      +
      +github.com|graphql|None|base=main,body=two
      +
      +---
      +Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/test_github_repo/pull/43).
      +* __->__ #43
      +* #42
      +,pullRequestId=PR_id_43,query=
      +mutation ($pullRequestId: ID!, $title: String!, $body: String!, $base: String!) {
      +  updatePullRequest(
      +    input: {pullRequestId: $pullRequestId, title: $title, body: $body, baseRefName: $base}
      +  ) {
      +    pullRequest {
      +      id
      +    }
      +  }
      +}
      +,title=two
      +
      +github.com|graphql|None|query=
      +query {
      +  viewer {
      +    login
      +  }
      +}
      +
      +
      +github.com|graphql|None|base=sapling-pr-archive-facebook_username,head=1a67244b0a776bfcc3be6bf811e98c993d78ce47,query=
      +mutation ($repositoryId: ID!, $base: String!, $head: String!) {
      +  mergeBranch(input: {repositoryId: $repositoryId, base: $base, head: $head}) {
      +    mergeCommit {
      +      oid
      +    }
      +  }
      +}
      +,repositoryId=R_test_github_repo
      +[1]

Reviewed By: muirdm

Differential Revision: D43486928

fbshipit-source-id: 4c1321dfab0e4f86db60a38bfd04e6abeba2f215
  • Loading branch information
quark-zju authored and facebook-github-bot committed Feb 22, 2023
1 parent 2a31a60 commit 4f872e7
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions eden/scm/edenscm/ext/github/mock_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Any, Callable, Dict, List, Optional, Union

import ghstack.query
from edenscm import error

from edenscm.ext.github.consts import query
from edenscm.ext.github.gh_submit import PullRequestState
Expand Down Expand Up @@ -96,10 +97,9 @@ async def make_request(

key = create_request_key(params, hostname, endpoint, method)

try:
return self.requests[key].get_response()
except KeyError:
if key not in self.requests:
raise MockRequestNotFound(key, self.requests)
return self.requests[key].get_response()

def _add_request(self, request_key: str, request: "MockRequest") -> None:
self.requests[request_key] = request
Expand Down Expand Up @@ -579,10 +579,34 @@ def get_response(self) -> Result[JsonDict, str]:
return self._response


class MockRequestNotFound(Exception):
class MockRequestNotFound(error.Abort):
def __init__(self, key: str, requests: Dict[str, MockRequest]) -> None:
key_list = "\n\n".join(requests.keys())
super().__init__(f"key not found: {key}\nAvailable keys:\n{key_list}")
import textwrap

from edenscm import mdiff

# Try to find a similar key. The diff should be within 30 lines.
best_diff = None
best_diff_lines = 30
for existing_key in requests.keys():
diff_text = b"".join(
t
for _b, ts in mdiff.unidiff(
existing_key.encode(), "", key.encode(), "", "existing", "got"
)[1]
for t in ts
).decode()
diff_lines = diff_text.count("\n")
if diff_lines < best_diff_lines:
best_diff = diff_text
best_diff_lines = diff_lines
if best_diff:
msg = f"Mock key has changed:\n{textwrap.indent(best_diff, '| ')}"
else:
key_list = "\n\n".join(textwrap.indent(k, "| ") for k in requests.keys())
indented_key = textwrap.indent(key, "| ")
msg = f"key not found:\n{indented_key}\nAvailable keys:\n{key_list}"
super().__init__(msg)


class MockResponseNotSet(Exception):
Expand Down

0 comments on commit 4f872e7

Please sign in to comment.