Skip to content

Commit

Permalink
Use poll env when checking for ls-remote branches.
Browse files Browse the repository at this point in the history
  • Loading branch information
timbrown5 committed Sep 26, 2023
1 parent 0dab948 commit 62d9290
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/main/java/hudson/plugins/git/BranchSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public List<Branch> filterMatchingBranches(Collection<Branch> branches, EnvVars
return items;
}

private String getExpandedName(EnvVars env) {
public String getExpandedName(EnvVars env) {
String expandedName = env.expand(name);
if (expandedName.length() == 0) {
return "**";
Expand Down
34 changes: 23 additions & 11 deletions src/main/java/hudson/plugins/git/GitSCM.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@

import javax.servlet.ServletException;

import java.util.HashMap;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
Expand Down Expand Up @@ -711,9 +712,7 @@ private PollingResult compareRemoteRevisionWithImpl(Job<?, ?> project, Launcher
if (buildData.lastBuild != null) {
listener.getLogger().println("[poll] Last Built Revision: " + buildData.lastBuild.revision);
}

final EnvVars pollEnv = project instanceof AbstractProject ? GitUtils.getPollEnvironment((AbstractProject) project, workspace, launcher, listener, false) : lastBuild.getEnvironment(listener);

final String singleBranch = getSingleBranch(pollEnv);

if (!requiresWorkspaceForPolling(pollEnv)) {
Expand Down Expand Up @@ -751,35 +750,50 @@ private PollingResult compareRemoteRevisionWithImpl(Job<?, ?> project, Launcher
it.remove();
}
}

Map<BranchSpec, String> headMatches = new HashMap<>();
for (BranchSpec branchSpec : getBranches()) {
for (Entry<String, ObjectId> entry : heads.entrySet()) {
final String head = entry.getKey();
// head is "refs/(heads|tags|whatever)/branchName

// Use pollEnv here to include Parameters from lastBuild.
// first, check the a canonical git reference is configured
if (!branchSpec.matches(head, environment)) {

if (!branchSpec.matches(head, pollEnv)) {
// convert head `refs/(heads|tags|whatever)/branch` into shortcut notation `remote/branch`
String name;
Matcher matcher = GIT_REF.matcher(head);
if (matcher.matches()) name = remote + head.substring(matcher.group(1).length());
else name = remote + "/" + head;

if (!branchSpec.matches(name, environment)) continue;
// Use pollEnv here to include Parameters from lastBuild.
// Record which branches in the spec we have found a match for so we can alter users when branches are ignored.
if (branchSpec.matches(name, pollEnv)){
headMatches.put(branchSpec, name);
} else {
continue;
}
}

final ObjectId sha1 = entry.getValue();
Build built = buildData.getLastBuild(sha1);
if (built != null) {
listener.getLogger().println("[poll] Latest remote head revision on " + head + " is: " + sha1.getName() + " - already built by " + built.getBuildNumber());
continue;
}

listener.getLogger().println(MessageFormat.format("[poll] pollEnv {0}", pollEnv));
listener.getLogger().println("[poll] Latest remote head revision on " + head + " is: " + sha1.getName());
return BUILD_NOW;
}
}
// Tell users if there are branches in the spec that are ignored.
for (BranchSpec branchSpec : getBranches()) {
// If there is a branch in the spec that doesn't exist in the remote, tell the users (as this could means they aren't building something they expect to).
if (!headMatches.containsKey(branchSpec)) {
// If the branchSpec gets expanded using variables in the environment then print the original and expanded versions.
String branchSpecString = branchSpec.toString();
String expandedBranchSpec = branchSpec.getExpandedName(pollEnv);
String branchMessageString = "testing" == expandedBranchSpec ? String.format("'%s'", branchSpecString) : String.format("'%s' (%s)", branchSpecString, expandedBranchSpec);

Check warning on line 793 in src/main/java/hudson/plugins/git/GitSCM.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 793 is only partially covered, one branch is missing

Check warning on line 793 in src/main/java/hudson/plugins/git/GitSCM.java

View check run for this annotation

ci.jenkins.io / SpotBugs

ES_COMPARING_STRINGS_WITH_EQ

LOW: Comparison of String objects using == or != in hudson.plugins.git.GitSCM.compareRemoteRevisionWithImpl(Job, Launcher, FilePath, TaskListener)
Raw output
<p>This code compares <code>java.lang.String</code> objects for reference equality using the == or != operators. Unless both strings are either constants in a source file, or have been interned using the <code>String.intern()</code> method, the same string value may be represented by two different String objects. Consider using the <code>equals(Object)</code> method instead.</p>
listener.getLogger().println("[poll] Could not find remote head for branch in spec " + branchMessageString);
}
}
}
}
return NO_CHANGES;
Expand Down Expand Up @@ -809,7 +823,6 @@ private PollingResult compareRemoteRevisionWithImpl(Job<?, ?> project, Launcher
}

listener.getLogger().println("Polling for changes in");

Collection<Revision> candidates = getBuildChooser().getCandidateRevisions(
true, singleBranch, git, listener, buildData, new BuildChooserContextImpl(project, null, environment));

Expand Down Expand Up @@ -1144,7 +1157,6 @@ public EnvVars getEnvironment() {

if (candidates.isEmpty() ) {
final String singleBranch = environment.expand( getSingleBranch(environment) );

candidates = getBuildChooser().getCandidateRevisions(
false, singleBranch, git, listener, buildData, context);
}
Expand Down
36 changes: 36 additions & 0 deletions src/test/java/hudson/plugins/git/GitSCMTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.jenkinsci.plugins.tokenmacro.TokenMacro;
import org.jenkinsci.plugins.gitclient.*;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.Rule;
Expand Down Expand Up @@ -2448,6 +2449,41 @@ public void testPolling_environmentValueInBranchSpec() throws Exception {
assertFalse("No changes to git since last build, thus no new build is expected", project.poll(listener).hasChanges());
}

@Test
@Issue("JENKINS-20427")
public void testPolling_environmentValueInBranchSpecTriggersBuild() throws Exception {
assumeTrue("Test class max time " + MAX_SECONDS_FOR_THESE_TESTS + " exceeded", isTimeAvailable());
// create parameterized project with environment value in branch specification
WorkflowJob project = r.jenkins.createProject(WorkflowJob.class, "pipeline-remote-poll-with-param");
List<UserRemoteConfig> remotes = new ArrayList<>();
remotes.addAll(testRepo.remoteConfigs());
GitSCM scm = new GitSCM(
remotes,
Collections.singletonList(new BranchSpec("${MY_BRANCH}")),
null, null,
Collections.emptyList());
project.setDefinition(new CpsScmFlowDefinition(scm, "./Jenkinsfile"));
project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("MY_BRANCH", "master")));

// commit something in order to create an initial base version in git
commit(
"Jenkinsfile",
"node {\n" +
" echo 'Hello world!'\n" +
"}",
johnDoe,
"Add Jenkinsfile"
);

// build the project
Run<?,?> run = r.buildAndAssertStatus(Result.SUCCESS, project);

// commit something in order to check that polling detects the change.
commit("toto/commitFile2", johnDoe, "Commit number 2");

assertTrue("There are changes to git since last build, thus a new build is expected", project.poll(listener).hasChanges());
}

public void baseTestPolling_parentHead(List<GitSCMExtension> extensions) throws Exception {
// create parameterized project with environment value in branch specification
FreeStyleProject project = createFreeStyleProject();
Expand Down

0 comments on commit 62d9290

Please sign in to comment.