chore: implementation of artifact type agnostic import (#39237)
## Description - Added implementation for ArtifactType agnostic git import Fixes #`Issue Number` ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/13305383592> > Commit: bdb5b6515ad365b611831082ee20af327b940687 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=13305383592&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Thu, 13 Feb 2025 11:38:58 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Streamlined Git artifact import with a simplified interface for easier repository integration. - Enhanced metadata reconstruction and remote repository management to improve artifact handling. - Advanced Git analytics and error tracking for improved operational insights. - Expanded application lookup via Git integration, offering more robust identification. - New methods for moving artifacts and retrieving artifact types from repositories. - Added support for handling artifact JSON types in Git repositories. - **Refactor** - Updated theme property management for improved internal consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
ec4ea27d7d
commit
7764d3df87
|
|
@ -1200,6 +1200,16 @@ public class FileUtilsCEImpl implements FileInterface {
|
|||
return metadataMono.subscribeOn(scheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> reconstructMetadataFromGitRepository(Path repoSuffix) {
|
||||
Mono<Object> metadataMono = Mono.fromCallable(() -> {
|
||||
Path baseRepoPath = Paths.get(gitServiceConfig.getGitRootPath()).resolve(repoSuffix);
|
||||
return fileOperations.readFile(baseRepoPath.resolve(CommonConstants.METADATA + JSON_EXTENSION));
|
||||
});
|
||||
|
||||
return metadataMono.subscribeOn(scheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Object> reconstructPageFromGitRepo(
|
||||
String pageName, String branchName, Path baseRepoSuffixPath, Boolean resetToLastCommitRequired) {
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ public interface FileInterface {
|
|||
Path repoSuffixPath,
|
||||
Boolean isResetToLastCommitRequired);
|
||||
|
||||
Mono<Object> reconstructMetadataFromGitRepository(Path repoSuffix);
|
||||
|
||||
Mono<Object> reconstructPageFromGitRepo(
|
||||
String pageName, String branchName, Path repoSuffixPath, Boolean checkoutRequired);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ public class GitConstantsCE {
|
|||
public static final String ACTION_COLLECTION_LIST = "actionCollectionList";
|
||||
|
||||
public static final String README_FILE_NAME = "README.md";
|
||||
public static final String ARTIFACT_JSON_TYPE = "artifactJsonType";
|
||||
|
||||
public static final String FIRST_COMMIT = "System added readme file";
|
||||
public static final String DEFAULT_COMMIT_MESSAGE = "System generated commit, ";
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public class FieldNameCE {
|
|||
public static final String ACTIONS = "actions";
|
||||
public static final String ASSET = "asset";
|
||||
public static final String APPLICATION = "application";
|
||||
public static final String ARTIFACT = "artifact";
|
||||
public static final String SOURCE_APPLICATION = "sourceApplication";
|
||||
public static final String COMMENT = "comment";
|
||||
public static final String COMMENT_THREAD = "commentThread";
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ public class Theme extends BaseDomain {
|
|||
|
||||
@JsonProperty("isSystemTheme") // manually setting property name to make sure it's compatible with Gson
|
||||
@JsonView({Views.Public.class, Git.class})
|
||||
private boolean isSystemTheme = false; // should be false by default
|
||||
// The primitive is changed to wrapper because of serialization - deserialization issues
|
||||
private Boolean isSystemTheme = false; // should be false by default
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
|
|
@ -59,6 +60,21 @@ public class Theme extends BaseDomain {
|
|||
private String backgroundColor;
|
||||
}
|
||||
|
||||
public void setSystemTheme(boolean isSystemTheme) {
|
||||
this.isSystemTheme = isSystemTheme;
|
||||
}
|
||||
|
||||
@JsonView({Views.Internal.class})
|
||||
public Boolean getSystemTheme() {
|
||||
return this.isSystemTheme;
|
||||
}
|
||||
|
||||
// To be deleted in later on refactors
|
||||
@JsonView({Views.Internal.class})
|
||||
public Boolean isSystemTheme() {
|
||||
return this.isSystemTheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sanitiseToExportDBObject() {
|
||||
this.setId(null);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ public interface CentralGitServiceCE {
|
|||
Mono<? extends ArtifactImportDTO> importArtifactFromGit(
|
||||
String workspaceId, GitConnectDTO gitConnectDTO, ArtifactType artifactType, GitType gitType);
|
||||
|
||||
Mono<? extends ArtifactImportDTO> importArtifactFromGit(
|
||||
String workspaceId, GitConnectDTO gitConnectDTO, GitType gitType);
|
||||
|
||||
Mono<? extends Artifact> connectArtifactToGit(
|
||||
String baseArtifactId,
|
||||
ArtifactType artifactType,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static com.appsmith.external.git.constants.ce.GitConstantsCE.DEFAULT_COMMIT_MESSAGE;
|
||||
|
|
@ -143,6 +144,204 @@ public class CentralGitServiceCEImpl implements CentralGitServiceCE {
|
|||
return gitPrivateRepoHelper.isRepoLimitReached(workspaceId, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<? extends ArtifactImportDTO> importArtifactFromGit(
|
||||
String workspaceId, GitConnectDTO gitConnectDTO, GitType gitType) {
|
||||
if (!StringUtils.hasText(workspaceId)) {
|
||||
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.WORKSPACE_ID));
|
||||
}
|
||||
|
||||
GitHandlingService gitHandlingService = gitHandlingServiceResolver.getGitHandlingService(gitType);
|
||||
Set<String> errors = gitHandlingService.validateGitConnectDTO(gitConnectDTO);
|
||||
|
||||
if (!CollectionUtils.isEmpty(errors)) {
|
||||
return Mono.error(new AppsmithException(
|
||||
AppsmithError.INVALID_PARAMETER, errors.stream().findAny().get()));
|
||||
}
|
||||
|
||||
final String repoName = gitHandlingService.getRepoName(gitConnectDTO);
|
||||
|
||||
// since at this point in the import flow, there is no context about the artifact type
|
||||
// it needs to be retrieved from the fetched repository itself. however, in order to retrieve
|
||||
// the artifact type from repository, the repository needs to be saved.
|
||||
// for saving the repo an identifier is required (which usually is the artifact id);
|
||||
// however, the artifact could only be generated after the artifact type is known.
|
||||
// hence this is a temporary placeholder to hold the repository and it's components
|
||||
String placeholder = "temp" + UUID.randomUUID();
|
||||
ArtifactJsonTransformationDTO tempJsonTransformationDTO =
|
||||
new ArtifactJsonTransformationDTO(workspaceId, placeholder, repoName);
|
||||
|
||||
ArtifactJsonTransformationDTO jsonDTOPostRefCreation =
|
||||
new ArtifactJsonTransformationDTO(workspaceId, placeholder, repoName);
|
||||
|
||||
Mono<Boolean> isRepositoryPrivateMonoCached =
|
||||
gitHandlingService.isRepoPrivate(gitConnectDTO).cache();
|
||||
|
||||
Mono<Boolean> isRepositoryLimitReachedForWorkspaceMono = isRepositoryPrivateMonoCached.flatMap(
|
||||
isRepositoryPrivate -> isRepositoryLimitReachedForWorkspace(workspaceId, isRepositoryPrivate));
|
||||
|
||||
Mono<GitAuth> gitAuthMonoCached = gitHandlingService.getGitAuthForUser().cache();
|
||||
|
||||
Mono<? extends Artifact> blankArtifactForImportMono = isRepositoryLimitReachedForWorkspaceMono
|
||||
.flatMap(isLimitReachedForPrivateRepositories -> {
|
||||
if (!TRUE.equals(isLimitReachedForPrivateRepositories)) {
|
||||
return gitAuthMonoCached;
|
||||
}
|
||||
|
||||
return gitAnalyticsUtils
|
||||
.addAnalyticsForGitOperation(
|
||||
AnalyticsEvents.GIT_IMPORT,
|
||||
workspaceId,
|
||||
AppsmithError.GIT_APPLICATION_LIMIT_ERROR.getErrorType(),
|
||||
AppsmithError.GIT_APPLICATION_LIMIT_ERROR.getMessage(),
|
||||
true,
|
||||
false)
|
||||
.then(Mono.error(new AppsmithException(AppsmithError.GIT_APPLICATION_LIMIT_ERROR)));
|
||||
})
|
||||
.flatMap(gitAuth -> {
|
||||
return gitHandlingService
|
||||
.fetchRemoteRepository(gitConnectDTO, gitAuth, tempJsonTransformationDTO)
|
||||
.flatMap(defaultBranch -> {
|
||||
return Mono.zip(
|
||||
Mono.just(defaultBranch),
|
||||
gitHandlingService.obtainArtifactTypeFromGitRepository(
|
||||
tempJsonTransformationDTO),
|
||||
isRepositoryPrivateMonoCached,
|
||||
Mono.just(gitAuth));
|
||||
});
|
||||
})
|
||||
.flatMap(tuple4 -> {
|
||||
String defaultBranch = tuple4.getT1();
|
||||
ArtifactType artifactType = tuple4.getT2();
|
||||
Boolean isRepoPrivate = tuple4.getT3();
|
||||
GitAuth gitAuth = tuple4.getT4();
|
||||
|
||||
GitArtifactHelper<?> contextHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType);
|
||||
AclPermission workspacePermission = contextHelper.getWorkspaceArtifactCreationPermission();
|
||||
|
||||
Mono<Workspace> workspaceMono = workspaceService
|
||||
.findById(workspaceId, workspacePermission)
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(
|
||||
AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId)));
|
||||
|
||||
return workspaceMono
|
||||
.flatMap(workspace -> contextHelper.createArtifactForImport(workspaceId, repoName))
|
||||
.map(baseArtifact -> {
|
||||
GitArtifactMetadata gitArtifactMetadata = new GitArtifactMetadata();
|
||||
gitArtifactMetadata.setGitAuth(gitAuth);
|
||||
gitArtifactMetadata.setDefaultArtifactId(baseArtifact.getId());
|
||||
gitArtifactMetadata.setDefaultBranchName(defaultBranch);
|
||||
gitArtifactMetadata.setRefName(defaultBranch);
|
||||
gitArtifactMetadata.setRepoName(repoName);
|
||||
gitArtifactMetadata.setIsRepoPrivate(isRepoPrivate);
|
||||
gitArtifactMetadata.setLastCommittedAt(Instant.now());
|
||||
|
||||
gitHandlingService.setRepositoryDetailsInGitArtifactMetadata(
|
||||
gitConnectDTO, gitArtifactMetadata);
|
||||
baseArtifact.setGitArtifactMetadata(gitArtifactMetadata);
|
||||
return baseArtifact;
|
||||
});
|
||||
});
|
||||
|
||||
Mono<? extends Artifact> containerArtifactForImport = Mono.usingWhen(
|
||||
blankArtifactForImportMono,
|
||||
baseArtifact -> {
|
||||
GitArtifactMetadata baseGitMetadata = baseArtifact.getGitArtifactMetadata();
|
||||
String defaultBranch = baseGitMetadata.getDefaultBranchName();
|
||||
|
||||
jsonDTOPostRefCreation.setBaseArtifactId(baseGitMetadata.getDefaultArtifactId());
|
||||
jsonDTOPostRefCreation.setRefType(RefType.branch);
|
||||
jsonDTOPostRefCreation.setRefName(defaultBranch);
|
||||
jsonDTOPostRefCreation.setArtifactType(baseArtifact.getArtifactType());
|
||||
|
||||
return Mono.just(baseArtifact);
|
||||
},
|
||||
// in any case repository details needs to be updated with the base artifact id
|
||||
baseArtifact ->
|
||||
gitHandlingService.updateImportedRepositoryDetails(baseArtifact, tempJsonTransformationDTO));
|
||||
|
||||
Mono<? extends ArtifactImportDTO> importGitArtifactMono = Mono.usingWhen(
|
||||
containerArtifactForImport,
|
||||
baseArtifact -> {
|
||||
GitArtifactMetadata baseGitMetadata = baseArtifact.getGitArtifactMetadata();
|
||||
String defaultBranch = baseGitMetadata.getDefaultBranchName();
|
||||
GitArtifactHelper<?> gitArtifactHelper =
|
||||
gitArtifactHelperResolver.getArtifactHelper(baseArtifact.getArtifactType());
|
||||
|
||||
Mono<List<Datasource>> datasourceMono = datasourceService
|
||||
.getAllByWorkspaceIdWithStorages(workspaceId, datasourcePermission.getEditPermission())
|
||||
.collectList();
|
||||
|
||||
Mono<List<Plugin>> pluginMono =
|
||||
pluginService.getDefaultPlugins().collectList();
|
||||
|
||||
Mono<? extends ArtifactExchangeJson> artifactExchangeJsonMono = gitHandlingService
|
||||
.reconstructArtifactJsonFromGitRepository(jsonDTOPostRefCreation)
|
||||
.onErrorResume(error -> {
|
||||
log.error("Error while constructing artifact from git repo", error);
|
||||
return Mono.error(
|
||||
new AppsmithException(AppsmithError.GIT_FILE_SYSTEM_ERROR, error.getMessage()));
|
||||
});
|
||||
|
||||
return Mono.zip(artifactExchangeJsonMono, datasourceMono, pluginMono)
|
||||
.flatMap(data -> {
|
||||
ArtifactExchangeJson artifactExchangeJson = data.getT1();
|
||||
List<Datasource> datasourceList = data.getT2();
|
||||
List<Plugin> pluginList = data.getT3();
|
||||
|
||||
if (artifactExchangeJson.getArtifact() == null
|
||||
|| gitArtifactHelper.isContextInArtifactEmpty(artifactExchangeJson)) {
|
||||
return Mono.error(new AppsmithException(
|
||||
AppsmithError.GIT_ACTION_FAILED,
|
||||
"import",
|
||||
"Cannot import artifact from an empty repo"));
|
||||
}
|
||||
|
||||
// If there is an existing datasource with the same name but a different type from that
|
||||
// in the repo, the import api should fail
|
||||
// TODO: change the implementation to compare datasource with gitSyncIds instead.
|
||||
if (checkIsDatasourceNameConflict(
|
||||
datasourceList, artifactExchangeJson.getDatasourceList(), pluginList)) {
|
||||
return Mono.error(new AppsmithException(
|
||||
AppsmithError.GIT_ACTION_FAILED,
|
||||
"import",
|
||||
"Datasource already exists with the same name"));
|
||||
}
|
||||
|
||||
artifactExchangeJson.getArtifact().setGitArtifactMetadata(baseGitMetadata);
|
||||
return importService
|
||||
.importArtifactInWorkspaceFromGit(
|
||||
workspaceId, baseArtifact.getId(), artifactExchangeJson, defaultBranch)
|
||||
.onErrorResume(throwable -> {
|
||||
log.error("Error in importing the artifact {}", baseArtifact.getId());
|
||||
return Mono.error(new AppsmithException(
|
||||
AppsmithError.GIT_FILE_SYSTEM_ERROR, throwable.getMessage()));
|
||||
});
|
||||
})
|
||||
.flatMap(artifact -> gitArtifactHelper.publishArtifact(artifact, false))
|
||||
.flatMap(artifact -> importService.getArtifactImportDTO(
|
||||
artifact.getWorkspaceId(), artifact.getId(), artifact, artifact.getArtifactType()));
|
||||
},
|
||||
baseArtifact -> {
|
||||
// on success send analytics
|
||||
return gitAnalyticsUtils.addAnalyticsForGitOperation(
|
||||
AnalyticsEvents.GIT_IMPORT,
|
||||
baseArtifact,
|
||||
baseArtifact.getGitArtifactMetadata().getIsRepoPrivate());
|
||||
},
|
||||
(baseArtifact, throwableError) -> {
|
||||
// on error
|
||||
return deleteArtifactCreatedFromGitImport(jsonDTOPostRefCreation, gitType);
|
||||
},
|
||||
baseArtifact -> {
|
||||
// on publisher cancellation
|
||||
return deleteArtifactCreatedFromGitImport(jsonDTOPostRefCreation, gitType);
|
||||
});
|
||||
|
||||
return Mono.create(
|
||||
sink -> importGitArtifactMono.subscribe(sink::success, sink::error, null, sink.currentContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<? extends ArtifactImportDTO> importArtifactFromGit(
|
||||
String workspaceId, GitConnectDTO gitConnectDTO, ArtifactType artifactType, GitType gitType) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.appsmith.external.dtos.GitStatusDTO;
|
|||
import com.appsmith.external.dtos.MergeStatusDTO;
|
||||
import com.appsmith.external.git.dtos.FetchRemoteDTO;
|
||||
import com.appsmith.git.dto.CommitDTO;
|
||||
import com.appsmith.server.constants.ArtifactType;
|
||||
import com.appsmith.server.domains.Artifact;
|
||||
import com.appsmith.server.domains.GitArtifactMetadata;
|
||||
import com.appsmith.server.domains.GitAuth;
|
||||
|
|
@ -15,6 +16,7 @@ import com.appsmith.server.git.dtos.ArtifactJsonTransformationDTO;
|
|||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
@ -33,6 +35,15 @@ public interface GitHandlingServiceCE {
|
|||
|
||||
Boolean isGitAuthInvalid(GitAuth gitAuth);
|
||||
|
||||
// TODO: use only the required params
|
||||
Mono<Path> updateImportedRepositoryDetails(
|
||||
Artifact baseArtifact, ArtifactJsonTransformationDTO jsonTransformationDTO);
|
||||
|
||||
Mono<ArtifactType> obtainArtifactTypeFromGitRepository(ArtifactJsonTransformationDTO jsonTransformationDTO);
|
||||
|
||||
Mono<String> fetchRemoteRepository(
|
||||
GitConnectDTO gitConnectDTO, GitAuth gitAuth, ArtifactJsonTransformationDTO jsonTransformationDTO);
|
||||
|
||||
Mono<String> fetchRemoteRepository(
|
||||
GitConnectDTO gitConnectDTO, GitAuth gitAuth, Artifact artifact, String repoName);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.appsmith.server.git.controllers;
|
||||
|
||||
import com.appsmith.external.views.Views;
|
||||
import com.appsmith.server.constants.ArtifactType;
|
||||
import com.appsmith.server.constants.Url;
|
||||
import com.appsmith.server.domains.GitAuth;
|
||||
import com.appsmith.server.domains.GitProfile;
|
||||
|
|
@ -88,7 +87,7 @@ public class GitArtifactControllerCE {
|
|||
|
||||
// TODO: remove artifact type from methods.
|
||||
return centralGitService
|
||||
.importArtifactFromGit(workspaceId, gitConnectDTO, ArtifactType.APPLICATION, GIT_TYPE)
|
||||
.importArtifactFromGit(workspaceId, gitConnectDTO, GIT_TYPE)
|
||||
.map(result -> new ResponseDTO<>(HttpStatus.CREATED.value(), result, null));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -164,6 +164,67 @@ public class GitFSServiceCEImpl implements GitHandlingServiceCE {
|
|||
return !StringUtils.hasText(gitAuth.getPrivateKey()) || !StringUtils.hasText(gitAuth.getPublicKey());
|
||||
}
|
||||
|
||||
public Mono<String> fetchRemoteRepository(
|
||||
GitConnectDTO gitConnectDTO, GitAuth gitAuth, ArtifactJsonTransformationDTO jsonTransformationDTO) {
|
||||
String workspaceId = jsonTransformationDTO.getWorkspaceId();
|
||||
String placeHolder = jsonTransformationDTO.getBaseArtifactId();
|
||||
String repoName = jsonTransformationDTO.getRepoName();
|
||||
Path temporaryStorage = Path.of(workspaceId, placeHolder, repoName);
|
||||
|
||||
return fsGitHandler
|
||||
.cloneRemoteIntoArtifactRepo(
|
||||
temporaryStorage, gitConnectDTO.getRemoteUrl(), gitAuth.getPrivateKey(), gitAuth.getPublicKey())
|
||||
.onErrorResume(error -> {
|
||||
log.error("Error in cloning the remote repo, {}", error.getMessage());
|
||||
return gitAnalyticsUtils
|
||||
.addAnalyticsForGitOperation(
|
||||
AnalyticsEvents.GIT_IMPORT,
|
||||
workspaceId,
|
||||
error.getClass().getName(),
|
||||
error.getMessage(),
|
||||
false,
|
||||
false)
|
||||
.flatMap(user -> commonGitFileUtils.deleteLocalRepo(temporaryStorage))
|
||||
.flatMap(isDeleted -> {
|
||||
if (error instanceof TransportException) {
|
||||
return Mono.error(
|
||||
new AppsmithException(AppsmithError.INVALID_GIT_SSH_CONFIGURATION));
|
||||
} else if (error instanceof InvalidRemoteException) {
|
||||
return Mono.error(
|
||||
new AppsmithException(AppsmithError.INVALID_PARAMETER, "remote url"));
|
||||
} else if (error instanceof TimeoutException) {
|
||||
return Mono.error(new AppsmithException(AppsmithError.GIT_EXECUTION_TIMEOUT));
|
||||
}
|
||||
return Mono.error(new AppsmithException(
|
||||
AppsmithError.GIT_ACTION_FAILED, "clone", error.getMessage()));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public Mono<ArtifactType> obtainArtifactTypeFromGitRepository(ArtifactJsonTransformationDTO jsonTransformationDTO) {
|
||||
String workspaceId = jsonTransformationDTO.getWorkspaceId();
|
||||
String placeHolder = jsonTransformationDTO.getBaseArtifactId();
|
||||
String repoName = jsonTransformationDTO.getRepoName();
|
||||
Path temporaryStorage = Path.of(workspaceId, placeHolder, repoName);
|
||||
|
||||
return commonGitFileUtils.getArtifactJsonTypeOfRepository(temporaryStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Path> updateImportedRepositoryDetails(
|
||||
Artifact baseArtifact, ArtifactJsonTransformationDTO jsonTransformationDTO) {
|
||||
String workspaceId = jsonTransformationDTO.getWorkspaceId();
|
||||
String placeHolder = jsonTransformationDTO.getBaseArtifactId();
|
||||
String repoName = jsonTransformationDTO.getRepoName();
|
||||
Path temporaryStorage = Path.of(workspaceId, placeHolder, repoName);
|
||||
|
||||
ArtifactType artifactType = baseArtifact.getArtifactType();
|
||||
GitArtifactHelper<?> gitArtifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType);
|
||||
Path newPath = gitArtifactHelper.getRepoSuffixPath(workspaceId, baseArtifact.getId(), repoName);
|
||||
|
||||
return commonGitFileUtils.moveArtifactFromTemporaryToBaseArtifactIdRepository(temporaryStorage, newPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> fetchRemoteRepository(
|
||||
GitConnectDTO gitConnectDTO, GitAuth gitAuth, Artifact artifact, String repoName) {
|
||||
|
|
|
|||
|
|
@ -72,13 +72,46 @@ public class GitAnalyticsUtils {
|
|||
Boolean isSystemGenerated,
|
||||
Boolean isMergeable) {
|
||||
|
||||
String branchName = artifact.getGitArtifactMetadata() != null
|
||||
? artifact.getGitArtifactMetadata().getRefName()
|
||||
: null;
|
||||
String branchName = (artifact == null || artifact.getGitArtifactMetadata() == null)
|
||||
? null
|
||||
: artifact.getGitArtifactMetadata().getRefName();
|
||||
return addAnalyticsForGitOperation(
|
||||
event, artifact, errorType, errorMessage, isRepoPrivate, isSystemGenerated, isMergeable, branchName);
|
||||
}
|
||||
|
||||
public Mono<Void> addAnalyticsForGitOperation(
|
||||
AnalyticsEvents event,
|
||||
String workspaceId,
|
||||
String errorType,
|
||||
String errorMessage,
|
||||
Boolean isRepoPrivate,
|
||||
Boolean isSystemGenerated) {
|
||||
|
||||
Map<String, Object> analyticsProps = new HashMap<>();
|
||||
|
||||
// Do not include the error data points in the map for success states
|
||||
if (StringUtils.hasText(errorMessage) || StringUtils.hasText(errorType)) {
|
||||
analyticsProps.put("errorMessage", errorMessage);
|
||||
analyticsProps.put("errorType", errorType);
|
||||
}
|
||||
|
||||
analyticsProps.putAll(Map.of(
|
||||
FieldName.WORKSPACE_ID,
|
||||
defaultIfNull(workspaceId, ""),
|
||||
FieldName.ARTIFACT_ID,
|
||||
defaultIfNull("", ""),
|
||||
"isRepoPrivate",
|
||||
defaultIfNull(isRepoPrivate, ""),
|
||||
"isSystemGenerated",
|
||||
defaultIfNull(isSystemGenerated, "")));
|
||||
|
||||
final Map<String, Object> eventData = Map.of(FieldName.APP_MODE, ApplicationMode.EDIT.toString());
|
||||
analyticsProps.put(FieldName.EVENT_DATA, eventData);
|
||||
return sessionUserService
|
||||
.getCurrentUser()
|
||||
.flatMap(user -> analyticsService.sendEvent(event.getEventName(), user.getUsername(), analyticsProps));
|
||||
}
|
||||
|
||||
public Mono<? extends Artifact> addAnalyticsForGitOperation(
|
||||
AnalyticsEvents event,
|
||||
Artifact artifact,
|
||||
|
|
@ -88,10 +121,12 @@ public class GitAnalyticsUtils {
|
|||
Boolean isSystemGenerated,
|
||||
Boolean isMergeable,
|
||||
String branchName) {
|
||||
GitArtifactMetadata gitData = artifact.getGitArtifactMetadata();
|
||||
|
||||
Map<String, Object> analyticsProps = new HashMap<>();
|
||||
if (gitData != null) {
|
||||
analyticsProps.put(FieldName.APPLICATION_ID, gitData.getDefaultArtifactId());
|
||||
if (artifact != null && artifact.getGitArtifactMetadata() != null) {
|
||||
GitArtifactMetadata gitData = artifact.getGitArtifactMetadata();
|
||||
analyticsProps.put(FieldName.ARTIFACT_ID, gitData.getDefaultArtifactId());
|
||||
analyticsProps.put("artifactType", artifact.getArtifactType());
|
||||
analyticsProps.put("appId", gitData.getDefaultArtifactId());
|
||||
analyticsProps.put(FieldName.BRANCH_NAME, branchName);
|
||||
analyticsProps.put(FieldName.GIT_HOSTING_PROVIDER, GitUtils.getGitProviderName(gitData.getRemoteUrl()));
|
||||
|
|
@ -113,14 +148,14 @@ public class GitAnalyticsUtils {
|
|||
analyticsProps.putAll(Map.of(
|
||||
"workspaceId",
|
||||
defaultIfNull(artifact.getWorkspaceId(), ""),
|
||||
"branchApplicationId",
|
||||
"branchedArtifactId",
|
||||
defaultIfNull(artifact.getId(), ""),
|
||||
"isRepoPrivate",
|
||||
defaultIfNull(isRepoPrivate, ""),
|
||||
"isSystemGenerated",
|
||||
defaultIfNull(isSystemGenerated, "")));
|
||||
final Map<String, Object> eventData =
|
||||
Map.of(FieldName.APP_MODE, ApplicationMode.EDIT.toString(), FieldName.APPLICATION, artifact);
|
||||
Map.of(FieldName.APP_MODE, ApplicationMode.EDIT.toString(), FieldName.ARTIFACT, artifact);
|
||||
analyticsProps.put(FieldName.EVENT_DATA, eventData);
|
||||
return sessionUserService.getCurrentUser().flatMap(user -> analyticsService
|
||||
.sendEvent(event.getEventName(), user.getUsername(), analyticsProps)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.appsmith.server.helpers;
|
|||
|
||||
import com.appsmith.external.git.FileInterface;
|
||||
import com.appsmith.external.git.operations.FileOperations;
|
||||
import com.appsmith.git.configurations.GitServiceConfig;
|
||||
import com.appsmith.git.files.FileUtilsImpl;
|
||||
import com.appsmith.server.actioncollections.base.ActionCollectionService;
|
||||
import com.appsmith.server.dtos.ApplicationJson;
|
||||
|
|
@ -22,6 +23,7 @@ public class CommonGitFileUtils extends CommonGitFileUtilsCE {
|
|||
|
||||
public CommonGitFileUtils(
|
||||
ArtifactGitFileUtils<ApplicationJson> applicationGitFileUtils,
|
||||
GitServiceConfig gitServiceConfig,
|
||||
FileInterface fileUtils,
|
||||
FileOperations fileOperations,
|
||||
AnalyticsService analyticsService,
|
||||
|
|
@ -32,6 +34,7 @@ public class CommonGitFileUtils extends CommonGitFileUtilsCE {
|
|||
ObjectMapper objectMapper) {
|
||||
super(
|
||||
applicationGitFileUtils,
|
||||
gitServiceConfig,
|
||||
fileUtils,
|
||||
fileOperations,
|
||||
analyticsService,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.appsmith.external.models.BaseDomain;
|
|||
import com.appsmith.external.models.CreatorContextType;
|
||||
import com.appsmith.external.models.DatasourceStorage;
|
||||
import com.appsmith.external.models.PluginType;
|
||||
import com.appsmith.git.configurations.GitServiceConfig;
|
||||
import com.appsmith.git.constants.CommonConstants;
|
||||
import com.appsmith.git.files.FileUtilsImpl;
|
||||
import com.appsmith.server.actioncollections.base.ActionCollectionService;
|
||||
|
|
@ -53,6 +54,7 @@ import reactor.core.publisher.Mono;
|
|||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -62,6 +64,7 @@ import java.util.Set;
|
|||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.appsmith.external.git.constants.ce.GitConstantsCE.ARTIFACT_JSON_TYPE;
|
||||
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitCommandConstantsCE.CHECKOUT_BRANCH;
|
||||
import static com.appsmith.external.git.constants.ce.GitConstantsCE.RECONSTRUCT_PAGE;
|
||||
import static com.appsmith.git.constants.CommonConstants.CLIENT_SCHEMA_VERSION;
|
||||
|
|
@ -79,6 +82,7 @@ import static com.appsmith.git.constants.ce.GitDirectoriesCE.DATASOURCE_DIRECTOR
|
|||
import static com.appsmith.git.constants.ce.GitDirectoriesCE.JS_LIB_DIRECTORY;
|
||||
import static com.appsmith.git.constants.ce.GitDirectoriesCE.PAGE_DIRECTORY;
|
||||
import static com.appsmith.git.files.FileUtilsCEImpl.getJsLibFileName;
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
@Slf4j
|
||||
|
|
@ -87,6 +91,7 @@ import static org.springframework.util.StringUtils.hasText;
|
|||
public class CommonGitFileUtilsCE {
|
||||
|
||||
protected final ArtifactGitFileUtils<ApplicationJson> applicationGitFileUtils;
|
||||
protected final GitServiceConfig gitServiceConfig;
|
||||
private final FileInterface fileUtils;
|
||||
private final FileOperations fileOperations;
|
||||
private final AnalyticsService analyticsService;
|
||||
|
|
@ -104,6 +109,7 @@ public class CommonGitFileUtilsCE {
|
|||
|
||||
public CommonGitFileUtilsCE(
|
||||
ArtifactGitFileUtils<ApplicationJson> applicationGitFileUtils,
|
||||
GitServiceConfig gitServiceConfig,
|
||||
FileInterface fileUtils,
|
||||
FileOperations fileOperations,
|
||||
AnalyticsService analyticsService,
|
||||
|
|
@ -113,6 +119,7 @@ public class CommonGitFileUtilsCE {
|
|||
JsonSchemaVersions jsonSchemaVersions,
|
||||
ObjectMapper objectMapper) {
|
||||
this.applicationGitFileUtils = applicationGitFileUtils;
|
||||
this.gitServiceConfig = gitServiceConfig;
|
||||
this.fileUtils = fileUtils;
|
||||
this.fileOperations = fileOperations;
|
||||
this.analyticsService = analyticsService;
|
||||
|
|
@ -779,6 +786,53 @@ public class CommonGitFileUtilsCE {
|
|||
});
|
||||
}
|
||||
|
||||
public Mono<Path> moveArtifactFromTemporaryToBaseArtifactIdRepository(
|
||||
Path currentRepositoryPath, Path newRepositoryPath) {
|
||||
Path currentGitPath = Path.of(gitServiceConfig.getGitRootPath()).resolve(currentRepositoryPath);
|
||||
Path targetPath = Path.of(gitServiceConfig.getGitRootPath()).resolve(newRepositoryPath);
|
||||
|
||||
return Mono.fromCallable(() -> {
|
||||
if (!Files.exists(targetPath)) {
|
||||
Files.createDirectories(targetPath);
|
||||
}
|
||||
|
||||
return Files.move(currentGitPath, targetPath, REPLACE_EXISTING);
|
||||
})
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
public Mono<ArtifactType> getArtifactJsonTypeOfRepository(Path repoSuffix) {
|
||||
Mono<ArtifactType> artifactTypeMono = fileUtils
|
||||
.reconstructMetadataFromGitRepository(repoSuffix)
|
||||
.flatMap(metadata -> {
|
||||
Gson gson = new Gson();
|
||||
JsonObject metadataJsonObject =
|
||||
gson.toJsonTree(metadata, Object.class).getAsJsonObject();
|
||||
|
||||
if (metadataJsonObject == null) {
|
||||
log.error(
|
||||
"Error in retrieving the metadata from the file system for repository {}", repoSuffix);
|
||||
return Mono.error(new AppsmithException(AppsmithError.GIT_FILE_SYSTEM_ERROR));
|
||||
}
|
||||
|
||||
JsonElement artifactJsonType = metadataJsonObject.get(ARTIFACT_JSON_TYPE);
|
||||
|
||||
if (artifactJsonType == null) {
|
||||
log.error(
|
||||
"artifactJsonType attribute not found in the metadata file for repository {}",
|
||||
repoSuffix);
|
||||
return Mono.error(new AppsmithException(AppsmithError.GIT_FILE_SYSTEM_ERROR));
|
||||
}
|
||||
|
||||
return Mono.just(artifactJsonType.getAsString());
|
||||
})
|
||||
.flatMap(artifactJsonType -> {
|
||||
return Mono.justOrEmpty(ArtifactType.valueOf(artifactJsonType));
|
||||
});
|
||||
|
||||
return Mono.create(sink -> artifactTypeMono.subscribe(sink::success, sink::error, null, sink.currentContext()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the server schema version in the application json for the given branch
|
||||
*
|
||||
|
|
|
|||
|
|
@ -161,8 +161,9 @@ public class CustomApplicationRepositoryCEImpl extends BaseAppsmithRepositoryImp
|
|||
public Flux<Application> getApplicationByGitBaseApplicationId(String baseApplicationId, AclPermission permission) {
|
||||
|
||||
return queryBuilder()
|
||||
.criteria(
|
||||
Bridge.equal(Application.Fields.gitApplicationMetadata_defaultApplicationId, baseApplicationId))
|
||||
.criteria(Bridge.or(
|
||||
Bridge.equal(Application.Fields.gitApplicationMetadata_defaultApplicationId, baseApplicationId),
|
||||
Bridge.equal(Application.Fields.gitApplicationMetadata_defaultArtifactId, baseApplicationId)))
|
||||
.permission(permission)
|
||||
.all();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user