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); + } +}