chore: Modifying git fetch remote method signature (#40896)

## Description
- Modified the git fetch remote method signature. Changed it from String
to BranchTrackingStatus, which tells about the numbers of commit local
is ahead and behind of remote
 
 - This will have an EE counterpart as well


Fixes #`Issue Number`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

/ok-to-test tags="@tag.Git"

### 🔍 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/15539521248>
> Commit: 0793974c3dc6daf18c1496a1c026be546454aa2c
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15539521248&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Git`
> Spec:
> <hr>Mon, 09 Jun 2025 19:23:06 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Remote fetch operations now provide detailed branch tracking status,
showing how many commits your local branch is ahead or behind the remote
branch.

- **API Changes**
- Endpoints and methods that previously returned a simple fetch result
now return comprehensive branch tracking information.
- Method signatures have been updated to reflect these changes for
improved clarity and consistency.

- **Bug Fixes**
- Improved error handling to ensure file locks are properly released
during remote fetch failures, preventing potential deadlocks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Manish Kumar 2025-06-10 12:47:24 +05:30 committed by GitHub
parent f4e0551c4a
commit b6fc1de100
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 54 additions and 13 deletions

View File

@ -1563,9 +1563,9 @@ public class FSGitHandlerCEImpl implements FSGitHandler {
}
@Override
public Mono<BranchTrackingStatus> getBranchTrackingStatus(Path repoPath, String branchName) {
public Mono<BranchTrackingStatus> getBranchTrackingStatus(Path repoSuffix, String branchName) {
return Mono.using(
() -> Git.open(repoPath.toFile()),
() -> Git.open(createRepoPath(repoSuffix).toFile()),
git -> Mono.fromCallable(() -> {
Span jgitBranchTrackingSpan =
observationHelper.createSpan(GitSpan.JGIT_BRANCH_TRACK);

View File

@ -249,5 +249,5 @@ public interface FSGitHandler {
Path createRepoPath(Path suffix);
Mono<BranchTrackingStatus> getBranchTrackingStatus(Path repoPath, String branchName);
Mono<BranchTrackingStatus> getBranchTrackingStatus(Path repoSuffix, String branchName);
}

View File

@ -15,6 +15,7 @@ import com.appsmith.server.dtos.GitConnectDTO;
import com.appsmith.server.dtos.GitDocsDTO;
import com.appsmith.server.dtos.GitMergeDTO;
import com.appsmith.server.dtos.GitPullDTO;
import org.eclipse.jgit.lib.BranchTrackingStatus;
import reactor.core.publisher.Mono;
import java.util.List;
@ -39,13 +40,26 @@ public interface CentralGitServiceCE {
Mono<List<GitRefDTO>> listBranchForArtifact(
String branchedArtifactId, ArtifactType artifactType, Boolean pruneBranches, GitType gitType);
Mono<String> fetchRemoteChanges(
Mono<BranchTrackingStatus> fetchRemoteChanges(
String referenceArtifactId,
ArtifactType artifactType,
boolean isFileLock,
GitType gitType,
RefType refType);
/**
* Fetches remote changes from remote git repository.
* This overloaded method is directly used for autocommit purpose
* @param baseArtifact : base artifact on which the repository was connected
* @param refArtifact : the reference/branch artifact for which remote changes are to be fetched
* @param isFileLock : would this require a redis file lock
* @param gitType : GitType of this operation
* @param refType : RefType for this operation
* @return : branchTrackingStatus, i.e., How many commits is local ahead and behind of remote
*/
Mono<BranchTrackingStatus> fetchRemoteChanges(
Artifact baseArtifact, Artifact refArtifact, boolean isFileLock, GitType gitType, RefType refType);
Mono<MergeStatusDTO> mergeBranch(
String branchedArtifactId, ArtifactType artifactType, GitMergeDTO gitMergeDTO, GitType gitType);

View File

@ -1906,7 +1906,8 @@ public class CentralGitServiceCEImpl implements CentralGitServiceCE {
});
}
public Mono<String> fetchRemoteChanges(
@Override
public Mono<BranchTrackingStatus> fetchRemoteChanges(
Artifact baseArtifact, Artifact refArtifact, boolean isFileLock, GitType gitType, RefType refType) {
if (refArtifact == null
@ -1941,9 +1942,12 @@ public class CentralGitServiceCEImpl implements CentralGitServiceCE {
GitHandlingService gitHandlingService = gitHandlingServiceResolver.getGitHandlingService(gitType);
// current user mono has been zipped just to run in parallel.
Mono<String> fetchRemoteMono = acquireGitLockMono
Mono<BranchTrackingStatus> fetchRemoteMono = acquireGitLockMono
.then(Mono.defer(() -> gitHandlingService.fetchRemoteReferences(
jsonTransformationDTO, baseArtifactGitData.getGitAuth(), FALSE)))
.flatMap(fetchedRemoteString -> {
return gitHandlingService.getBranchTrackingStatus(jsonTransformationDTO);
})
.flatMap(fetchedRemoteStatusString -> {
return gitRedisUtils
.releaseFileLock(artifactType, baseArtifactId, isFileLock)
@ -1960,14 +1964,17 @@ public class CentralGitServiceCEImpl implements CentralGitServiceCE {
refArtifactGitData.getRefName(),
gitType,
throwable);
return Mono.error(
new AppsmithException(AppsmithError.GIT_ACTION_FAILED, "fetch", throwable.getMessage()));
return gitRedisUtils
.releaseFileLock(artifactType, baseArtifactId, isFileLock)
.then(Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED, "fetch", throwable.getMessage())));
})
.elapsed()
.zipWith(currUserMono)
.flatMap(objects -> {
Long elapsedTime = objects.getT1().getT1();
String fetchRemote = objects.getT1().getT2();
BranchTrackingStatus fetchRemote = objects.getT1().getT2();
User currentUser = objects.getT2();
return gitAnalyticsUtils
.sendUnitExecutionTimeAnalyticsEvent(
@ -1995,7 +2002,7 @@ public class CentralGitServiceCEImpl implements CentralGitServiceCE {
* @return Mono of {@link BranchTrackingStatus}
*/
@Override
public Mono<String> fetchRemoteChanges(
public Mono<BranchTrackingStatus> fetchRemoteChanges(
String refArtifactId, ArtifactType artifactType, boolean isFileLock, GitType gitType, RefType refType) {
GitArtifactHelper<?> artifactGitHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType);
AclPermission artifactEditPermission = artifactGitHelper.getArtifactEditPermission();

View File

@ -13,6 +13,7 @@ import com.appsmith.server.dtos.ArtifactExchangeJson;
import com.appsmith.server.dtos.GitConnectDTO;
import com.appsmith.server.dtos.GitMergeDTO;
import com.appsmith.server.git.dtos.ArtifactJsonTransformationDTO;
import org.eclipse.jgit.lib.BranchTrackingStatus;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
@ -94,6 +95,8 @@ public interface GitHandlingServiceCE {
Mono<String> fetchRemoteReferences(
ArtifactJsonTransformationDTO jsonTransformationDTO, FetchRemoteDTO fetchRemoteDTO, GitAuth gitAuth);
Mono<BranchTrackingStatus> getBranchTrackingStatus(ArtifactJsonTransformationDTO artifactJsonTransformationDTO);
Mono<String> mergeBranches(ArtifactJsonTransformationDTO jsonTransformationDTO, GitMergeDTO gitMergeDTO);
Mono<MergeStatusDTO> isBranchMergable(ArtifactJsonTransformationDTO JsonTransformationDTO, GitMergeDTO gitMergeDTO);

View File

@ -450,8 +450,9 @@ public class CommonGitServiceCEImpl implements CommonGitServiceCE {
baseArtifactId,
finalBranchName,
throwable);
return Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED, "fetch", throwable.getMessage()));
return releaseFileLock(baseArtifactId, isFileLock)
.then(Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED, "fetch", throwable.getMessage())));
});
})
.elapsed()

View File

@ -28,6 +28,7 @@ import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.eclipse.jgit.lib.BranchTrackingStatus;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@ -142,7 +143,7 @@ public class GitApplicationControllerCE {
@JsonView(Views.Public.class)
@GetMapping("/{referencedApplicationId}/fetch/remote")
public Mono<ResponseDTO<String>> fetchRemoteChanges(
public Mono<ResponseDTO<BranchTrackingStatus>> fetchRemoteChanges(
@PathVariable String referencedApplicationId,
@RequestHeader(required = false, defaultValue = "branch") RefType refType) {
log.info("Going to compare with remote for default referencedApplicationId {}", referencedApplicationId);

View File

@ -42,6 +42,7 @@ import org.eclipse.jgit.api.errors.EmptyCommitException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.BranchTrackingStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import reactor.core.observability.micrometer.Micrometer;
@ -674,6 +675,20 @@ public class GitFSServiceCEImpl implements GitHandlingServiceCE {
return fsGitHandler.fetchRemote(repoSuffix, false, fetchRemoteDTO, publicKey, privateKey);
}
@Override
public Mono<BranchTrackingStatus> getBranchTrackingStatus(ArtifactJsonTransformationDTO jsonTransformationDTO) {
String workspaceId = jsonTransformationDTO.getWorkspaceId();
String baseArtifactId = jsonTransformationDTO.getBaseArtifactId();
String repoName = jsonTransformationDTO.getRepoName();
String refName = jsonTransformationDTO.getRefName();
ArtifactType artifactType = jsonTransformationDTO.getArtifactType();
GitArtifactHelper<?> gitArtifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType);
Path repoSuffix = gitArtifactHelper.getRepoSuffixPath(workspaceId, baseArtifactId, repoName);
return fsGitHandler.getBranchTrackingStatus(repoSuffix, refName);
}
@Override
public Mono<String> mergeBranches(ArtifactJsonTransformationDTO jsonTransformationDTO, GitMergeDTO gitMergeDTO) {
String workspaceId = jsonTransformationDTO.getWorkspaceId();