From 3d41578f6825b817d45d4627f007e079fcf2bf14 Mon Sep 17 00:00:00 2001 From: Venkata Shreyas Kabekkodu Date: Tue, 18 Aug 2026 17:31:52 +0530 Subject: [PATCH 1/2] Add support for parameterized repository URLs in GitHubSCMBuilder Signed-off-by: Venkata Shreyas Kabekkodu --- .../GitHubSCMBuilder.java | 13 ++++++- .../GitHubSCMBuilderTest.java | 38 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilder.java b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilder.java index 39ddb8e1a..675ee86a8 100644 --- a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilder.java +++ b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilder.java @@ -69,6 +69,11 @@ public class GitHubSCMBuilder extends GitSCMBuilder { /** The context within which credentials should be resolved. */ @CheckForNull private final SCMSourceOwner context; + + @NonNull + private final String checkoutRepositoryUrl; + + private final boolean configuredByUrl; /** The API URL */ @NonNull private final String apiUri; @@ -99,6 +104,8 @@ public GitHubSCMBuilder( @NonNull GitHubSCMSource source, @NonNull SCMHead head, @CheckForNull SCMRevision revision) { super(head, revision, /*dummy value*/ guessRemote(source), source.getCredentialsId()); this.context = source.getOwner(); + checkoutRepositoryUrl = source.getRepositoryUrl(); + configuredByUrl = source.isConfiguredByUrl(); apiUri = StringUtils.defaultIfBlank(source.getApiUri(), GitHubServerConfig.GITHUB_URL); repoOwner = source.getRepoOwner(); repository = source.getRepository(); @@ -246,7 +253,11 @@ public static RepositoryUriResolver uriResolver( */ @NonNull public final GitHubSCMBuilder withGitHubRemote() { - withRemote(uriResolver().getRepositoryUri(apiUri, repoOwner, repository)); + String remote = uriResolver().getRepositoryUri(apiUri, repoOwner, repository); + if (uriResolver() == HTTPS && configuredByUrl) { + remote = checkoutRepositoryUrl; + } + withRemote(remote); final SCMHead h = head(); String repoUrl; if (h instanceof PullRequestSCMHead) { diff --git a/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java b/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java index 1b39e0f4c..b6c747664 100644 --- a/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java +++ b/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java @@ -21,6 +21,12 @@ import com.cloudbees.plugins.credentials.domains.Domain; import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; import hudson.model.Descriptor; +import hudson.model.FreeStyleBuild; +import hudson.model.FreeStyleProject; +import hudson.model.ParametersAction; +import hudson.model.ParametersDefinitionProperty; +import hudson.model.StringParameterDefinition; +import hudson.model.StringParameterValue; import hudson.plugins.git.GitSCM; import hudson.plugins.git.Revision; import hudson.plugins.git.UserRemoteConfig; @@ -162,6 +168,38 @@ public void given__cloud_branch_rev_anon__when__build__then__scmBuilt() throws E assertThat(revisions.iterator().next().getSha1String(), is("cafebabedeadbeefcafebabedeadbeefcafebabe")); } + @Test + public void given__parameterized_repository_url__when__build__then__parameter_is_preserved() throws Exception { + createGitHubSCMSourceForTest(true, "https://github.com/tester/${repo}"); + BranchSCMHead head = new BranchSCMHead("test-branch"); + GitHubSCMBuilder instance = new GitHubSCMBuilder(source, head, null); + + GitSCM actual = instance.build(); + + assertThat(actual.getUserRemoteConfigs().get(0).getUrl(), is("https://github.com/tester/${repo}")); + } + + @Test + public void given__parameterized_repository_name__when__checkout_remote_is_expanded__then__repository_is_selected() + throws Exception { + source = new GitHubSCMSource("tester", "${repo}", null, false); + BranchSCMHead head = new BranchSCMHead("test-branch"); + GitSCM scm = new GitHubSCMBuilder(source, head, null).build(); + FreeStyleProject project = j.createFreeStyleProject("parameterized-repository-" + configuredByUrl); + project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("repo", "test-repo"))); + + FreeStyleBuild build = project.scheduleBuild2( + 0, + new hudson.model.Cause.UserIdCause(), + new ParametersAction(new StringParameterValue("repo", "test-repo"))) + .waitForStart(); + j.waitUntilNoActivity(); + + assertThat( + scm.getParamExpandedRepos(build).get(0).getURIs().get(0).toString(), + is("https://github.com/tester/test-repo.git")); + } + @Test public void given__cloud_branch_rev_userpass__when__build__then__scmBuilt() throws Exception { createGitHubSCMSourceForTest(false, null); From 7bcd9638b82724b45f794f46c04737ea3366b9eb Mon Sep 17 00:00:00 2001 From: Venkata Shreyas Kabekkodu Date: Tue, 18 Aug 2026 18:35:44 +0530 Subject: [PATCH 2/2] Add tests for parameterized repository owner and name in GitHubSCMBuilder Signed-off-by: Venkata Shreyas Kabekkodu --- .../GitHubSCMBuilderTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java b/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java index b6c747664..8482a95fb 100644 --- a/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java +++ b/src/test/java/org/jenkinsci/plugins/github_branch_source/GitHubSCMBuilderTest.java @@ -2704,6 +2704,52 @@ public void given__server_pullMerge_norev_userkey__when__build__then__scmBuilt() assertThat(merge.getBaseHash(), is(nullValue())); } + @Test + public void given__parameterized_repository_owner__when__checkout_remote_is_expanded__then__repository_is_selected() + throws Exception { + source = new GitHubSCMSource("${owner}", "test-repo", null, false); + BranchSCMHead head = new BranchSCMHead("test-branch"); + GitSCM scm = new GitHubSCMBuilder(source, head, null).build(); + FreeStyleProject project = j.createFreeStyleProject("parameterized-owner-" + configuredByUrl); + project.addProperty(new ParametersDefinitionProperty(new StringParameterDefinition("owner", "tester"))); + + FreeStyleBuild build = project.scheduleBuild2( + 0, + new hudson.model.Cause.UserIdCause(), + new ParametersAction(new StringParameterValue("owner", "tester"))) + .waitForStart(); + j.waitUntilNoActivity(); + + assertThat( + scm.getParamExpandedRepos(build).get(0).getURIs().get(0).toString(), + is("https://github.com/tester/test-repo.git")); + } + + @Test + public void + given__parameterized_owner_and_repository__when__checkout_remote_is_expanded__then__repository_is_selected() + throws Exception { + source = new GitHubSCMSource("${owner}", "${repo}", null, false); + BranchSCMHead head = new BranchSCMHead("test-branch"); + GitSCM scm = new GitHubSCMBuilder(source, head, null).build(); + FreeStyleProject project = j.createFreeStyleProject("parameterized-both-" + configuredByUrl); + project.addProperty(new ParametersDefinitionProperty( + new StringParameterDefinition("owner", "tester"), new StringParameterDefinition("repo", "test-repo"))); + + FreeStyleBuild build = project.scheduleBuild2( + 0, + new hudson.model.Cause.UserIdCause(), + new ParametersAction( + new StringParameterValue("owner", "tester"), + new StringParameterValue("repo", "test-repo"))) + .waitForStart(); + j.waitUntilNoActivity(); + + assertThat( + scm.getParamExpandedRepos(build).get(0).getURIs().get(0).toString(), + is("https://github.com/tester/test-repo.git")); + } + private static T getExtension(GitSCM scm, Class type) { for (GitSCMExtension e : scm.getExtensions()) { if (type.isInstance(e)) {