diff options
Diffstat (limited to 'mod/mod-build-result.cxx')
-rw-r--r-- | mod/mod-build-result.cxx | 72 |
1 files changed, 53 insertions, 19 deletions
diff --git a/mod/mod-build-result.cxx b/mod/mod-build-result.cxx index fb6edb5..be0075b 100644 --- a/mod/mod-build-result.cxx +++ b/mod/mod-build-result.cxx @@ -17,6 +17,7 @@ #include <odb/transaction.hxx> #include <web/module> +#include <web/mime-url-encoding> #include <brep/build> #include <brep/build-odb> @@ -28,6 +29,7 @@ using namespace std; using namespace butl; using namespace bbot; +using namespace web; using namespace brep::cli; using namespace odb::core; @@ -193,6 +195,9 @@ handle (request& rq, response&) // Load and update the package build configuration (if present). // shared_ptr<build> b; + optional<result_status> prev_status; + bool notify (false); + { transaction t (build_db_->begin ()); b = build_db_->find<build> (id); @@ -200,42 +205,55 @@ handle (request& rq, response&) if (b == nullptr) warn_expired ("no package configuration"); else if (b->state != build_state::testing) - { warn_expired ("package configuration state is " + to_string (b->state)); - b = nullptr; - } else { - b->state = build_state::tested; - b->timestamp = timestamp::clock::now (); + // Don's send email for the success-to-success status change, unless the + // build was forced. + // + notify = !(rqm.result.status == result_status::success && + b->status && *b->status == rqm.result.status && !b->forced); + + prev_status = move (b->status); - assert (!b->status); + b->state = build_state::tested; b->status = rqm.result.status; + b->forced = false; - // Need to manually load the lazy-load section prior to changing its - // members and updating the object's persistent state. + // Mark the section as loaded, so results are updated. // - // @@ TODO: ODB now allows marking a section as loaded so can optimize - // this. - // - build_db_->load (*b, b->results_section); + b->results_section.load (); b->results = move (rqm.result.results); + b->timestamp = timestamp::clock::now (); + build_db_->update (b); } t.commit (); } - if (b == nullptr) - return true; // Warning is already logged. + if (!notify) + return true; + + assert (b != nullptr); // Send email to the package owner. // try { string subj (b->package_name + '/' + b->package_version.string () + ' ' + - b->configuration + " build: " + to_string (*b->status)); + b->configuration); + + if (!prev_status) + subj += " build: " + to_string (*b->status); + else + { + subj += " rebuild: " + to_string (*b->status); + + if (*prev_status != *b->status) + subj += " after " + to_string (*prev_status); + } // If the package email address is not specified, then it is assumed to be // the same as the project email address. @@ -264,11 +282,27 @@ handle (request& rq, response&) sm.out << "No operations results available." << endl; else { + string url (options_->host () + options_->root ().string ()); + string pkg (mime_url_encode (b->package_name)); + string cfg (mime_url_encode (b->configuration)); + + // Note that '+' is the only package version character that potentially + // needs to be url-encoded, and only in the query part of the URL. + // However, we print the package version either as part of URL path or + // as the build-force URL query part (where it is not encoded by + // design). + // + const version& ver (b->package_version); + for (const auto& r: b->results) - sm.out << r.operation << ": " << r.status << ", " - << options_->host () << options_->root ().representation () - << b->package_name << '/' << b->package_version << "/log/" - << b->configuration << '/' << r.operation << endl; + sm.out << r.operation << ": " << r.status << ", " << url << '/' << pkg + << '/' << ver << "/log/" << cfg << '/' << r.operation << endl; + + sm.out << endl + << "force rebuild: " << url << "?build-force&p=" << pkg + << "&v=" << ver << "&c=" << cfg << "&reason=" << endl << endl + << "Note: enter the rebuild reason in the above URL (" + << "using '+' instead of space characters)." << endl; } sm.out.close (); |