From dad65720c4c3ccaeb1176d22e8f8084c8c1ac8e0 Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Sun, 29 Nov 2020 20:27:07 +0800 Subject: [PATCH 01/10] Add withChecks step --- .../plugins/checks/steps/ChecksInfo.java | 17 +++++ .../plugins/checks/steps/WithChecksStep.java | 73 +++++++++++++++++++ .../plugins/checks/steps/package-info.java | 8 ++ 3 files changed, 98 insertions(+) create mode 100644 src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java create mode 100644 src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java create mode 100644 src/main/java/io/jenkins/plugins/checks/steps/package-info.java diff --git a/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java b/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java new file mode 100644 index 00000000..862c4224 --- /dev/null +++ b/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java @@ -0,0 +1,17 @@ +package io.jenkins.plugins.checks.steps; + +import java.io.Serializable; + +public class ChecksInfo implements Serializable { + private static final long serialVersionUID = 1L; + + private String name; + + public ChecksInfo(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java new file mode 100644 index 00000000..de77c6ab --- /dev/null +++ b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java @@ -0,0 +1,73 @@ +package io.jenkins.plugins.checks.steps; + +import hudson.Extension; +import hudson.model.Run; +import hudson.model.TaskListener; +import org.jenkinsci.plugins.workflow.steps.*; +import org.kohsuke.stapler.DataBoundConstructor; + +import java.io.Serializable; +import java.util.*; + +public class WithChecksStep extends Step implements Serializable { + private static final long serialVersionUID = 1L; + + private String name; + + /** + * Constructor used for pipeline by Stapler. + */ + @DataBoundConstructor + public WithChecksStep(final String name) { + super(); + + this.name = name; + } + + @Override + public StepExecution start(final StepContext stepContext) { + return new WithChecksStep.WithChecksStepExecution(stepContext, this); + } + + @Extension + public static class WithChecksStepDescriptor extends StepDescriptor { + @Override + public String getFunctionName() { + return "withChecks"; + } + + @Override + public Set> getRequiredContext() { + return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(Run.class, TaskListener.class))); + } + + @Override + public boolean takesImplicitBlockArgument() { + return true; + } + } + + static class WithChecksStepExecution extends AbstractStepExecutionImpl { + private WithChecksStep step; + + WithChecksStepExecution(final StepContext context, final WithChecksStep step) { + super(context); + this.step = step; + } + + @Override + public boolean start() { + StepContext context = getContext(); + context.newBodyInvoker() + .withContext(new ChecksInfo(step.name)) + .withCallback(BodyExecutionCallback.wrap(context)) + .start(); + return false; + } + + @Override + public void stop(Throwable cause) { + getContext().onFailure(cause); + } + } +} diff --git a/src/main/java/io/jenkins/plugins/checks/steps/package-info.java b/src/main/java/io/jenkins/plugins/checks/steps/package-info.java new file mode 100644 index 00000000..c3a9aa05 --- /dev/null +++ b/src/main/java/io/jenkins/plugins/checks/steps/package-info.java @@ -0,0 +1,8 @@ +/** + * Provides default Findbugs annotations. + */ +@DefaultAnnotation(NonNull.class) +package io.jenkins.plugins.checks.steps; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotation; +import edu.umd.cs.findbugs.annotations.NonNull; From 7b78a3be034885cbdf9bd069a9971f9311a7bd02 Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Tue, 15 Dec 2020 00:47:33 +0800 Subject: [PATCH 02/10] Add test for WithChecksStep. --- pom.xml | 10 ++ .../plugins/checks/steps/ChecksInfo.java | 13 ++- .../plugins/checks/steps/WithChecksStep.java | 32 +++++- .../checks/steps/WithChecksStepITest.java | 104 ++++++++++++++++++ .../checks/steps/WithChecksStepTest.java | 33 ++++++ 5 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java create mode 100644 src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepTest.java diff --git a/pom.xml b/pom.xml index e23dd1c8..102c36da 100644 --- a/pom.xml +++ b/pom.xml @@ -114,6 +114,16 @@ class io.jenkins.plugins.checks.BuildStatusChecksPublisher BuildStatusChecksPublisher has no consumers, should be safe to move. + + java.class.added + class io.jenkins.plugins.checks.steps.ChecksInfo + Adding a new step wil not break back compatibility + + + java.class.added + class io.jenkins.plugins.checks.steps.WithChecksStep + Adding a new step wil not break back compatibility + diff --git a/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java b/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java index 862c4224..74ff9303 100644 --- a/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java +++ b/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java @@ -2,12 +2,21 @@ import java.io.Serializable; +/** + * A collection of checks properties that will be injected into {@link WithChecksStep} closure. + */ public class ChecksInfo implements Serializable { private static final long serialVersionUID = 1L; - private String name; + private final String name; - public ChecksInfo(String name) { + /** + * Creates a {@link ChecksInfo} with checks name. + * + * @param name + * the name of the check + */ + public ChecksInfo(final String name) { this.name = name; } diff --git a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java index de77c6ab..a66761ad 100644 --- a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java +++ b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java @@ -1,5 +1,6 @@ package io.jenkins.plugins.checks.steps; +import edu.hm.hafner.util.VisibleForTesting; import hudson.Extension; import hudson.model.Run; import hudson.model.TaskListener; @@ -9,13 +10,19 @@ import java.io.Serializable; import java.util.*; +/** + * Pipeline step that injects a {@link ChecksInfo} into the closure. + */ public class WithChecksStep extends Step implements Serializable { private static final long serialVersionUID = 1L; - private String name; + private final String name; /** - * Constructor used for pipeline by Stapler. + * Creates the step with a name to inject. + * + * @param name + * name to inject */ @DataBoundConstructor public WithChecksStep(final String name) { @@ -26,9 +33,12 @@ public WithChecksStep(final String name) { @Override public StepExecution start(final StepContext stepContext) { - return new WithChecksStep.WithChecksStepExecution(stepContext, this); + return new WithChecksStepExecution(stepContext, this); } + /** + * This step's descriptor which defines the function name ("withChecks") and required context. + */ @Extension public static class WithChecksStepDescriptor extends StepDescriptor { @Override @@ -47,8 +57,13 @@ public boolean takesImplicitBlockArgument() { } } + /** + * The step's execution to actually inject the {@link ChecksInfo} into the closure. + */ static class WithChecksStepExecution extends AbstractStepExecutionImpl { - private WithChecksStep step; + private static final long serialVersionUID = 1L; + + private final WithChecksStep step; WithChecksStepExecution(final StepContext context, final WithChecksStep step) { super(context); @@ -59,14 +74,19 @@ static class WithChecksStepExecution extends AbstractStepExecutionImpl { public boolean start() { StepContext context = getContext(); context.newBodyInvoker() - .withContext(new ChecksInfo(step.name)) + .withContext(extractChecksInfo()) .withCallback(BodyExecutionCallback.wrap(context)) .start(); return false; } + @VisibleForTesting + ChecksInfo extractChecksInfo() { + return new ChecksInfo(step.name); + } + @Override - public void stop(Throwable cause) { + public void stop(final Throwable cause) { getContext().onFailure(cause); } } diff --git a/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java b/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java new file mode 100644 index 00000000..a6dc5bab --- /dev/null +++ b/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepITest.java @@ -0,0 +1,104 @@ +package io.jenkins.plugins.checks.steps; + +import hudson.model.Run; +import io.jenkins.plugins.util.IntegrationTestWithJenkinsPerTest; +import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.jenkinsci.plugins.workflow.steps.*; +import org.junit.Test; +import org.jvnet.hudson.test.TestExtension; +import org.kohsuke.stapler.DataBoundConstructor; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests the "withChecks" step. + */ +public class WithChecksStepITest extends IntegrationTestWithJenkinsPerTest { + /** + * Tests that the step can inject the {@link ChecksInfo} into the closure. + */ + @Test + public void shouldInjectChecksInfoIntoClosure() { + WorkflowJob job = createPipeline(); + job.setDefinition(asStage("withChecks('test injection') { assertChecksInfoInjection('test injection') }")); + + buildSuccessfully(job); + } + + /** + * Assert that the injected {@link ChecksInfo} is as expected. + */ + @TestExtension + public static class AssertChecksInfoInjectionStep extends Step implements Serializable { + private static final long serialVersionUID = 1L; + + private final ChecksInfo expected; + + /** + * Required by {@link TestExtension} annotation. + */ + public AssertChecksInfoInjectionStep() { + this(""); + } + + /** + * Creates the step with expected name injected. + * + * @param expectedName + * expected name that will be injected + */ + @DataBoundConstructor + public AssertChecksInfoInjectionStep(final String expectedName) { + super(); + + expected = new ChecksInfo(expectedName); + } + + @Override + public StepExecution start(final StepContext stepContext) { + return new AssertChecksInfoInjectionStepExecution(stepContext, this); + } + + /** + * Descriptor for {@link AssertChecksInfoInjectionStep} that defines function name and required context. + */ + @TestExtension + public static class AssertChecksInfoStepInjectionDescriptor extends StepDescriptor { + @Override + public String getFunctionName() { + return "assertChecksInfoInjection"; + } + + @Override + public Set> getRequiredContext() { + return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(Run.class, ChecksInfo.class))); + } + } + + static class AssertChecksInfoInjectionStepExecution extends SynchronousNonBlockingStepExecution { + private static final long serialVersionUID = 1L; + + private final AssertChecksInfoInjectionStep step; + + AssertChecksInfoInjectionStepExecution(final StepContext context, final AssertChecksInfoInjectionStep step) { + super(context); + + this.step = step; + } + + @Override + protected Void run() throws Exception { + assertThat(getContext().get(ChecksInfo.class)) + .usingRecursiveComparison() + .isEqualTo(step.expected); + return null; + } + } + } +} diff --git a/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepTest.java b/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepTest.java new file mode 100644 index 00000000..86d9941f --- /dev/null +++ b/src/test/java/io/jenkins/plugins/checks/steps/WithChecksStepTest.java @@ -0,0 +1,33 @@ +package io.jenkins.plugins.checks.steps; + +import hudson.model.Run; +import hudson.model.TaskListener; +import org.jenkinsci.plugins.workflow.steps.StepContext; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class WithChecksStepTest { + @Test + void shouldStartWithCorrectExecution() throws IOException, InterruptedException { + StepContext context = mock(StepContext.class); + + when(context.get(Run.class)).thenReturn(mock(Run.class)); + when(context.get(TaskListener.class)).thenReturn(TaskListener.NULL); + + assertThat(((WithChecksStep.WithChecksStepExecution) (new WithChecksStep("test").start(context))) + .extractChecksInfo()) + .hasFieldOrPropertyWithValue("name", "test"); + } + + @Test + void shouldDefinePublishChecksStepDescriptorCorrectly() { + WithChecksStep.WithChecksStepDescriptor descriptor = new WithChecksStep.WithChecksStepDescriptor(); + assertThat(descriptor.getFunctionName()).isEqualTo("withChecks"); + assertThat(descriptor.getRequiredContext().toArray()).containsExactlyInAnyOrder(Run.class, TaskListener.class); + } +} From 80e6a26201336c3180f56671c0c158734891f360 Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Wed, 16 Dec 2020 16:23:48 +0800 Subject: [PATCH 03/10] Add document and snippet generator support. --- README.md | 10 +++++++++- pom.xml | 10 ---------- .../plugins/checks/steps/WithChecksStep.java | 19 ++++++++++++++++++- .../checks/steps/WithChecksStep/config.jelly | 8 ++++++++ .../steps/WithChecksStep/config.properties | 1 + 5 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.jelly create mode 100644 src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.properties diff --git a/README.md b/README.md index 3160a063..68764ab6 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,20 @@ If enabled, the statuses will be published in different stages of a Jenkins buil ### Pipeline Usage -Instead of depending on consumers plugins, the users can publish their checks directly in the pipeline script: +- publishChecks: you can publish checks directly in the pipeline script instead of depending on consumer plugins: ``` publishChecks name: 'example', title: 'Pipeline Check', summary: 'check through pipeline', text: 'you can publish checks in pipeline script', detailsURL: 'https://github.com/jenkinsci/checks-api-plugin#pipeline-usage' ``` +- withChecks: you can inject the check's name into the closure for other steps to use: + +``` +withChecks(name: 'injected name') { + // some other steps that will extract the name +} +``` + ## Guides - [Consumers Guide](docs/consumers-guide.md) diff --git a/pom.xml b/pom.xml index 102c36da..e23dd1c8 100644 --- a/pom.xml +++ b/pom.xml @@ -114,16 +114,6 @@ class io.jenkins.plugins.checks.BuildStatusChecksPublisher BuildStatusChecksPublisher has no consumers, should be safe to move. - - java.class.added - class io.jenkins.plugins.checks.steps.ChecksInfo - Adding a new step wil not break back compatibility - - - java.class.added - class io.jenkins.plugins.checks.steps.WithChecksStep - Adding a new step wil not break back compatibility - diff --git a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java index a66761ad..0fb3aeaf 100644 --- a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java +++ b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java @@ -1,11 +1,13 @@ package io.jenkins.plugins.checks.steps; import edu.hm.hafner.util.VisibleForTesting; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.model.Run; import hudson.model.TaskListener; import org.jenkinsci.plugins.workflow.steps.*; import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; import java.io.Serializable; import java.util.*; @@ -16,7 +18,7 @@ public class WithChecksStep extends Step implements Serializable { private static final long serialVersionUID = 1L; - private final String name; + private String name; /** * Creates the step with a name to inject. @@ -31,6 +33,15 @@ public WithChecksStep(final String name) { this.name = name; } + @DataBoundSetter + public void setName(final String name) { + this.name = name; + } + + public String getName() { + return name; + } + @Override public StepExecution start(final StepContext stepContext) { return new WithChecksStepExecution(stepContext, this); @@ -55,6 +66,12 @@ public Set> getRequiredContext() { public boolean takesImplicitBlockArgument() { return true; } + + @NonNull + @Override + public String getDisplayName() { + return "Inject checks properties into its closure"; + } } /** diff --git a/src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.jelly b/src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.jelly new file mode 100644 index 00000000..88b713b5 --- /dev/null +++ b/src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.jelly @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.properties b/src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.properties new file mode 100644 index 00000000..d4c852fb --- /dev/null +++ b/src/main/resources/io/jenkins/plugins/checks/steps/WithChecksStep/config.properties @@ -0,0 +1 @@ +title.name=Name From f4b246a8a0c5e027a08e068e8f60253701bba773 Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Wed, 16 Dec 2020 16:38:13 +0800 Subject: [PATCH 04/10] Bump version to 1.2.0 for adding ChecksInfo and WithChecksStep. --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e23dd1c8..3e383ec8 100644 --- a/pom.xml +++ b/pom.xml @@ -19,8 +19,7 @@ 8 - 1.1.1 - -SNAPSHOT + 1.2.0 1.4.0 From c76461fc2806d4bf4bc5f32b9cc41194af4a736d Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Wed, 16 Dec 2020 18:17:49 +0800 Subject: [PATCH 05/10] remove unused setter --- .../io/jenkins/plugins/checks/steps/WithChecksStep.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java index 0fb3aeaf..1282b206 100644 --- a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java +++ b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java @@ -18,7 +18,7 @@ public class WithChecksStep extends Step implements Serializable { private static final long serialVersionUID = 1L; - private String name; + private final String name; /** * Creates the step with a name to inject. @@ -33,11 +33,6 @@ public WithChecksStep(final String name) { this.name = name; } - @DataBoundSetter - public void setName(final String name) { - this.name = name; - } - public String getName() { return name; } From d37be3419634a20e85e0947860f8ae943af7df92 Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Wed, 16 Dec 2020 19:28:31 +0800 Subject: [PATCH 06/10] Remove unused import --- .../java/io/jenkins/plugins/checks/steps/WithChecksStep.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java index 1282b206..9a2b87c1 100644 --- a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java +++ b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java @@ -7,7 +7,6 @@ import hudson.model.TaskListener; import org.jenkinsci.plugins.workflow.steps.*; import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.DataBoundSetter; import java.io.Serializable; import java.util.*; From 69a09ff5462a42c9c7a2758175270961b18800aa Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Thu, 17 Dec 2020 18:10:07 +0800 Subject: [PATCH 07/10] Add callback for withChecks. --- pom.xml | 6 ++ .../plugins/checks/steps/ChecksInfo.java | 2 + .../plugins/checks/steps/WithChecksStep.java | 98 +++++++++++++++++-- 3 files changed, 99 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index d486d803..8a4793d5 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,12 @@ test-jar + + org.jenkins-ci.plugins + display-url-api + 2.3.3 + + org.jenkins-ci.plugins.workflow workflow-step-api diff --git a/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java b/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java index 74ff9303..f9e3c644 100644 --- a/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java +++ b/src/main/java/io/jenkins/plugins/checks/steps/ChecksInfo.java @@ -1,6 +1,7 @@ package io.jenkins.plugins.checks.steps; import java.io.Serializable; +import java.util.Objects; /** * A collection of checks properties that will be injected into {@link WithChecksStep} closure. @@ -17,6 +18,7 @@ public class ChecksInfo implements Serializable { * the name of the check */ public ChecksInfo(final String name) { + Objects.requireNonNull(name); this.name = name; } diff --git a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java index 9a2b87c1..7bf8d0d0 100644 --- a/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java +++ b/src/main/java/io/jenkins/plugins/checks/steps/WithChecksStep.java @@ -5,11 +5,19 @@ import hudson.Extension; import hudson.model.Run; import hudson.model.TaskListener; +import io.jenkins.plugins.checks.api.*; +import io.jenkins.plugins.util.PluginLogger; +import org.jenkinsci.plugins.displayurlapi.DisplayURLProvider; import org.jenkinsci.plugins.workflow.steps.*; import org.kohsuke.stapler.DataBoundConstructor; +import java.io.IOException; import java.io.Serializable; import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static hudson.Util.fixNull; /** * Pipeline step that injects a {@link ChecksInfo} into the closure. @@ -22,8 +30,7 @@ public class WithChecksStep extends Step implements Serializable { /** * Creates the step with a name to inject. * - * @param name - * name to inject + * @param name name to inject */ @DataBoundConstructor public WithChecksStep(final String name) { @@ -73,6 +80,7 @@ public String getDisplayName() { */ static class WithChecksStepExecution extends AbstractStepExecutionImpl { private static final long serialVersionUID = 1L; + private static final Logger SYSTEM_LOGGER = Logger.getLogger(WithChecksStepExecution.class.getName()); private final WithChecksStep step; @@ -83,10 +91,10 @@ static class WithChecksStepExecution extends AbstractStepExecutionImpl { @Override public boolean start() { - StepContext context = getContext(); - context.newBodyInvoker() - .withContext(extractChecksInfo()) - .withCallback(BodyExecutionCallback.wrap(context)) + ChecksInfo info = extractChecksInfo(); + getContext().newBodyInvoker() + .withContext(info) + .withCallback(new WithChecksCallBack(info)) .start(); return false; } @@ -98,7 +106,83 @@ ChecksInfo extractChecksInfo() { @Override public void stop(final Throwable cause) { - getContext().onFailure(cause); + publish(getContext(), new ChecksDetails.ChecksDetailsBuilder() + .withName(step.getName()) + .withStatus(ChecksStatus.COMPLETED) + .withConclusion(ChecksConclusion.CANCELED)); + } + + private void publish(final StepContext context, final ChecksDetails.ChecksDetailsBuilder builder) { + TaskListener listener = TaskListener.NULL; + try { + listener = fixNull(context.get(TaskListener.class), TaskListener.NULL); + } + catch (IOException | InterruptedException e) { + SYSTEM_LOGGER.log(Level.WARNING, "Failed getting TaskListener from the context: " + e); + } + + PluginLogger pluginLogger = new PluginLogger(listener.getLogger(), "Checks API"); + + Run run; + try { + run = context.get(Run.class); + } + catch (IOException | InterruptedException e) { + String msg = "Failed getting Run from the context on the start of withChecks step: " + e; + pluginLogger.log(msg); + SYSTEM_LOGGER.log(Level.WARNING, msg); + context.onFailure(new IllegalStateException(msg)); + return; + } + + if (run == null) { + String msg = "No Run found in the context."; + pluginLogger.log(msg); + SYSTEM_LOGGER.log(Level.WARNING, msg); + context.onFailure(new IllegalStateException(msg)); + return; + } + + ChecksPublisherFactory.fromRun(run, listener) + .publish(builder.withDetailsURL(DisplayURLProvider.get().getRunURL(run)) + .build()); + } + + class WithChecksCallBack extends BodyExecutionCallback { + private static final long serialVersionUID = 1L; + + private final ChecksInfo info; + + WithChecksCallBack(final ChecksInfo info) { + super(); + + this.info = info; + } + + @Override + public void onStart(final StepContext context) { + publish(context, new ChecksDetails.ChecksDetailsBuilder() + .withName(info.getName()) + .withStatus(ChecksStatus.IN_PROGRESS) + .withConclusion(ChecksConclusion.NONE)); + } + + @Override + public void onSuccess(final StepContext context, final Object result) { + context.onSuccess(result); + } + + @Override + public void onFailure(final StepContext context, final Throwable t) { + publish(context, new ChecksDetails.ChecksDetailsBuilder() + .withName(info.getName()) + .withStatus(ChecksStatus.COMPLETED) + .withConclusion(ChecksConclusion.FAILURE) + .withOutput(new ChecksOutput.ChecksOutputBuilder() + .withSummary("occurred while executing withChecks step.") + .withText(t.toString()).build())); + context.onFailure(t); + } } } } From d38dbf616b24dd88598258bda294d51fc0f2ea49 Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Sat, 19 Dec 2020 16:17:58 +0800 Subject: [PATCH 08/10] Add consumer doc. --- docs/consumers-guide.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/consumers-guide.md b/docs/consumers-guide.md index ed676b51..3d6a0ac4 100644 --- a/docs/consumers-guide.md +++ b/docs/consumers-guide.md @@ -42,3 +42,13 @@ Consumers can set these parameters through the checks models: The publishers are created through the static factory method (`fromRun` or `fromJob`) of `ChecksPublisherFactory`. The factory will iterate all available implementations of the `ChecksPublisher` in order to find the suitable publisher for the Jenkins `Run` or `Job`. + +## Pipeline Step: withChecks + +The withChecks step injects a `ChecksInfo` object into its closure so that other plugin developers can resolve them in their [Step](https://javadoc.jenkins.io/plugin/workflow-step-api/org/jenkinsci/plugins/workflow/steps/Step.html) implementation: + +``` +getContext().get(ChecksInfo.class) +``` + +Currently, the `ChecksInfo` object only includes a `name` specified by users. From a45182e722c8b1e175f18581cb4c111e731cd93e Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Sat, 19 Dec 2020 16:19:22 +0800 Subject: [PATCH 09/10] Remove unnessary denpendency version in pom --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8a4793d5..ddb15a6f 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,6 @@ org.jenkins-ci.plugins display-url-api - 2.3.3 From e724c04f2d2a75842b070f1e851a5f43e8b2b034 Mon Sep 17 00:00:00 2001 From: Kezhi Xiong Date: Sat, 19 Dec 2020 16:33:19 +0800 Subject: [PATCH 10/10] Improve consumer doc --- docs/consumers-guide.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/consumers-guide.md b/docs/consumers-guide.md index 3d6a0ac4..ddc53412 100644 --- a/docs/consumers-guide.md +++ b/docs/consumers-guide.md @@ -45,10 +45,20 @@ The factory will iterate all available implementations of the `ChecksPublisher` ## Pipeline Step: withChecks -The withChecks step injects a `ChecksInfo` object into its closure so that other plugin developers can resolve them in their [Step](https://javadoc.jenkins.io/plugin/workflow-step-api/org/jenkinsci/plugins/workflow/steps/Step.html) implementation: +The `withChecks` step injects a `ChecksInfo` object into its closure by users: + +```groovy +withChecks('MyCheck') { + junit '*.xml' +} +``` + +The injected object can be resolved by other plugin developers in their [Step](https://javadoc.jenkins.io/plugin/workflow-step-api/org/jenkinsci/plugins/workflow/steps/Step.html) implementation: ``` getContext().get(ChecksInfo.class) ``` -Currently, the `ChecksInfo` object only includes a `name` specified by users. +Currently, the `ChecksInfo` object only includes a `name` specified by users, +it is recommended that you look for this name and set it over your default checks name +