private static int Main2 (string [] arguments) { Lock process_lock; ReportBuildBotStatusResponse status_response; BuildBotStatus status; try { if (!Configuration.LoadConfiguration (arguments)) return 1; if (!Configuration.VerifyBuildBotConfiguration ()) return 1; process_lock = Lock.Create ("MonkeyWrench.Builder"); if (process_lock == null) { Logger.Log ("Builder could not acquire lock. Exiting"); return 1; } Logger.Log ("Builder lock aquired successfully."); } catch (Exception ex) { Logger.Log ("Could not aquire lock: {0}", ex.Message); return 1; } try { WebService = WebServices.Create (); WebService.CreateLogin (Configuration.Host, Configuration.WebServicePassword); status = new BuildBotStatus (); status.Host = Configuration.Host; status.FillInAssemblyAttributes (); status_response = WebService.ReportBuildBotStatus (WebService.WebServiceLogin, status); if (status_response.Exception != null) { Logger.Log ("Failed to report status: {0}", status_response.Exception.Message); return 1; } if (!string.IsNullOrEmpty (status_response.ConfiguredVersion) && status_response.ConfiguredVersion != status.AssemblyVersion) { if (!Update (status, status_response)) { Console.Error.WriteLine ("Automatic update to: {0} / {1} failed (see log for details). Please update manually.", status_response.ConfiguredVersion, status_response.ConfiguredRevision); return 2; /* Magic return code that means "automatic update failed" */ } else { Console.WriteLine ("The builder has been updated. Please run 'make build' again."); return 1; } } response = WebService.GetBuildInfoMultiple (WebService.WebServiceLogin, Configuration.Host, true); if (!response.Host.enabled) { Logger.Log ("This host is disabled. Exiting."); return 0; } Logger.Log ("Builder will now build {0} lists of work items.", response.Work.Count); for (int i = 0; i < response.Work.Count; i++) { //foreach (var item in response.Work) Logger.Log ("Building list #{0}/{1}", i+ 1, response.Work.Count); Build (response.Work [i]);//item); } Logger.Log ("Builder finished successfully."); return 0; } catch (Exception ex) { Logger.Log ("An exception occurred: {0}", ex.ToString ()); return 1; } finally { process_lock.Unlock (); } }
public ReportBuildBotStatusResponse ReportBuildBotStatus (WebServiceLogin login, BuildBotStatus status) { ReportBuildBotStatusResponse response = new ReportBuildBotStatusResponse (); using (DB db = new DB ()) { VerifyUserInRole (db, login, Roles.BuildBot, true); log.DebugFormat ("BuildBot '{2}' reported in. v{0}: {1}", status.AssemblyVersion, status.AssemblyDescription, status.Host); using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = @" DELETE FROM BuildBotStatus WHERE host_id = (SELECT id FROM Host WHERE host = @host); INSERT INTO BuildBotStatus (host_id, version, description) VALUES ((SELECT id FROM Host WHERE host = @host), @version, @description); "; DB.CreateParameter (cmd, "host", status.Host); DB.CreateParameter (cmd, "version", status.AssemblyVersion); DB.CreateParameter (cmd, "description", status.AssemblyDescription); cmd.ExecuteNonQuery (); } using (IDbCommand cmd = db.CreateCommand ()) { cmd.CommandText = "SELECT * FROM Release INNER JOIN Host ON Host.release_id = Release.id WHERE Host.host = @host;"; DB.CreateParameter (cmd, "host", status.Host); using (IDataReader reader = cmd.ExecuteReader ()) { if (reader.Read ()) { DBRelease release = new DBRelease (reader); response.ConfiguredVersion = release.version; response.ConfiguredRevision = release.revision; } } } } return response; }
private static bool Update (BuildBotStatus status, ReportBuildBotStatusResponse status_response) { StringBuilder output = new StringBuilder (); Logger.Log ("This host is at version {0}, while it should be running version {1} ({2}). Will try to update.", status.AssemblyVersion, status_response.ConfiguredVersion, status_response.ConfiguredRevision); try { /* Check with git status if working copy is clean */ using (Process git = new Process ()) { git.StartInfo.FileName = "git"; git.StartInfo.Arguments = "status -s"; git.StartInfo.UseShellExecute = false; git.StartInfo.RedirectStandardError = true; git.StartInfo.RedirectStandardOutput = true; git.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e) { lock (output) { output.AppendLine (e.Data); } }; git.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e) { lock (output) { output.AppendLine (e.Data); } }; git.Start (); git.BeginErrorReadLine (); git.BeginOutputReadLine (); if (!git.WaitForExit ((int) TimeSpan.FromMinutes (1).TotalMilliseconds)) { Logger.Log ("Builder.Update (): Could not get git status, git didn't get any status in 1 minute."); return false; } if (git.ExitCode != 0) { Logger.Log ("Builder.Update (): git status failed: {0}", output.ToString ()); return false; } string stdout = output.ToString ().Trim (); if (string.IsNullOrEmpty (stdout)) { /* OK */ } else if (stdout.Contains ("nothing to commit (working directory clean)")) { /* OK - git 1.6 doesn't seem to understand the -s flag */ } else { Logger.Log ("Builder.Update (): git status shows that there are local changes: \n{0}", output); return false; } } /* git status shows we're clean, now run git fetch */ output.Length = 0; using (Process git = new Process ()) { git.StartInfo.FileName = "git"; git.StartInfo.Arguments = "fetch"; git.StartInfo.UseShellExecute = false; git.StartInfo.RedirectStandardError = true; git.StartInfo.RedirectStandardOutput = true; git.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e) { lock (output) { output.AppendLine (e.Data); } }; git.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e) { lock (output) { output.AppendLine (e.Data); } }; git.Start (); git.BeginErrorReadLine (); git.BeginOutputReadLine (); if (!git.WaitForExit ((int) TimeSpan.FromMinutes (1).TotalMilliseconds)) { Logger.Log ("Builder.Update (): git fetch didn't finish in 1 minute"); return false; } if (git.ExitCode != 0) { Logger.Log ("Builder.Update (): git status failed: {0}", output.ToString ()); return false; } } /* git fetch done, checkout the revision we want */ output.Length = 0; using (Process git = new Process ()) { git.StartInfo.FileName = "git"; git.StartInfo.Arguments = "reset --hard " + status_response.ConfiguredRevision; git.StartInfo.UseShellExecute = false; git.StartInfo.RedirectStandardError = true; git.StartInfo.RedirectStandardOutput = true; git.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e) { lock (output) { output.AppendLine (e.Data); } }; git.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e) { lock (output) { output.AppendLine (e.Data); } }; git.Start (); git.BeginErrorReadLine (); git.BeginOutputReadLine (); if (!git.WaitForExit ((int) TimeSpan.FromMinutes (1).TotalMilliseconds)) { Logger.Log ("Builder.Update (): Could not checkout the required revision in 1 minute."); return false; } if (git.ExitCode != 0) { Logger.Log ("Builder.Update (): git reset failed: {0}", output.ToString ()); return false; } } Logger.Log ("Successfully updated to {0} {1})", status_response.ConfiguredVersion, status_response.ConfiguredRevision); } catch (Exception ex) { Logger.Log ("Builder.Update (): exception caught: {0}", ex.Message); return false; } return true; }