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

Jenkins-65697 - feat - added BITBUCKET_PAYLOAD to multi-branch #103

Merged
merged 1 commit into from
Aug 11, 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
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@
<artifactId>workflow-multibranch</artifactId>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>git</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>scm-api</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class BitBucketMultibranchTrigger extends Trigger<WorkflowMultiBranchProj
private static final Logger LOGGER = Logger.getLogger(BitBucketMultibranchTrigger.class.getName());

private String overrideUrl;
private String payload;

@DataBoundConstructor
public BitBucketMultibranchTrigger() { }
Expand All @@ -34,6 +35,14 @@ public void setOverrideUrl(String overrideUrl){
this.overrideUrl = overrideUrl;
}

public void setPayload(String payload) {
this.payload = payload;
}

public String getPayload() {
return payload;
}

@Extension
public static class MultibranchDescriptor extends TriggerDescriptor {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.cloudbees.jenkins.plugins;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.EnvVars;
import hudson.Extension;
import hudson.model.*;
import jenkins.branch.MultiBranchProject;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;

@Extension
public class BitbucketEnvironmentContributor extends EnvironmentContributor {
private static final Logger LOGGER = Logger.getLogger(BitbucketEnvironmentContributor.class.getName());

@Override
public void buildEnvironmentFor(@NonNull Run r, @NonNull EnvVars envs, @NonNull TaskListener listener) throws IOException, InterruptedException {
super.buildEnvironmentFor(r, envs, listener);
}

@SuppressWarnings("rawtypes")
@Override
public void buildEnvironmentFor(@NonNull Job j, @NonNull EnvVars envs, @NonNull TaskListener listener) throws IOException, InterruptedException {
super.buildEnvironmentFor(j, envs, listener);
ItemGroup parent = j.getParent();
AtomicReference<BitBucketMultibranchTrigger> bitBucketMultibranchTrigger = new AtomicReference<>(null);
if ( parent instanceof MultiBranchProject){
((MultiBranchProject<?, ?>) parent).getTriggers().forEach((triggerDescriptor, trigger) -> {
if ( trigger instanceof BitBucketMultibranchTrigger){
bitBucketMultibranchTrigger.set((BitBucketMultibranchTrigger) trigger);
}
});
}

if ( bitBucketMultibranchTrigger.get() != null){
if ( bitBucketMultibranchTrigger.get().getPayload() == null){
LOGGER.finest("BITBUCKET_PAYLOAD is null, ignoring");
} else {
envs.put("BITBUCKET_PAYLOAD", bitBucketMultibranchTrigger.get().getPayload());
}
}
}
}
32 changes: 30 additions & 2 deletions src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.cloudbees.jenkins.plugins;

import hudson.model.CauseAction;
import hudson.model.Job;
import hudson.plugins.git.GitSCM;
import hudson.plugins.git.GitStatus;
Expand All @@ -12,6 +13,7 @@
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;

Expand Down Expand Up @@ -92,8 +94,34 @@ public void triggerMatchingJobs(String user, String url, String scm, String payl
for (SCMSource scmSource : scmSources) {
LOGGER.log(Level.FINER, "Considering candidate scmSource {0}", scmSource);
if (match(scmSource, remote)) {
LOGGER.log(Level.FINER, "Triggering BitBucket scmSourceOwner [{0}]", scmSourceOwner);
scmSourceOwner.onSCMSourceUpdated(scmSource);
if (scmSourceOwner instanceof WorkflowMultiBranchProject) {
LOGGER.finest("scmSourceOwner [" + scmSourceOwner.getName() + "] is of type WorkflowMultiBranchProject");
WorkflowMultiBranchProject workflowMultiBranchProject = (WorkflowMultiBranchProject) scmSourceOwner;
AtomicReference<BitBucketMultibranchTrigger> bitBucketMultibranchTrigger = new AtomicReference<>(null);
if ( workflowMultiBranchProject.getTriggers().isEmpty()) {
LOGGER.finest("No triggers found");
} else {
workflowMultiBranchProject.getTriggers().forEach(((triggerDescriptor, trigger) -> {
if (trigger instanceof BitBucketMultibranchTrigger) {
LOGGER.finest("Found BitBucketMultibranchTrigger type");
bitBucketMultibranchTrigger.set((BitBucketMultibranchTrigger) trigger);
}
}));
}
if ( bitBucketMultibranchTrigger.get() == null){
scmSourceOwner.onSCMSourceUpdated(scmSource);
} else {
if (workflowMultiBranchProject.isBuildable()){
bitBucketMultibranchTrigger.get().setPayload(payload);
BitBucketPushCause bitBucketPushCause = new BitBucketPushCause(user);
workflowMultiBranchProject.scheduleBuild2(0, new CauseAction(bitBucketPushCause));
} else {
LOGGER.finest("workflowMultiBranchProject is not builtable");
}
}
} else {
scmSourceOwner.onSCMSourceUpdated(scmSource);
}
} else if (scmSourceOwner instanceof WorkflowMultiBranchProject) {
LOGGER.finest("scmSourceOwner [" + scmSourceOwner.getName() + "] is of type WorkflowMultiBranchProject");
WorkflowMultiBranchProject workflowMultiBranchProject = (WorkflowMultiBranchProject) scmSourceOwner;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.cloudbees.jenkins.plugins;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.EnvVars;
import hudson.console.AnnotatedLargeText;
import hudson.model.*;
import jenkins.branch.BranchSource;
import jenkins.branch.MultiBranchProject;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
import jenkins.plugins.git.traits.BranchDiscoveryTrait;
import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jvnet.hudson.test.JenkinsRule;
import org.junit.Rule;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

import static org.junit.Assert.*;


@SuppressWarnings({"rawtypes", "ResultOfMethodCallIgnored"})
public class BitbucketMultibranchTest {

@Rule
public JenkinsRule jenkinsRule = new JenkinsRule();

@Rule
public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();


@Test
public void testWorkflowMultiBranchProject() throws Exception{
BitbucketEnvironmentContributor instance =
jenkinsRule.jenkins.getExtensionList(EnvironmentContributor.class).get(BitbucketEnvironmentContributor.class);
assertNotNull(instance);


// Initialize a Git repository
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "pipeline { agent any; triggers { bitbucketPush } stages { stage('Build') { steps { echo 'Building...' } } } }");
sampleRepo.git("add", "Jenkinsfile");
sampleRepo.git("commit", "--message=Initial commit");

// Create a new WorkflowMultiBranchProject
WorkflowMultiBranchProject workflowMultiBranchProject = jenkinsRule.jenkins.createProject(WorkflowMultiBranchProject.class, "my-project");

// Add a GitSCMSource to the project
GitSCMSource gitSource = new GitSCMSource(sampleRepo.toString());
gitSource.getTraits().add(new BranchDiscoveryTrait());

workflowMultiBranchProject.getSourcesList().add(new BranchSource(gitSource));

// Schedule and find a branch project
WorkflowJob job = scheduleAndFindBranchProject(workflowMultiBranchProject);


// Get the last build and perform assertions
WorkflowRun build = job.getLastBuild();
assertNotNull(build);
assertEquals(1, build.getNumber());
jenkinsRule.assertBuildStatusSuccess(build);
jenkinsRule.assertLogContains("Branch indexing", build);
}

private static class Bla extends CauseAction implements EnvironmentContributingAction {

@Override
public void buildEnvironment(@NonNull Run<?, ?> run, @NonNull EnvVars env) {
EnvironmentContributingAction.super.buildEnvironment(run, env);
env.put("BITBUCKET_PAYLOAD", "checking_payload");
}
}

private WorkflowJob scheduleAndFindBranchProject(WorkflowMultiBranchProject workflowMultiBranchProject) throws Exception {

// Schedule indexing and wait for completion
Queue.Item queueItem = workflowMultiBranchProject.scheduleBuild2(0,
new CauseAction(new BitBucketPushCause("tzachs")), new Bla());

Queue.Executable executable = Objects.requireNonNull(queueItem).getFuture().get();
if ( executable instanceof MultiBranchProject.BranchIndexing){
MultiBranchProject.BranchIndexing branchIndexing = (MultiBranchProject.BranchIndexing) executable;
String multiBranchLog = getLog(branchIndexing.getLogText());
jenkinsRule.assertStringContains(multiBranchLog, "Starting branch indexing");
jenkinsRule.assertStringContains(multiBranchLog, "Started by BitBucket push by tzachs");
}
jenkinsRule.waitUntilNoActivity();

return workflowMultiBranchProject.getItem("master");

}

private String getLog(AnnotatedLargeText logText) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();

logText.writeLogTo(0, baos);

return baos.toString(StandardCharsets.UTF_8);
}
}
Loading