Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

* Your contribution here.
* [#107](https://github.com/jenkinsci/ansicolor-plugin/pull/107): Removing startup banner - [@jglick](https://github.com/jglick).
* [#128](https://github.com/jenkinsci/ansicolor-plugin/pull/128): Restoring limited compatibility for coloration generated remotely by Pipeline builds on agents - [@jglick](https://github.com/jglick).

0.5.2 (08/17/2017)
============
Expand Down
39 changes: 34 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>2.25</version>
<version>3.25</version>
<relativePath />
</parent>

<artifactId>ansicolor</artifactId>
Expand Down Expand Up @@ -45,23 +46,51 @@
</distributionManagement>

<properties>
<jenkins.version>1.642.3</jenkins.version>
<jenkins.version>2.121.2</jenkins.version>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to stats this is not a big deal, even if there are active trunk releases of this plugin for unrelated changes.

But, if baseline is an obstacle, the POM changes could be reverted. In that case the only src/main/ change would be to convert some uses of lambdas to inner classes, pretty simple; the src/test/ code could remain, but would no longer reproduce the problem unless run under plugin-compat-tester.

<java.level>8</java.level>
</properties>

<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>2.12</version>
<version>2.15</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-aggregator</artifactId>
<version>2.5</version>
<artifactId>workflow-cps</artifactId>
<version>2.59</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.26</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.25</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<version>2.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.17</version>
</dependency>
</dependencies>
</dependencyManagement>

<repositories>
<repository>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
import hudson.console.ConsoleLogFilter;
import hudson.console.LineTransformationOutputStream;
import hudson.model.AbstractBuild;
import java.io.ByteArrayOutputStream;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.util.JenkinsJVM;

/**
* {@link ConsoleLogFilter} that adds a {@link SimpleHtmlNote} to each line.
Expand All @@ -20,10 +24,40 @@ public final class AnsiColorConsoleLogFilter extends ConsoleLogFilter implements
private static final Logger LOG = Logger.getLogger(AnsiColorConsoleLogFilter.class.getName());

private AnsiColorMap colorMap;
private final Map<String, byte[]> notes;

public AnsiColorConsoleLogFilter(AnsiColorMap colorMap) {
super();
this.colorMap = colorMap;
this.notes = new HashMap<>();
// some cases of AnsiHtmlOutputStream.setForegroundColor:
for (AnsiColorMap.Color color : AnsiColorMap.Color.values()) {
pregenerateNote(new AnsiAttributeElement(AnsiAttributeElement.AnsiAttrType.FG, "span", "style=\"color: " + colorMap.getNormal(color.ordinal()) + ";\""));
}
// TODO other cases, and other methods
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tedious part. Handling bright colors, swapColors, bold/italic/underline, etc. Basically every call to the AnsiAttributeElement constructor from AnsiHtmlOutputStream which could be predicted given an AnsiColorMap—probably all but the explicit use of RGB coördinates, which I am guessing are rarely used anyway.

LOG.log(Level.FINE, "Notes pregenerated for {0}", notes.keySet());
}

private void pregenerateNote(AnsiAttributeElement element) {
element.emitOpen(html -> pregenerateNote(html));
element.emitClose(html -> pregenerateNote(html));
}

private void pregenerateNote(String html) {
if (!notes.containsKey(html)) {
JenkinsJVM.checkJenkinsJVM();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See jenkinsci/ant-plugin#32 for a simpler patch that illustrates the idiom.

ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
new SimpleHtmlNote(html).encodeTo(baos);
} catch (IOException x) { // should be impossible
throw new RuntimeException(x);
}
notes.put(html, baos.toByteArray());
}
}

private Object readResolve() { // handle old program.dat
return notes == null ? new AnsiColorConsoleLogFilter(colorMap) : this;
}

@SuppressWarnings("rawtypes")
Expand All @@ -39,7 +73,12 @@ public OutputStream decorateLogger(AbstractBuild build, final OutputStream logge
@Override
public void emitHtml(String html) {
try {
new SimpleHtmlNote(html).encodeTo(logger);
byte[] pregenerated = notes.get(html);
if (pregenerated != null) {
logger.write(pregenerated);
} else {
new SimpleHtmlNote(html).encodeTo(logger);
}
} catch (IOException e) {
LOG.log(Level.WARNING, "Failed to add HTML markup '" + html + "'", e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package hudson.plugins.ansicolor;

import hudson.Functions;
import hudson.console.ConsoleNote;
import java.io.StringWriter;
import java.util.logging.Level;
import static org.hamcrest.CoreMatchers.instanceOf;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Assume;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.runners.model.Statement;
import org.jvnet.hudson.test.BuildWatcher;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.LoggerRule;
import org.jvnet.hudson.test.RestartableJenkinsRule;

public class AnsiColorBuildWrapperTest {
Expand Down Expand Up @@ -42,17 +45,21 @@ public void testDecorateLogger() {
public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule
public RestartableJenkinsRule story = new RestartableJenkinsRule();
@Rule
public LoggerRule logging = new LoggerRule().recordPackage(ConsoleNote.class, Level.FINE);

@Issue("JENKINS-54133")
@Test
public void testWorkflowWrap() throws Exception {
story.addStep(new Statement() {

@Override
public void evaluate() throws Throwable {
Assume.assumeTrue(!Functions.isWindows());
story.j.createSlave();
WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"node {\n"
"node('!master') {\n"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like this should be a separate test.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed unnecessary as AnsiColorStepTest already tests the behavior on master.

+ " wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm', 'defaultFg': 1, 'defaultBg': 2]) {\n"
+ " sh(\"\"\"#!/bin/bash\n"
+ " printf 'The following word is supposed to be \\\\e[31mred\\\\e[0m\\\\n'\"\"\"\n"
Expand Down