Skip to content

Commit 7b5be5f

Browse files
committed
Throw an error if Devfile from unsupported ssh repository is not resolved
1 parent e531c3c commit 7b5be5f

File tree

6 files changed

+194
-13
lines changed

6 files changed

+194
-13
lines changed

.ci/openshift-ci/test-gitea-no-pat-oauth-flow.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ trap "catchFinish" EXIT SIGINT
3131
setupTestEnvironment ${OCP_NON_ADMIN_USER_NAME}
3232
setupSSHKeyPairs "${GITEA_PRIVATE_KEY}" "${GITEA_PUBLIC_KEY}"
3333

34-
testFactoryResolverResponse ${PUBLIC_REPO_SSH_URL} 200
35-
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 200
34+
testFactoryResolverResponse ${PUBLIC_REPO_SSH_URL} 500
35+
testFactoryResolverResponse ${PRIVATE_REPO_SSH_URL} 500
3636
testFactoryResolverResponse ${PUBLIC_REPO_RAW_PATH_URL} 200
3737

3838
testCloneGitRepoProjectShouldExists ${PUBLIC_REPO_WORKSPACE_NAME} ${PUBLIC_PROJECT_NAME} ${PUBLIC_REPO_SSH_URL} ${USER_CHE_NAMESPACE}

wsmaster/che-core-api-factory-git-ssh/pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
<findbugs.failonerror>true</findbugs.failonerror>
2727
</properties>
2828
<dependencies>
29+
<dependency>
30+
<groupId>com.google.guava</groupId>
31+
<artifactId>guava</artifactId>
32+
</dependency>
2933
<dependency>
3034
<groupId>jakarta.inject</groupId>
3135
<artifactId>jakarta.inject-api</artifactId>

wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshFactoryParametersResolver.java

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012-2024 Red Hat, Inc.
2+
* Copyright (c) 2012-2025 Red Hat, Inc.
33
* This program and the accompanying materials are made
44
* available under the terms of the Eclipse Public License 2.0
55
* which is available at https://www.eclipse.org/legal/epl-2.0/
@@ -12,7 +12,6 @@
1212
package org.eclipse.che.api.factory.server.git.ssh;
1313

1414
import static org.eclipse.che.api.factory.server.FactoryResolverPriority.LOWEST;
15-
import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION;
1615
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
1716
import static org.eclipse.che.dto.server.DtoFactory.newDto;
1817

@@ -35,7 +34,7 @@
3534
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
3635

3736
/**
38-
* Provides Factory Parameters resolver for Git Ssh repositories.
37+
* Provides Factory Parameters resolver for SSH urls of unsupported Git providers.
3938
*
4039
* @author Anatolii Bazko
4140
*/
@@ -90,15 +89,11 @@ public FactoryMetaDto createFactory(@NotNull final Map<String, String> factoryPa
9089
gitSshUrl, urlFetcher, personalAccessTokenManager),
9190
extractOverrideParams(factoryParameters),
9291
true)
93-
.orElseGet(
94-
() -> newDto(FactoryDevfileV2Dto.class).withV(CURRENT_VERSION).withSource("repo"))
92+
.orElseThrow(() -> new ApiException("Failed to fetch devfile"))
9593
.acceptVisitor(new GitSshFactoryVisitor(gitSshUrl));
9694
}
9795

