// Inserts various fields from the current running job into the history table static public bool insertHistory(BuildQueueItem jobInfo, string comments, string results, string date) { try { // Need to replace ' with '' for SQL insert comments = comments.Replace("'", "`"); results = results.Replace("'", "`"); int maxInsertSize = Globals.Config.getInt(Globals.Config.cMaxInsertSize); if (comments.Length > maxInsertSize) { comments = comments.Substring(0, maxInsertSize); } if (results.Length > maxInsertSize) { results = results.Substring(0, maxInsertSize); } string query = "INSERT INTO " + Globals.Config.getString(Globals.Config.cDBHistoryTableName) + " (buildnum, builduser, buildstart, buildend, results, comments, buildconfig) VALUES ('" + jobInfo.buildnum + "', '" + jobInfo.builduser + "', '" + jobInfo.timestart + "', '" + date + "', '" + results + "', '" + comments + "', '" + jobInfo.buildconfig + "')"; exSQL(query, true); return(true); } catch { } return(false); }
static public bool getJobFromQueue(int jobNumber, ref BuildQueueItem jobInfo) { string query = "SELECT * FROM " + Globals.Config.getString(Globals.Config.cDBQueueTableName) + " WHERE queuenum = " + jobNumber; try { SqlDataReader rs = exSQL(query, false); if (rs.Read() == true) { if (isDBNULL("queuenum", rs) == false) { jobInfo.queuenum = (int)rs["queuenum"]; } if (isDBNULL("buildnum", rs) == false) { jobInfo.buildnum = ((string)(rs["buildnum"])).Trim(); } if (isDBNULL("builduser", rs) == false) { jobInfo.builduser = ((string)(rs["builduser"])).Trim(); } if (isDBNULL("timestart", rs) == false) { jobInfo.timestart = ((string)(rs["timestart"])).Trim(); } if (isDBNULL("buildconfig", rs) == false) { jobInfo.buildconfig = (int)rs["buildconfig"]; } if (isDBNULL("buildparams", rs) == false) { jobInfo.buildparams = ((string)(rs["buildparams"])).Trim(); } if (isDBNULL("comment", rs) == false) { jobInfo.comment = ((string)(rs["comment"])).Trim(); } rs.Close(); mDBConnection.Close(); return(true); } else { rs.Close(); mDBConnection.Close(); return(false); } } catch { } return(false); }
private void runJob() { BuildQueueItem currentJobInfo = new BuildQueueItem(); string results = "No errors."; bool bUserHasQuit = false; bool bSuccess = false; logServer_Async("---------------------------"); logServer_Async("Begin runJob #" + mCurrentJobNum); //-- Get job info // bSuccess = Database.getJobFromQueue(mCurrentJobNum, ref currentJobInfo); if (bSuccess) { //-- Get build type for current config BuildTypeItem builtTypeInfo = new BuildTypeItem(); bSuccess = Database.getBuildTypeFromTypes(currentJobInfo.buildconfig, ref builtTypeInfo); if (bSuccess) { Job job = null; switch (builtTypeInfo.type) { case "RunBatchBuild": job = new JobRunBatchBuild(builtTypeInfo.extra); break; default: break; } if (job != null) { // init job job.init(builtTypeInfo.name); logServer_Async("Launching job..."); logServer_Async(String.Format("[started by: {0}, job type: {1}]", currentJobInfo.builduser, builtTypeInfo.name)); // run the job QUITCODE quitCode = job.run(); logServer_Async("Job returned (exitcode: " + quitCode.ToString() + ")"); bUserHasQuit = (quitCode == QUITCODE.USERQUIT); string userName = currentJobInfo.builduser; string fullBuildNumber = getBuildNumber(/*getBuildVersion(false)*/ currentJobInfo.queuenum.ToString(), currentJobInfo.buildconfig); switch (quitCode) { case QUITCODE.NONE: { //-- prop logs to share logServer_Async("Copying logs..."); string logsSrc = Globals.Config.getString(Globals.Config.cLogRoot); string logsDest = Globals.Config.getString(Globals.Config.cLogDest) + fullBuildNumber; bSuccess = propLogs(logsSrc, logsDest); if (!bSuccess) { string errorMsg = "FAILURE: Unable to copy logs"; logServer_Async(errorMsg); results = errorMsg; break; } string buildCount = null; string changeListNumber = null; string emailSubjectLine = null; //-- this is a hack here. //-- For archive builds retreive the build number number from the file work\tools\databuild\buildcount.txt and // the changelist number from work\tools\databuild\changeListSubmission.txt if ((currentJobInfo.buildconfig == 0) || (currentJobInfo.buildconfig == 18) || (currentJobInfo.buildconfig == 27) || (currentJobInfo.buildconfig == 28)) { string archiveBuildPath = Path.GetDirectoryName(builtTypeInfo.extra); if (File.Exists(archiveBuildPath + "\\buildcount.txt") == true) { StreamReader rdr = File.OpenText(archiveBuildPath + "\\buildcount.txt"); buildCount = rdr.ReadToEnd(); buildCount = buildCount.Trim(); rdr.Close(); } if (File.Exists(archiveBuildPath + "\\changeListSubmission.txt") == true) { StreamReader rdr = File.OpenText(archiveBuildPath + "\\changeListSubmission.txt"); Regex changeList1EX = new Regex(@"^Submitting change (?<changelistnumber>\d*)\.$", RegexOptions.Singleline); String line; while ((line = rdr.ReadLine()) != null) { MatchCollection matches = changeList1EX.Matches(line); foreach (Match m in matches) { if (m.Success == true) { changeListNumber = m.Groups["changelistnumber"].Value; break; } } } rdr.Close(); } } //-- send email logServer_Async("Sending email..."); bSuccess = buildSuccessMail(currentJobInfo.comment, logsDest); if (!bSuccess) { string errorMsg = "FAILURE: Unable to create build success mail"; logServer_Async(errorMsg); results = errorMsg; break; } if (String.IsNullOrEmpty(buildCount)) { emailSubjectLine = mMailPrependString + "New " + builtTypeInfo.name; } else { if (String.IsNullOrEmpty(changeListNumber)) { emailSubjectLine = mMailPrependString + "New " + builtTypeInfo.name + " (#" + buildCount + ")"; } else { emailSubjectLine = mMailPrependString + "New " + builtTypeInfo.name + " (#" + buildCount + ")" + " (#" + changeListNumber + ")"; } } bSuccess = sendMail(Globals.Config.getString(Globals.Config.cBuildAlias), Globals.Config.getString(Globals.Config.cMailTemplateReport), emailSubjectLine, userName); if (!bSuccess) { string errorMsg = "FAILURE: Unable to send build success mail"; logServer_Async(errorMsg); results = errorMsg; } } break; case QUITCODE.USERQUIT: // TODO: send build user a msg that their build got canned. break; case QUITCODE.ERROR: { //-- prop logs to share logServer_Async("Copying logs..."); string logsSrc = Globals.Config.getString(Globals.Config.cLogRoot); string logsDest = Globals.Config.getString(Globals.Config.cLogDest) + fullBuildNumber; bSuccess = propLogs(logsSrc, logsDest); if (!bSuccess) { string errorMsg = "FAILURE: Unable to copy logs"; logServer_Async(errorMsg); results = errorMsg; break; } //-- send email logServer_Async("Sending email..."); // Get errors StreamReader rdr = File.OpenText(job.LogFileName); results = rdr.ReadToEnd(); rdr.Close(); // Only use last 20 lines results = cropToLastNumLines(20, results); bSuccess = buildErrorMail(currentJobInfo.comment, logsDest, results); if (!bSuccess) { string errorMsg = "FAILURE: Unable to create build failure mail"; logServer_Async(errorMsg); results = errorMsg; break; } bSuccess = sendMail(Globals.Config.getString(Globals.Config.cFailedBuildAlias), Globals.Config.getString(Globals.Config.cMailTemplateReport), mMailPrependString + "FAILED: " + builtTypeInfo.name + ", from: " + userName, userName); if (!bSuccess) { string errorMsg = "FAILURE: Unable to send build failure mail"; logServer_Async(errorMsg); results = errorMsg; } } break; } job.End(); } else { string errorMsg = "FAILURE: Build type \"" + builtTypeInfo.type + "\" is not recognized by the build system"; logServer_Async(errorMsg); results = errorMsg; } } else { string errorMsg = "FAILURE: Invalid build configuration id (buildconfig = " + currentJobInfo.buildconfig + ") not in " + Globals.Config.getString(Globals.Config.cDBBuildTypes) + " table"; logServer_Async(errorMsg); results = errorMsg; } } else { string errorMsg = "FAILURE: Invalid job number (queuenum = " + mCurrentJobNum + ") not in " + Globals.Config.getString(Globals.Config.cDBQueueTableName) + " table"; logServer_Async(errorMsg); results = errorMsg; } //-- Enter the history if the user didn't quit. if (!bUserHasQuit) { try// DBHistory contains everything we will insert into the history field { string vVersion = /*job.getBuildVersion(false) + */ "\\"; string newPath = Globals.Config.getString(Globals.Config.cLogDest) + vVersion; if (File.Exists(newPath + Globals.Config.getString(Globals.Config.cHistoryPlaytest)) == true) { StreamReader rdr = File.OpenText(newPath + Globals.Config.getString(Globals.Config.cHistoryPlaytest)); results = rdr.ReadToEnd() + "\r\n"; } if (File.Exists(newPath + Globals.Config.getString(Globals.Config.cHistoryDebug)) == true) { StreamReader rdr = File.OpenText(newPath + Globals.Config.getString(Globals.Config.cHistoryDebug)); results = results + rdr.ReadToEnd() + "\r\n"; } if (File.Exists(newPath + Globals.Config.getString(Globals.Config.cHistoryFinal)) == true) { StreamReader rdr = File.OpenText(newPath + Globals.Config.getString(Globals.Config.cHistoryFinal)); results = results + rdr.ReadToEnd() + "\r\n"; } } catch (Exception exp) { logServer_Async("ERROR: Failed calling OpenText:" + exp.Message); } //-- Adding to history entry logServer_Async("Adding entry to history table..."); string date = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString(); try // InsertHistory can fail for a bunch of reasons, so we catch and insert some default comments { currentJobInfo.buildnum = currentJobInfo.queuenum.ToString(); Database.insertHistory(currentJobInfo, currentJobInfo.comment, results, date); } catch (Exception exp) { logServer_Async("ERROR: Failed to call insertHistory, possibly too long of a string, will insert default comments:" + exp.Message); try { Database.insertHistory(currentJobInfo, "Failed to add comments", null, date); } catch (Exception exp1) { logServer_Async("ERROR: Failed to call InsertHistory a second time, comments will be null:" + exp1.Message); } } } try // Remove job from queue { // Remove job from build queue table Database.removeJobFromQueue(mCurrentJobNum); } catch (Exception exp1) { logServer_Async("ERROR: Failed to call to remove job from the BuildQueue table" + exp1.Message); } logServer_Async("End job"); logServer_Async("---------------------------"); mCurrentJobNum = -1; }