Skip to content

Commit

Permalink
MARP-997 recent sorting should be based on first publish date (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
phhung-axonivy authored Dec 13, 2024
1 parent a50762f commit d89c12a
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class RequestMappingConstants {
public static final String FEEDBACK = API + "/feedback";
public static final String IMAGE = API + "/image";
public static final String SYNC = "sync";
public static final String SYNC_PRODUCT_VERSION = SYNC + "/product-version";
public static final String SYNC_FIRST_PUBLISHED_DATE_ALL_PRODUCTS = SYNC + "/first-published-date";
public static final String SYNC_ONE_PRODUCT_BY_ID = "sync/{id}";
public static final String SWAGGER_URL = "/swagger-ui/index.html";
public static final String GIT_HUB_LOGIN = "/github/login";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,25 @@ public ResponseEntity<Message> syncOneProduct(
return new ResponseEntity<>(message, HttpStatus.OK);
}

@PutMapping(SYNC_FIRST_PUBLISHED_DATE_ALL_PRODUCTS)
@Operation(hidden = true)
public ResponseEntity<Message> syncFirstPublishedDateOfAllProducts(
@RequestHeader(value = AUTHORIZATION) String authorizationHeader) {
String token = AuthorizationUtils.getBearerToken(authorizationHeader);
gitHubService.validateUserInOrganizationAndTeam(token, GitHubConstants.AXONIVY_MARKET_ORGANIZATION_NAME,
GitHubConstants.AXONIVY_MARKET_TEAM_NAME);

var message = new Message();
var isSuccess = productService.syncFirstPublishedDateOfAllProducts();
if (isSuccess) {
message.setHelpCode(ErrorCode.SUCCESSFUL.getCode());
message.setMessageDetails("Sync successfully!");
} else {
message.setMessageDetails("Sync unsuccessfully!");
}
return new ResponseEntity<>(message, HttpStatus.OK);
}

@SuppressWarnings("unchecked")
private ResponseEntity<PagedModel<ProductModel>> generateEmptyPagedModel() {
var emptyPagedModel = (PagedModel<ProductModel>) pagedResourcesAssembler.toEmptyModel(Page.empty(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class Product implements Serializable {
@Transient
private int installationCount;
private Date newestPublishedDate;
private Date firstPublishedDate;
private String newestReleaseVersion;
@Transient
private ProductModuleContent productModuleContent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public enum SortOption {
POPULARITY("popularity", "marketplaceData.installationCount", Sort.Direction.DESC),
ALPHABETICALLY("alphabetically", "names", Sort.Direction.ASC),
RECENT("recent", "newestPublishedDate", Sort.Direction.DESC),
RECENT("recent", "firstPublishedDate", Sort.Direction.DESC),
STANDARD("standard", "marketplaceData.customOrder", Sort.Direction.DESC),
ID("id", "_id", Sort.Direction.ASC);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ public interface ProductService {

boolean syncOneProduct(String productId, String marketItemPath, Boolean overrideMarketItemPath);

void clearAllProductVersion();
boolean syncFirstPublishedDateOfAllProducts();
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.kohsuke.github.GHCommit;
import org.kohsuke.github.GHContent;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GHTag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
Expand All @@ -57,15 +58,7 @@
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.*;

import static com.axonivy.market.constants.CommonConstants.SLASH;
import static com.axonivy.market.constants.MavenConstants.*;
Expand Down Expand Up @@ -370,8 +363,8 @@ private List<String> syncProductsFromGitHubRepo(Boolean resetSync) {
} else if (productRepo.findById(product.getId()).isPresent()) {
continue;
}

updateProductContentForNonStandardProduct(ghContentEntity.getValue(), product);
updateFirstPublishedDate(product);
updateProductFromReleasedVersions(product);
transferComputedDataFromDB(product);
productMarketplaceDataRepo.checkAndInitProductMarketplaceDataIfNotExist(product.getId());
Expand Down Expand Up @@ -412,6 +405,53 @@ private String mapVendorImage(String productId, GHContent ghContent, String imag
return EMPTY;
}

private void updateFirstPublishedDate(Product product) {
try {
if (StringUtils.isNotBlank(product.getRepositoryName())) {
List<GHTag> gitHubTags = gitHubService.getRepositoryTags(product.getRepositoryName());
Date firstTagPublishedDate = getFirstTagPublishedDate(gitHubTags);
product.setFirstPublishedDate(firstTagPublishedDate);
}
} catch (IOException e) {
log.error("Get GH Tags failed: ", e);
}
}

private Date getFirstTagPublishedDate(List<GHTag> gitHubTags) {
Date firstTagPublishedDate = null;
try {
if (!CollectionUtils.isEmpty(gitHubTags)) {
List<GHTag> sortedTags = sortByTagCommitDate(gitHubTags);
GHCommit commit = sortedTags.get(0).getCommit();
if (commit != null) {
firstTagPublishedDate = commit.getCommitDate();
}
}
} catch (IOException e) {
log.error("Get first tag published date failed: ", e);
}

return firstTagPublishedDate;
}

private List<GHTag> sortByTagCommitDate(List<GHTag> gitHubTags) {
List<GHTag> sortedTags = new ArrayList<>(gitHubTags);
sortedTags.sort(Comparator.comparing(this::sortByCommitDate, Comparator.nullsLast(Comparator.naturalOrder())));
return sortedTags;
}

private Date sortByCommitDate(GHTag gitHubTag) {
Date commitDate = null;
try {
if (gitHubTag.getCommit() != null) {
commitDate = gitHubTag.getCommit().getCommitDate();
}
} catch (IOException e) {
log.error("Get commit date of tag commit failed: ", e);
}
return commitDate;
}

private void updateProductFromReleasedVersions(Product product) {
if (ObjectUtils.isEmpty(product.getArtifacts())) {
return;
Expand Down Expand Up @@ -536,7 +576,6 @@ private String createProductArtifactId(Artifact mavenArtifact) {
: mavenArtifact.getArtifactId().concat(PRODUCT_ARTIFACT_POSTFIX);
}


// Cover 3 cases after removing non-numeric characters (8, 11.1 and 10.0.2)
@Override
public String getCompatibilityFromOldestVersion(String oldestVersion) {
Expand Down Expand Up @@ -628,6 +667,7 @@ public boolean syncOneProduct(String productId, String marketItemPath, Boolean o
log.info("Update data of product {} from meta.json and logo files", productId);
mappingMetaDataAndLogoFromGHContent(gitHubContents, product);
updateProductContentForNonStandardProduct(gitHubContents, product);
updateFirstPublishedDate(product);
updateProductFromReleasedVersions(product);
productMarketplaceDataRepo.checkAndInitProductMarketplaceDataIfNotExist(productId);
productRepo.save(product);
Expand All @@ -640,13 +680,6 @@ public boolean syncOneProduct(String productId, String marketItemPath, Boolean o
return false;
}

@Override
public void clearAllProductVersion() {
metadataRepo.deleteAll();
metadataSyncRepo.deleteAll();
mavenArtifactVersionRepo.deleteAll();
}

private Product renewProductById(String productId, String marketItemPath, Boolean overrideMarketItemPath) {
Product product = new Product();
productRepo.findById(productId).ifPresent(foundProduct -> {
Expand Down Expand Up @@ -692,4 +725,28 @@ private void updateProductContentForNonStandardProduct(List<GHContent> ghContent
productModuleContentRepo.save(initialContent);
}
}

@Override
public boolean syncFirstPublishedDateOfAllProducts() {
try {
List<Product> products = productRepo.findAll();
if (!CollectionUtils.isEmpty(products)) {
for (Product product : products) {
if (product.getFirstPublishedDate() == null) {
log.info("sync FirstPublishedDate of product {} is starting ...", product.getId());
updateFirstPublishedDate(product);
productRepo.save(product);
log.info("Sync FirstPublishedDate of product {} is finished!", product.getId());
} else {
log.info("FirstPublishedDate of product {} is existing!", product.getId());
}
}
}
log.info("sync FirstPublishedDate of all products is finished!");
return true;
} catch (Exception e) {
log.error(e.getStackTrace());
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class BaseSetup {
protected static final String SAMPLE_PRODUCT_ID = "amazon-comprehend";
protected static final String SAMPLE_PRODUCT_PATH = "/market/connector/amazon-comprehend";
protected static final String SAMPLE_PRODUCT_NAME = "prody Comprehend";
protected static final String SAMPLE_PRODUCT_REPOSITORY_NAME = "axonivy-market/amazon-comprehend";
protected static final Pageable PAGEABLE = PageRequest.of(0, 20,
Sort.by(SortOption.ALPHABETICALLY.getOption()).descending());
protected static final String MOCK_PRODUCT_ID = "bpmn-statistic";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,32 @@ private Product createProductMock() {
mockProduct.setTags(List.of("AI"));
return mockProduct;
}

@Test
void testSyncFirstPublishedDateOfAllProductsInvalidToken() {
doThrow(new UnauthorizedException(ErrorCode.GITHUB_USER_UNAUTHORIZED.getCode(),
ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText())).when(gitHubService)
.validateUserInOrganizationAndTeam(any(String.class), any(String.class), any(String.class));

UnauthorizedException exception = assertThrows(UnauthorizedException.class,
() -> productController.syncFirstPublishedDateOfAllProducts(INVALID_AUTHORIZATION_HEADER));

assertEquals(ErrorCode.GITHUB_USER_UNAUTHORIZED.getHelpText(), exception.getMessage());
}

@Test
void testSyncFirstPublishedDateOfAllProductsFailed() {
when(service.syncFirstPublishedDateOfAllProducts()).thenReturn(false);
var response = productController.syncFirstPublishedDateOfAllProducts(AUTHORIZATION_HEADER);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode());
}

@Test
void testSyncFirstPublishedDateOfAllProductsSuccess() {
when(service.syncFirstPublishedDateOfAllProducts()).thenReturn(true);
var response = productController.syncFirstPublishedDateOfAllProducts(AUTHORIZATION_HEADER);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(ErrorCode.SUCCESSFUL.getCode(), response.getBody().getHelpCode());
}
}
Loading

0 comments on commit d89c12a

Please sign in to comment.