Skip to content

Commit

Permalink
Backwards compatibility for color references (#200)
Browse files Browse the repository at this point in the history
* Backwards compatibility for color references

This change improves the backwards compatibility for legacy badge
color references that are not jenkins color classes. Colors that reference defined jenkins palette or semantic names are converted to
their respective css variable references.

* Add legacy color reference tests

* Add more test cases for full coverage

---------

Co-authored-by: strangelookingnerd <49242855+strangelookingnerd@users.noreply.github.com>
  • Loading branch information
cronik and strangelookingnerd authored Oct 23, 2024
1 parent f94fb19 commit 60a6d3e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

/**
* An abstract action providing an id amongst other fields to build a badge.
Expand Down Expand Up @@ -209,7 +211,7 @@ protected Object readResolve() {
} else if (color.startsWith("jenkins-!-")) {
style += "color: var(--" + color.replaceFirst("jenkins-!-", "") + ");";
} else {
style += "color: " + color + ";";
style += "color: " + getJenkinsColorStyle(color) + ";";
}
}
if (!style.isEmpty()) {
Expand All @@ -218,4 +220,51 @@ protected Object readResolve() {

return this;
}

/**
* Get the Jenkins color style for the given color reference. Returns {@code color} if the color is not a
* known Jenkins palette color or semantic color.
* @param color color reference
* @return jenkins color style variable
*/
@NonNull
@Restricted(NoExternalUse.class)
public static String getJenkinsColorStyle(@NonNull String color) {
String primary = color;
if (color.startsWith("light-") && color.length() > 6) {
primary = color.substring(6);
} else if (color.startsWith("dark-") && color.length() > 5) {
primary = color.substring(5);
}
// https://github.com/jenkinsci/jenkins/blob/master/src/main/scss/abstracts/_theme.scss
switch (primary) {
// palette
case "blue":
case "brown":
case "cyan":
case "green":
case "indigo":
case "orange":
case "pink":
case "purple":
case "red":
case "yellow":
case "white":
case "black":
return "var(--" + color + ")";
// semantics
case "accent":
case "text":
case "error":
case "warning":
case "success":
case "destructive":
case "build":
case "danger":
case "info":
return "var(--" + color + "-color)";
default:
return color;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package com.jenkinsci.plugins.badge.dsl;

import com.jenkinsci.plugins.badge.action.AbstractBadgeAction;
import com.jenkinsci.plugins.badge.action.BadgeAction;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
Expand Down Expand Up @@ -60,7 +61,7 @@ public void setColor(String color) {
} else if (color.startsWith("jenkins-!-")) {
newStyle += "color: var(--" + color.replaceFirst("jenkins-!-", "") + ");";
} else {
newStyle += "color: " + color + ";";
newStyle += "color: " + AbstractBadgeAction.getJenkinsColorStyle(color) + ";";
}
setStyle(newStyle + StringUtils.defaultString(getStyle()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package com.jenkinsci.plugins.badge.dsl;

import com.jenkinsci.plugins.badge.action.AbstractBadgeAction;
import com.jenkinsci.plugins.badge.action.BadgeAction;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
Expand Down Expand Up @@ -220,7 +221,7 @@ protected Void run() throws Exception {
} else if (shortText.getColor().startsWith("jenkins-!-")) {
style += "color: var(--" + shortText.getColor().replaceFirst("jenkins-!-", "") + ");";
} else {
style += "color: " + shortText.getColor() + ";";
style += "color: " + AbstractBadgeAction.getJenkinsColorStyle(shortText.getColor()) + ";";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@
*/
package com.jenkinsci.plugins.badge.dsl;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import com.jenkinsci.plugins.badge.action.BadgeAction;
import com.jenkinsci.plugins.badge.action.BadgeSummaryAction;
import hudson.markup.RawHtmlMarkupFormatter;
import hudson.model.BuildBadgeAction;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.junit.jupiter.WithJenkins;

Expand All @@ -44,38 +47,49 @@
class LegacyPipelineTest {

@Test
void color(JenkinsRule r) throws Exception {
WorkflowRun run = runJob(r, "addBadge(color: 'red')");

List<BuildBadgeAction> badgeActions = run.getBadgeActions();
assertEquals(1, badgeActions.size());

BadgeAction action = (BadgeAction) badgeActions.get(0);
assertEquals("color: red;", action.getStyle());

run = runJob(r, "addBadge(color: 'jenkins-!-color-red')");

badgeActions = run.getBadgeActions();
assertEquals(1, badgeActions.size());

action = (BadgeAction) badgeActions.get(0);
assertEquals("color: var(--red);", action.getStyle());

run = runJob(r, "addBadge(color: 'jenkins-!-warning-color')");

badgeActions = run.getBadgeActions();
assertEquals(1, badgeActions.size());

action = (BadgeAction) badgeActions.get(0);
assertEquals("color: var(--warning-color);", action.getStyle());
void color(JenkinsRule r) {
List<String> colors = Arrays.asList(
"blue", "brown", "cyan", "green", "indigo", "orange", "pink", "purple", "red", "yellow", "white",
"black");
Stream<List<String>> palette =
colors.stream().map(c -> Arrays.asList("'" + c + "'", "color: var(--" + c + ");"));
Stream<List<String>> paletteLight =
colors.stream().map(c -> Arrays.asList("'light-" + c + "'", "color: var(--light-" + c + ");"));
Stream<List<String>> paletteDark =
colors.stream().map(c -> Arrays.asList("'dark-" + c + "'", "color: var(--dark-" + c + ");"));

List<String> semantics = Arrays.asList(
"accent", "text", "error", "warning", "success", "destructive", "build", "danger", "info");
Stream<List<String>> semantic =
semantics.stream().map(c -> Arrays.asList("'" + c + "'", "color: var(--" + c + "-color);"));

Stream<List<String>> other = Stream.of(
Arrays.asList("'light-'", "color: light-;"),
Arrays.asList("'dark-'", "color: dark-;"),
Arrays.asList("'#ff0000'", "color: #ff0000;"),
Arrays.asList("'tortoise'", "color: tortoise;"),
Arrays.asList("'jenkins-!-color-red'", "color: var(--red);"),
Arrays.asList("'jenkins-!-warning-color'", "color: var(--warning-color);"),
Arrays.asList("''", "color: ;"),
Arrays.asList("null", null));

assertAll("palette", colorTests(r, palette));
assertAll("palette-light", colorTests(r, paletteLight));
assertAll("palette-dark", colorTests(r, paletteDark));
assertAll("semantic", colorTests(r, semantic));
assertAll("other", colorTests(r, other));
}

run = runJob(r, "addBadge(color: null)");
private static Stream<Executable> colorTests(JenkinsRule r, Stream<List<String>> tests) {
return tests.map(params -> () -> {
WorkflowRun run = runJob(r, "addBadge(color: " + params.get(0) + ")");

badgeActions = run.getBadgeActions();
assertEquals(1, badgeActions.size());
List<BuildBadgeAction> badgeActions = run.getBadgeActions();
assertEquals(1, badgeActions.size());

action = (BadgeAction) badgeActions.get(0);
assertNull(action.getStyle());
BadgeAction action = (BadgeAction) badgeActions.get(0);
assertEquals(params.get(1), action.getStyle());
});
}

@Test
Expand Down

0 comments on commit 60a6d3e

Please sign in to comment.