aboutsummaryrefslogtreecommitdiff
path: root/mod/mod-ci-github.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'mod/mod-ci-github.cxx')
-rw-r--r--mod/mod-ci-github.cxx80
1 files changed, 78 insertions, 2 deletions
diff --git a/mod/mod-ci-github.cxx b/mod/mod-ci-github.cxx
index 8f0af2e..c59b1af 100644
--- a/mod/mod-ci-github.cxx
+++ b/mod/mod-ci-github.cxx
@@ -1034,8 +1034,9 @@ namespace brep
// Replace the existing CI tenant if it exists.
//
// Note that GitHub UI does not allow re-running the entire check suite
- // until all the check runs are completed.
- //
+ // until all the check runs are completed. However if we got here as a
+ // result of re-requesting the check suite from build_canceled() the check
+ // runs could be in any state.
// Create an unloaded CI tenant.
//
@@ -3213,6 +3214,81 @@ namespace brep
error << "unhandled exception: " << e.what ();
}
+ void ci_github::
+ build_canceled (const string& /* tenant_id */,
+ const tenant_service& ts,
+ const diag_epilogue& log_writer) const noexcept
+ try
+ {
+ // NOTE: this function is noexcept and should not throw.
+
+ NOTIFICATION_DIAG (log_writer);
+
+ // We end up here when the service data could not be saved so re-request
+ // the check suite in order to restart all of the builds.
+
+ // Load the unsaved service data.
+ //
+ service_data sd;
+ try
+ {
+ sd = service_data (*ts.data);
+ }
+ catch (const invalid_argument& e)
+ {
+ error << "failed to parse service data: " << e;
+ return;
+ }
+
+ // Get a new installation access token if the current one has expired.
+ //
+ const gh_installation_access_token* iat (nullptr);
+ optional<gh_installation_access_token> new_iat;
+
+ if (system_clock::now () > sd.installation_access.expires_at)
+ {
+ if (optional<string> jwt = generate_jwt (sd.app_id, trace, error))
+ {
+ new_iat = obtain_installation_access_token (sd.installation_id,
+ move (*jwt),
+ error);
+ if (new_iat)
+ iat = &*new_iat;
+ }
+ }
+ else
+ iat = &sd.installation_access;
+
+ if (iat != nullptr)
+ {
+ // Re-request the check suite.
+
+ // Note that the conclusion check run is created before the tenant is
+ // loaded so the unsaved service data should always contain the check
+ // suite node id.
+ //
+ assert (sd.check_suite_node_id.has_value ());
+
+ // Let unlikely invalid_argument propagate.
+ //
+ if (gq_rerequest_check_suite (error,
+ iat->token,
+ sd.repository_node_id,
+ *sd.check_suite_node_id))
+ {
+ l3 ([&]{trace << "re-requested check suite " << *sd.check_suite_node_id;});
+ }
+ else
+ error << "failed to re-request check suite " << *sd.check_suite_node_id;
+ }
+ }
+ catch (const std::exception& e)
+ {
+ NOTIFICATION_DIAG (log_writer);
+
+ error << "unhandled exception: " << e.what ();
+ }
+
string ci_github::
details_url (const build& b) const
{