Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support GitHubAppCredentials owner inference when specified on a pipeline using GitHub SCM #396

Merged
merged 3 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<properties>
<changelist>999999-SNAPSHOT</changelist>
<jenkins.version>2.361.4</jenkins.version>
<jenkins.version>2.440.3</jenkins.version>
<useBeta>true</useBeta>
</properties>

Expand All @@ -41,11 +41,17 @@
<dependencies>
<dependency>
<groupId>io.jenkins.tools.bom</groupId>
<artifactId>bom-2.361.x</artifactId>
<version>2102.v854b_fec19c92</version>
<artifactId>bom-2.440.x</artifactId>
<version>3276.vcd71db_867fb_2</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<!-- TODO remove when available in bom-2.440.x -->
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>github-branch-source</artifactId>
<version>1797.v86fdb_4d57d43</version>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import edu.hm.hafner.util.FilteredLog;
import edu.umd.cs.findbugs.annotations.CheckForNull;

import org.jenkinsci.plugins.github_branch_source.GitHubAppCredentials;
import hudson.model.Job;
import hudson.model.Run;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.apache.commons.lang3.StringUtils;

import edu.hm.hafner.util.VisibleForTesting;
import edu.umd.cs.findbugs.annotations.Nullable;

import org.kohsuke.github.GHCheckRun;
import org.kohsuke.github.GHCheckRunBuilder;
Expand All @@ -35,6 +36,9 @@
private final PluginLogger buildLogger;
private final String gitHubUrl;

@Nullable
private StandardUsernameCredentials credentials;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

credentials where moved from method variable to class field. This helps GitHubChecksPublisherITest to check that owner is propagated from context to credentials.


/**
* Creates a new instance of GitHubChecksPublisher.
*
Expand Down Expand Up @@ -63,9 +67,8 @@
@Override
public void publish(final ChecksDetails details) {
try {
StandardUsernameCredentials credentials = context.getCredentials();
// Prevent publication with unsupported credential types
switch (credentials.getClass().getSimpleName()) {
switch (getCredentials().getClass().getSimpleName()) {

Check warning on line 71 in src/main/java/io/jenkins/plugins/checks/github/GitHubChecksPublisher.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 71 is only partially covered, one branch is missing
case "GitHubAppCredentials":
case "VaultUsernamePasswordCredentialImpl":
break;
Expand All @@ -74,12 +77,12 @@
}

String apiUri = null;
if (credentials instanceof GitHubAppCredentials) {
apiUri = ((GitHubAppCredentials) credentials).getApiUri();
if (getCredentials() instanceof GitHubAppCredentials) {

Check warning on line 80 in src/main/java/io/jenkins/plugins/checks/github/GitHubChecksPublisher.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 80 is only partially covered, one branch is missing
apiUri = ((GitHubAppCredentials) getCredentials()).getApiUri();
}

GitHub gitHub = Connector.connect(StringUtils.defaultIfBlank(apiUri, gitHubUrl),
credentials);
getCredentials());

GitHubChecksDetails gitHubDetails = new GitHubChecksDetails(details);

Expand Down Expand Up @@ -124,12 +127,27 @@
@VisibleForTesting
GHCheckRunBuilder getCreator(final GitHub gitHub, final GitHubChecksDetails details) throws IOException {
GHCheckRunBuilder builder = gitHub.getRepository(context.getRepository())
.createCheckRun(details.getName(), context.getHeadSha())
.withStartedAt(details.getStartedAt().orElse(Date.from(Instant.now())));
.createCheckRun(details.getName(), context.getHeadSha())
.withStartedAt(details.getStartedAt().orElse(Date.from(Instant.now())));

return applyDetails(builder, details);
}

@VisibleForTesting
StandardUsernameCredentials getCredentials() {
if (credentials == null) {
credentials = context.getCredentials();
if (credentials instanceof GitHubAppCredentials) {

Check warning on line 140 in src/main/java/io/jenkins/plugins/checks/github/GitHubChecksPublisher.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 140 is only partially covered, one branch is missing
final var gitHubAppCredentials = (GitHubAppCredentials) credentials;
if (context instanceof GitHubSCMSourceChecksContext) {

Check warning on line 142 in src/main/java/io/jenkins/plugins/checks/github/GitHubChecksPublisher.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 142 is only partially covered, one branch is missing
final var gitHubSCMSourceChecksContext = (GitHubSCMSourceChecksContext) context;
credentials = gitHubAppCredentials.withOwner(gitHubSCMSourceChecksContext.getOwner());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I think it is undesirable to have the withOwner method be considered a public API of the plugin. Is there a reason we cannot use Connector.lookupScanCredentials from github-branch-source instead to handle contextualization automatically? It looks like it would require some API changes to SCMFacade methods to have them accept an owner parameter, but would that be ok, or is there some fundamental problem with it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds fine if someone wants to work on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll create a follow-up PR ASAP.

}
}
}
return credentials;
}

private GHCheckRunBuilder applyDetails(final GHCheckRunBuilder builder, final GitHubChecksDetails details) {
builder
.withStatus(details.getStatus())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public String getRepository() {
}
}

String getOwner() {
return Optional.ofNullable(resolveSource()).map(GitHubSCMSource::getRepoOwner).orElse(null);
}

@Override
public boolean isValid(final FilteredLog logger) {
logger.logError("Trying to resolve checks parameters from GitHub SCM...");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@

import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;

/**
Expand Down Expand Up @@ -325,6 +328,15 @@ public void testChecksPublisherUpdatesCorrectly() throws Exception {
"https://github.example.com/"
);

// Check that the owner is passed from context to credentials
if (context instanceof GitHubSCMSourceChecksContext) {
var credentials = publisher.getCredentials();
if (credentials instanceof GitHubAppCredentials) {
var gitHubAppCredentials = (GitHubAppCredentials) credentials;
assertThat(gitHubAppCredentials.getOwner()).isEqualTo("XiongKezhi");
}
}

assertThat(context.getId(checksName1)).isNotPresent();
assertThat(context.getId(checksName2)).isNotPresent();

Expand Down