Skip to content

Commit

Permalink
Merge pull request #13 from jenkinsci/checks-for-queue-items
Browse files Browse the repository at this point in the history
Publish checks for job
  • Loading branch information
XiongKezhi authored Aug 4, 2020
2 parents 21cc277 + 7f249ee commit c1dbec9
Show file tree
Hide file tree
Showing 9 changed files with 451 additions and 207 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<useBeta>true</useBeta>

<!-- Jenkins Plug-in Dependencies Versions -->
<checks-api.version>0.1.0</checks-api.version>
<checks-api.version>0.1.1-rc24.26e46eb1548a</checks-api.version>
<plugin-util-api.version>1.2.2</plugin-util-api.version>
<github-api.version>1.115</github-api.version>
<github-branch-source.version>2.8.3</github-branch-source.version>
Expand Down
130 changes: 110 additions & 20 deletions src/main/java/io/jenkins/plugins/checks/github/GitHubChecksContext.java
Original file line number Diff line number Diff line change
@@ -1,37 +1,72 @@
package io.jenkins.plugins.checks.github;

import edu.hm.hafner.util.VisibleForTesting;
import edu.umd.cs.findbugs.annotations.Nullable;
import hudson.model.Job;
import hudson.model.Run;
import jenkins.plugins.git.AbstractGitSCMSource;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMRevision;
import org.jenkinsci.plugins.displayurlapi.DisplayURLProvider;
import org.jenkinsci.plugins.github_branch_source.GitHubAppCredentials;
import org.jenkinsci.plugins.github_branch_source.GitHubSCMSource;
import hudson.model.Run;
import jenkins.scm.api.SCMSource;
import org.jenkinsci.plugins.github_branch_source.PullRequestSCMRevision;

import java.util.Optional;

