aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancois Kritzinger <francois@codesynthesis.com>2024-04-29 10:51:12 +0200
committerFrancois Kritzinger <francois@codesynthesis.com>2024-10-15 09:05:28 +0200
commit0ab2f6b15d9d7cada6530ceeef9df203a4ba2fcf (patch)
treef3dea74babd429a985c75902a7702347c261d21a
parent4bcadc03c96bebd2391736e49c92b873d57cfc8e (diff)
Handle warning_success webhook query parameter
-rw-r--r--mod/mod-ci-github-gq.cxx52
-rw-r--r--mod/mod-ci-github-gq.hxx14
-rw-r--r--mod/mod-ci-github-service-data.cxx10
-rw-r--r--mod/mod-ci-github-service-data.hxx3
-rw-r--r--mod/mod-ci-github.cxx42
-rw-r--r--mod/mod-ci-github.hxx5
6 files changed, 92 insertions, 34 deletions
diff --git a/mod/mod-ci-github-gq.cxx b/mod/mod-ci-github-gq.cxx
index b9e5908..c37c889 100644
--- a/mod/mod-ci-github-gq.cxx
+++ b/mod/mod-ci-github-gq.cxx
@@ -317,15 +317,16 @@ namespace brep
// Serialize `createCheckRun` mutations for one or more builds to GraphQL.
//
- // The result_status is required if the build_state is built because GitHub
- // does not allow a check run status of completed without a conclusion.
+ // The `co` (conclusion) argument is required if the build_state is built
+ // because GitHub does not allow a check run status of completed without a
+ // conclusion.
//
static string
gq_mutation_create_check_runs (const string& ri, // Repository ID
const string& hs, // Head SHA
const vector<check_run>& crs,
- build_state st,
- optional<result_status> rs = nullopt)
+ const string& st, // Check run status.
+ const optional<string>& co = nullopt)
{
ostringstream os;
@@ -341,12 +342,11 @@ namespace brep
<< " name: " << gq_str (crs[i].name) << ',' << '\n'
<< " repositoryId: " << gq_str (ri) << ',' << '\n'
<< " headSha: " << gq_str (hs) << ',' << '\n'
- << " status: " << gq_enum (gh_to_status (st));
- if (rs)
+ << " status: " << gq_enum (st);
+ if (co)
{
- // @@ TODO Pass valid boolean
os << ',' << '\n'
- << " conclusion: " << gq_enum (gh_to_conclusion (*rs, false));
+ << " conclusion: " << gq_enum (*co);
}
os << "})" << '\n'
// Specify the selection set (fields to be returned).
@@ -367,14 +367,15 @@ namespace brep
// Serialize an `updateCheckRun` mutation for one build to GraphQL.
//
- // The result_status is required if the build_state is built because GitHub
- // does not allow updating a check run to completed without a conclusion.
+ // The `co` (conclusion) argument is required if the build_state is built
+ // because GitHub does not allow updating a check run to completed without a
+ // conclusion.
//
static string
gq_mutation_update_check_run (const string& ri, // Repository ID.
const string& ni, // Node ID.
- build_state st,
- optional<result_status> rs)
+ const string& st, // Check run status.
+ const optional<string>& co)
{
ostringstream os;
@@ -382,12 +383,11 @@ namespace brep
<< "cr0:updateCheckRun(input: {" << '\n'
<< " checkRunId: " << gq_str (ni) << ',' << '\n'
<< " repositoryId: " << gq_str (ri) << ',' << '\n'
- << " status: " << gq_enum (gh_to_status (st));
- if (rs)
+ << " status: " << gq_enum (st);
+ if (co)
{
- // @@ TODO Pass valid boolean
os << ',' << '\n'
- << " conclusion: " << gq_enum (gh_to_conclusion (*rs, false));
+ << " conclusion: " << gq_enum (*co);
}
os << "})" << '\n'
// Specify the selection set (fields to be returned).
@@ -417,7 +417,7 @@ namespace brep
assert (st != build_state::built);
string rq (gq_serialize_request (
- gq_mutation_create_check_runs (rid, hs, crs, st)));
+ gq_mutation_create_check_runs (rid, hs, crs, gh_to_status (st))));
return gq_mutate_check_runs (error, crs, iat, move (rq), st);
}
@@ -429,7 +429,8 @@ namespace brep
const string& rid,
const string& hs,
build_state st,
- optional<result_status> rs)
+ optional<result_status> rs,
+ bool ws)
{
// Must have a result if state is built.
//
@@ -437,8 +438,12 @@ namespace brep
vector<check_run> crs {move (cr)};
+ optional<string> co; // Conclusion.
+ if (rs)
+ co = gh_to_conclusion (*rs, ws);
+
string rq (gq_serialize_request (
- gq_mutation_create_check_runs (rid, hs, crs, st, rs)));
+ gq_mutation_create_check_runs (rid, hs, crs, gh_to_status (st), co)));
bool r (gq_mutate_check_runs (error, crs, iat, move (rq), st));
@@ -454,14 +459,19 @@ namespace brep
const string& rid,
const string& nid,
build_state st,
- optional<result_status> rs)
+ optional<result_status> rs,
+ bool ws)
{
// Must have a result if state is built.
//
assert (st != build_state::built || rs);
+ optional<string> co; // Conclusion.
+ if (rs)
+ co = gh_to_conclusion (*rs, ws);
+
string rq (gq_serialize_request (
- gq_mutation_update_check_run (rid, nid, st, rs)));
+ gq_mutation_update_check_run (rid, nid, gh_to_status (st), co)));
vector<check_run> crs {move (cr)};
diff --git a/mod/mod-ci-github-gq.hxx b/mod/mod-ci-github-gq.hxx
index 33aeec4..a8e5e02 100644
--- a/mod/mod-ci-github-gq.hxx
+++ b/mod/mod-ci-github-gq.hxx
@@ -38,6 +38,9 @@ namespace brep
// The result_status is required if the build_state is built because GitHub
// does not allow a check run status of `completed` without a conclusion.
//
+ // If warning_success is true, then map result_status::warning to SUCCESS
+ // and to FAILURE otherwise.
+ //
// @@ TODO Support output (title, summary, text).
//
bool
@@ -47,7 +50,8 @@ namespace brep
const string& repository_id,
const string& head_sha,
build_state,
- optional<result_status> = nullopt);
+ optional<result_status> = nullopt,
+ bool warning_success = true);
// Update a check run on GitHub.
//
@@ -56,7 +60,10 @@ namespace brep
// failed.
//
// The result_status is required if the build_state is built because GitHub
- // does not allow updating a check run to `completed` without a conclusion.
+ // does not allow a check run status of `completed` without a conclusion.
+ //
+ // If warning_success is true, then map result_status::warning to SUCCESS
+ // and to FAILURE otherwise.
//
// @@ TODO Support output (title, summary, text).
//
@@ -67,7 +74,8 @@ namespace brep
const string& repository_id,
const string& node_id,
build_state,
- optional<result_status> = nullopt);
+ optional<result_status> = nullopt,
+ bool warning_success = true);
}
#endif // MOD_MOD_CI_GITHUB_GQ_HXX
diff --git a/mod/mod-ci-github-service-data.cxx b/mod/mod-ci-github-service-data.cxx
index a53f445..83e952b 100644
--- a/mod/mod-ci-github-service-data.cxx
+++ b/mod/mod-ci-github-service-data.cxx
@@ -26,6 +26,8 @@ namespace brep
to_string (version));
}
+ warning_success = p.next_expect_member_boolean<bool> ("warning_success");
+
// Installation access token.
//
p.next_expect_member_object ("installation_access");
@@ -64,12 +66,14 @@ namespace brep
}
service_data::
- service_data (string iat_tok,
+ service_data (bool ws,
+ string iat_tok,
timestamp iat_ea,
uint64_t iid,
string rid,
string hs)
- : installation_access (move (iat_tok), iat_ea),
+ : warning_success (ws),
+ installation_access (move (iat_tok), iat_ea),
installation_id (iid),
repository_id (move (rid)),
head_sha (move (hs))
@@ -86,6 +90,8 @@ namespace brep
s.member ("version", 1);
+ s.member ("warning_success", warning_success);
+
// Installation access token.
//
s.member_begin_object ("installation_access");
diff --git a/mod/mod-ci-github-service-data.hxx b/mod/mod-ci-github-service-data.hxx
index 99c50ae..8d0b634 100644
--- a/mod/mod-ci-github-service-data.hxx
+++ b/mod/mod-ci-github-service-data.hxx
@@ -77,7 +77,8 @@ namespace brep
explicit
service_data (const string& json);
- service_data (string iat_token,
+ service_data (bool warning_success,
+ string iat_token,
timestamp iat_expires_at,
uint64_t installation_id,
string repository_id,
diff --git a/mod/mod-ci-github.cxx b/mod/mod-ci-github.cxx
index 644993b..4ee3cc0 100644
--- a/mod/mod-ci-github.cxx
+++ b/mod/mod-ci-github.cxx
@@ -226,6 +226,35 @@ namespace brep
fail << "unable to compute request HMAC: " << e;
}
+ // Process the `warning` webhook request query parameter.
+ //
+ bool warning_success;
+ {
+ const name_values& rps (rq.parameters (1024, true /* url_only */));
+
+ auto i (find_if (rps.begin (), rps.end (),
+ [] (auto&& rp) {return rp.name == "warning";}));
+
+ if (i == rps.end ())
+ throw invalid_request (400,
+ "missing 'warning' webhook query parameter");
+
+ if (!i->value)
+ throw invalid_request (
+ 400, "missing 'warning' webhook query parameter value");
+
+ const string& v (*i->value);
+
+ if (v == "success") warning_success = true;
+ else if (v == "failure") warning_success = false;
+ else
+ {
+ throw invalid_request (
+ 400,
+ "invalid 'warning' webhook query parameter value: '" + v + '\'');
+ }
+ }
+
// There is a webhook event (specified in the x-github-event header) and
// each event contains a bunch of actions (specified in the JSON request
// body).
@@ -257,14 +286,14 @@ namespace brep
if (cs.action == "requested")
{
- return handle_check_suite_request (move (cs));
+ return handle_check_suite_request (move (cs), warning_success);
}
else if (cs.action == "rerequested")
{
// Someone manually requested to re-run the check runs in this check
// suite. Treat as a new request.
//
- return handle_check_suite_request (move (cs));
+ return handle_check_suite_request (move (cs), warning_success);
}
else if (cs.action == "completed")
{
@@ -305,7 +334,7 @@ namespace brep
}
bool ci_github::
- handle_check_suite_request (gh_check_suite_event cs)
+ handle_check_suite_request (gh_check_suite_event cs, bool warning_success)
{
HANDLER_DIAG;
@@ -331,7 +360,8 @@ namespace brep
cs.check_suite.head_branch,
repository_type::git);
- string sd (service_data (move (iat->token),
+ string sd (service_data (warning_success,
+ move (iat->token),
iat->expires_at,
cs.installation.id,
move (cs.repository.node_id),
@@ -825,7 +855,7 @@ namespace brep
sd.repository_id,
*cr.node_id,
build_state::built,
- b.status))
+ *b.status, sd.warning_success))
{
assert (cr.state == build_state::built);
@@ -848,7 +878,7 @@ namespace brep
sd.repository_id,
sd.head_sha,
build_state::built,
- b.status))
+ *b.status, sd.warning_success))
{
assert (cr.state == build_state::built);
diff --git a/mod/mod-ci-github.hxx b/mod/mod-ci-github.hxx
index 07feca8..b16085e 100644
--- a/mod/mod-ci-github.hxx
+++ b/mod/mod-ci-github.hxx
@@ -60,8 +60,11 @@ namespace brep
// Handle the check_suite event `requested` and `rerequested` actions.
//
+ // If warning_success is true, then map result_status::warning to SUCCESS
+ // and to FAILURE otherwise.
+ //
bool
- handle_check_suite_request (gh_check_suite_event);
+ handle_check_suite_request (gh_check_suite_event, bool warning_success);
optional<string>
generate_jwt (const basic_mark& trace, const basic_mark& error) const;