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.completed ? revisionWork.endtime : revision.date, Lane = lane.lane, Project = parentLane.lane, State = revisionWork.State, Author = revision.author, BuildBot = host.host, Url = url }); }
private void DownloadRevisionLog(int revision_id, bool diff /* diff or log */) { DBRevision revision; DBLane lane; using (DB db = new DB()) { WebServiceLogin login = Authentication.CreateLogin(Request); revision = DBRevision_Extensions.Create(db, revision_id); // no access restricion on revision logs/diffs Authentication.VerifyAnonymousAccess(Context, db, login); Response.ContentType = MimeTypes.TXT; if (revision == null) { Response.Write("Revision not found."); } else { lane = DBLane_Extensions.Create(db, revision.lane_id); using (Process git = new Process()) { git.StartInfo.RedirectStandardOutput = true; git.StartInfo.RedirectStandardError = true; git.StartInfo.UseShellExecute = false; git.StartInfo.FileName = "git"; if (diff) { git.StartInfo.Arguments = "diff --no-color --no-prefix " + revision.revision + "~ " + revision.revision; } else { git.StartInfo.Arguments = "log -1 --no-color --no-prefix " + revision.revision; } git.StartInfo.WorkingDirectory = Configuration.GetSchedulerRepositoryCacheDirectory(lane.repository); git.OutputDataReceived += (object sender, DataReceivedEventArgs ea) => { Response.Write(ea.Data); Response.Write('\n'); }; git.ErrorDataReceived += (object sender, DataReceivedEventArgs ea) => { Response.Write(ea.Data); Response.Write('\n'); }; // Logger.Log ("Executing: '{0} {1}' in {2}", git.StartInfo.FileName, git.StartInfo.Arguments, git.StartInfo.WorkingDirectory); git.Start(); git.BeginErrorReadLine(); git.BeginOutputReadLine(); if (!git.WaitForExit(1000 * 60 * 5 /* 5 minutes */)) { git.Kill(); Response.Write("Error: git diff didn't finish in 5 minutes, aborting.\n"); } } } } }
static DBLane GetTopMostParent(DBLane forLane, DB db) { var parent = forLane; while (parent.parent_lane_id != null) { parent = DBLane_Extensions.Create(db, parent.parent_lane_id.Value); } return(parent); }
public virtual void Notify(DBWork work, DBRevisionWork revision_work) { List <DBPerson> people = new List <DBPerson> (); DBRevision revision; DBLane lane; DBHost host; string message; bool nonfatal; log.DebugFormat("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)) { log.DebugFormat("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()) { log.DebugFormat("Notify no emails"); return; } if (this.emails.Any(x => !x.EndsWith("@hipchat.xamarin.com", StringComparison.OrdinalIgnoreCase))) { log.Warn("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()) { log.Debug("Notify no actionable emails!"); return; } log.DebugFormat("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)) { log.DebugFormat("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)) { log.DebugFormat("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); log.DebugFormat("response from server: {0}", resString); } }
public DBLane CloneLane(int lane_id, string new_name, bool copy_files) { DBLane result = null; DBLane master = DBLane_Extensions.Create(this, lane_id); if (this.LookupLane(new_name, false) != null) { throw new Exception(string.Format("The lane '{0}' already exists.", new_name)); } try { using (IDbTransaction transaction = BeginTransaction()) { result = new DBLane(); result.lane = new_name; result.max_revision = master.max_revision; result.min_revision = master.min_revision; result.repository = master.repository; result.source_control = master.source_control; result.parent_lane_id = master.parent_lane_id; result.additional_roles = master.additional_roles; result.enabled = master.enabled; result.Save(this); foreach (DBLanefile filemaster in master.GetFiles(this, null)) { int fid; if (copy_files) { DBLanefile clone = new DBLanefile(); clone.contents = filemaster.contents; clone.mime = filemaster.mime; clone.name = filemaster.name; clone.additional_roles = filemaster.additional_roles; clone.Save(this); fid = clone.id; } else { fid = filemaster.id; } DBLanefiles lane_files = new DBLanefiles(); lane_files.lane_id = result.id; lane_files.lanefile_id = fid; lane_files.Save(this); } foreach (DBCommand cmdmaster in GetCommands(master.id)) { DBCommand clone = new DBCommand(); clone.lane_id = result.id; clone.alwaysexecute = cmdmaster.alwaysexecute; clone.arguments = cmdmaster.arguments; clone.command = cmdmaster.command; clone.filename = cmdmaster.filename; clone.nonfatal = cmdmaster.nonfatal; clone.sequence = cmdmaster.sequence; clone.timeout = cmdmaster.timeout; clone.working_directory = cmdmaster.working_directory; clone.upload_files = cmdmaster.upload_files; clone.Save(this); } foreach (DBHostLaneView hostlanemaster in master.GetHosts(this)) { DBHostLane clone = new DBHostLane(); clone.enabled = false; clone.lane_id = result.id; clone.host_id = hostlanemaster.host_id; clone.Save(this); } foreach (DBEnvironmentVariable env in master.GetEnvironmentVariables(this)) { DBEnvironmentVariable clone = new DBEnvironmentVariable(); clone.host_id = env.host_id; clone.lane_id = result.id; clone.name = env.name; clone.value = env.value; clone.Save(this); } foreach (DBLaneNotification notification in master.GetNotifications(this)) { DBLaneNotification clone = new DBLaneNotification(); clone.lane_id = result.id; clone.notification_id = notification.notification_id; clone.Save(this); } foreach (var tag in master.GetTags(this)) { var clone = new DBLaneTag(); clone.lane_id = result.id; clone.tag = tag.tag; clone.Save(this); } transaction.Commit(); } } catch { result = null; throw; } return(result); }
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}*"", ""link_names"": ""{5}"", ""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", nonfatal ? "0" : "1" ); 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); } } } }