Output the console text of a Jenkins job that my Job is running

我的未来我决定 提交于 2019-11-30 21:37:28

Interesting question. I can't comprehend the downvote.

  • The first of your links describes how you should be able to do it: via "repeated GET requests".
  • The second is about setting the result of an upstream job according to the content of a downstream job's console output. This can be achieved easier by something else but parsing the console output.
  • The third is about the opposite direction: passing output from an upstream job to a downstream job.

I'm going to try the first and will update this answer accordingly then.

UPDATE 1

The following updates the upstream's log once the downstream build has finished.

// From: Output the console text of a Jenkins job that my Job is running
//       http://stackoverflow.com/a/31573477/1744774
final String JENKINS_HOST = 'http://<your Jenkins host>'
final String DOWNSTREAM_NAME = '<your downstream job's name>'

final String SEPARATOR = new String(new char[8]).replace('\0', '-')
final int DOWNSTREAM_BUILD_NO = build(DOWNSTREAM_NAME).getBuild().getNumber()

println("${SEPARATOR} Begin console HTML output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")
printConsoleOutputHtmlFrom(
    "${JENKINS_HOST}/job/${DOWNSTREAM_NAME}/${DOWNSTREAM_BUILD_NO}/console")

println("${SEPARATOR} Begin console text output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")
printConsoleOutputTextFrom(
    "${JENKINS_HOST}/job/${DOWNSTREAM_NAME}/${DOWNSTREAM_BUILD_NO}/consoleText")

println("${SEPARATOR} End console output of ${DOWNSTREAM_NAME} ${SEPARATOR}")

import org.xml.sax.InputSource

void printConsoleOutputHtmlFrom(String consoleUrl)
  {
  println(xPathExpression('//pre[contains(@class, "console-output")]')
              .evaluate(new InputSource(responseFrom(consoleUrl))))
  }

import java.nio.charset.StandardCharsets

void printConsoleOutputTextFrom(String consoleTextUrl)
  {
  BufferedReader log = new BufferedReader(
      new InputStreamReader(responseFrom(consoleTextUrl), StandardCharsets.UTF_8.name()));
  while ((line = log.readLine()) != null)
    {
    println(line)
    }
  }

InputStream responseFrom(String url)
  {
  // See Using java.net.URLConnection to fire and handle HTTP requests 
  //     http://stackoverflow.com/a/2793153/1744774
  URLConnection connection = new URL(url).openConnection();
  connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
  return connection.getInputStream();  
  }

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

XPathExpression xPathExpression(String expression)
  {
  // See How to read XML using XPath in Java
  //     http://stackoverflow.com/a/2811101/1744774
  XPathFactory xPathFactory = XPathFactory.newInstance();
  XPath xPath = xPathFactory.newXPath();
  return xPath.compile(expression);
  }

References:

UPDATE 2

The following updates the upstream's log on the fly.

// From: Output the console text of a Jenkins job that my Job is running
//       http://stackoverflow.com/a/31573477/1744774
final String JENKINS_HOST = 'http://<your Jenkins host>'
final String DOWNSTREAM_NAME = '<your downstream job's name>'

final String SEPARATOR = new String(new char[8]).replace('\0', '-')

import java.util.concurrent.TimeUnit

parallel(
  { build(DOWNSTREAM_NAME) },
  {
  final String THIS_BUILD_NAME = build.getProject().getName()
  final int THIS_BUILD_NO = build.getNumber()
  final int DOWNSTREAM_BUILD_NO = downstreamBuildNoFrom(
      "${JENKINS_HOST}/job/${THIS_BUILD_NAME}/${THIS_BUILD_NO}/consoleText") 

  println("${SEPARATOR} Begin console output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")

  printConsoleOutputTextChunksFrom(
      "${JENKINS_HOST}/job/${DOWNSTREAM_NAME}/${DOWNSTREAM_BUILD_NO}/consoleText", 3L, TimeUnit.SECONDS)

  println("${SEPARATOR} End console output of ${DOWNSTREAM_NAME} #${DOWNSTREAM_BUILD_NO} ${SEPARATOR}")
  })

int downstreamBuildNoFrom(String thisBuildConsoleTextUrl)
  {
  int downstreamBuildNo = -1
  while (downstreamBuildNo <= 0)
    {
    TimeUnit.SECONDS.sleep(1L)
    BufferedReader log = new BufferedReader(
        new InputStreamReader(responseFrom(thisBuildConsoleTextUrl), StandardCharsets.UTF_8.name()));
    while ((line = log.readLine()) != null)
      {
      if (line.matches('.* Build .* started'))
        {
        final int buildNoIdx = line.indexOf('#') + 1
        downstreamBuildNo = Integer.parseUnsignedInt(
            line.substring(buildNoIdx, line.indexOf(' ', buildNoIdx)))
        break
        }
      /*if (log.lines().anyMatch(t -> t.matches(".* Build .* started")))
        {
        // in case of Java >=8
        }*/
      }
    }
  return downstreamBuildNo
  } // downstreamBuildNoFrom()

import java.nio.charset.StandardCharsets

void printConsoleOutputTextChunksFrom(String consoleTextUrl, long updateInterval, TimeUnit updateIntervalUnit)
  {
  final int LINE_BREAK_LENGTH = System.getProperty("line.separator").length()
  int charsPrintedSoFar = 0
  while (true) // effectively a do { ... }
    {
    int charsPrintedThisTime = 0
    BufferedReader chunk = new BufferedReader(
        new InputStreamReader(responseFrom(consoleTextUrl), StandardCharsets.UTF_8.name()))
    chunk.skip(charsPrintedSoFar)
    while ((line = chunk.readLine()) != null)
      {
      println(line)
      charsPrintedThisTime = line.length() + LINE_BREAK_LENGTH
      charsPrintedSoFar += charsPrintedThisTime
      }
    updateIntervalUnit.sleep(updateInterval)
    if (charsPrintedThisTime == 0)
      break
    } 
  } // printConsoleOutputTextChunksFrom()

InputStream responseFrom(String url)
  {
  // See Using java.net.URLConnection to fire and handle HTTP requests 
  //     http://stackoverflow.com/a/2793153/1744774
  URLConnection connection = new URL(url).openConnection();
  connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
  return connection.getInputStream();  
  }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!