From 60a6d3ec4a4a306e98ea8fbe9cf1e60e1eafaa4a Mon Sep 17 00:00:00 2001 From: Kyle Cronin Date: Wed, 23 Oct 2024 08:41:47 -0400 Subject: [PATCH] Backwards compatibility for color references (#200) * 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> --- .../badge/action/AbstractBadgeAction.java | 51 ++++++++++++- .../plugins/badge/dsl/AddBadgeStep.java | 3 +- .../plugins/badge/dsl/AddShortTextStep.java | 3 +- .../plugins/badge/dsl/LegacyPipelineTest.java | 74 +++++++++++-------- 4 files changed, 98 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/jenkinsci/plugins/badge/action/AbstractBadgeAction.java b/src/main/java/com/jenkinsci/plugins/badge/action/AbstractBadgeAction.java index 337c986..c233996 100644 --- a/src/main/java/com/jenkinsci/plugins/badge/action/AbstractBadgeAction.java +++ b/src/main/java/com/jenkinsci/plugins/badge/action/AbstractBadgeAction.java @@ -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. @@ -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()) { @@ -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; + } + } } diff --git a/src/main/java/com/jenkinsci/plugins/badge/dsl/AddBadgeStep.java b/src/main/java/com/jenkinsci/plugins/badge/dsl/AddBadgeStep.java index a274bdd..542359d 100644 --- a/src/main/java/com/jenkinsci/plugins/badge/dsl/AddBadgeStep.java +++ b/src/main/java/com/jenkinsci/plugins/badge/dsl/AddBadgeStep.java @@ -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; @@ -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())); } diff --git a/src/main/java/com/jenkinsci/plugins/badge/dsl/AddShortTextStep.java b/src/main/java/com/jenkinsci/plugins/badge/dsl/AddShortTextStep.java index 5f196fe..21f250b 100644 --- a/src/main/java/com/jenkinsci/plugins/badge/dsl/AddShortTextStep.java +++ b/src/main/java/com/jenkinsci/plugins/badge/dsl/AddShortTextStep.java @@ -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; @@ -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()) + ";"; } } diff --git a/src/test/java/com/jenkinsci/plugins/badge/dsl/LegacyPipelineTest.java b/src/test/java/com/jenkinsci/plugins/badge/dsl/LegacyPipelineTest.java index 5ef43f3..f4e84fc 100644 --- a/src/test/java/com/jenkinsci/plugins/badge/dsl/LegacyPipelineTest.java +++ b/src/test/java/com/jenkinsci/plugins/badge/dsl/LegacyPipelineTest.java @@ -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; @@ -44,38 +47,49 @@ class LegacyPipelineTest { @Test - void color(JenkinsRule r) throws Exception { - WorkflowRun run = runJob(r, "addBadge(color: 'red')"); - - List 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 colors = Arrays.asList( + "blue", "brown", "cyan", "green", "indigo", "orange", "pink", "purple", "red", "yellow", "white", + "black"); + Stream> palette = + colors.stream().map(c -> Arrays.asList("'" + c + "'", "color: var(--" + c + ");")); + Stream> paletteLight = + colors.stream().map(c -> Arrays.asList("'light-" + c + "'", "color: var(--light-" + c + ");")); + Stream> paletteDark = + colors.stream().map(c -> Arrays.asList("'dark-" + c + "'", "color: var(--dark-" + c + ");")); + + List semantics = Arrays.asList( + "accent", "text", "error", "warning", "success", "destructive", "build", "danger", "info"); + Stream> semantic = + semantics.stream().map(c -> Arrays.asList("'" + c + "'", "color: var(--" + c + "-color);")); + + Stream> 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 colorTests(JenkinsRule r, Stream> tests) { + return tests.map(params -> () -> { + WorkflowRun run = runJob(r, "addBadge(color: " + params.get(0) + ")"); - badgeActions = run.getBadgeActions(); - assertEquals(1, badgeActions.size()); + List 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