Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@

@Override
public String getHeadSha() {
// When checkout fails, BuildData is either absent from the current run or
// carries a stale build number from a previous build. In both cases,
// GIT_COMMIT from run.getEnvironment() is also unreliable because
// GitSCM.buildEnvironment() walks back through previous builds' BuildData.
BuildData gitBuildData = run.getAction(BuildData.class);
if (gitBuildData == null

Check warning on line 56 in src/main/java/io/jenkins/plugins/checks/github/GitSCMChecksContext.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 56 is only partially covered, one branch is missing
|| gitBuildData.lastBuild == null
|| gitBuildData.lastBuild.getBuildNumber() != run.getNumber()) {

Check warning on line 58 in src/main/java/io/jenkins/plugins/checks/github/GitSCMChecksContext.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 58 is only partially covered, one branch is missing
return StringUtils.EMPTY;
}

try {
String head = getGitCommitEnvironment();
if (StringUtils.isNotBlank(head)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import hudson.model.TaskListener;
import hudson.plugins.git.GitSCM;
import hudson.plugins.git.UserRemoteConfig;
import hudson.plugins.git.util.Build;
import hudson.plugins.git.util.BuildData;
import jenkins.scm.api.SCMHead;
import org.jenkinsci.plugins.displayurlapi.DisplayURLProvider;
import org.jenkinsci.plugins.github_branch_source.GitHubAppCredentials;
Expand Down Expand Up @@ -78,6 +80,12 @@ void shouldCreateGitHubChecksPublisherFromRunForProjectWithValidGitSCM() throws
SCMFacade scmFacade = mock(SCMFacade.class);
EnvVars envVars = mock(EnvVars.class);

BuildData buildData = mock(BuildData.class);
Build lastBuild = mock(Build.class);
buildData.lastBuild = lastBuild;
when(lastBuild.getBuildNumber()).thenReturn(1);
when(run.getNumber()).thenReturn(1);
when(run.getAction(BuildData.class)).thenReturn(buildData);
when(run.getParent()).thenReturn(job);
when(run.getEnvironment(TaskListener.NULL)).thenReturn(envVars);
when(envVars.get("GIT_COMMIT")).thenReturn("a1b2c3");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,35 @@ void shouldRetrieveContextFromPipeline(JenkinsRule j) throws Exception {
assertThat(gitSCMChecksContext.getCredentialsId()).isEqualTo(CREDENTIALS_ID);
assertThat(gitSCMChecksContext.getHeadSha()).isEqualTo(EXISTING_HASH);
}

/**
* Verifies that when a checkout fails on a subsequent build, {@link GitSCMChecksContext#getHeadSha()}
* returns empty rather than returning the stale SHA from the previous successful build.
* This prevents checks from being posted against the wrong commit when checkout fails
* (e.g. due to network flakiness).
*/
@Test
void shouldReturnEmptyHeadShaWhenCheckoutFails(JenkinsRule j) throws Exception {
FreeStyleProject job = j.createFreeStyleProject();

// First build: successful checkout populates BuildData with the correct SHA
GitSCM scm = new GitSCM(GitSCM.createRepoList(HTTP_URL, CREDENTIALS_ID),
Collections.singletonList(new BranchSpec(EXISTING_HASH)),
null, null, Collections.emptyList());
job.setScm(scm);
Run<?, ?> successfulRun = buildSuccessfully(j, job);
assertThat(new GitSCMChecksContext(successfulRun, URL_NAME).getHeadSha()).isEqualTo(EXISTING_HASH);

// Second build: use a non-existent SHA to simulate checkout failure.
// The Git plugin carries over BuildData from the previous build, but since
// the checkout never completes, lastBuild.hudsonBuildNumber still refers
// to build #1.
job.setScm(new GitSCM(GitSCM.createRepoList(HTTP_URL, CREDENTIALS_ID),
Collections.singletonList(new BranchSpec("0000000000000000000000000000000000000001")),
null, null, Collections.emptyList()));
Run<?, ?> failedRun = j.assertBuildStatus(Result.FAILURE, job.scheduleBuild2(0, new Action[0]));

// Must return empty, not the previous build's SHA
assertThat(new GitSCMChecksContext(failedRun, URL_NAME).getHeadSha()).isEmpty();
}
}
Loading