From 9b733c41bbe8f376dbd02a812d1a69be4c9c4f91 Mon Sep 17 00:00:00 2001
From: tzachs <259481+tzachs@users.noreply.github.com>
Date: Sun, 11 Aug 2024 21:57:02 +0300
Subject: [PATCH] Jenkins-65698 - feat - added BITBUCKET_PAYLOAD to
multi-branch
---
pom.xml | 13 +++
.../plugins/BitBucketMultibranchTrigger.java | 9 ++
.../BitbucketEnvironmentContributor.java | 44 ++++++++
.../jenkins/plugins/BitbucketJobProbe.java | 32 +++++-
.../plugins/BitbucketMultibranchTest.java | 106 ++++++++++++++++++
5 files changed, 202 insertions(+), 2 deletions(-)
create mode 100644 src/main/java/com/cloudbees/jenkins/plugins/BitbucketEnvironmentContributor.java
create mode 100644 src/test/java/com/cloudbees/jenkins/plugins/BitbucketMultibranchTest.java
diff --git a/pom.xml b/pom.xml
index 1778531..712466a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,19 @@
workflow-multibranch
+
+ org.jenkins-ci.plugins
+ git
+ tests
+ test
+
+
+ org.jenkins-ci.plugins
+ scm-api
+ tests
+ test
+
+
diff --git a/src/main/java/com/cloudbees/jenkins/plugins/BitBucketMultibranchTrigger.java b/src/main/java/com/cloudbees/jenkins/plugins/BitBucketMultibranchTrigger.java
index c1c8c5a..cce0ff3 100644
--- a/src/main/java/com/cloudbees/jenkins/plugins/BitBucketMultibranchTrigger.java
+++ b/src/main/java/com/cloudbees/jenkins/plugins/BitBucketMultibranchTrigger.java
@@ -20,6 +20,7 @@ public class BitBucketMultibranchTrigger extends Trigger 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());
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java
index 040c724..9a4f6bd 100644
--- a/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java
+++ b/src/main/java/com/cloudbees/jenkins/plugins/BitbucketJobProbe.java
@@ -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;
@@ -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;
@@ -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 = 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;
diff --git a/src/test/java/com/cloudbees/jenkins/plugins/BitbucketMultibranchTest.java b/src/test/java/com/cloudbees/jenkins/plugins/BitbucketMultibranchTest.java
new file mode 100644
index 0000000..df12b07
--- /dev/null
+++ b/src/test/java/com/cloudbees/jenkins/plugins/BitbucketMultibranchTest.java
@@ -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);
+ }
+}