diff --git a/src/main/java/org/jenkinsci/plugins/github/extension/status/GitHubStatusBackrefSource.java b/src/main/java/org/jenkinsci/plugins/github/extension/status/GitHubStatusBackrefSource.java new file mode 100644 index 000000000..92130eed7 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/github/extension/status/GitHubStatusBackrefSource.java @@ -0,0 +1,25 @@ +package org.jenkinsci.plugins.github.extension.status; + +import hudson.ExtensionPoint; +import hudson.model.AbstractDescribableImpl; +import hudson.model.Run; +import hudson.model.TaskListener; + +/** + * Extension point to provide backref for the status, i.e. to the build or to the test report. + * + * @author pupssman (Kalinin Ivan) + * @since 1.21.2 + */ +public abstract class GitHubStatusBackrefSource extends AbstractDescribableImpl + implements ExtensionPoint { + + /** + * @param run actual run + * @param listener build listener + * + * @return URL that points to the status source, i.e. test result page + */ + public abstract String get(Run run, TaskListener listener); + +} diff --git a/src/main/java/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter.java b/src/main/java/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter.java index d479933cb..492f349e9 100644 --- a/src/main/java/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter.java +++ b/src/main/java/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter.java @@ -14,11 +14,13 @@ import org.jenkinsci.plugins.github.common.CombineErrorHandler; import org.jenkinsci.plugins.github.extension.status.GitHubCommitShaSource; import org.jenkinsci.plugins.github.extension.status.GitHubReposSource; +import org.jenkinsci.plugins.github.extension.status.GitHubStatusBackrefSource; import org.jenkinsci.plugins.github.extension.status.GitHubStatusContextSource; import org.jenkinsci.plugins.github.extension.status.GitHubStatusResultSource; import org.jenkinsci.plugins.github.extension.status.StatusErrorHandler; import org.jenkinsci.plugins.github.status.sources.AnyDefinedRepositorySource; import org.jenkinsci.plugins.github.status.sources.BuildDataRevisionShaSource; +import org.jenkinsci.plugins.github.status.sources.BuildRefBackrefSource; import org.jenkinsci.plugins.github.status.sources.DefaultCommitContextSource; import org.jenkinsci.plugins.github.status.sources.DefaultStatusResultSource; import org.kohsuke.github.GHCommitState; @@ -44,6 +46,7 @@ public class GitHubCommitStatusSetter extends Notifier implements SimpleBuildSte private GitHubReposSource reposSource = new AnyDefinedRepositorySource(); private GitHubStatusContextSource contextSource = new DefaultCommitContextSource(); private GitHubStatusResultSource statusResultSource = new DefaultStatusResultSource(); + private GitHubStatusBackrefSource statusBackrefSource = new BuildRefBackrefSource(); private List errorHandlers = new ArrayList<>(); @DataBoundConstructor @@ -70,6 +73,11 @@ public void setStatusResultSource(GitHubStatusResultSource statusResultSource) { this.statusResultSource = statusResultSource; } + @DataBoundSetter + public void setStatusBackrefSource(GitHubStatusBackrefSource statusBackrefSource) { + this.statusBackrefSource = statusBackrefSource; + } + @DataBoundSetter public void setErrorHandlers(List errorHandlers) { this.errorHandlers = errorHandlers; @@ -103,6 +111,13 @@ public GitHubStatusResultSource getStatusResultSource() { return statusResultSource; } + /** + * @return backref provider + */ + public GitHubStatusBackrefSource getStatusBackrefSource() { + return statusBackrefSource; + } + /** * @return error handlers */ @@ -121,7 +136,7 @@ public void perform(@Nonnull Run run, @Nonnull FilePath workspace, @Nonnul List repos = getReposSource().repos(run, listener); String contextName = getContextSource().context(run, listener); - String backref = run.getAbsoluteUrl(); + String backref = getStatusBackrefSource().get(run, listener); GitHubStatusResultSource.StatusResult result = getStatusResultSource().get(run, listener); @@ -146,6 +161,13 @@ public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.NONE; } + public Object readResolve() { + if (getStatusBackrefSource() == null) { + setStatusBackrefSource(new BuildRefBackrefSource()); + } + return this; + } + @Extension public static class GitHubCommitStatusSetterDescr extends BuildStepDescriptor { diff --git a/src/main/java/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource.java b/src/main/java/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource.java new file mode 100644 index 000000000..1dfce1095 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource.java @@ -0,0 +1,35 @@ +package org.jenkinsci.plugins.github.status.sources; + +import org.jenkinsci.plugins.github.extension.status.GitHubStatusBackrefSource; + +import hudson.Extension; +import hudson.model.Descriptor; +import hudson.model.Run; +import hudson.model.TaskListener; + +/** + * Gets backref from Run URL. + * + * @author pupssman (Kalinin Ivan) + * @since 1.21.2 + * + */ +public class BuildRefBackrefSource extends GitHubStatusBackrefSource { + + /** + * Returns absolute URL of the Run + */ + @SuppressWarnings("deprecation") + @Override + public String get(Run run, TaskListener listener) { + return run.getAbsoluteUrl(); + } + + @Extension + public static class BuildRefBackrefSourceDescriptor extends Descriptor { + @Override + public String getDisplayName() { + return "Backref to the build"; + } + } +} diff --git a/src/main/java/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource.java b/src/main/java/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource.java new file mode 100644 index 000000000..ba6c7de01 --- /dev/null +++ b/src/main/java/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource.java @@ -0,0 +1,57 @@ +package org.jenkinsci.plugins.github.status.sources; + +import org.jenkinsci.plugins.github.common.ExpandableMessage; +import org.jenkinsci.plugins.github.extension.status.GitHubStatusBackrefSource; +import org.kohsuke.stapler.DataBoundConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import hudson.Extension; +import hudson.model.Descriptor; +import hudson.model.Run; +import hudson.model.TaskListener; + +/** + * Allows to manually enter backref, with env/token expansion. + * + * @author pupssman (Kalinin Ivan) + * @since 1.21.2 + * + */ +public class ManuallyEnteredBackrefSource extends GitHubStatusBackrefSource { + private static final Logger LOG = LoggerFactory.getLogger(ManuallyEnteredBackrefSource.class); + + private String backref; + + @DataBoundConstructor + public ManuallyEnteredBackrefSource(String backref) { + this.backref = backref; + } + + public String getBackref() { + return backref; + } + + /** + * Just returns what user entered. Expands env vars and token macro + */ + @SuppressWarnings("deprecation") + @Override + public String get(Run run, TaskListener listener) { + try { + return new ExpandableMessage(backref).expandAll(run, listener); + } catch (Exception e) { + LOG.debug("Can't expand backref, returning as is", e); + return backref; + } + } + + @Extension + public static class ManuallyEnteredBackrefSourceDescriptor extends Descriptor { + @Override + public String getDisplayName() { + return "Manually entered backref"; + } + } + +} diff --git a/src/main/resources/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter/config.groovy b/src/main/resources/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter/config.groovy index 2b807f165..c059c8f05 100644 --- a/src/main/resources/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter/config.groovy +++ b/src/main/resources/org/jenkinsci/plugins/github/status/GitHubCommitStatusSetter/config.groovy @@ -14,6 +14,7 @@ f.section(title: _('Where:')) { f.section(title: _('What:')) { f.dropdownDescriptorSelector(title: _('Commit context: '), field: 'contextSource') f.dropdownDescriptorSelector(title: _('Status result: '), field: 'statusResultSource') + f.dropdownDescriptorSelector(title: _('Status backref: '), field: 'statusBackrefSource') } f.advanced { diff --git a/src/main/resources/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource/config.groovy b/src/main/resources/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource/config.groovy new file mode 100644 index 000000000..4f8a98388 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource/config.groovy @@ -0,0 +1,7 @@ +package org.jenkinsci.plugins.github.status.sources.BuildRefBackrefSource + + +def f = namespace(lib.FormTagLib); + +f.helpLink(url: descriptor.getHelpFile()) +f.helpArea() diff --git a/src/main/resources/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource/help.html b/src/main/resources/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource/help.html new file mode 100644 index 000000000..602bd33a4 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSource/help.html @@ -0,0 +1,3 @@ +
+ Points commit status backref back to the producing build page. +
diff --git a/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/config.groovy b/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/config.groovy new file mode 100644 index 000000000..1340398e3 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/config.groovy @@ -0,0 +1,8 @@ +package org.jenkinsci.plugins.github.status.sources.ManuallyEnteredBackrefSource + + +def f = namespace(lib.FormTagLib); + +f.entry(title: _('Backref URL'), field: 'backref') { + f.textbox() +} diff --git a/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/help-backref.html b/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/help-backref.html new file mode 100644 index 000000000..4528d2bcb --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/help-backref.html @@ -0,0 +1,3 @@ +
+ A backref URL. Allows env vars and token macro. +
diff --git a/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/help.html b/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/help.html new file mode 100644 index 000000000..9dfe523d5 --- /dev/null +++ b/src/main/resources/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredBackrefSource/help.html @@ -0,0 +1,3 @@ +
+ A manually entered backref URL. +
diff --git a/src/test/java/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSourceTest.java b/src/test/java/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSourceTest.java new file mode 100644 index 000000000..7955759c4 --- /dev/null +++ b/src/test/java/org/jenkinsci/plugins/github/status/sources/BuildRefBackrefSourceTest.java @@ -0,0 +1,45 @@ +package org.jenkinsci.plugins.github.status.sources; + +import hudson.model.FreeStyleProject; +import hudson.model.Run; +import hudson.model.TaskListener; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.jvnet.hudson.test.JenkinsRule; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.mockito.runners.MockitoJUnitRunner; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; + +/** + * @author pupssman (Kalinin Ivan) + */ +@RunWith(MockitoJUnitRunner.class) +public class BuildRefBackrefSourceTest { + + @Rule + public JenkinsRule jenkinsRule = new JenkinsRule(); + + @Mock(answer = Answers.RETURNS_MOCKS) + private TaskListener listener; + + @Test + /** + * Should've used mocked Run, but getAbsoluteUrl is final. + * + * @throws Exception + */ + public void shouldReturnRunAbsoluteUrl() throws Exception { + Run run = jenkinsRule.buildAndAssertSuccess(jenkinsRule.createFreeStyleProject()); + + String result = new BuildRefBackrefSource().get(run, listener); + assertThat("state", result, is(run.getAbsoluteUrl())); + } + +} diff --git a/src/test/java/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredSourcesTest.java b/src/test/java/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredSourcesTest.java index 2aea545ba..b583fd113 100644 --- a/src/test/java/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredSourcesTest.java +++ b/src/test/java/org/jenkinsci/plugins/github/status/sources/ManuallyEnteredSourcesTest.java @@ -48,4 +48,13 @@ public void shouldExpandSha() throws Exception { String context = new ManuallyEnteredShaSource("").get(run, listener); assertThat(context, equalTo(EXPANDED)); } + + @Test + public void shouldExpandBackref() throws Exception { + when(run.getEnvironment(listener)).thenReturn(env); + when(env.expand(Matchers.anyString())).thenReturn(EXPANDED); + + String context = new ManuallyEnteredBackrefSource("").get(run, listener); + assertThat(context, equalTo(EXPANDED)); + } } \ No newline at end of file