aboutsummaryrefslogtreecommitdiff
path: root/mod/mod-ci-github-gq.cxx
diff options
context:
space:
mode:
authorFrancois Kritzinger <francois@codesynthesis.com>2024-12-10 10:31:47 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-12-10 16:44:55 +0200
commit40a3855e2341529624050b4324e73e774967111a (patch)
tree63c61c115c7f8fbec239459d604124d74087b108 /mod/mod-ci-github-gq.cxx
parentf845f18af3d3c18cbfb09ebfecac81bdb3c91953 (diff)
Handle re-runs of single check runs
Diffstat (limited to 'mod/mod-ci-github-gq.cxx')
-rw-r--r--mod/mod-ci-github-gq.cxx177
1 files changed, 120 insertions, 57 deletions
diff --git a/mod/mod-ci-github-gq.cxx b/mod/mod-ci-github-gq.cxx
index 1909e1f..fa701a8 100644
--- a/mod/mod-ci-github-gq.cxx
+++ b/mod/mod-ci-github-gq.cxx
@@ -168,14 +168,14 @@ namespace brep
// {
// "cr0": {
// "checkRun": {
- // "id": "CR_kwDOLc8CoM8AAAAFQ5GqPg",
+ // "node_id": "CR_kwDOLc8CoM8AAAAFQ5GqPg",
// "name": "libb2/0.98.1+2/x86_64-linux-gnu/linux_debian_12-gcc_13.1-O3/default/dev/0.17.0-a.1",
// "status": "QUEUED"
// }
// },
// "cr1": {
// "checkRun": {
- // "id": "CR_kwDOLc8CoM8AAAAFQ5GqhQ",
+ // "node_id": "CR_kwDOLc8CoM8AAAAFQ5GqhQ",
// "name": "libb2/0.98.1+2/x86_64-linux-gnu/linux_debian_12-gcc_13.1/default/dev/0.17.0-a.1",
// "status": "QUEUED"
// }
@@ -219,16 +219,17 @@ namespace brep
return r;
}
- // Send a GraphQL mutation request `rq` that operates on one or more check
- // runs. Update the check runs in `crs` with the new state and the node ID
- // if unset. Return false and issue diagnostics if the request failed.
+ // Send a GraphQL mutation request `rq` that creates or updates one or more
+ // check runs. The requested build state is taken from each check_run
+ // object. Update the check runs in `crs` with the new data (state, node ID
+ // if unset, and state_synced). Return false and issue diagnostics if the
+ // request failed.
//
static bool
gq_mutate_check_runs (const basic_mark& error,
vector<check_run>& crs,
const string& iat,
- string rq,
- build_state st) noexcept
+ string rq) noexcept
{
vector<gh_check_run> rcrs;
@@ -264,6 +265,7 @@ namespace brep
//
const gh_check_run& rcr (rcrs[i]); // Received check run.
+ build_state st (crs[i].state); // Requested state.
build_state rst (gh_from_status (rcr.status)); // Received state.
// Note that GitHub won't allow us to change a built check run to
@@ -297,7 +299,7 @@ namespace brep
error << "unexpected number of check_run objects in response";
}
else
- error << "failed to update check run: error HTTP response status "
+ error << "failed to mutate check runs: error HTTP response status "
<< sc;
}
catch (const json::invalid_json_input& e)
@@ -350,9 +352,11 @@ namespace brep
// Serialize `createCheckRun` mutations for one or more builds to GraphQL.
//
- // The conclusion argument (`co`) is required if the build_state is built
- // because GitHub does not allow a check run status of completed without a
- // conclusion.
+ // The check run parameters (names, build states, details_urls, etc.) are
+ // taken from each object in `crs`.
+ //
+ // Note that build results are not supported because we never create
+ // multiple check runs in the built state.
//
// The details URL argument (`du`) can be empty for queued but not for the
// other states.
@@ -360,15 +364,8 @@ namespace brep
static string
gq_mutation_create_check_runs (const string& ri, // Repository ID
const string& hs, // Head SHA
- const optional<string>& du, // Details URL.
- const vector<check_run>& crs,
- const string& st, // Check run status.
- optional<gq_built_result> br = nullopt)
+ const vector<check_run>& crs)
{
- // Ensure details URL is non-empty if present.
- //
- assert (!du || !du->empty ());
-
ostringstream os;
os << "mutation {" << '\n';
@@ -377,33 +374,34 @@ namespace brep
//
for (size_t i (0); i != crs.size (); ++i)
{
+ const check_run& cr (crs[i]);
+
+ assert (cr.state != build_state::built); // Not supported.
+
+ // Ensure details URL is non-empty if present.
+ //
+ assert (!cr.details_url || !cr.details_url->empty ());
+
string al ("cr" + to_string (i)); // Field alias.
os << gq_name (al) << ":createCheckRun(input: {" << '\n'
- << " name: " << gq_str (crs[i].name) << '\n'
+ << " name: " << gq_str (cr.name) << '\n'
<< " repositoryId: " << gq_str (ri) << '\n'
<< " headSha: " << gq_str (hs) << '\n'
- << " status: " << gq_enum (st);
- if (du)
- {
- os << '\n';
- os << " detailsUrl: " << gq_str (*du);
- }
- if (br)
+ << " status: " << gq_enum (gh_to_status (cr.state));
+ if (cr.details_url)
{
os << '\n';
- os << " conclusion: " << gq_enum (br->conclusion) << '\n'
- << " output: {" << '\n'
- << " title: " << gq_str (br->title) << '\n'
- << " summary: " << gq_str (br->summary) << '\n'
- << " }";
+ os << " detailsUrl: " << gq_str (*cr.details_url);
}
os << "})" << '\n'
- // Specify the selection set (fields to be returned).
+ // Specify the selection set (fields to be returned). Note that we
+ // rename `id` to `node_id` (using a field alias) for consistency with
+ // webhook events and REST API responses.
//
<< "{" << '\n'
<< " checkRun {" << '\n'
- << " id" << '\n'
+ << " node_id: id" << '\n'
<< " name" << '\n'
<< " status" << '\n'
<< " }" << '\n'
@@ -415,6 +413,71 @@ namespace brep
return os.str ();
}
+ // Serialize a `createCheckRun` mutation for a build to GraphQL.
+ //
+ // The build result argument (`br`) is required if the build_state is built
+ // because GitHub does not allow a check run status of completed without a
+ // conclusion.
+ //
+ // The details URL argument (`du`) can be empty for queued but not for the
+ // other states.
+ //
+ static string
+ gq_mutation_create_check_run (const string& ri, // Repository ID
+ const string& hs, // Head SHA
+ const optional<string>& du, // Details URL.
+ const check_run& cr,
+ const string& st, // Check run status.
+ optional<gq_built_result> br = nullopt)
+ {
+ // Ensure details URL is non-empty if present.
+ //
+ assert (!du || !du->empty ());
+
+ ostringstream os;
+
+ os << "mutation {" << '\n';
+
+ // Serialize a `createCheckRun` for the build.
+ //
+ os << gq_name ("cr0") << ":createCheckRun(input: {" << '\n'
+ << " name: " << gq_str (cr.name) << '\n'
+ << " repositoryId: " << gq_str (ri) << '\n'
+ << " headSha: " << gq_str (hs) << '\n'
+ << " status: " << gq_enum (st);
+ if (du)
+ {
+ os << '\n';
+ os << " detailsUrl: " << gq_str (*du);
+ }
+ if (br)
+ {
+ os << '\n';
+ os << " conclusion: " << gq_enum (br->conclusion) << '\n'
+ << " output: {" << '\n'
+ << " title: " << gq_str (br->title) << '\n'
+ << " summary: " << gq_str (br->summary) << '\n'
+ << " }";
+ }
+ os << "})" << '\n'
+ // Specify the selection set (fields to be returned). Note that we
+ // rename `id` to `node_id` (using a field alias) for consistency with
+ // webhook events and REST API responses.
+ //
+ << "{" << '\n'
+ << " checkRun {" << '\n'
+ << " node_id: id" << '\n'
+ << " name" << '\n'
+ << " status" << '\n'
+ << " }" << '\n'
+ << "}" << '\n';
+
+ os << "}" << '\n';
+
+ return os.str ();
+ }
+
+
// Serialize an `updateCheckRun` mutation for one build to GraphQL.
//
// The `co` (conclusion) argument is required if the build_state is built
@@ -460,11 +523,13 @@ namespace brep
<< " }";
}
os << "})" << '\n'
- // Specify the selection set (fields to be returned).
+ // Specify the selection set (fields to be returned). Note that we
+ // rename `id` to `node_id` (using a field alias) for consistency with
+ // webhook events and REST API responses.
//
<< "{" << '\n'
<< " checkRun {" << '\n'
- << " id" << '\n'
+ << " node_id: id" << '\n'
<< " name" << '\n'
<< " status" << '\n'
<< " }" << '\n'
@@ -479,23 +544,19 @@ namespace brep
vector<check_run>& crs,
const string& iat,
const string& rid,
- const string& hs,
- build_state st)
+ const string& hs)
{
// No support for result_status so state cannot be built.
//
- assert (st != build_state::built);
+#ifndef NDEBUG
+ for (const check_run& cr: crs)
+ assert (cr.state != build_state::built);
+#endif
- // Empty details URL because it's not available until building.
- //
string rq (
- gq_serialize_request (gq_mutation_create_check_runs (rid,
- hs,
- nullopt,
- crs,
- gh_to_status (st))));
+ gq_serialize_request (gq_mutation_create_check_runs (rid, hs, crs)));
- return gq_mutate_check_runs (error, crs, iat, move (rq), st);
+ return gq_mutate_check_runs (error, crs, iat, move (rq));
}
bool
@@ -512,18 +573,19 @@ namespace brep
//
assert (st != build_state::built || br);
- vector<check_run> crs {move (cr)};
-
string rq (
gq_serialize_request (
- gq_mutation_create_check_runs (rid,
- hs,
- du,
- crs,
- gh_to_status (st),
- move (br))));
+ gq_mutation_create_check_run (rid,
+ hs,
+ du,
+ cr,
+ gh_to_status (st),
+ move (br))));
+
+ vector<check_run> crs {move (cr)};
+ crs[0].state = st;
- bool r (gq_mutate_check_runs (error, crs, iat, move (rq), st));
+ bool r (gq_mutate_check_runs (error, crs, iat, move (rq)));
cr = move (crs[0]);
@@ -561,8 +623,9 @@ namespace brep
move (br))));
vector<check_run> crs {move (cr)};
+ crs[0].state = st;
- bool r (gq_mutate_check_runs (error, crs, iat, move (rq), st));
+ bool r (gq_mutate_check_runs (error, crs, iat, move (rq)));
cr = move (crs[0]);