(→Script Which Can be Used to Trigger All Delayed Builds to Run Immediately)
|
(→AHPSCRIPTS-107)
|
Line 1840: | |||
BuildService.getInstance().runWorkflow(buildRequest); | BuildService.getInstance().runWorkflow(buildRequest); | ||
}</pre> | }</pre> | ||
+ | = Parse Output of a Command and Create Report Containing Errors Found in it = | ||
+ | ==== AHPSCRIPTS-20 ==== | ||
+ | <pre>import com.urbancode.anthill3.domain.singleton.serversettings.*; | ||
+ | import com.urbancode.anthill3.domain.workflow.WorkflowCase ; | ||
+ | import com.urbancode.vcsdriver3.*; | ||
+ | import com.urbancode.anthill3.domain.buildlife.*; | ||
+ | import com.urbancode.anthill3.domain.jobtrace.*; | ||
+ | import com.urbancode.anthill3.domain.jobtrace.buildlife.*; | ||
+ | import com.urbancode.anthill3.runtime.paths.*; | ||
+ | import com.urbancode.anthill3.services.jobs.*; | ||
+ | import com.urbancode.devilfish.services.var.VarService; | ||
+ | import java.io.*; | ||
+ | import java.util.*; | ||
+ | private org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger("ContextScript"); | ||
+ | // SETTINGS | ||
+ | // FOUND_TOKEN: indication of build failure | ||
+ | // BUILD_STEP_NAME: Name of the step within the job that should be inspected | ||
+ | // COMMAND_NAME: Command within the build step that should have its logged inspected | ||
+ | // REPORT_NAME: Name of the report to publish. | ||
+ | // LINES_BEFORE: Lines before and including the 'Found Token' to include in the log. | ||
+ | // LINES_AFTER: Lines after the 'Found Token' to include in the log. | ||
+ | String FOUND_TOKEN = "error"; | ||
+ | String BUILD_STEP_NAME = "Echo"; | ||
+ | String COMMAND_NAME = "shell-command"; | ||
+ | String REPORT_NAME = "Error Report"; | ||
+ | int LINES_BEFORE = 6; | ||
+ | int LINES_AFTER = 1; | ||
+ | //------------------------------------------------------- | ||
+ | class LogSection { | ||
+ | int lineNumber = 0; | ||
+ | String text = null; | ||
+ | LogSection(int lineNumber, String text) { | ||
+ | this.lineNumber = lineNumber; | ||
+ | this.text = text; | ||
+ | } | ||
+ | } | ||
+ | //------------------------------------------------------- | ||
+ | LogSection[] getLogSectionsForStep(StepTrace step) { | ||
+ | CommandTrace[] cmdTraceArray = step.getCommandTraceArray(); | ||
+ | CommandTrace antCmdTrace = null; | ||
+ | for (int i = 0; i < cmdTraceArray.length; i++) { | ||
+ | if (cmdTraceArray[i].getName().equalsIgnoreCase(COMMAND_NAME)) { | ||
+ | cmdTrace = cmdTraceArray[i]; | ||
+ | log.warn("Found the command we want: " + cmdTraceArray[i].getName()); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | if (cmdTrace == null) { | ||
+ | throw new Exception("Expected to find" + COMMAND_NAME + "command in " + BUILD_STEP_NAME + " step"); | ||
+ | } | ||
+ | String commandOutput = LogHelper.getOutput(cmdTrace); | ||
+ | List resultList = new LinkedList(); | ||
+ | String[] logCache = new String[LINES_BEFORE]; | ||
+ | if (commandOutput != null) { | ||
+ | StringTokenizer logfile = new StringTokenizer(commandOutput,"\n\r\f"); | ||
+ | int index = 0; | ||
+ | while (logfile.hasMoreTokens()) { | ||
+ | String line = logfile.nextToken(); | ||
+ | logCache[index % LINES_BEFORE] = line; | ||
+ | if (line.startsWith(FOUND_TOKEN)) { | ||
+ | int lineNumber = index + 1; | ||
+ | StringBuffer result = new StringBuffer(); | ||
+ | // put the cached lines into the log. | ||
+ | int startIndex = (index > LINES_BEFORE) ? index - LINES_BEFORE + 1 : 0; | ||
+ | for (int i = startIndex; i <= index; i++) { | ||
+ | if (i == index) { | ||
+ | result.append("<b>"); | ||
+ | } | ||
+ | result.append(i + 1).append(": ").append(logCache[i % LINES_BEFORE]).append("\n"); | ||
+ | if (i == index) { | ||
+ | result.append("</b>"); | ||
+ | } | ||
+ | } | ||
+ | // get lines after if applicable | ||
+ | for (int i = 0; i < LINES_AFTER && logfile.hasMoreTokens(); i++) { | ||
+ | String next = logfile.nextToken(); | ||
+ | index++; | ||
+ | result.append(index + 1).append(": ").append(next).append("\n"); | ||
+ | } | ||
+ | LogSection marker = new LogSection(lineNumber, result.toString()); | ||
+ | resultList.add(marker); | ||
+ | } | ||
+ | index++; | ||
+ | } | ||
+ | } | ||
+ | return (LogSection[]) resultList.toArray(new LogSection[resultList.size()]); | ||
+ | } | ||
+ | //------------------------------------------------------- | ||
+ | LogSection[] logSections = null; | ||
+ | BuildLifeJobTrace jobTrace = JobTraceLookup.getCurrent(); | ||
+ | StepTrace[] stepTraceArray = jobTrace.getStepTraceArray(); | ||
+ | StepTrace stepTrace = null; | ||
+ | for (int j = 0; j < stepTraceArray.length && stepTrace == null; j++) { | ||
+ | if (stepTraceArray[j].getName().equalsIgnoreCase(BUILD_STEP_NAME)) { | ||
+ | stepTrace = stepTraceArray[j]; | ||
+ | logSections = getLogSectionsForStep(stepTrace); | ||
+ | } | ||
+ | } | ||
+ | String reportPath = PublishPathHelper.getInstance().getPublishPath(JobTraceLookup.getCurrent(), REPORT_NAME); | ||
+ | VarService vs = VarService.getInstance(); | ||
+ | reportPath = vs.resolve(reportPath); | ||
+ | File reportDir = new File(reportPath); | ||
+ | reportDir.mkdirs(); | ||
+ | File reportFile = new File(reportDir, "Error_Report.html"); | ||
+ | FileWriter writer = new FileWriter(reportFile); | ||
+ | writer.write("<html><head><style>"); | ||
+ | writer.write(".errors {"); | ||
+ | writer.write(" border: 1px solid #f04040;"); | ||
+ | writer.write(" background-color: #ffa0a0;"); | ||
+ | writer.write(" font-family: arial, helvetica, sans-serif;"); | ||
+ | writer.write(" font-size: 11px;"); | ||
+ | writer.write(" color: #000000;"); | ||
+ | writer.write("}"); | ||
+ | writer.write(".errors_header {"); | ||
+ | writer.write(" border-bottom: 1px solid #f04040;"); | ||
+ | writer.write(" background-color: #f04040;"); | ||
+ | writer.write(" font-size: 12px;"); | ||
+ | writer.write(" font-weight: bold;"); | ||
+ | writer.write(" color: #FFFFFF;"); | ||
+ | writer.write(" padding: 4px;"); | ||
+ | writer.write("}"); | ||
+ | writer.write(".errors_body {"); | ||
+ | writer.write(" margin-right: 10px;"); | ||
+ | writer.write(" padding-top: 4px;"); | ||
+ | writer.write(" padding-left: 4px;"); | ||
+ | writer.write(" padding-bottom: 4px;"); | ||
+ | writer.write("}"); | ||
+ | writer.write(".errors_section {"); | ||
+ | writer.write(" margin-left: 15px;"); | ||
+ | writer.write(" padding-top: 4px;"); | ||
+ | writer.write(" padding-left: 4px;"); | ||
+ | writer.write(" padding-bottom: 4px;"); | ||
+ | writer.write("}"); | ||
+ | writer.write(".errors_output {"); | ||
+ | writer.write(" margin-top: 4px;"); | ||
+ | writer.write(" margin-left: 15px;"); | ||
+ | writer.write(" background-color: #FFFFFF;"); | ||
+ | writer.write(" padding-top: 4px;"); | ||
+ | writer.write(" padding-left: 4px;"); | ||
+ | writer.write(" padding-bottom: 4px;"); | ||
+ | writer.write("}"); | ||
+ | writer.write("</style></head><body>"); | ||
+ | writer.write("<div class=\"errors\">"); | ||
+ | writer.write("<div class=\"errors_header\">Errors:</div>"); | ||
+ | writer.write("<div class=\"errors_body\">"); | ||
+ | writer.write("<div class=\"errors_section\">"); | ||
+ | writer.write("<b>Step " + (stepTrace.getSeq() + 1) + ": " + stepTrace.getName() + " Failed</b>"); | ||
+ | for (int i=0; i<logSections.length; i++) { | ||
+ | writer.write("<pre class=\"errors_output\">"); | ||
+ | writer.write(logSections[i].text); | ||
+ | writer.write("</pre>"); | ||
+ | } | ||
+ | writer.write("</div>"); | ||
+ | writer.write("</div>"); | ||
+ | writer.write("</div>"); | ||
+ | writer.write("</body></html>"); | ||
+ | writer.close();</pre> |