Skip to content

Commit

Permalink
Merge branch 'develop' into feature/MARP-975-Display-compatibility-ra…
Browse files Browse the repository at this point in the history
…nge-in-Marketplace-Items
  • Loading branch information
tvtphuc-axonivy authored Dec 19, 2024
2 parents 88e39cb + f1b7648 commit f1f9aee
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 16 deletions.
2 changes: 1 addition & 1 deletion marketplace-build/dev/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ services:
volumes:
- /home/axonivy/marketplace/data/market-installations.json:/app/data/market-installation.json
- marketcache:/app/data/market-cache
- ./logs:/app/logs
- ../logs:/app/logs
environment:
- MONGODB_HOST=${SERVICE_MONGODB_HOST}
- MONGODB_DATABASE=${SERVICE_MONGODB_DATABASE}
Expand Down
2 changes: 1 addition & 1 deletion marketplace-build/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ services:
volumes:
- /home/axonivy/marketplace/data/market-installations.json:/app/data/market-installation.json
- marketcache:/app/data/market-cache
- ./logs:/app/logs
- ../logs:/app/logs
environment:
- MONGODB_HOST=${SERVICE_MONGODB_HOST}
- MONGODB_DATABASE=${SERVICE_MONGODB_DATABASE}
Expand Down
2 changes: 1 addition & 1 deletion marketplace-build/release/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ services:
volumes:
- /home/axonivy/marketplace/data/market-installations.json:/app/data/market-installation.json
- marketcache:/app/data/market-cache
- ./logs:/app/logs
- ../logs:/app/logs
environment:
- MONGODB_HOST=${SERVICE_MONGODB_HOST}
- MONGODB_DATABASE=${SERVICE_MONGODB_DATABASE}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -173,11 +172,13 @@ public List<ProductSecurityInfo> getSecurityDetailsForAllProducts(String accessT
GitHub gitHub = getGitHub(accessToken);
GHOrganization organization = gitHub.getOrganization(orgName);

return organization.listRepositories().toList().stream()
.map(repo -> CompletableFuture.supplyAsync(() -> fetchSecurityInfoSafe(repo, organization, accessToken), taskScheduler.getScheduledExecutor()))
.map(CompletableFuture::join)
.sorted(Comparator.comparing(ProductSecurityInfo::getRepoName))
.collect(Collectors.toList());
List<CompletableFuture<ProductSecurityInfo>> futures = organization.listRepositories().toList().stream()
.map(repo -> CompletableFuture.supplyAsync(() -> fetchSecurityInfoSafe(repo, organization, accessToken),
taskScheduler.getScheduledExecutor())).toList();

return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenApply(v -> futures.stream().map(CompletableFuture::join).sorted(
Comparator.comparing(ProductSecurityInfo::getRepoName)).collect(Collectors.toList())).join();
} catch (IOException e) {
log.error(e.getStackTrace());
return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@
import static com.axonivy.market.constants.ProductJsonConstants.DEFAULT_PRODUCT_TYPE;

public class ProductContentUtils {
public static final String DEMO_SETUP_TITLE = "(?i)## Demo|## Setup";
/*
* Accept any combination of #, can be ## or ###, and whitespaces before Demo/Setup word
* Match exactly Demo or Setup
*/
public static final String DEMO_SETUP_TITLE = "(?m)^[#\\s]*##?\\s*(Demo|Setup)\\s*$";
private static final String HASH = "#";
public static final String DESCRIPTION = "description";
public static final String DEMO = "demo";
public static final String SETUP = "setup";
public static final String README_IMAGE_FORMAT = "\\(([^)]*?/)?%s\\)";
public static final String README_IMAGE_FORMAT = "\\(([^)]*?/)?%s(\\s+\"[^\"]+\")?\\)";
public static final String IMAGE_DOWNLOAD_URL_FORMAT = "(%s)";

private ProductContentUtils() {
Expand Down Expand Up @@ -141,6 +145,11 @@ public static void updateProductModuleTabContents(ProductModuleContent productMo
productModuleContent.setSetup(replaceEmptyContentsWithEnContent(moduleContents.get(SETUP)));
}

/**
* Cover some inconsistent cases:
* Products contain image names in round brackets (employee-onboarding, demo-projects, etc.)
* Image with name contains in other images' (mattermost)
*/
public static String replaceImageDirWithImageCustomId(Map<String, String> imageUrls, String readmeContents) {
for (Map.Entry<String, String> entry : imageUrls.entrySet()) {
String imagePattern = String.format(README_IMAGE_FORMAT, Pattern.quote(entry.getKey()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class BaseSetup {
protected static final String MOCK_PRODUCT_REPOSITORY_NAME = "axonivy-market/bpmn-statistic";
protected static final String MOCK_IMAGE_ID_FORMAT_1 = "imageId-66e2b14868f2f95b2f95549a";
protected static final String MOCK_IMAGE_ID_FORMAT_2 = "imageId-66e2b14868f2f95b2f95550a";
protected static final String MOCK_IMAGE_ID_FORMAT_3 = "imageId-66e2b14868f2f95b2f95551a";
protected static final String MOCK_PRODUCT_JSON_FILE_PATH = "src/test/resources/product.json";
protected static final String MOCK_PRODUCT_JSON_FILE_PATH_NO_URL = "src/test/resources/productMissingURL.json";
protected static final String MOCK_PRODUCT_JSON_WITH_DROPINS_FILE_PATH = "src/test/resources/product-dropins.json";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class GitHubServiceImplTest {
private GitHubAccessTokenResponse gitHubAccessTokenResponse;

@Mock
private GHTeam team1;
private GHTeam ghTeam;

@Spy
@InjectMocks
Expand Down Expand Up @@ -281,7 +281,7 @@ void testIsUserInOrganizationAndTeam_TeamNotFound() throws IOException {
String organization = "my-org";
String teamName = "my-team";
Set<GHTeam> teams = new HashSet<>();
teams.add(team1);
teams.add(ghTeam);
Map<String, Set<GHTeam>> hashMapTeams = new HashMap<>();
hashMapTeams.put(organization, teams);
when(gitHub.getMyTeams()).thenReturn(hashMapTeams);
Expand All @@ -296,8 +296,8 @@ void testIsUserInOrganizationAndTeam_TeamFound() throws IOException {
String organization = "my-org";
String teamName = "my-team";
Set<GHTeam> teams = new HashSet<>();
when(team1.getName()).thenReturn(teamName);
teams.add(team1);
when(ghTeam.getName()).thenReturn(teamName);
teams.add(ghTeam);
Map<String, Set<GHTeam>> hashMapTeams = new HashMap<>();
hashMapTeams.put(organization, teams);
when(gitHub.getMyTeams()).thenReturn(hashMapTeams);
Expand Down Expand Up @@ -511,4 +511,17 @@ void testGetDependabotAlerts_Disabled() {
Dependabot result = gitHubService.getDependabotAlerts(ghRepository, ghOrganization, accessToken);
assertEquals(AccessLevel.DISABLED, result.getStatus());
}

@Test
void testGetSecurityDetailsForAllProducts() throws Exception {
String accessToken = "mockAccessToken";
String orgName = "mockOrganization";
GHOrganization ghOrganization = mock(GHOrganization.class);
when(gitHubService.getGitHub(accessToken)).thenReturn(gitHub);
when(gitHub.getOrganization(orgName)).thenReturn(ghOrganization);
PagedIterable<GHRepository> mockPagedIterable = mock(PagedIterable.class);
when(ghOrganization.listRepositories()).thenReturn(mockPagedIterable);
List<ProductSecurityInfo> result = gitHubService.getSecurityDetailsForAllProducts(accessToken, orgName);
assertEquals(0, result.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ void testReplaceImageDirWithImageCustomId() {
Map<String, String> imageUrls = new HashMap<>();
imageUrls.put("slash-command.png", MOCK_IMAGE_ID_FORMAT_1);
imageUrls.put("create-slash-command.png", MOCK_IMAGE_ID_FORMAT_2);
imageUrls.put("screen2.png", MOCK_IMAGE_ID_FORMAT_3);

String expectedResult = readmeContents.replace("images/slash-command.png",
MOCK_IMAGE_ID_FORMAT_1).replace("images/create-slash-command.png",
MOCK_IMAGE_ID_FORMAT_2);
MOCK_IMAGE_ID_FORMAT_2).replace("screen2.png \"Restful Person Manager\"", MOCK_IMAGE_ID_FORMAT_3);
String updatedContents = ProductContentUtils.replaceImageDirWithImageCustomId(imageUrls, readmeContents);

assertEquals(expectedResult, updatedContents);
Expand Down Expand Up @@ -114,6 +115,40 @@ void testGetExtractedPartsOfEmptyReadme() {
assertTrue(StringUtils.isBlank(readmeContentsModel.getSetup()));
}

@Test
void testGetExtractedPartsOfReadmeAtCorrectHeadings() {
String readmeContents = getMockReadmeContent();
ReadmeContentsModel readmeContentsModel = ProductContentUtils.getExtractedPartsOfReadme(readmeContents);
assertTrue(readmeContentsModel.getDescription().startsWith("Axon Ivy’s mattermost connector"));
assertTrue(readmeContentsModel.getDemo().startsWith("### Demo sample"));
assertTrue(readmeContentsModel.getSetup().startsWith("### Setup guideline"));
}

@Test
void testGetExtractedPartsOfReadmeWithInconsistentFormats() {
String readmeContentsWithHeading3 = """
#Product-name
Test README
### Setup
Setup content (./image.png)""";
ReadmeContentsModel readmeContentsModel = ProductContentUtils.getExtractedPartsOfReadme(readmeContentsWithHeading3);
assertTrue(readmeContentsModel.getDescription().startsWith("Test README"));
assertTrue(readmeContentsModel.getSetup().startsWith("Setup content (./image.png)"));

String readmeContentsWithSpaceHeading = """
#Product-name
Test README
##Demo
### Demo project
Demo content
## Setup
Setup content (./image.png)""";
ReadmeContentsModel readmeContentsModel1 =
ProductContentUtils.getExtractedPartsOfReadme(readmeContentsWithSpaceHeading);
assertTrue(readmeContentsModel1.getDemo().startsWith("### Demo project"));
assertTrue(readmeContentsModel1.getSetup().startsWith("Setup content (./image.png)"));
}

@Test
void testHasImageDirectives() {
String readmeContents = getMockReadmeContent();
Expand Down
3 changes: 3 additions & 0 deletions marketplace-service/src/test/resources/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ This connector:
- allow you to start the Axon Ivy process by hitting the slash command key from the mattermost's channel.
- allow you to send a message to the mattermost's channel from the Axon Ivy workplace.
- notifies users on the channel for new Axon Ivy workflow Tasks.
![Restful Person Manager](screen2.png "Restful Person Manager")

## Demo

### Demo sample
1. Hit the slash command key on the channel's chat.
The Axon Ivy process will be triggered and create a new task.
The task's information will be sent to the channel by a message.
Expand All @@ -20,6 +22,7 @@ This connector:

## Setup

### Setup guideline
Mattermost Instance

1. Ref to [Deploy Mattermost](https://docs.mattermost.com/guides/deployment.html).
Expand Down

0 comments on commit f1f9aee

Please sign in to comment.