Skip to content

Commit 21c5c13

Browse files
authored
Merge pull request #826 from janfaracik/detail-widget
Add GitHub branch and pull request info to the 'Details' widget
2 parents 50ffb78 + da8130c commit 21c5c13

File tree

10 files changed

+487
-2
lines changed

10 files changed

+487
-2
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<hpi.compatibleSinceVersion>2.2.0</hpi.compatibleSinceVersion>
3636
<!-- https://www.jenkins.io/doc/developer/plugin-development/choosing-jenkins-baseline/ -->
3737
<jenkins.baseline>2.504</jenkins.baseline>
38-
<jenkins.version>${jenkins.baseline}.1</jenkins.version>
38+
<jenkins.version>${jenkins.baseline}.3</jenkins.version>
3939
<spotless.check.skip>false</spotless.check.skip>
4040
</properties>
4141

@@ -44,7 +44,7 @@
4444
<dependency>
4545
<groupId>io.jenkins.tools.bom</groupId>
4646
<artifactId>bom-${jenkins.baseline}.x</artifactId>
47-
<version>5294.va_d2e144c80e1</version>
47+
<version>5506.va_222b_131ec34</version>
4848
<type>pom</type>
4949
<scope>import</scope>
5050
</dependency>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.jenkinsci.plugins.github_branch_source;
2+
3+
import edu.umd.cs.findbugs.annotations.Nullable;
4+
import hudson.model.Actionable;
5+
import hudson.model.Run;
6+
import jenkins.model.details.Detail;
7+
import jenkins.model.details.DetailGroup;
8+
import jenkins.scm.api.SCMDetailGroup;
9+
import jenkins.scm.api.metadata.ObjectMetadataAction;
10+
11+
public class GitHubBranchDetail extends Detail {
12+
public GitHubBranchDetail(Actionable object) {
13+
super(object);
14+
}
15+
16+
@Nullable
17+
@Override
18+
public String getIconClassName() {
19+
return "symbol-git-branch-outline plugin-ionicons-api";
20+
}
21+
22+
@Nullable
23+
@Override
24+
public String getDisplayName() {
25+
return getObjectMetadataAction().getObjectDisplayName();
26+
}
27+
28+
@Override
29+
public String getLink() {
30+
return getObjectMetadataAction().getObjectUrl();
31+
}
32+
33+
@Override
34+
public DetailGroup getGroup() {
35+
return SCMDetailGroup.get();
36+
}
37+
38+
private ObjectMetadataAction getObjectMetadataAction() {
39+
Run<?, ?> run = (Run<?, ?>) getObject();
40+
return run.getParent().getAction(ObjectMetadataAction.class);
41+
}
42+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package org.jenkinsci.plugins.github_branch_source;
2+
3+
import hudson.model.Actionable;
4+
import hudson.model.Run;
5+
import jenkins.model.details.Detail;
6+
import jenkins.model.details.DetailGroup;
7+
import jenkins.plugins.git.AbstractGitSCMSource;
8+
import jenkins.scm.api.SCMDetailGroup;
9+
import jenkins.scm.api.SCMRevision;
10+
import jenkins.scm.api.SCMRevisionAction;
11+
12+
public class GitHubCommitDetail extends Detail {
13+
public GitHubCommitDetail(Actionable object) {
14+
super(object);
15+
}
16+
17+
public String getIconClassName() {
18+
return "symbol-git-commit-outline plugin-ionicons-api";
19+
}
20+
21+
@Override
22+
public String getDisplayName() {
23+
SCMRevision revision = getRevision();
24+
25+
if (revision == null) {
26+
return null;
27+
}
28+
29+
if (revision instanceof AbstractGitSCMSource.SCMRevisionImpl abstractRevision) {
30+
return abstractRevision.getHash().substring(0, 7);
31+
}
32+
33+
if (revision instanceof PullRequestSCMRevision pullRequestSCMRevision) {
34+
return pullRequestSCMRevision.getPullHash().substring(0, 7);
35+
}
36+
37+
return null;
38+
}
39+
40+
@Override
41+
public String getLink() {
42+
SCMRevision revision = getRevision();
43+
44+
if (revision == null) {
45+
return null;
46+
}
47+
48+
if (revision instanceof AbstractGitSCMSource.SCMRevisionImpl abstractRevision) {
49+
return new GitHubRepositoryDetail(getObject()).getLink() + "/commit/" + abstractRevision.getHash();
50+
}
51+
52+
if (revision instanceof PullRequestSCMRevision pullRequestSCMRevision) {
53+
Run<?, ?> run = (Run<?, ?>) getObject();
54+
GitHubLink repoLink = run.getParent().getAction(GitHubLink.class);
55+
return repoLink.getUrl() + "/commits/" + pullRequestSCMRevision.getPullHash();
56+
}
57+
58+
return null;
59+
}
60+
61+
@Override
62+
public DetailGroup getGroup() {
63+
return SCMDetailGroup.get();
64+
}
65+
66+
private SCMRevision getRevision() {
67+
SCMRevisionAction scmRevisionAction = getObject().getAction(SCMRevisionAction.class);
68+
69+
if (scmRevisionAction == null) {
70+
return null;
71+
}
72+
73+
return scmRevisionAction.getRevision();
74+
}
75+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.jenkinsci.plugins.github_branch_source;
2+
3+
import edu.umd.cs.findbugs.annotations.NonNull;
4+
import hudson.Extension;
5+
import hudson.model.Run;
6+
import java.util.ArrayList;
7+
import java.util.Collections;
8+
import java.util.List;
9+
import jenkins.model.details.Detail;
10+
import jenkins.model.details.DetailFactory;
11+
import jenkins.scm.api.SCMRevision;
12+
import jenkins.scm.api.SCMRevisionAction;
13+
import jenkins.scm.api.SCMSource;
14+
15+
@Extension
16+
public final class GitHubDetailFactory extends DetailFactory<Run> {
17+
18+
@Override
19+
public Class<Run> type() {
20+
return Run.class;
21+
}
22+
23+
@NonNull
24+
@Override
25+
public List<? extends Detail> createFor(@NonNull Run target) {
26+
SCMSource src = SCMSource.SourceByItem.findSource(target.getParent());
27+
28+
// Don't add details for non-GitHub SCM sources
29+
if (!(src instanceof GitHubSCMSource)) {
30+
return Collections.emptyList();
31+
}
32+
33+
SCMRevisionAction scmRevisionAction = target.getAction(SCMRevisionAction.class);
34+
35+
if (scmRevisionAction == null) {
36+
return Collections.emptyList();
37+
}
38+
39+
List<Detail> details = new ArrayList<>();
40+
SCMRevision revision = scmRevisionAction.getRevision();
41+
42+
if (revision instanceof PullRequestSCMRevision) {
43+
details.add(new GitHubPullRequestDetail(target));
44+
} else {
45+
details.add(new GitHubBranchDetail(target));
46+
}
47+
48+
details.add(new GitHubCommitDetail(target));
49+
details.add(new GitHubRepositoryDetail(target));
50+
51+
return details;
52+
}
53+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.jenkinsci.plugins.github_branch_source;
2+
3+
import edu.umd.cs.findbugs.annotations.Nullable;
4+
import hudson.model.Actionable;
5+
import hudson.model.Run;
6+
import jenkins.model.details.Detail;
7+
import jenkins.model.details.DetailGroup;
8+
import jenkins.scm.api.SCMDetailGroup;
9+
import jenkins.scm.api.metadata.ObjectMetadataAction;
10+
11+
public class GitHubPullRequestDetail extends Detail {
12+
public GitHubPullRequestDetail(Actionable object) {
13+
super(object);
14+
}
15+
16+
@Nullable
17+
@Override
18+
public String getIconClassName() {
19+
return "symbol-git-pull-request-outline plugin-ionicons-api";
20+
}
21+
22+
@Nullable
23+
@Override
24+
public String getDisplayName() {
25+
return getObjectMetadataAction().getObjectDisplayName();
26+
}
27+
28+
@Override
29+
public String getLink() {
30+
return getObjectMetadataAction().getObjectUrl();
31+
}
32+
33+
@Override
34+
public DetailGroup getGroup() {
35+
return SCMDetailGroup.get();
36+
}
37+
38+
private ObjectMetadataAction getObjectMetadataAction() {
39+
Run<?, ?> run = (Run<?, ?>) getObject();
40+
return run.getParent().getAction(ObjectMetadataAction.class);
41+
}
42+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package org.jenkinsci.plugins.github_branch_source;
2+
3+
import edu.umd.cs.findbugs.annotations.Nullable;
4+
import hudson.model.Actionable;
5+
import hudson.model.Run;
6+
import jenkins.model.details.Detail;
7+
import jenkins.model.details.DetailGroup;
8+
import jenkins.scm.api.SCMDetailGroup;
9+
import jenkins.scm.api.SCMSource;
10+
11+
public class GitHubRepositoryDetail extends Detail {
12+
public GitHubRepositoryDetail(Actionable object) {
13+
super(object);
14+
}
15+
16+
@Nullable
17+
@Override
18+
public String getIconClassName() {
19+
return "symbol-logo-github plugin-ionicons-api";
20+
}
21+
22+
@Nullable
23+
@Override
24+
public String getDisplayName() {
25+
GitHubSCMSource source = getSCMSource();
26+
27+
if (source == null) {
28+
return null;
29+
}
30+
31+
return source.getRepoOwner() + "/" + source.getRepository();
32+
}
33+
34+
@Override
35+
public String getLink() {
36+
GitHubSCMSource source = getSCMSource();
37+
38+
if (source == null) {
39+
return null;
40+
}
41+
42+
return source.getRepositoryUrl();
43+
}
44+
45+
@Override
46+
public DetailGroup getGroup() {
47+
return SCMDetailGroup.get();
48+
}
49+
50+
private GitHubSCMSource getSCMSource() {
51+
var source = SCMSource.SourceByItem.findSource(((Run) getObject()).getParent());
52+
53+
if (source instanceof GitHubSCMSource githubSource) {
54+
return githubSource;
55+
}
56+
57+
return null;
58+
}
59+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.jenkinsci.plugins.github_branch_source;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
import static org.mockito.Mockito.*;
5+
6+
import hudson.model.Job;
7+
import hudson.model.Run;
8+
import jenkins.scm.api.metadata.ObjectMetadataAction;
9+
import org.junit.jupiter.api.Test;
10+
11+
class GitHubBranchDetailTest {
12+
13+
@Test
14+
void displaysAsExpected() {
15+
Run run = mock(Run.class);
16+
Job job = mock(Job.class);
17+
when(run.getParent()).thenReturn(job);
18+
ObjectMetadataAction metadata = mock(ObjectMetadataAction.class);
19+
when(metadata.getObjectDisplayName()).thenReturn("main");
20+
when(metadata.getObjectUrl()).thenReturn("https://github.com/octo/hello-world/tree/main");
21+
when(job.getAction(ObjectMetadataAction.class)).thenReturn(metadata);
22+
23+
GitHubBranchDetail detail = new GitHubBranchDetail(run);
24+
25+
assertEquals("main", detail.getDisplayName());
26+
assertEquals("https://github.com/octo/hello-world/tree/main", detail.getLink());
27+
}
28+
}

0 commit comments

Comments
 (0)