private static void ProcessNotify (DBWork work, DBRevisionWork revision_work) { List<NotificationBase> notifications; Logger.Log ("Notifications.ProcessNotify (lane_id: {1} revision_id: {2} host_id: {3} State: {0})", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); try { lock (lock_obj) { // We broadcast the notification to the API endpoint WebNotification.BroadcastBuildNotification (work, revision_work); if (!notifications_per_lane.TryGetValue (revision_work.lane_id, out notifications)) { Logger.Log ("Notifications.ProcessNotify (lane_id: {1} revision_id: {2} host_id: {3} State: {0}): Lane doesn't have any notifications enabled", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); return; } foreach (var notification in notifications) { notification.Notify (work, revision_work); } } } catch (Exception ex) { Logger.Log ("Exception while processing notification: {0}", ex.Message); } }
void NotifySlack (DBWork work, DBRevisionWork revision_work, List<DBPerson> people, string message) { bool nonfatal = false; if (!Evaluate (work, revision_work, out nonfatal)) { log.DebugFormat ("SlackNotification: lane_id: {1} revision_id: {2} host_id: {3} State: {0}: evaluation returned false", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); return; } else { log.DebugFormat ("SlackNotification: lane_id: {1} revision_id: {2} host_id: {3} State: {0} enabled: {4}, {5} people", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id, enabled, people.Count); } if (nonfatal) { message = "Test failure"; } else { message = "Build failure"; } DBRevision revision; DBLane lane; DBHost host; using (DB db = new DB ()) { revision = DBRevision_Extensions.Create (db, revision_work.revision_id); lane = DBLane_Extensions.Create (db, revision_work.lane_id); host = DBHost_Extensions.Create (db, revision_work.host_id); } message = string.Format ("{0} in revision {1} on {2}/{3} ({4}/ViewLane.aspx?lane_id={5}&host_id={6}&revision_id={7})", message, (revision.revision.Length > 8 ? revision.revision.Substring (0, 8) : revision.revision), lane.lane, host.host, Configuration.GetWebSiteUrl (), lane.id, host.id, revision.id); foreach (var person in people) { if (string.IsNullOrEmpty (person.irc_nicknames)) { using (var db = new DB ()) { var computed_nicks = new List<string> (); var email_lists = new List<IEnumerable<string>> (); email_lists.Add (person.GetEmails (db)); if (person.Emails != null) email_lists.Add (person.Emails); foreach (var emails in email_lists) { foreach (var email in emails) { var at = email.IndexOf ('@'); if (at > 0) { computed_nicks.Add (email.Substring (0, at)); } } } if (computed_nicks.Count == 0 && !string.IsNullOrEmpty (person.fullname)) computed_nicks.Add (person.fullname); person.irc_nicknames = string.Join (",", computed_nicks.ToArray ()); } } if (string.IsNullOrEmpty (person.irc_nicknames)) { log.DebugFormat ("SlackNotification: could not find somebody to notify for revision with id {0} on lane {1}", revision_work.revision_id, revision_work.lane_id); continue; } } var rooms = identity.channels.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries); var finalApi = identity.servers; var webClient = new WebClient (); foreach (var r in rooms) { string prefix; string room = r; if (room.StartsWith ("*")) { room = room.Substring (1); prefix = ""; } else { prefix = "@"; } var prefixNames = string.Join (", ", people.SelectMany (x => x.irc_nicknames.Split (',')).Distinct ().Select (x => string.Format("{1}{0}", x, prefix))); var finalMessage = prefixNames + ": " + message; if (cache [room + "|" + finalMessage] != null) continue; cache.Add (room + "|" + finalMessage, string.Empty, new DateTimeOffset (DateTime.UtcNow.AddHours (1), TimeSpan.Zero)); var json = string.Format (@" {{ ""channel"": ""{0}"", ""username"": ""Wrench"", ""text"": ""*{1}*"", ""attachments"": [ {{ ""fallback"": ""{2}{3}"", ""color"": ""{4}"", ""fields"":[ {{ ""value"": ""{2}{3}"", ""short"": false }} ] }} ] }} ", r, nonfatal ? "Test failure" : "Build failure", nonfatal ? ":crying_cat_face: " : ":pouting_cat: ", finalMessage.Replace ("\\", "\\\\").Replace ("\"", "\\\""), nonfatal ? "warning" : "danger" ); var postData = new NameValueCollection (); postData.Add ("payload", json); try { var res = webClient.UploadValues (finalApi, postData); var resString = Encoding.UTF8.GetString (res); log.DebugFormat ("SlackNotification: response from server: {0}", resString); } catch (WebException wex) { string responseText = null; if (wex.Response != null) { using (var responseStream = wex.Response.GetResponseStream ()) { if (responseStream != null) { using (var reader = new StreamReader (responseStream)) responseText = reader.ReadToEnd (); } } } if (responseText == null) { log.ErrorFormat ("SlackNotification: exception from server (no response): {0}", wex.Message); } else { log.ErrorFormat ("SlackNotification: server error: {0} with exception: {1}", responseText, wex.Message); } } } }
public static void Notify (DBWork work, DBRevisionWork revision_work) { Logger.Log ("Notifications.Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0})", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); if (notifications == null) return; if (!(work.State == DBState.Failed || work.State == DBState.Issues || work.State == DBState.Timeout)) return; ThreadPool.QueueUserWorkItem ((v) => ProcessNotify (work, revision_work)); }
public void UploadLinks (WebServiceLogin login, DBWork work, string [] links) { using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.BuildBot, true); using (var cmd = db.CreateCommand ()) { StringBuilder sql = new StringBuilder (); for (int i = 0; i < links.Length; i++) { sql.AppendFormat ("INSERT INTO FileLink (link, work_id) VALUES (@link{0}, {1});", i, work.id); DB.CreateParameter (cmd, "link" + i.ToString (), links [i]); } cmd.CommandText = sql.ToString (); cmd.ExecuteNonQuery (); } } }
public DBState GetWorkState (WebServiceLogin login, DBWork work) { using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.BuildBot, true); work.Reload (db); return work.State; } }
public void Notify (DBWork work, DBRevisionWork revision_work) { List<DBPerson> people = new List<DBPerson> (); DBRevision revision; DBLane lane; DBHost host; string message; bool nonfatal; Logger.Log ("NotificationBase.Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0})", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); nonfatal = false; if (!Evaluate (work, revision_work, out nonfatal)) { Logger.Log ("NotificationBase.Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0}) = evaluation returned false", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); return; } if (nonfatal) { message = "Test failure"; } else { message = "{red}{bold}Build failure{default}"; } using (DB db = new DB ()) { revision = DBRevision_Extensions.Create (db, revision_work.revision_id); lane = DBLane_Extensions.Create (db, revision_work.lane_id); host = DBHost_Extensions.Create (db, revision_work.host_id); } message = string.Format ("{0} in revision {1} on {2}/{3}: {4}/ViewLane.aspx?lane_id={5}&host_id={6}&revision_id={7}", message, (revision.revision.Length > 8 ? revision.revision.Substring (0, 8) : revision.revision), lane.lane, host.host, Configuration.GetWebSiteUrl (), lane.id, host.id, revision.id); MonkeyWrench.Scheduler.Scheduler.FindPeopleForCommit (lane, revision, people); people = FindPeople (people); Notify (work, revision_work, people, message); }
protected override void Notify (DBWork work, DBRevisionWork revision_work, List<DBPerson> people, string message) { if (!this.emails.Any ()) { Logger.Log ("EmailNotification.Notify no emails"); return; } if (this.emails.Any (x => !x.EndsWith ("@hipchat.xamarin.com", StringComparison.OrdinalIgnoreCase))) { Logger.Log ("EmailNotification.Notify skipping non-HipChat emails because we don't know how to send email!"); return; } var actionableEmails = this.emails.Where (x => x.EndsWith ("@hipchat.xamarin.com")).ToList (); if (!actionableEmails.Any ()) { Logger.Log ("EmailNotification.Notify no actionable emails!"); return; } Logger.Log ("EmailNotification.Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0}) enabled: {4}, {5} people", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id, true, people.Count); bool nonfatal = false; if (!Evaluate (work, revision_work, out nonfatal)) { Logger.Log ("EmailNotification.Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0}) = evaluation returned false", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); return; } if (nonfatal) { message = "Test failure"; } else { message = "Build failure"; } DBRevision revision; DBLane lane; DBHost host; using (DB db = new DB ()) { revision = DBRevision_Extensions.Create (db, revision_work.revision_id); lane = DBLane_Extensions.Create (db, revision_work.lane_id); host = DBHost_Extensions.Create (db, revision_work.host_id); } message = string.Format ("{0} in revision {1} on {2}/{3} ({4}/ViewLane.aspx?lane_id={5}&host_id={6}&revision_id={7})", message, (revision.revision.Length > 8 ? revision.revision.Substring (0, 8) : revision.revision), lane.lane, host.host, Configuration.GetWebSiteUrl (), lane.id, host.id, revision.id); foreach (var person in people) { if (string.IsNullOrEmpty (person.irc_nicknames)) { using (var db = new DB ()) { var computed_nicks = new List<string> (); var email_lists = new List<IEnumerable<string>> (); email_lists.Add (person.GetEmails (db)); if (person.Emails != null) email_lists.Add (person.Emails); foreach (var emails in email_lists) { foreach (var email in emails) { var at = email.IndexOf ('@'); if (at > 0) { computed_nicks.Add (email.Substring (0, at)); } } } if (computed_nicks.Count == 0 && !string.IsNullOrEmpty (person.fullname)) computed_nicks.Add (person.fullname); person.irc_nicknames = string.Join (",", computed_nicks.ToArray ()); } } if (string.IsNullOrEmpty (person.irc_nicknames)) { Logger.Log ("HipChatNotification: could not find somebody to notify for revision with id {0} on lane {1}", revision_work.revision_id, revision_work.lane_id); continue; } } var apiToken = identity.password; var rooms = actionableEmails.Select (email => email.Split ('@') [0]).ToList (); const string finalApi = "https://hipchat.xamarin.com/v1/rooms/message"; var webClient = new WebClient (); foreach (var r in rooms) { string prefix; string room = r; if (room.StartsWith ("*")) { room = room.Substring (1); prefix = ""; } else { prefix = "@"; } var prefixNames = string.Join (", ", people.SelectMany (x => x.irc_nicknames.Split (',')).Distinct ().Select (x => string.Format("{1}{0}", x, prefix))); var finalMessage = prefixNames + ": " + message; if (cache [room + "|" + finalMessage] != null) continue; cache.Add (room + "|" + finalMessage, string.Empty, new DateTimeOffset (DateTime.UtcNow.AddHours (1), TimeSpan.Zero)); var postData = new NameValueCollection (); postData.Add ("auth_token", apiToken); postData.Add ("room_id", room); postData.Add ("from", "Wrench"); postData.Add ("message", finalMessage); postData.Add ("notify", nonfatal ? "0" : "1"); // TODO: Maybe send HTML eventually, though HTML doesn't allow @-mentions. :( postData.Add ("message_format", "text"); postData.Add ("color", nonfatal ? "yellow" : "red"); postData.Add ("format", "json"); var res = webClient.UploadValues (finalApi, postData); var resString = Encoding.UTF8.GetString (res); Logger.Log ("HipChatNotification: response from server: {0}", resString); } }
public static void BroadcastBuildNotification (DBWork work, DBRevisionWork revisionWork) { BroadcastBuildNotification (new Lazy<Build> (() => GetBuildFromDBItems (work, revisionWork))); }
static Build GetBuildFromDBItems (DBWork work, DBRevisionWork revisionWork) { DBRevision revision; DBLane lane, parentLane; DBHost host; using (DB db = new DB ()) { revision = DBRevision_Extensions.Create (db, revisionWork.revision_id); lane = DBLane_Extensions.Create (db, revisionWork.lane_id); parentLane = GetTopMostParent (lane, db); host = DBHost_Extensions.Create (db, revisionWork.host_id); } var url = Configuration.GetWebSiteUrl (); url += string.Format ("/ViewLane.aspx?lane_id={0}&host_id={1}&revision_id={2}", lane.id, host.id, revision.id); return new Build { Commit = revision.revision, CommitId = revision.id, Date = revisionWork.endtime ?? revision.date, Lane = lane.lane, Project = parentLane.lane, State = revisionWork.State, Author = revision.author, BuildBot = host.host, Url = url }; }
public override void Notify (DBWork work, DBRevisionWork revision_work) { if (!(work.State == DBState.Failed || work.State == DBState.Issues || work.State == DBState.Timeout)) return; base.Notify (work, revision_work); }
public DBWork GetNextStep (string lane) { DBWork result = null; using (IDbCommand cmd = CreateCommand ()) { cmd.CommandText = "SELECT * FROM steps WHERE lane = @lane AND (state = 0 OR state = 1) ORDER BY revision DESC, sequence LIMIT 1"; DB.CreateParameter (cmd, "lane", lane); using (IDataReader reader = cmd.ExecuteReader ()) { while (reader.Read ()) { if (result != null) throw new Exception ("Got more than one step"); result = new DBWork (); result.Load (reader); } } } return result; }
public ReportBuildStateResponse ReportBuildState (WebServiceLogin login, DBWork work) { ReportBuildStateResponse response = new ReportBuildStateResponse (); using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.BuildBot, true); Logger.Log (2, "ReportBuildState, state: {0}, start time: {1}, end time: {2}", work.State, work.starttime, work.endtime); if (work.starttime > new DateTime (2000, 1, 1) && work.endtime < work.starttime) { // the issue here is that the server interprets the datetime as local time, while it's always as utc. try { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT starttime FROM Work WHERE id = " + work.id; work.starttime = (DateTime) cmd.ExecuteScalar (); } } catch (Exception ex) { Logger.Log ("ReportBuildState: Exception while fixing timezone data: {0}", ex.Message); } } work.Save (db); work.Reload (db); response.Work = work; DBRevisionWork rw = DBRevisionWork_Extensions.Create (db, work.revisionwork_id); bool was_completed = rw.completed; rw.UpdateState (db); if (!was_completed && rw.completed) { rw.endtime = DBRecord.DatabaseNow; rw.Save (db); } response.RevisionWorkCompleted = rw.completed; MonkeyWrench.Web.WebService.Notifications.Notify (work, rw); return response; } }
private static void ProcessNotify (DBWork work, DBRevisionWork revision_work) { log.DebugFormat ("Running notifiers for lane_id: {1}, revision_id: {2}, host_id: {3}, State: {0}", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); try { lock (lock_obj) { List<NotificationBase> notifiers; // We broadcast the notification to the API endpoint WebNotification.BroadcastBuildNotification (work, revision_work); if (!notifications_per_lane.TryGetValue (revision_work.lane_id, out notifiers)) { return; } foreach (var notification in notifiers) { notification.Notify (work, revision_work); } } } catch (Exception ex) { log.ErrorFormat ("Exception while processing notification: {0}", ex); } }
public static void Notify (DBWork work, DBRevisionWork revision_work) { log.DebugFormat ("Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0})", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id); if (notifications == null) return; queued_notifications.Add (new QueuedNotification { IsInfo = false, work = work, revision_work = revision_work }); }
protected bool Evaluate (DBWork work, DBRevisionWork revision_work, out bool nonfatal) { DBState newest_state = work.State; nonfatal = false; if (work.State == DBState.Success) return false; if ((work.State == DBState.Issues || work.State == DBState.Timeout) && Notification.Type == DBNotificationType.FatalFailuresOnly) return false; /* We need to see if there are any successfull builds later than this one */ using (DB db = new DB ()) { using (var cmd = db.CreateCommand ()) { cmd.CommandText += @"SELECT nonfatal FROM Command WHERE id = @command_id;"; DB.CreateParameter (cmd, "command_id", work.command_id); using (IDataReader reader = cmd.ExecuteReader ()) { if (reader.Read ()) nonfatal = reader.GetBoolean (0); } } using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = @" SELECT state FROM RevisionWork INNER JOIN Revision ON RevisionWork.revision_id = Revision.id WHERE RevisionWork.lane_id = @lane_id AND RevisionWork.host_id = @host_id AND RevisionWork.completed AND Revision.date > (SELECT date FROM Revision WHERE id = @revision_id) AND"; if (nonfatal) { cmd.CommandText += " RevisionWork.state = 3 "; } else { cmd.CommandText += " (RevisionWork.state = 3 OR RevisionWork.state = 8) "; } cmd.CommandText += @" ORDER BY Revision.date DESC LIMIT 1; "; DB.CreateParameter (cmd, "lane_id", revision_work.lane_id); DB.CreateParameter (cmd, "host_id", revision_work.host_id); DB.CreateParameter (cmd, "revision_id", revision_work.revision_id); DB.CreateParameter (cmd, "command_id", work.command_id); object obj_state = null; using (IDataReader reader = cmd.ExecuteReader ()) { if (reader.Read ()) obj_state = reader [0]; } if (obj_state != DBNull.Value && obj_state != null) { Logger.Log ("NotificationBase.Evaluate: Later work succeeded, nothing to notify"); return false; } } } switch (Notification.Type) { case DBNotificationType.AllFailures: return work.State == DBState.Issues || work.State == DBState.Failed || work.State == DBState.Timeout; case DBNotificationType.FatalFailuresOnly: if (nonfatal) return false; return work.State == DBState.Failed && newest_state == DBState.Failed; case DBNotificationType.NonFatalFailuresOnly: return (work.State == DBState.Issues || work.State == DBState.Timeout) || nonfatal; default: return false; } }
private static void UpdateBuildLogDB (DB db, DBLane lane, List<DBHost> hosts, List<DBHostLane> hostlanes) { List<DBRevision> revisions; List<DBCommand> commands = null; List<DBLaneDependency> dependencies = null; DBHostLane hostlane; DBWork work; bool got_dependencies = false; bool got_commands = false; try { Logger.Log ("Updating build db log... Got {0} hosts", hosts.Count); foreach (DBHost host in hosts) { hostlane = null; for (int i = 0; i < hostlanes.Count; i++) { if (hostlanes [i].lane_id == lane.id && hostlanes [i].host_id == host.id) { hostlane = hostlanes [i]; break; } } if (hostlane == null) { Logger.Log ("Lane '{0}' is not configured for host '{1}', not adding any work.", lane.lane, host.host); continue; } else if (!hostlane.enabled) { Logger.Log ("Lane '{0}' is disabled for host '{1}', not adding any work.", lane.lane, host.host); continue; } AddRevisionWork (db, lane, host); revisions = db.GetDBRevisionsWithoutWork (lane.id, host.id); Logger.Log ("Updating build db log... Got {0} revisions for host {1}", revisions.Count, host.host); foreach (DBRevision revision in revisions) { bool dependencies_satisfied = true; if (!got_commands) { commands = db.GetCommands (lane.id); got_commands = true; } if (!got_dependencies) { dependencies = DBLaneDependency_Extensions.GetDependencies (db, lane); got_dependencies = true; } if (dependencies != null) { Logger.Log ("Lane '{0}', revision '{1}' checking dependencies...", lane.lane, revision.revision); foreach (DBLaneDependency dependency in dependencies) dependencies_satisfied &= dependency.IsSuccess (db, revision.revision); Logger.Log ("Lane '{0}', revision '{1}' dependency checking resulted in: {2}.", lane.lane, revision.revision, dependencies_satisfied); } int revisionwork_id; bool pending_dependencies; using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT add_revisionwork (@lane_id, @host_id, @revision_id);"; DB.CreateParameter (cmd, "lane_id", lane.id); DB.CreateParameter (cmd, "host_id", host.id); DB.CreateParameter (cmd, "revision_id", revision.id); revisionwork_id = (int) cmd.ExecuteScalar (); } using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT state FROM RevisionWork WHERE id = @id;"; DB.CreateParameter (cmd, "id", revisionwork_id); pending_dependencies = (int) DBState.DependencyNotFulfilled == (int) cmd.ExecuteScalar (); } if (pending_dependencies && !dependencies_satisfied) continue; Logger.Log ("Pending dependencies: {0}", pending_dependencies); foreach (DBCommand command in commands) { work = null; if (pending_dependencies) { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT * FROM Work WHERE revisionwork_id = @revisionwork_id AND command_id = @command_id;"; DB.CreateParameter (cmd, "revisionwork_id", revisionwork_id); DB.CreateParameter (cmd, "command_id", command.id); using (IDataReader reader = cmd.ExecuteReader ()) { if (reader.Read ()) work = new DBWork (reader); } } } if (work == null) { work = new DBWork (); work.command_id = command.id; work.revisionwork_id = revisionwork_id; } work.State = dependencies_satisfied ? DBState.NotDone : DBState.DependencyNotFulfilled; work.Save (db); Logger.Log ("Saved revision {0}, host {2}, command {1}", revision.revision, command.command, host.host); } if (!dependencies_satisfied) { db.ExecuteScalar (string.Format ("UPDATE RevisionWork SET state = 9 WHERE id = {0} AND state = 0;", revisionwork_id)); } else { db.ExecuteScalar (string.Format ("UPDATE RevisionWork SET state = 0 WHERE id = {0} AND state = 9;", revisionwork_id)); } } } } catch (Exception ex) { Logger.Log ("There was an exception while updating build db: {0}", ex.ToString ()); } Logger.Log ("Updating build db log... [Done]"); }
protected abstract void Notify (DBWork work, DBRevisionWork revision_work, List<DBPerson> people, string message);
public ReportBuildStateResponse ReportBuildState (WebServiceLogin login, DBWork work) { ReportBuildStateResponse response = new ReportBuildStateResponse (); using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.BuildBot, true); Logger.Log (2, "ReportBuildState, state: {0}, start time: {1}, end time: {2}", work.State, work.starttime, work.endtime); if (work.starttime > new DateTime (2000, 1, 1) && work.endtime < work.starttime) { // the issue here is that the server interprets the datetime as local time, while it's always as utc. try { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT starttime FROM Work WHERE id = " + work.id; work.starttime = (DateTime) cmd.ExecuteScalar (); } } catch (Exception ex) { Logger.Log ("ReportBuildState: Exception while fixing timezone data: {0}", ex.Message); } } work.Save (db); work.Reload (db); response.Work = work; DBRevisionWork rw = DBRevisionWork_Extensions.Create (db, work.revisionwork_id); bool was_completed = rw.completed; rw.UpdateState (db); if (!was_completed && rw.completed) { rw.endtime = DBRecord.DatabaseNow; rw.Save (db); } response.RevisionWorkCompleted = rw.completed; using (var cmd = db.CreateCommand ()) { cmd.CommandText = "UPDATE Lane SET changed_date = @date WHERE id = @id;"; DB.CreateParameter (cmd, "date", DateTime.UtcNow); DB.CreateParameter (cmd, "id", rw.lane_id); cmd.ExecuteNonQuery (); } Notifications.Notify (work, rw); // Check if any other lane depends on this one if (response.RevisionWorkCompleted) { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT id FROM LaneDependency WHERE dependent_lane_id = @lane_id LIMIT 1;"; DB.CreateParameter (cmd, "lane_id", rw.lane_id); object value = cmd.ExecuteScalar (); if (value != null && value.GetType () == typeof (int)) { // If so, run the scheduler MonkeyWrench.Scheduler.Scheduler.ExecuteSchedulerAsync (false); } } } return response; } }
protected override void Notify (DBWork work, DBRevisionWork revision_work, List<DBPerson> people, string message) { Logger.Log ("IrcNotification.Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0}) enabled: {4}, {5} people", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id, enabled, people.Count); if (!enabled) return; foreach (var person in people) { if (string.IsNullOrEmpty (person.irc_nicknames)) { using (DB db = new DB ()) { List<string> computed_nicks = new List<string> (); List<IEnumerable<string>> email_lists = new List<IEnumerable<string>> (); email_lists.Add (person.GetEmails (db)); if (person.Emails != null) email_lists.Add (person.Emails); foreach (var emails in email_lists) { foreach (var email in emails) { int at = email.IndexOf ('@'); if (at > 0) { computed_nicks.Add (email.Substring (0, at)); } } } if (computed_nicks.Count == 0 && !string.IsNullOrEmpty (person.fullname)) computed_nicks.Add (person.fullname); person.irc_nicknames = string.Join (",", computed_nicks.ToArray ()); } } if (string.IsNullOrEmpty (person.irc_nicknames)) { Logger.Log ("IrcNotification: could not find somebody to notify for revision with id {0} on lane {1}", revision_work.revision_id, revision_work.lane_id); continue; } message = message.Replace ("{red}", "\u00034").Replace ("{bold}", "\u0002").Replace ("{default}", "\u000F"); var messages = new List<string> (); foreach (var nick in person.irc_nicknames.Split (',')) { var msg = nick + ": " + message; if (cache [msg] != null) continue; cache.Add (msg, string.Empty, new DateTimeOffset (DateTime.UtcNow.AddHours (1), TimeSpan.Zero)); messages.Add (msg); } if (messages.Count > 0) SendMessages (messages); } }
protected override void Notify (DBWork work, DBRevisionWork revision_work, List<DBPerson> people, string message) { IrcState state; Logger.Log ("IrcNotification.Notify (lane_id: {1} revision_id: {2} host_id: {3} State: {0}) enabled: {4}", work.State, revision_work.lane_id, revision_work.revision_id, revision_work.host_id, enabled); if (!enabled) return; foreach (var person in people) { if (string.IsNullOrEmpty (person.irc_nicknames)) { using (DB db = new DB ()) { List<string> computed_nicks = new List<string> (); List<IEnumerable<string>> email_lists = new List<IEnumerable<string>> (); email_lists.Add (person.GetEmails (db)); if (person.Emails != null) email_lists.Add (person.Emails); foreach (var emails in email_lists) { foreach (var email in emails) { int at = email.IndexOf ('@'); if (at > 0) { computed_nicks.Add (email.Substring (0, at)); } } } if (computed_nicks.Count == 0 && !string.IsNullOrEmpty (person.fullname)) computed_nicks.Add (person.fullname); person.irc_nicknames = string.Join (",", computed_nicks.ToArray ()); } } if (string.IsNullOrEmpty (person.irc_nicknames)) { Logger.Log ("IrcNotification: could not find somebody to notify for revision with id {0} on lane {1}", revision_work.revision_id, revision_work.lane_id); continue; } message = message.Replace ("{red}", "\u00034").Replace ("{bold}", "\u0002").Replace ("{default}", "\u000F"); if (!identity.join_channels) { state = Connect (); if (!state.WaitForConnected (TimeSpan.FromSeconds (30))) { Logger.Log ("IrcNotification: could not connect to server in 30 seconds."); continue; } } else { state = joined_state; } foreach (var nick in person.irc_nicknames.Split (',')) { foreach (var channel in channels) { state.Client.SendMessage (SendType.Message, channel, nick + ": " + message); } } if (!identity.join_channels) { if (!state.WaitForEmptySendBuffer (TimeSpan.FromSeconds (30))) Logger.Log ("IrcNotification: waited for 30 seconds for messages to be sent, disconnecting now"); Disconnect (state); } } }
public void UploadCompressedFile (WebServiceLogin login, DBWork work, string filename, byte [] contents, bool hidden, string compressed_mime) { using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.BuildBot, true); string tmp = null; try { tmp = Path.GetTempFileName (); File.WriteAllBytes (tmp, contents); work.AddFile (db, tmp, filename, hidden, compressed_mime); } finally { if (!string.IsNullOrEmpty (tmp)) { try { File.Delete (tmp); } catch { // ignore exceptions } } } } }
/** * Notification callback for work updates. */ public override void Notify (DBWork work, DBRevisionWork revision_work) { // Get info RevisionWorkInfo info; using (var db = new DB ()) info = getWorkInfo (db, revision_work.id, work.id); // Create object to send var statusObj = createPayload(revision_work.lane_id, revision_work.host_id, revision_work.revision_id, String.Format("Lane: {0}, Status: {1}, Step: {2}, StepStatus: {3}", info.laneName, revision_work.State, info.command, work.State ), STATE_TO_GITHUB [revision_work.State] ); sendNotification (info.repoURL, info.hash, statusObj); }
public void UploadFile (WebServiceLogin login, DBWork work, string filename, byte [] contents, bool hidden) { UploadCompressedFile (login, work, filename, contents, hidden, null); }
// Don't care about related people and the autogenerated message. protected override void Notify (DBWork work, DBRevisionWork revision_work, List<DBPerson> people, string message) { throw new NotImplementedException (); }
public ReportBuildStateResponse ReportBuildState (WebServiceLogin login, DBWork work) { ReportBuildStateResponse response = new ReportBuildStateResponse (); using (DB db = new DB ()) using (var transaction = db.BeginTransaction ()) { VerifyUserInRole (db, login, Roles.BuildBot, true); log.DebugFormat ("ReportBuildState, state: {0}, start time: {1}, end time: {2}", work.State, work.starttime, work.endtime); if (work.starttime > new DateTime (2000, 1, 1) && work.endtime < work.starttime) { // the issue here is that the server interprets the datetime as local time, while it's always as utc. try { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT starttime FROM Work WHERE id = " + work.id; var value = cmd.ExecuteScalar (); if (value is DateTime) work.starttime = (DateTime) value; } } catch (Exception ex) { log.ErrorFormat ("ReportBuildState: Exception while fixing timezone data: {0}", ex); } } work.Save (db); work.Reload (db); response.Work = work; DBRevisionWork rw = DBRevisionWork_Extensions.Create (db, work.revisionwork_id); bool was_completed = rw.completed; rw.UpdateState (db); if (rw.startedtime == null) { rw.startedtime = work.starttime; rw.Save (db); } if (!was_completed && rw.completed) { rw.endtime = DBRecord.DatabaseNow; rw.Save (db); } Notifications.Notify (work, rw); if (!was_completed && rw.completed) { var notifyInfo = new GenericNotificationInfo (); notifyInfo.laneID = rw.lane_id; notifyInfo.hostID = rw.host_id; notifyInfo.revisionID = rw.revision_id; notifyInfo.message = "Completed"; notifyInfo.state = rw.State; Notifications.NotifyGeneric (notifyInfo); } response.RevisionWorkCompleted = rw.completed; using (var cmd = db.CreateCommand ()) { cmd.CommandText = "UPDATE Lane SET changed_date = @date WHERE id = @id;"; DB.CreateParameter (cmd, "date", DateTime.UtcNow); DB.CreateParameter (cmd, "id", rw.lane_id); cmd.ExecuteNonQuery (); } // Check if any other lane depends on this one if (response.RevisionWorkCompleted) { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT 1 FROM LaneDependency WHERE dependent_lane_id = @lane_id LIMIT 1;"; DB.CreateParameter (cmd, "lane_id", rw.lane_id); object value = cmd.ExecuteScalar (); if (value is int) { // If so, run the scheduler MonkeyWrench.Scheduler.Scheduler.ExecuteSchedulerAsync (false); } } } transaction.Commit (); return response; } }
private bool Evaluate (DBWork work, DBRevisionWork revision_work) { DBState newest_state = work.State; /* We need to see if the latest completed build is still failing */ using (DB db = new DB ()) { using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = @" SELECT state FROM RevisionWork INNER JOIN Revision ON RevisionWork.revision_id = Revision.id WHERE RevisionWork.lane_id = @lane_id AND RevisionWork.host_id = @host_id AND RevisionWork.completed AND Revision.date > (SELECT date FROM Revision WHERE id = @revision_id) ORDER BY Revision.date DESC LIMIT 1 "; DB.CreateParameter (cmd, "lane_id", revision_work.lane_id); DB.CreateParameter (cmd, "host_id", revision_work.host_id); DB.CreateParameter (cmd, "revision_id", revision_work.revision_id); object obj_state = cmd.ExecuteScalar (); if (obj_state is DBState) newest_state = (DBState) obj_state; } } if (newest_state == DBState.Success) return false; switch (Notification.Type) { case DBNotificationType.AllFailures: return work.State == DBState.Issues || work.State == DBState.Failed; case DBNotificationType.FatalFailuresOnly: return work.State == DBState.Failed && newest_state == DBState.Failed; case DBNotificationType.NonFatalFailuresOnly: return work.State == DBState.Issues; default: return false; } }