diff options
-rw-r--r-- | mod/mod-ci-github-gq.cxx | 51 | ||||
-rw-r--r-- | mod/mod-ci-github-gq.hxx | 37 |
2 files changed, 61 insertions, 27 deletions
diff --git a/mod/mod-ci-github-gq.cxx b/mod/mod-ci-github-gq.cxx index 1e9af74..cfa4a55 100644 --- a/mod/mod-ci-github-gq.cxx +++ b/mod/mod-ci-github-gq.cxx @@ -578,7 +578,10 @@ namespace brep os << "query {" << '\n' << " node(id:" << gq_str (nid) << ") {" << '\n' << " ... on PullRequest {" << '\n' - << " mergeable potentialMergeCommit { oid }" << '\n' + << " headRefOid" << '\n' + << " mergeStateStatus" << '\n' + << " mergeable" << '\n' + << " potentialMergeCommit { oid }" << '\n' << " }" << '\n' << " }" << '\n' << "}" << '\n'; @@ -586,10 +589,10 @@ namespace brep return os.str (); } - optional<string> - gq_pull_request_mergeable (const basic_mark& error, - const string& iat, - const string& nid) + optional<gq_pr_pre_check> + gq_pull_request_pre_check_info (const basic_mark& error, + const string& iat, + const string& nid) { string rq (gq_serialize_request (gq_query_pr_mergeability (nid))); @@ -610,7 +613,7 @@ namespace brep // The response value. Absent if the merge commit is still being // generated. // - optional<string> value; + optional<gq_pr_pre_check> r; resp (json::parser& p) { @@ -624,32 +627,42 @@ namespace brep { found = true; + string hs (p.next_expect_member_string ("headRefOid")); + string ms (p.next_expect_member_string ("mergeStateStatus")); string ma (p.next_expect_member_string ("mergeable")); - if (ma == "MERGEABLE") + if (ms == "BEHIND") + { + // The PR head branch is not up to date with the PR base + // branch. + // + // Note that we can only get here if the head-not-behind + // protection rule is active on the PR base branch. + // + r = {move (hs), true, ""}; + } + else if (ma == "MERGEABLE") { p.next_expect_member_object ("potentialMergeCommit"); string oid (p.next_expect_member_string ("oid")); p.next_expect (event::end_object); - value = move (oid); + r = {move (hs), false, move (oid)}; } else { if (ma == "CONFLICTING") - value = ""; + r = {move (hs), false, ""}; if (ma == "UNKNOWN") - ; // Still being generated; leave value absent. + ; // Still being generated; leave r absent. else - { - // @@ Let's throw invalid_json. - // - parse_error = "unexpected mergeable value '" + ma + '\''; - - // Carry on as if it were UNKNOWN. - } + throw_json (p, "unexpected mergeable value '" + ma + '\''); + } - // Skip the merge commit ID (which should be null). + if (!r || r->merge_commit_sha.empty ()) + { + // Skip the merge commit ID if it has not yet been extracted + // (in which case it should be null). // p.next_expect_name ("potentialMergeCommit"); p.next_expect_value_skip (); @@ -677,7 +690,7 @@ namespace brep else if (!rs.parse_error.empty ()) error << rs.parse_error; - return rs.value; + return rs.r; } else error << "failed to fetch pull request: error HTTP response status " diff --git a/mod/mod-ci-github-gq.hxx b/mod/mod-ci-github-gq.hxx index ad9797a..f52299c 100644 --- a/mod/mod-ci-github-gq.hxx +++ b/mod/mod-ci-github-gq.hxx @@ -83,10 +83,15 @@ namespace brep build_state, optional<gq_built_result> = nullopt); - // Fetch a pull request's mergeability from GitHub. Return absent value if - // the merge commit is still being generated. Return empty string if the - // pull request is not auto-mergeable. Otherwise return the test merge - // commit id. + // Fetch pre-check information for a pull request from GitHub. This + // information is used to decide whether or not to CI the PR and is + // comprised of the PR's head commit SHA, whether its head branch is behind + // its base branch, and its test merge commit SHA. + // + // Return absent value if the merge commit is still being generated (which + // means PR head branch behindness is not yet known either). See the + // gq_pr_pre_check struct's field comments for non-absent return value + // semantics. // // Issue diagnostics and return absent if the request failed (which means it // will be treated by the caller as still being generated). @@ -95,10 +100,26 @@ namespace brep // merge commit. (For details see // https://docs.github.com/rest/guides/getting-started-with-the-git-database-api#checking-mergeability-of-pull-requests.) // - optional<string> - gq_pull_request_mergeable (const basic_mark& error, - const string& installation_access_token, - const string& node_id); + struct gq_pr_pre_check + { + // The PR head commit ID. + // + string head_sha; + + // True if the PR's head branch is behind its base branch. + // + bool behind; + + // The commit ID of the test merge commit. Empty if behind or the PR is + // not auto-mergeable. + // + string merge_commit_sha; + }; + + optional<gq_pr_pre_check> + gq_pull_request_pre_check_info (const basic_mark& error, + const string& installation_access_token, + const string& node_id); // Fetch the last 100 open pull requests with the specified base branch from // the repository with the specified node ID. |