Skip to content

Commit da96066

Browse files
authored
Merge pull request #40934 from appsmithorg/release
13/06 Daily Promotion
2 parents 36d8eaa + dea1c03 commit da96066

File tree

11 files changed

+177
-30
lines changed

11 files changed

+177
-30
lines changed

app/client/cypress/e2e/Regression/ClientSide/BugTests/ApiBugs_Spec.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -66,34 +66,23 @@ describe(
6666
AppSidebar.navigate(AppSidebarButton.Editor);
6767
});
6868

69-
it("3. Bug 18876 Ensures application does not crash when saving datasource", () => {
70-
apiPage.CreateAndFillApi(
71-
dataManager.dsValues[dataManager.defaultEnviorment].mockApiUrl,
72-
"FirstAPI",
73-
10000,
74-
"POST",
75-
);
76-
apiPage.SelectPaneTab("Authentication");
77-
cy.get(apiPage._saveAsDS).last().click({ force: true });
78-
cy.go("back");
79-
cy.get(dataSources._datasourceModalSave).click();
80-
// ensures app does not crash and datasource is saved.
81-
cy.contains("Edit datasource to access authentication settings").should(
82-
"exist",
83-
);
84-
});
85-
86-
it("4. Bug 16683, When Api url has dynamic binding expressions, ensures the query params is not truncated", function () {
69+
it("3. Bug 16683, When Api url has dynamic binding expressions, ensures the query params is not truncated", function () {
8770
const apiUrl = `http://host.docker.internal:5001/v1/mock-api?records=4{{Math.random() > 0.5 ? '&param1=5' : '&param2=6'}}`;
8871

8972
apiPage.CreateAndFillApi(apiUrl, "BindingExpressions");
9073
apiPage.ValidateQueryParams({
9174
key: "records",
9275
value: "4{{Math.random() > 0.5 ? '&param1=5' : '&param2=6'}}",
9376
});
77+
78+
// Delete the action
79+
agHelper.ActionContextMenuWithInPane({
80+
action: "Delete",
81+
entityType: entityItems.Api,
82+
});
9483
});
9584

96-
it("5. Bug 26897, Invalid binding of table data when used existing suggested widgets for an action returning object & array", function () {
85+
it("4. Bug 26897, Invalid binding of table data when used existing suggested widgets for an action returning object & array", function () {
9786
entityExplorer.DragDropWidgetNVerify(draggableWidgets.TABLE);
9887

9988
// Case where api returns array response
@@ -129,5 +118,22 @@ describe(
129118
"{{OBJECT_RESPONSE.data.users}}",
130119
);
131120
});
121+
122+
it("5. Bug 18876 Ensures application does not crash when saving datasource", () => {
123+
apiPage.CreateAndFillApi(
124+
dataManager.dsValues[dataManager.defaultEnviorment].mockApiUrl,
125+
"FirstAPI",
126+
10000,
127+
"POST",
128+
);
129+
apiPage.SelectPaneTab("Authentication");
130+
cy.get(apiPage._saveAsDS).last().click({ force: true });
131+
cy.go("back");
132+
cy.get(dataSources._datasourceModalSave).click();
133+
// ensures app does not crash and datasource is saved.
134+
cy.contains("Edit datasource to access authentication settings").should(
135+
"exist",
136+
);
137+
});
132138
},
133139
);

app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.appsmith.git.files;
22

3+
import com.appsmith.external.dtos.GitStatusDTO;
34
import com.appsmith.external.dtos.ModifiedResources;
45
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
56
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
@@ -19,6 +20,7 @@
1920
import com.appsmith.git.constants.CommonConstants;
2021
import com.appsmith.git.helpers.DSLTransformerHelper;
2122
import com.fasterxml.jackson.databind.ObjectMapper;
23+
import io.micrometer.observation.ObservationRegistry;
2224
import io.micrometer.tracing.Span;
2325
import lombok.Getter;
2426
import lombok.extern.slf4j.Slf4j;
@@ -31,6 +33,7 @@
3133
import org.springframework.stereotype.Component;
3234
import org.springframework.util.FileSystemUtils;
3335
import org.springframework.util.StringUtils;
36+
import reactor.core.observability.micrometer.Micrometer;
3437
import reactor.core.publisher.Mono;
3538
import reactor.core.scheduler.Scheduler;
3639
import reactor.core.scheduler.Schedulers;
@@ -90,7 +93,7 @@ public class FileUtilsCEImpl implements FileInterface {
9093
protected final FileOperations fileOperations;
9194
private final ObservationHelper observationHelper;
9295
protected final ObjectMapper objectMapper;
93-
96+
private final ObservationRegistry observationRegistry;
9497
private static final String EDIT_MODE_URL_TEMPLATE = "{{editModeUrl}}";
9598

9699
private static final String VIEW_MODE_URL_TEMPLATE = "{{viewModeUrl}}";
@@ -108,13 +111,15 @@ public FileUtilsCEImpl(
108111
GitExecutor gitExecutor,
109112
FileOperations fileOperations,
110113
ObservationHelper observationHelper,
111-
ObjectMapper objectMapper) {
114+
ObjectMapper objectMapper,
115+
ObservationRegistry observationRegistry) {
112116
this.gitServiceConfig = gitServiceConfig;
113117
this.fsGitHandler = fsGitHandler;
114118
this.gitExecutor = gitExecutor;
115119
this.fileOperations = fileOperations;
116120
this.observationHelper = observationHelper;
117121
this.objectMapper = objectMapper;
122+
this.observationRegistry = observationRegistry;
118123
}
119124

120125
protected Map<GitResourceType, GitResourceType> getModifiedResourcesTypes() {
@@ -290,6 +295,66 @@ public Mono<Path> saveArtifactToGitRepo(
290295
.subscribeOn(scheduler);
291296
}
292297

298+
public Mono<GitStatusDTO> computeGitStatus(
299+
Path baseRepoSuffix, GitResourceMap gitResourceMapFromDB, String branchName, boolean keepWorkingDirChanges)
300+
throws GitAPIException, IOException {
301+
return fsGitHandler
302+
.resetToLastCommit(baseRepoSuffix, branchName, keepWorkingDirChanges)
303+
.flatMap(__ -> constructGitResourceMapFromGitRepo(baseRepoSuffix, branchName))
304+
.flatMap(gitResourceMapFromFS -> {
305+
Map<GitResourceIdentity, Object> resourceMapFromDB = gitResourceMapFromDB.getGitResourceMap();
306+
Map<GitResourceIdentity, Object> resourceMapFromFS = gitResourceMapFromFS.getGitResourceMap();
307+
308+
Map<String, Object> filePathObjectsMapFromFS = resourceMapFromFS.entrySet().parallelStream()
309+
.collect(
310+
Collectors.toMap(entry -> entry.getKey().getFilePath(), entry -> entry.getValue()));
311+
312+
Map<String, Object> filePathToObjectsFromDB = resourceMapFromDB.entrySet().parallelStream()
313+
.collect(
314+
Collectors.toMap(entry -> entry.getKey().getFilePath(), entry -> entry.getValue()));
315+
316+
Set<String> filePathsInDb = new HashSet<>(filePathToObjectsFromDB.keySet());
317+
Set<String> filePathsInFS = new HashSet<>(filePathObjectsMapFromFS.keySet());
318+
319+
// added files
320+
Set<String> addedFiles = new HashSet<>(filePathsInDb);
321+
addedFiles.removeAll(filePathsInFS);
322+
323+
// removed files
324+
Set<String> removedFiles = new HashSet<>(filePathsInFS);
325+
removedFiles.removeAll(filePathsInDb);
326+
removedFiles.remove(README_FILE_NAME);
327+
328+
// common files
329+
Set<String> commonFiles = new HashSet<>(filePathsInDb);
330+
commonFiles.retainAll(filePathsInFS);
331+
332+
// modified files
333+
Set<String> modifiedFiles = commonFiles.stream()
334+
.filter(filePath -> {
335+
Object fileInDB = filePathToObjectsFromDB.get(filePath);
336+
Object fileInFS = filePathObjectsMapFromFS.get(filePath);
337+
try {
338+
return fileOperations.hasFileChanged(fileInDB, fileInFS);
339+
} catch (IOException e) {
340+
log.error("Error while checking if file has changed", e);
341+
return false;
342+
}
343+
})
344+
.collect(Collectors.toSet());
345+
346+
GitStatusDTO localRepoStatus = new GitStatusDTO();
347+
localRepoStatus.setAdded(addedFiles);
348+
localRepoStatus.setModified(modifiedFiles);
349+
localRepoStatus.setRemoved(removedFiles);
350+
boolean isClean = addedFiles.isEmpty() && modifiedFiles.isEmpty() && removedFiles.isEmpty();
351+
localRepoStatus.setIsClean(isClean);
352+
353+
fsGitHandler.populateModifiedEntities(localRepoStatus);
354+
return Mono.just(localRepoStatus);
355+
});
356+
}
357+
293358
protected Set<String> getWhitelistedPaths() {
294359
String pages = PAGE_DIRECTORY + DELIMITER_PATH;
295360
String datasources = DATASOURCE_DIRECTORY + DELIMITER_PATH;
@@ -802,7 +867,10 @@ public Mono<ApplicationGitReference> reconstructApplicationReferenceFromGitRepo(
802867
@Override
803868
public Mono<GitResourceMap> constructGitResourceMapFromGitRepo(Path repositorySuffix, String refName) {
804869
Path repositoryPath = Paths.get(gitServiceConfig.getGitRootPath()).resolve(repositorySuffix);
805-
return Mono.fromCallable(() -> fetchGitResourceMap(repositoryPath)).subscribeOn(scheduler);
870+
return Mono.fromCallable(() -> fetchGitResourceMap(repositoryPath))
871+
.subscribeOn(scheduler)
872+
.name("construct-git-resource-map")
873+
.tap(Micrometer.observation(observationRegistry));
806874
}
807875

808876
/**

app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsImpl.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.appsmith.external.helpers.ObservationHelper;
88
import com.appsmith.git.configurations.GitServiceConfig;
99
import com.fasterxml.jackson.databind.ObjectMapper;
10+
import io.micrometer.observation.ObservationRegistry;
1011
import lombok.Getter;
1112
import lombok.extern.slf4j.Slf4j;
1213
import org.springframework.context.annotation.Import;
@@ -26,7 +27,15 @@ public FileUtilsImpl(
2627
GitExecutor gitExecutor,
2728
FileOperations fileOperations,
2829
ObservationHelper observationHelper,
29-
ObjectMapper objectMapper) {
30-
super(gitServiceConfig, fsGitHandler, gitExecutor, fileOperations, observationHelper, objectMapper);
30+
ObjectMapper objectMapper,
31+
ObservationRegistry observationRegistry) {
32+
super(
33+
gitServiceConfig,
34+
fsGitHandler,
35+
gitExecutor,
36+
fileOperations,
37+
observationHelper,
38+
objectMapper,
39+
observationRegistry);
3140
}
3241
}

app/server/appsmith-git/src/main/java/com/appsmith/git/handler/ce/FSGitHandlerCEImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,8 @@ public Mono<GitStatusDTO> getStatus(Path repoPath, String branchName, boolean ke
935935
.subscribeOn(scheduler);
936936
}
937937

938-
protected void populateModifiedEntities(GitStatusDTO response) {
938+
@Override
939+
public void populateModifiedEntities(GitStatusDTO response) {
939940
populatePageChanges(response);
940941
populateQueryChanges(response);
941942
populateJsObjectChanges(response);

app/server/appsmith-git/src/test/java/com/appsmith/git/helpers/FileUtilsImplTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.appsmith.git.files.operations.FileOperationsImpl;
1010
import com.appsmith.git.service.GitExecutorImpl;
1111
import com.fasterxml.jackson.databind.ObjectMapper;
12+
import io.micrometer.observation.ObservationRegistry;
1213
import org.apache.commons.io.FileUtils;
1314
import org.eclipse.jgit.api.errors.GitAPIException;
1415
import org.junit.jupiter.api.AfterEach;
@@ -51,7 +52,8 @@ public void setUp() {
5152
gitExecutor,
5253
fileOperations,
5354
ObservationHelper.NOOP,
54-
new ObjectMapper());
55+
new ObjectMapper(),
56+
ObservationRegistry.NOOP);
5557
}
5658

5759
@AfterEach

app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/FileInterface.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.appsmith.external.git;
22

3+
import com.appsmith.external.dtos.GitStatusDTO;
34
import com.appsmith.external.git.models.GitResourceMap;
45
import com.appsmith.external.models.ApplicationGitReference;
56
import com.appsmith.external.models.ArtifactGitReference;
@@ -42,6 +43,10 @@ Mono<Path> saveArtifactToGitRepo(
4243
Path baseRepoSuffix, GitResourceMap gitResourceMap, String branchName, boolean keepWorkingDirChanges)
4344
throws GitAPIException, IOException;
4445

46+
Mono<GitStatusDTO> computeGitStatus(
47+
Path baseRepoSuffix, GitResourceMap gitResourceMap, String branchName, boolean keepWorkingDirChanges)
48+
throws GitAPIException, IOException;
49+
4550
/**
4651
* This method will reconstruct the application from the repo
4752
*

app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/handler/FSGitHandler.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ Mono<MergeStatusDTO> pullApplication(
160160
*/
161161
Mono<GitStatusDTO> getStatus(Path repoPath, String branchName, boolean keepWorkingDirChanges);
162162

163+
void populateModifiedEntities(GitStatusDTO response);
164+
163165
/**
164166
* This method merges source branch into destination branch for a git repository which is present on the partial
165167
* path provided. <B> This assumes that the branch on which the merge will happen is already checked out </B>

app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCEImpl.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,8 +1675,10 @@ protected Mono<GitStatusDTO> getStatus(
16751675
Mono<GitStatusDTO> lockHandledStatusMono = Mono.usingWhen(
16761676
exportedArtifactJsonMono,
16771677
artifactExchangeJson -> {
1678-
Mono<Boolean> prepareForStatus =
1679-
gitHandlingService.prepareChangesToBeCommitted(jsonTransformationDTO, artifactExchangeJson);
1678+
Mono<GitStatusDTO> statusMono = gitHandlingService
1679+
.computeGitStatus(jsonTransformationDTO, artifactExchangeJson)
1680+
.name("in-memory-status-computation")
1681+
.tap(Micrometer.observation(observationRegistry));
16801682

16811683
Mono<String> fetchRemoteMono = Mono.just("ignored");
16821684

@@ -1694,8 +1696,31 @@ protected Mono<GitStatusDTO> getStatus(
16941696
error.getMessage()))));
16951697
}
16961698

1697-
return Mono.zip(prepareForStatus, fetchRemoteMono)
1698-
.then(Mono.defer(() -> gitHandlingService.getStatus(jsonTransformationDTO)))
1699+
return Mono.zip(statusMono, fetchRemoteMono)
1700+
.flatMap(tuple -> {
1701+
return gitHandlingService
1702+
.getBranchTrackingStatus(jsonTransformationDTO)
1703+
.map(branchTrackingStatus -> {
1704+
GitStatusDTO status = tuple.getT1();
1705+
1706+
if (branchTrackingStatus != null) {
1707+
status.setAheadCount(branchTrackingStatus.getAheadCount());
1708+
status.setBehindCount(branchTrackingStatus.getBehindCount());
1709+
status.setRemoteBranch(branchTrackingStatus.getRemoteTrackingBranch());
1710+
1711+
} else {
1712+
log.debug(
1713+
"Remote tracking details not present for branch: {}, repo: {}",
1714+
finalBranchName,
1715+
repoName);
1716+
status.setAheadCount(0);
1717+
status.setBehindCount(0);
1718+
status.setRemoteBranch("untracked");
1719+
}
1720+
1721+
return status;
1722+
});
1723+
})
16991724
.onErrorResume(throwable -> {
17001725
/*
17011726
in case of any error, the global exception handler will release the lock

app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/GitHandlingServiceCE.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ Mono<Boolean> initialiseReadMe(
8686
Mono<Boolean> prepareChangesToBeCommitted(
8787
ArtifactJsonTransformationDTO jsonTransformationDTO, ArtifactExchangeJson artifactExchangeJson);
8888

89+
Mono<GitStatusDTO> computeGitStatus(
90+
ArtifactJsonTransformationDTO jsonTransformationDTO, ArtifactExchangeJson artifactExchangeJson);
91+
8992
Mono<Tuple2<? extends Artifact, String>> commitArtifact(
9093
Artifact branchedArtifact, CommitDTO commitDTO, ArtifactJsonTransformationDTO jsonTransformationDTO);
9194

app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,19 @@ public Mono<GitStatusDTO> getStatus(ArtifactJsonTransformationDTO jsonTransforma
764764
keepWorkingDirChanges -> fsGitHandler.getStatus(repoPath, refName, keepWorkingDirChanges));
765765
}
766766

767+
public Mono<GitStatusDTO> computeGitStatus(
768+
ArtifactJsonTransformationDTO jsonTransformationDTO, ArtifactExchangeJson artifactExchangeJson) {
769+
String workspaceId = jsonTransformationDTO.getWorkspaceId();
770+
String baseArtifactId = jsonTransformationDTO.getBaseArtifactId();
771+
String repoName = jsonTransformationDTO.getRepoName();
772+
String branchName = jsonTransformationDTO.getRefName();
773+
774+
ArtifactType artifactType = jsonTransformationDTO.getArtifactType();
775+
GitArtifactHelper<?> gitArtifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType);
776+
Path repoSuffix = gitArtifactHelper.getRepoSuffixPath(workspaceId, baseArtifactId, repoName);
777+
return commonGitFileUtils.computeGitStatus(repoSuffix, artifactExchangeJson, branchName);
778+
}
779+
767780
@Override
768781
public Mono<String> createGitReference(
769782
ArtifactJsonTransformationDTO baseRefJsonTransformationDTO,

0 commit comments

Comments
 (0)