Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display json errors instead of uncaught exception #34

Merged
merged 2 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 37 additions & 30 deletions lib/contributions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -136,36 +136,43 @@ let of_json ~period:(from, to_) ~user json =
| exception Ppx_yojson_conv_lib.Yojson_conv.Of_yojson_error (exn, _) ->
Error (`Msg (Printexc.to_string exn))
in
let* root =
match user with
| User.Viewer ->
json.data.viewer |> Option.to_result ~none:(`Msg "viewer field missing")
| User.User _ ->
json.data.user |> Option.to_result ~none:(`Msg "user field missing")
in
let username = root.login in
let contribs = root.contributionsCollection in
let items =
let issues = read_issues contribs.issueContributions.nodes in
let issue_comments = read_issue_comments root.issueComments.nodes in
let prs = read_prs contribs.pullRequestContributions.nodes in
let reviews = read_reviews contribs.pullRequestReviewContributions.nodes in
let repos = read_repos contribs.repositoryContributions.nodes in
issues @ issue_comments @ prs @ reviews @ repos
in
let activity =
(* GitHub seems to ignore the time part, so do the filtering here. *)
items
|> List.filter (fun item -> item.date >= from && item.date <= to_)
|> List.fold_left
(fun acc item ->
let items =
Repo_map.find_opt item.repo acc |> Option.value ~default:[]
in
Repo_map.add item.repo (item :: items) acc)
Repo_map.empty
in
Ok { username; activity }
match json.data with
| Some data ->
let* root =
match user with
| User.Viewer ->
data.viewer |> Option.to_result ~none:(`Msg "viewer field missing")
| User.User _ ->
data.user |> Option.to_result ~none:(`Msg "user field missing")
in
let username = root.login in
let contribs = root.contributionsCollection in
let items =
let issues = read_issues contribs.issueContributions.nodes in
let issue_comments = read_issue_comments root.issueComments.nodes in
let prs = read_prs contribs.pullRequestContributions.nodes in
let reviews =
read_reviews contribs.pullRequestReviewContributions.nodes
in
let repos = read_repos contribs.repositoryContributions.nodes in
issues @ issue_comments @ prs @ reviews @ repos
in
let activity =
(* GitHub seems to ignore the time part, so do the filtering here. *)
items
|> List.filter (fun item -> item.date >= from && item.date <= to_)
|> List.fold_left
(fun acc item ->
let items =
Repo_map.find_opt item.repo acc |> Option.value ~default:[]
in
Repo_map.add item.repo (item :: items) acc)
Repo_map.empty
in
Ok { username; activity }
| None ->
Fmt.error_msg "@[%a@]" (Fmt.list Fmt.string)
(List.map (fun x -> x.Json.message) json.errors)

let id url =
match Astring.String.cut ~sep:"/" ~rev:true url with
Expand Down
9 changes: 8 additions & 1 deletion lib/contributions_json_response.ml
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,11 @@ type data = {
[@@deriving yojson]
(** The key is either [viewer] or [user] depending on the request but the value associated is the same. *)

type t = { data : data } [@@deriving yojson]
type error = { message : string }
[@@deriving yojson] [@@yojson.allow_extra_fields]

type t = {
data : data option; [@yojson.option]
errors : error list; [@default []]
}
[@@deriving yojson]
33 changes: 33 additions & 0 deletions test/lib/test_contributions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,35 @@ let activity_example ~user =
let activity_example_json ~user =
Yojson.Safe.from_string (activity_example ~user)

let error_example =
{|
{
"errors": [
{
"path": [
"query",
"viewer",
"contributionsCollection",
"to"
],
"extensions": {
"code": "argumentLiteralsIncompatible",
"typeName": "Field",
"argumentName": "to"
},
"locations": [
{
"line": 4,
"column": 5
}
],
"message": "Error."
}
]
} |}

let error_example_json = Yojson.Safe.from_string error_example

let contributions_example1 ~user =
let open Contributions in
{
Expand Down Expand Up @@ -493,6 +522,10 @@ let test_of_json =
username = user |> or_viewer;
activity = Contributions.Repo_map.empty;
}));
(let user = User.User "gpetiot" in
make_test "errors"
~period:("2024-02-27T12:05:04Z", "2024-03-13T11:09:56Z")
~user error_example_json ~expected:(Fmt.error_msg "Error."));
]

let test_is_empty =
Expand Down
Loading