|
(→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> | ||