Skip to content

Commit

Permalink
chore: pr for delete references (#38210)
Browse files Browse the repository at this point in the history
## Description
 - Implementation for delete references


Fixes #37456 

> [!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/12374977893>
> Commit: ccb37fc
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12374977893&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Git`
> Spec:
> <hr>Tue, 17 Dec 2024 15:09:45 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

## Summary by CodeRabbit

- **New Features**
- Introduced a method to delete Git references, enhancing reference
management capabilities.
	- Added error handling for branch deletion scenarios.
  
- **Changes**
	- Renamed existing method for clarity regarding Git reference creation.
- Updated method signatures to reflect new functionality and improved
naming conventions.
- Added new methods to retrieve and set reference names in Git artifact
metadata.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
sondermanish authored Dec 17, 2024
1 parent a3c5547 commit 35a5d83
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -130,5 +130,17 @@ public void setDefaultApplicationId(String defaultApplicationId) {
this.defaultArtifactId = defaultApplicationId;
}

/**
* this returns the branchName instead of reference name
* @return returns the ref name.
*/
public String getRefName() {
return this.getBranchName();
}

public void setRefName(String refName) {
this.branchName = refName;
}

public static class Fields {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ Mono<? extends Artifact> checkoutReference(

Mono<? extends Artifact> createReference(
String referencedArtifactId, GitRefDTO refDTO, ArtifactType artifactType, GitType gitType);

Mono<? extends Artifact> deleteGitReference(
String baseArtifactId, GitRefDTO gitRefDTO, ArtifactType artifactType, GitType gitType);
}
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ public Mono<? extends Artifact> createReference(
Artifact newRefArtifact = tuple.getT1();

Mono<String> refCreationMono = gitHandlingService
.prepareForNewRefCreation(jsonTransformationDTO)
.createGitReference(jsonTransformationDTO)
// TODO: ths error could be shipped to handling layer as well?
.onErrorResume(error -> Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED,
Expand Down Expand Up @@ -572,6 +572,127 @@ public Mono<? extends Artifact> createReference(
return Mono.create(sink -> createBranchMono.subscribe(sink::success, sink::error, null, sink.currentContext()));
}

@Override
public Mono<? extends Artifact> deleteGitReference(
String baseArtifactId, GitRefDTO gitRefDTO, ArtifactType artifactType, GitType gitType) {

String refName = gitRefDTO.getRefName();
RefType refType = gitRefDTO.getRefType();

if (refType == null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, REF_TYPE));
}

if (!hasText(refName)) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, REF_NAME));
}

if (!hasText(baseArtifactId)) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID));
}

GitArtifactHelper<?> gitArtifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType);
AclPermission artifactEditPermission = gitArtifactHelper.getArtifactEditPermission();

Mono<? extends Artifact> baseArtifactMono =
gitArtifactHelper.getArtifactById(baseArtifactId, artifactEditPermission);

Mono<? extends Artifact> branchedArtifactMono =
gitArtifactHelper.getArtifactByBaseIdAndBranchName(baseArtifactId, refName, artifactEditPermission);

return Mono.zip(baseArtifactMono, branchedArtifactMono).flatMap(tuple2 -> {
Artifact baseArtifact = tuple2.getT1();
Artifact referenceArtifact = tuple2.getT2();
return deleteGitReference(baseArtifact, referenceArtifact, gitType, refType);
});
}

protected Mono<? extends Artifact> deleteGitReference(
Artifact baseArtifact, Artifact referenceArtifact, GitType gitType, RefType refType) {

GitArtifactMetadata baseGitMetadata = baseArtifact.getGitArtifactMetadata();
GitArtifactMetadata referenceArtifactMetadata = referenceArtifact.getGitArtifactMetadata();

GitHandlingService gitHandlingService = gitHandlingServiceResolver.getGitHandlingService(gitType);
GitArtifactHelper<?> gitArtifactHelper =
gitArtifactHelperResolver.getArtifactHelper(baseArtifact.getArtifactType());

// TODO: write a migration to shift everything to refName in gitMetadata
final String finalRefName = referenceArtifactMetadata.getRefName();
final String baseArtifactId = referenceArtifact.getGitArtifactMetadata().getDefaultArtifactId();

if (finalRefName.equals(baseGitMetadata.getDefaultBranchName())) {
return Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED, "delete ref", " Cannot delete default branch"));
}

Mono<? extends Artifact> deleteReferenceMono = gitPrivateRepoHelper
.isBranchProtected(baseGitMetadata, finalRefName)
.flatMap(isBranchProtected -> {
if (!TRUE.equals(isBranchProtected)) {
return gitRedisUtils.acquireGitLock(
baseArtifactId, GitConstants.GitCommandConstants.DELETE, TRUE);
}

return Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED,
"delete",
"Cannot delete protected branch " + finalRefName));
})
.flatMap(ignoreLockAcquisition -> {
ArtifactJsonTransformationDTO jsonTransformationDTO = new ArtifactJsonTransformationDTO();
jsonTransformationDTO.setWorkspaceId(baseArtifact.getWorkspaceId());
jsonTransformationDTO.setArtifactType(baseArtifact.getArtifactType());
jsonTransformationDTO.setRefType(refType);
jsonTransformationDTO.setRefName(finalRefName);
jsonTransformationDTO.setBaseArtifactId(baseArtifactId);
jsonTransformationDTO.setRepoName(referenceArtifactMetadata.getRepoName());

return gitHandlingService
.deleteGitReference(jsonTransformationDTO)
.doFinally(signalType -> gitRedisUtils.releaseFileLock(baseArtifactId, TRUE))
.flatMap(isReferenceDeleted -> {
if (FALSE.equals(isReferenceDeleted)) {
return Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED,
" delete branch. Branch does not exists in the repo"));
}

if (referenceArtifact.getId().equals(baseArtifactId)) {
return Mono.just(referenceArtifact);
}

return gitArtifactHelper
.deleteArtifactByResource(referenceArtifact)
.onErrorResume(throwable -> {
log.error(
"An error occurred while deleting db artifact and resources for reference {}",
throwable.getMessage());

return gitAnalyticsUtils
.addAnalyticsForGitOperation(
AnalyticsEvents.GIT_DELETE_BRANCH,
referenceArtifact,
throwable.getClass().getName(),
throwable.getMessage(),
baseGitMetadata.getIsRepoPrivate())
.then(Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED,
"Cannot delete branch from database")));
});
});
})
.flatMap(deletedArtifact -> gitAnalyticsUtils.addAnalyticsForGitOperation(
AnalyticsEvents.GIT_DELETE_BRANCH,
deletedArtifact,
deletedArtifact.getGitArtifactMetadata().getIsRepoPrivate()))
.name(GitSpan.OPS_DELETE_BRANCH)
.tap(Micrometer.observation(observationRegistry));

return Mono.create(
sink -> deleteReferenceMono.subscribe(sink::success, sink::error, null, sink.currentContext()));
}

/**
* Connect the artifact from Appsmith to a git repo
* This is the prerequisite step needed to perform all the git operation for an artifact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,7 @@ Mono<? extends ArtifactExchangeJson> recreateArtifactJsonFromLastCommit(

Mono<GitStatusDTO> getStatus(ArtifactJsonTransformationDTO jsonTransformationDTO);

Mono<String> prepareForNewRefCreation(ArtifactJsonTransformationDTO artifactJsonTransformationDTO);
Mono<String> createGitReference(ArtifactJsonTransformationDTO artifactJsonTransformationDTO);

Mono<Boolean> deleteGitReference(ArtifactJsonTransformationDTO jsonTransformationDTO);
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import io.micrometer.observation.ObservationRegistry;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException;
import org.eclipse.jgit.api.errors.EmptyCommitException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.TransportException;
Expand Down Expand Up @@ -661,7 +662,7 @@ public Mono<GitStatusDTO> getStatus(ArtifactJsonTransformationDTO jsonTransforma
}

@Override
public Mono<String> prepareForNewRefCreation(ArtifactJsonTransformationDTO jsonTransformationDTO) {
public Mono<String> createGitReference(ArtifactJsonTransformationDTO jsonTransformationDTO) {
GitArtifactHelper<?> gitArtifactHelper =
gitArtifactHelperResolver.getArtifactHelper(jsonTransformationDTO.getArtifactType());

Expand All @@ -672,4 +673,29 @@ public Mono<String> prepareForNewRefCreation(ArtifactJsonTransformationDTO jsonT

return fsGitHandler.createAndCheckoutToBranch(repoSuffix, jsonTransformationDTO.getRefName());
}

@Override
public Mono<Boolean> deleteGitReference(ArtifactJsonTransformationDTO jsonTransformationDTO) {
GitArtifactHelper<?> gitArtifactHelper =
gitArtifactHelperResolver.getArtifactHelper(jsonTransformationDTO.getArtifactType());

Path repoSuffix = gitArtifactHelper.getRepoSuffixPath(
jsonTransformationDTO.getWorkspaceId(),
jsonTransformationDTO.getBaseArtifactId(),
jsonTransformationDTO.getRepoName());

return fsGitHandler
.deleteBranch(repoSuffix, jsonTransformationDTO.getRefName())
.onErrorResume(throwable -> {
log.error("Delete branch failed {}", throwable.getMessage());
if (throwable instanceof CannotDeleteCurrentBranchException) {
return Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED,
"delete branch",
"Cannot delete current checked out branch"));
}
return Mono.error(new AppsmithException(
AppsmithError.GIT_ACTION_FAILED, "delete branch", throwable.getMessage()));
});
}
}

0 comments on commit 35a5d83

Please sign in to comment.