[JENKINS-67309] Git plugin and GitHub Branch Source plugin both define branchDiscoveryTrait
Steps to reproduce
Clone the git plugin's repository, then add the following to pom.xml:
org.jenkins-ci.plugins github-branch-source 2.11.3 test
Then run GlobalLibraryWithModernJCasCCompatibilityTest.
Expected results
The test passes
Actual results
The test fails with
Expected: iterable with items [(an instance of jenkins.plugins.git.traits.BranchDiscoveryTrait), (an instance of jenkins.plugins.git.traits.TagDiscoveryTrait), (an instance of jenkins.plugins.git.traits.LocalBranchTrait), (an instance of jenkins.plugins.git.traits.CleanAfterCheckoutTrait), (an instance of jenkins.plugins.git.traits.CleanBeforeCheckoutTrait), (an instance of jenkins.plugins.git.traits.GitLFSPullTrait), (an instance of jenkins.plugins.git.traits.IgnoreOnPushNotificationTrait), (an instance of jenkins.plugins.git.traits.PruneStaleBranchTrait), (an instance of jenkins.plugins.git.traits.AuthorInChangelogTrait), (an instance of jenkins.plugins.git.traits.WipeWorkspaceTrait), (an instance of jenkins.plugins.git.traits.DiscoverOtherRefsTrait and hasProperty("nameMapping", "mapping") and hasProperty("ref", "other/refs")), (an instance of jenkins.scm.impl.trait.RegexSCMHeadFilterTrait and hasProperty("regex", ".*acme*")), (an instance of jenkins.scm.impl.trait.WildcardSCMHeadFilterTrait and hasProperty("excludes", "excluded") and hasProperty("includes", "master")), (an instance of jenkins.plugins.git.traits.RemoteNameSCMSourceTrait and hasProperty("remoteName", "other_remote")), (an instance of jenkins.plugins.git.traits.CheckoutOptionTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.CheckoutOption) and hasProperty("extension", hasProperty("timeout", <1>))), (an instance of jenkins.plugins.git.traits.CloneOptionTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.CloneOption) and hasProperty("extension", hasProperty("depth", <2>)) and hasProperty("extension", hasProperty("honorRefspec", <true>)) and hasProperty("extension", hasProperty("noTags", <false>)) and hasProperty("extension", hasProperty("reference", "/my/path/2")) and hasProperty("extension", hasProperty("shallow", <true>)) and hasProperty("extension", hasProperty("timeout", <2>))), (an instance of jenkins.plugins.git.traits.SubmoduleOptionTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.SubmoduleOption) and hasProperty("extension", hasProperty("disableSubmodules", <true>)) and hasProperty("extension", hasProperty("parentCredentials", <true>)) and hasProperty("extension", hasProperty("recursiveSubmodules", <true>)) and hasProperty("extension", hasProperty("reference", "/my/path/3")) and hasProperty("extension", hasProperty("timeout", <3>)) and hasProperty("extension", hasProperty("trackingSubmodules", <true>))), (an instance of jenkins.plugins.git.traits.GitBrowserSCMSourceTrait and hasProperty("browser", an instance of hudson.plugins.git.browser.BitbucketWeb) and hasProperty("browser", hasProperty("repoUrl", "bitbucketweb.url"))), (an instance of jenkins.plugins.git.traits.UserIdentityTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.UserIdentity) and hasProperty("extension", hasProperty("name", "my_user")) and hasProperty("extension", hasProperty("email", "my@email.com"))), (an instance of jenkins.plugins.git.traits.RefSpecsSCMSourceTrait and hasProperty("templates", a collection with size <1>) and hasProperty("templates", iterable with items [(an instance of jenkins.plugins.git.traits.RefSpecsSCMSourceTrait$RefSpecTemplate and hasProperty("value", "+refs/heads/*:refs/remotes/@{remote}/*"))] in any order))] in any order
but: not matched: <org.jenkinsci.plugins.github_branch_source.BranchDiscoveryTrait@3d89981d>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:6)
at jenkins.plugins.git.GlobalLibraryWithModernJCasCCompatibilityTest.assertConfiguredAsExpected(GlobalLibraryWithModernJCasCCompatibilityTest.java:64)
at io.jenkins.plugins.casc.misc.RoundTripAbstractTest.lambda$roundTripTest$0(RoundTripAbstractTest.java:104)
at org.jvnet.hudson.test.RestartableJenkinsRule$3.evaluate(RestartableJenkinsRule.java:246)
at org.jvnet.hudson.test.RestartableJenkinsRule$6.evaluate(RestartableJenkinsRule.java:294)
at org.jvnet.hudson.test.JenkinsRule$1.evaluate(JenkinsRule.java:601)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299)
at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:748)
Evaluation
Both plugins define branchDiscoveryTrait. To disambiguate, a @Symbol annotation should be added to each plugin with a differentiating name.
Originally reported by basil, imported from: Git plugin and GitHub Branch Source plugin both define branchDiscoveryTrait
- status: Open
- priority: Minor
- component(s): git-plugin, github-branch-source-plugin
- resolution: Unresolved
- votes: 0
- watchers: 2
- imported: 2025-12-02
Raw content of original issue
Steps to reproduce
Clone the git plugin's repository, then add the following to pom.xml:
<dependency> <groupId>org.jenkins-ci.plugins</groupId> <artifactId>github-branch-source</artifactId> <version>2.11.3</version> <scope>test</scope> </dependency>Then run GlobalLibraryWithModernJCasCCompatibilityTest.
Expected results
The test passes
Actual results
The test fails with
Expected: iterable with items [(an instance of jenkins.plugins.git.traits.BranchDiscoveryTrait), (an instance of jenkins.plugins.git.traits.TagDiscoveryTrait), (an instance of jenkins.plugins.git.traits.LocalBranchTrait), (an instance of jenkins.plugins.git.traits.CleanAfterCheckoutTrait), (an instance of jenkins.plugins.git.traits.CleanBeforeCheckoutTrait), (an instance of jenkins.plugins.git.traits.GitLFSPullTrait), (an instance of jenkins.plugins.git.traits.IgnoreOnPushNotificationTrait), (an instance of jenkins.plugins.git.traits.PruneStaleBranchTrait), (an instance of jenkins.plugins.git.traits.AuthorInChangelogTrait), (an instance of jenkins.plugins.git.traits.WipeWorkspaceTrait), (an instance of jenkins.plugins.git.traits.DiscoverOtherRefsTrait and hasProperty("nameMapping", "mapping") and hasProperty("ref", "other/refs")), (an instance of jenkins.scm.impl.trait.RegexSCMHeadFilterTrait and hasProperty("regex", ".*acme*")), (an instance of jenkins.scm.impl.trait.WildcardSCMHeadFilterTrait and hasProperty("excludes", "excluded") and hasProperty("includes", "master")), (an instance of jenkins.plugins.git.traits.RemoteNameSCMSourceTrait and hasProperty("remoteName", "other_remote")), (an instance of jenkins.plugins.git.traits.CheckoutOptionTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.CheckoutOption) and hasProperty("extension", hasProperty("timeout", <1>))), (an instance of jenkins.plugins.git.traits.CloneOptionTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.CloneOption) and hasProperty("extension", hasProperty("depth", <2>)) and hasProperty("extension", hasProperty("honorRefspec", <true>)) and hasProperty("extension", hasProperty("noTags", <false>)) and hasProperty("extension", hasProperty("reference", "/my/path/2")) and hasProperty("extension", hasProperty("shallow", <true>)) and hasProperty("extension", hasProperty("timeout", <2>))), (an instance of jenkins.plugins.git.traits.SubmoduleOptionTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.SubmoduleOption) and hasProperty("extension", hasProperty("disableSubmodules", <true>)) and hasProperty("extension", hasProperty("parentCredentials", <true>)) and hasProperty("extension", hasProperty("recursiveSubmodules", <true>)) and hasProperty("extension", hasProperty("reference", "/my/path/3")) and hasProperty("extension", hasProperty("timeout", <3>)) and hasProperty("extension", hasProperty("trackingSubmodules", <true>))), (an instance of jenkins.plugins.git.traits.GitBrowserSCMSourceTrait and hasProperty("browser", an instance of hudson.plugins.git.browser.BitbucketWeb) and hasProperty("browser", hasProperty("repoUrl", "bitbucketweb.url"))), (an instance of jenkins.plugins.git.traits.UserIdentityTrait and hasProperty("extension", an instance of hudson.plugins.git.extensions.impl.UserIdentity) and hasProperty("extension", hasProperty("name", "my_user")) and hasProperty("extension", hasProperty("email", "[email protected]"))), (an instance of jenkins.plugins.git.traits.RefSpecsSCMSourceTrait and hasProperty("templates", a collection with size <1>) and hasProperty("templates", iterable with items [(an instance of jenkins.plugins.git.traits.RefSpecsSCMSourceTrait$RefSpecTemplate and hasProperty("value", "+refs/heads/*:refs/remotes/@{remote}/*"))] in any order))] in any order but: not matched: <org.jenkinsci.plugins.github_branch_source.BranchDiscoveryTrait@3d89981d> at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20) at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:6) at jenkins.plugins.git.GlobalLibraryWithModernJCasCCompatibilityTest.assertConfiguredAsExpected(GlobalLibraryWithModernJCasCCompatibilityTest.java:64) at io.jenkins.plugins.casc.misc.RoundTripAbstractTest.lambda$roundTripTest$0(RoundTripAbstractTest.java:104) at org.jvnet.hudson.test.RestartableJenkinsRule$3.evaluate(RestartableJenkinsRule.java:246) at org.jvnet.hudson.test.RestartableJenkinsRule$6.evaluate(RestartableJenkinsRule.java:294) at org.jvnet.hudson.test.JenkinsRule$1.evaluate(JenkinsRule.java:601) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:299) at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:293) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.lang.Thread.run(Thread.java:748)Evaluation
Both plugins define branchDiscoveryTrait. To disambiguate, a @Symbol annotation should be added to each plugin with a differentiating name.
markewaite:
- Original comment link
Raw content of original comment:
The structs documentation says that the trait name needs to be unique within the extension point. I assumed that explains the test failure, since the additional trait from the GitHub branch source is also a valid trait name.
However, SCMSourceTrait is not listed as an extension defined by the scm-api in the extension points report. I'm not sure if SCMSourceTrait is an extension point, since it is not listed as one. I'll need help to understand the preferred approach to resolve this.
The structs documentation says that the trait name needs to be unique within the extension point. I assumed that explains the test failure, since the additional trait from the GitHub branch source is also a valid trait name.
However, SCMSourceTrait is not listed as an extension defined by the scm-api in the extension points report. I'm not sure if SCMSourceTrait is an extension point, since it is not listed as one. I'll need help to understand the preferred approach to resolve this.
basil:
- Original comment link
Raw content of original comment:
I am asking that this bug be reprioritized, as it is getting in the way of my efforts to use a recent version of PCT and/or JENKINS-45047 in jenkinsci/bom.
I am asking that this bug be reprioritized, as it is getting in the way of my efforts to use a recent version of PCT and/or JENKINS-45047 in jenkinsci/bom.
markewaite:
- Original comment link
Raw content of original comment:
I have a development branch that adds many symbols to the git plugin. See https://github.com/MarkEWaite/git-plugin/tree/add-symbols for the details of that branch. It proposes to add the symbol gitBranchDiscovery to that class in the git plugin.
I have a development branch that adds many symbols to the git plugin. See https://github.com/MarkEWaite/git-plugin/tree/add-symbols for the details of that branch. It proposes to add the symbol gitBranchDiscovery to that class in the git plugin.