98-
/**
99-
* Visitor that puts the default devfile or updates devfile projects into the Git Ssh Factory, if
100-
* needed.
101-
*/
96+
/** Visitor that updates factory dto with git ssh information. */
10297
private class GitSshFactoryVisitor implements FactoryVisitor {
10398

10499
private final GitSshUrl gitSshUrl;

wsmaster/che-core-api-factory-git-ssh/src/main/java/org/eclipse/che/api/factory/server/git/ssh/GitSshUrl.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012-2023 Red Hat, Inc.
2+
* Copyright (c) 2012-2025 Red Hat, Inc.
33
* This program and the accompanying materials are made
44
* available under the terms of the Eclipse Public License 2.0
55
* which is available at https://www.eclipse.org/legal/epl-2.0/
@@ -73,7 +73,7 @@ public Optional<String> filename() {
7373

7474
@Override
7575
public String location() {
76-
return devfileFilename;
76+
return String.format("https://%s/%s/%s", hostName, repository, devfileFilename);
7777
}
7878
};
7979
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Copyright (c) 2012-2025 Red Hat, Inc.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Red Hat, Inc. - initial API and implementation
11+
*/
12+
package org.eclipse.che.api.factory.server.git.ssh;
13+
14+
import static java.util.Collections.singletonMap;
15+
import static org.eclipse.che.api.factory.shared.Constants.CURRENT_VERSION;
16+
import static org.eclipse.che.api.factory.shared.Constants.URL_PARAMETER_NAME;
17+
import static org.eclipse.che.dto.server.DtoFactory.newDto;
18+
import static org.mockito.ArgumentMatchers.any;
19+
import static org.mockito.ArgumentMatchers.eq;
20+
import static org.mockito.Mockito.when;
21+
import static org.testng.Assert.assertEquals;
22+
import static org.testng.Assert.assertFalse;
23+
import static org.testng.Assert.assertTrue;
24+
25+
import com.google.common.collect.ImmutableMap;
26+
import java.util.Collections;
27+
import java.util.Map;
28+
import java.util.Optional;
29+
import org.eclipse.che.api.core.ApiException;
30+
import org.eclipse.che.api.factory.server.scm.AuthorisationRequestManager;
31+
import org.eclipse.che.api.factory.server.scm.PersonalAccessTokenManager;
32+
import org.eclipse.che.api.factory.server.urlfactory.DevfileFilenamesProvider;
33+
import org.eclipse.che.api.factory.server.urlfactory.URLFactoryBuilder;
34+
import org.eclipse.che.api.factory.shared.dto.FactoryDevfileV2Dto;
35+
import org.eclipse.che.api.factory.shared.dto.ScmInfoDto;
36+
import org.eclipse.che.api.workspace.server.devfile.FileContentProvider;
37+
import org.eclipse.che.api.workspace.server.devfile.URLFetcher;
38+
import org.mockito.Mock;
39+
import org.mockito.testng.MockitoTestNGListener;
40+
import org.testng.annotations.BeforeMethod;
41+
import org.testng.annotations.Listeners;
42+
import org.testng.annotations.Test;
43+
44+
@Listeners(MockitoTestNGListener.class)
45+
public class GitSshFactoryParametersResolverTest {
46+
47+
@Mock private DevfileFilenamesProvider devfileFilenamesProvider;
48+
@Mock private URLFetcher urlFetcher;
49+
@Mock private URLFactoryBuilder urlFactoryBuilder;
50+
@Mock private PersonalAccessTokenManager personalAccessTokenManager;
51+
@Mock private AuthorisationRequestManager authorisationRequestManager;
52+
@Mock private GitSshURLParser gitSshURLParser;
53+
@Mock private GitSshUrl gitSshUrl;
54+
private GitSshFactoryParametersResolver gitSshFactoryParametersResolver;
55+
56+
@BeforeMethod
57+
protected void init() {
58+
gitSshFactoryParametersResolver =
59+
new GitSshFactoryParametersResolver(
60+
gitSshURLParser,
61+
urlFetcher,
62+
urlFactoryBuilder,
63+
personalAccessTokenManager,
64+
authorisationRequestManager);
65+
}
66+
67+
@Test
68+
public void ShouldNotAcceptMissingParameter() {
69+
// given
70+
Map<String, String> parameters = singletonMap("foo", "this is a foo bar");
71+
// when
72+
boolean accept = gitSshFactoryParametersResolver.accept(parameters);
73+
// then
74+
assertFalse(accept);
75+
}
76+
77+
@Test
78+
public void ShouldNotAcceptInvalidUrl() {
79+
// given
80+
String url = "https://provider.com/user/repo.git";
81+
when(gitSshURLParser.isValid(eq(url))).thenReturn(false);
82+
Map<String, String> parameters = singletonMap(URL_PARAMETER_NAME, url);
83+
// when
84+
boolean accept = gitSshFactoryParametersResolver.accept(parameters);
85+
// then
86+
assertFalse(accept);
87+
}
88+
89+
@Test
90+
public void shouldAcceptValidUrl() {
91+
// given
92+
String url = "git@provider.com:user/repo.git";
93+
when(gitSshURLParser.isValid(eq(url))).thenReturn(true);
94+
Map<String, String> parameters = singletonMap(URL_PARAMETER_NAME, url);
95+
// when
96+
boolean accept = gitSshFactoryParametersResolver.accept(parameters);
97+
// then
98+
assertTrue(accept);
99+
}
100+
101+
@Test
102+
public void shouldCreateFactoryWithDevfile() throws Exception {
103+
// given
104+
String url = "git@provider.com:user/repo.git";
105+
when(gitSshUrl.getProviderName()).thenReturn("git-ssh");
106+
when(gitSshUrl.getRepositoryLocation()).thenReturn("repository-location");
107+
ImmutableMap<String, String> params = ImmutableMap.of(URL_PARAMETER_NAME, url);
108+
when(gitSshURLParser.parse(eq(url))).thenReturn(gitSshUrl);
109+
when(urlFactoryBuilder.createFactoryFromDevfile(
110+
eq(gitSshUrl), any(FileContentProvider.class), eq(Collections.emptyMap()), eq(true)))
111+
.thenReturn(Optional.of(generateDevfileV2Factory()));
112+
// when
113+
FactoryDevfileV2Dto factory =
114+
(FactoryDevfileV2Dto) gitSshFactoryParametersResolver.createFactory(params);
115+
// then
116+
ScmInfoDto scmInfo = factory.getScmInfo();
117+
assertEquals(scmInfo.getScmProviderName(), "git-ssh");
118+
assertEquals(scmInfo.getRepositoryUrl(), "repository-location");
119+
}
120+
121+
@Test(
122+
expectedExceptions = ApiException.class,
123+
expectedExceptionsMessageRegExp = "Failed to fetch devfile")
124+
public void shouldThrowException() throws Exception {
125+
// given
126+
String url = "git@provider.com:user/repo.git";
127+
ImmutableMap<String, String> params = ImmutableMap.of(URL_PARAMETER_NAME, url);
128+
when(gitSshURLParser.parse(eq(url))).thenReturn(gitSshUrl);
129+
when(urlFactoryBuilder.createFactoryFromDevfile(
130+
eq(gitSshUrl), any(FileContentProvider.class), eq(Collections.emptyMap()), eq(true)))
131+
.thenReturn(Optional.empty());
132+
// when
133+
FactoryDevfileV2Dto factory =
134+
(FactoryDevfileV2Dto) gitSshFactoryParametersResolver.createFactory(params);
135+
}
136+
137+
private FactoryDevfileV2Dto generateDevfileV2Factory() {
138+
return newDto(FactoryDevfileV2Dto.class)
139+
.withV(CURRENT_VERSION)
140+
.withSource("repo")
141+
.withDevfile(Map.of("schemaVersion", "2.0.0"));
142+
}
143+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2012-2025 Red Hat, Inc.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Red Hat, Inc. - initial API and implementation
11+
*/
12+
package org.eclipse.che.api.factory.server.git.ssh;
13+
14+
import static org.testng.Assert.assertEquals;
15+
16+
import java.util.Arrays;
17+
import java.util.List;
18+
import org.eclipse.che.api.factory.server.urlfactory.RemoteFactoryUrl.DevfileLocation;
19+
import org.mockito.testng.MockitoTestNGListener;
20+
import org.testng.annotations.Listeners;
21+
import org.testng.annotations.Test;
22+
23+
@Listeners(MockitoTestNGListener.class)
24+
public class GitSshUrlTest {
25+
26+
@Test
27+
public void shouldReturnDevfileLocations() throws Exception {
28+
String[] devfileNames = {"devfile.yaml", ".devfile.yaml"};
29+
GitSshUrl sshUrl =
30+
new GitSshUrl()
31+
.withRepository("repository")
32+
.withHostName("hostname")
33+
.withDevfileFilenames(Arrays.asList(devfileNames));
34+
List<DevfileLocation> devfileLocations = sshUrl.devfileFileLocations();
35+
assertEquals(devfileLocations.size(), 2);
36+
assertEquals(devfileLocations.get(0).location(), "https://hostname/repository/devfile.yaml");
37+
assertEquals(devfileLocations.get(1).location(), "https://hostname/repository/.devfile.yaml");
38+
}
39+
}

0 commit comments

Comments
 (0)