/**
* Provides check properties that should be resolved Jenkins job.
*/
class GitHubChecksContext {
private final GitHubSCMSource source;
private final GitHubAppCredentials credentials;
private final String headSha;
private final String url;
@Nullable
private final Run<?, ?> run;
private final Job<?, ?> job;
private final GitHubSCMFacade scmFacade;
private final DisplayURLProvider urlProvider;

/**
* Creates a {@link GitHubChecksContext} according to the run. All attributes are computed during this period.
*
* @param run
* a run of a GitHub Branch Source project
* @param run a run of a GitHub Branch Source project
*/
GitHubChecksContext(final Run<?, ?> run) {
GitHubContextResolver resolver = new GitHubContextResolver();
this.source = resolver.resolveSource(run);
this.credentials = resolver.resolveCredentials(source, run);
this.headSha = resolver.resolveHeadSha(source, run);
this.url = run.getParent().getAbsoluteUrl() + run.getNumber() + "/";
this(run, new GitHubSCMFacade(), DisplayURLProvider.get());
}

/**
* Creates a {@link GitHubChecksContext} according to the run. All attributes are computed during this period.
*
* @param job a run of a GitHub Branch Source project
*/
GitHubChecksContext(final Job<?, ?> job) {
this(job, new GitHubSCMFacade(), DisplayURLProvider.get());
}

@VisibleForTesting
GitHubChecksContext(final Run<?, ?> run, final GitHubSCMFacade scmFacade, final DisplayURLProvider urlProvider) {
this.job = run.getParent();
this.run = run;
this.scmFacade = scmFacade;
this.urlProvider = urlProvider;
}

@VisibleForTesting
@SuppressWarnings("PMD.NullAssignment")
// run can be null when job is provided
GitHubChecksContext(final Job<?, ?> job, final GitHubSCMFacade scmFacade, final DisplayURLProvider urlProvider) {
this.job = job;
this.run = null;
this.scmFacade = scmFacade;
this.urlProvider = urlProvider;
}

/**
* Returns the {@link SCMSource} of the run.
* Returns the Jenkins job.
*
* @return {@link SCMSource} of the run or null
* @return job for which the checks will be based on
*/
public SCMSource getSource() {
return source;
public Job<?, ?> getJob() {
return job;
}

/**
Expand All @@ -40,7 +75,7 @@ public SCMSource getSource() {
* @return the commit sha of the run or null
*/
public String getHeadSha() {
return headSha;
return resolveHeadSha();
}

/**
Expand All @@ -50,6 +85,7 @@ public String getHeadSha() {
* @return the source repository's full name
*/
public String getRepository() {
GitHubSCMSource source = resolveSource();
return source.getRepoOwner() + "/" + source.getRepository();
}

Expand All @@ -59,7 +95,7 @@ public String getRepository() {
* @return the credentials or null
*/
public GitHubAppCredentials getCredentials() {
return credentials;
return resolveCredentials();
}

/**
Expand All @@ -68,6 +104,60 @@ public GitHubAppCredentials getCredentials() {
* @return the URL of the summary page
*/
public String getURL() {
return url;
if (run == null) {
return urlProvider.getJobURL(job);
}
else {
return urlProvider.getRunURL(run);
}
}

private GitHubSCMSource resolveSource() {
Optional<GitHubSCMSource> source
= scmFacade.findGitHubSCMSource(job);
if (!source.isPresent()) {
throw new IllegalStateException("No GitHub SCM source available for job: " + job.getName());
}

return source.get();
}

private GitHubAppCredentials resolveCredentials() {
String credentialsId = resolveSource().getCredentialsId();
if (credentialsId == null) {
throw new IllegalStateException("No credentials available for job: " + job.getName());
}

Optional<GitHubAppCredentials> foundCredentials
= scmFacade.findGitHubAppCredentials(job, credentialsId);
if (!foundCredentials.isPresent()) {
throw new IllegalStateException("No GitHub APP credentials available for job: " + job.getName());
}

return foundCredentials.get();
}

private String resolveHeadSha() {
Optional<SCMHead> head = scmFacade.findHead(job);
if (!head.isPresent()) {
throw new IllegalStateException("No SCM head available for job: " + job.getName());
}

Optional<SCMRevision> revision = scmFacade.findRevision(resolveSource(), head.get());
if (!revision.isPresent()) {
throw new IllegalStateException(
String.format("No SCM revision available for repository: %s and head: %s",
getRepository(), head.get().getName()));
}

if (revision.get() instanceof AbstractGitSCMSource.SCMRevisionImpl) {
return ((AbstractGitSCMSource.SCMRevisionImpl) revision.get()).getHash();
}
else if (revision.get() instanceof PullRequestSCMRevision) {
return ((PullRequestSCMRevision) revision.get()).getPullHash();
}
else {
throw new IllegalStateException("Unsupported revision type: " + revision.get().getClass().getName());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,25 @@
import org.jenkinsci.plugins.github_branch_source.Connector;
import org.jenkinsci.plugins.github_branch_source.GitHubAppCredentials;

import hudson.model.Run;

import io.jenkins.plugins.checks.api.ChecksDetails;
import io.jenkins.plugins.checks.api.ChecksPublisher;

/**
* A publisher which publishes GitHub check runs.
*/
public class GitHubChecksPublisher extends ChecksPublisher {
private final Run<?, ?> run;
private final GitHubChecksContext context;

/**
* {@inheritDoc}.
*
* @param run
* a run of a GitHub branch source project
* @param context
* a context which contains SCM properties
*/
public GitHubChecksPublisher(final Run<?, ?> run) {
public GitHubChecksPublisher(final GitHubChecksContext context) {
super();

this.run = run;
this.context = context;
}

private static final Logger LOGGER = Logger.getLogger(GitHubChecksPublisher.class.getName());
Expand All @@ -51,11 +49,10 @@ public GitHubChecksPublisher(final Run<?, ?> run) {
@Override
public void publish(final ChecksDetails details) {
try {
GitHubChecksContext context = new GitHubChecksContext(run);
GitHubAppCredentials credentials = context.getCredentials();
GitHub gitHub = Connector.connect(StringUtils.defaultIfBlank(credentials.getApiUri(), GITHUB_URL),
credentials);
GHCheckRunBuilder builder = createBuilder(gitHub, new GitHubChecksDetails(details), context);
GHCheckRunBuilder builder = createBuilder(gitHub, new GitHubChecksDetails(details));
builder.create();
}
catch (IllegalStateException | IOException e) {
Expand All @@ -65,8 +62,7 @@ public void publish(final ChecksDetails details) {
}

@VisibleForTesting
GHCheckRunBuilder createBuilder(final GitHub gitHub, final GitHubChecksDetails details,
final GitHubChecksContext context) throws IOException {
GHCheckRunBuilder createBuilder(final GitHub gitHub, final GitHubChecksDetails details) throws IOException {
GHCheckRunBuilder builder = gitHub.getRepository(context.getRepository())
.createCheckRun(details.getName(), context.getHeadSha())
.withStatus(details.getStatus())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.Optional;

import edu.hm.hafner.util.VisibleForTesting;
import hudson.model.Job;
import hudson.model.TaskListener;
import org.jenkinsci.plugins.github_branch_source.GitHubSCMSource;

import hudson.Extension;
Expand Down Expand Up @@ -33,17 +35,28 @@ public GitHubChecksPublisherFactory() {
}

@Override
protected Optional<ChecksPublisher> createPublisher(final Run<?, ?> run) {
Optional<GitHubSCMSource> source = scmFacade.findGitHubSCMSource(run);
protected Optional<ChecksPublisher> createPublisher(final Run<?, ?> run, final TaskListener taskListener) {
return createPublisher(new GitHubChecksContext(run));
}

@Override
protected Optional<ChecksPublisher> createPublisher(final Job<?, ?> job, final TaskListener taskListener) {
return createPublisher(new GitHubChecksContext(job));
}

protected Optional<ChecksPublisher> createPublisher(final GitHubChecksContext context) {
Job<?, ?> job = context.getJob();
Optional<GitHubSCMSource> source = scmFacade.findGitHubSCMSource(job);
if (!source.isPresent()) {
return Optional.empty();
}

String credentialsId = source.get().getCredentialsId();
if (credentialsId == null || !scmFacade.findGitHubAppCredentials(run, credentialsId).isPresent()) {
if (credentialsId == null
|| !scmFacade.findGitHubAppCredentials(job, credentialsId).isPresent()) {
return Optional.empty();
}

return Optional.of(new GitHubChecksPublisher(run));
return Optional.of(new GitHubChecksPublisher(context));
}
}

This file was deleted.

Loading

0 comments on commit c1dbec9

Please sign in to comment.