chore: making autocommit GA (#36347)

## Description
- Removal of release_git_autocommit_feature_enabled flag
- Removal of fallback implementation to classes which was autocommit
flag annotated
- Removal of irrelevant test cases post removal of fallback
implementation.


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/10994151881>
> Commit: 42b43f19e4b47d70f8c9784ae1c4c67601d79412
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10994151881&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Git`
> Spec:
> <hr>Mon, 23 Sep 2024 12:53:01 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**
- Enhanced file operations for resource management in Git, including
methods for saving, deleting, and reading resources.
- Streamlined handling of auto-commit functionalities, making certain
features universally accessible.

- **Bug Fixes**
- Removed outdated fallback implementations for auto-commit eligibility
and Git auto-commit helpers.

- **Refactor**
- Simplified constructors and dependencies in file operation classes,
improving maintainability.
- Eliminated feature flag dependencies from various components,
including tests, focusing on core functionality.

- **Tests**
- Removed tests related to feature flags, streamlining the testing
process for auto-commit and migration functionalities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: brayn003 <rudra@appsmith.com>
This commit is contained in:
Manish Kumar 2024-09-25 14:32:01 +05:30 committed by GitHub
parent a93e87ba18
commit 842443c267
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 27483 additions and 897 deletions

View File

@ -21,9 +21,6 @@ describe(
}, },
function () { function () {
it("Check if autocommit progress bar is visible and network requests are properly called", function () { it("Check if autocommit progress bar is visible and network requests are properly called", function () {
featureFlagIntercept({
release_git_autocommit_feature_enabled: true,
});
agHelper.GenerateUUID(); agHelper.GenerateUUID();
cy.get("@guid").then((uid) => { cy.get("@guid").then((uid) => {
wsName = "GitAC-" + uid; wsName = "GitAC-" + uid;

View File

@ -21,8 +21,6 @@ export const FEATURE_FLAG = {
"license_git_branch_protection_enabled", "license_git_branch_protection_enabled",
license_git_continuous_delivery_enabled: license_git_continuous_delivery_enabled:
"license_git_continuous_delivery_enabled", "license_git_continuous_delivery_enabled",
release_git_autocommit_feature_enabled:
"release_git_autocommit_feature_enabled",
license_widget_rtl_support_enabled: "license_widget_rtl_support_enabled", license_widget_rtl_support_enabled: "license_widget_rtl_support_enabled",
ab_one_click_learning_popover_enabled: ab_one_click_learning_popover_enabled:
"ab_one_click_learning_popover_enabled", "ab_one_click_learning_popover_enabled",
@ -68,7 +66,6 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
release_drag_drop_building_blocks_enabled: false, release_drag_drop_building_blocks_enabled: false,
release_table_cell_label_value_enabled: false, release_table_cell_label_value_enabled: false,
license_git_branch_protection_enabled: false, license_git_branch_protection_enabled: false,
release_git_autocommit_feature_enabled: false,
license_git_continuous_delivery_enabled: false, license_git_continuous_delivery_enabled: false,
license_widget_rtl_support_enabled: false, license_widget_rtl_support_enabled: false,
ab_one_click_learning_popover_enabled: false, ab_one_click_learning_popover_enabled: false,

View File

@ -12769,7 +12769,6 @@ export const defaultAppState = {
release_anvil_enabled: false, release_anvil_enabled: false,
release_app_sidebar_enabled: false, release_app_sidebar_enabled: false,
license_git_branch_protection_enabled: false, license_git_branch_protection_enabled: false,
release_git_autocommit_feature_enabled: true,
license_widget_rtl_support_enabled: false, license_widget_rtl_support_enabled: false,
release_show_new_sidebar_announcement_enabled: false, release_show_new_sidebar_announcement_enabled: false,
rollout_app_sidebar_enabled: false, rollout_app_sidebar_enabled: false,

View File

@ -15,9 +15,8 @@ import {
setIsDisconnectGitModalOpen, setIsDisconnectGitModalOpen,
setGitSettingsModalOpenAction, setGitSettingsModalOpenAction,
} from "actions/gitSyncActions"; } from "actions/gitSyncActions";
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import { Button, Divider, Text } from "@appsmith/ads"; import { Button, Divider, Text } from "@appsmith/ads";
import React from "react"; import React, { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { import {
getAutocommitEnabledSelector, getAutocommitEnabledSelector,
@ -26,7 +25,6 @@ import {
} from "selectors/gitSyncSelectors"; } from "selectors/gitSyncSelectors";
import styled from "styled-components"; import styled from "styled-components";
import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import AnalyticsUtil from "ee/utils/AnalyticsUtil";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { import {
useHasConnectToGitPermission, useHasConnectToGitPermission,
useHasManageAutoCommitPermission, useHasManageAutoCommitPermission,
@ -71,9 +69,6 @@ const StyledDivider = styled(Divider)`
function DangerZone() { function DangerZone() {
const isConnectToGitPermitted = useHasConnectToGitPermission(); const isConnectToGitPermitted = useHasConnectToGitPermission();
const isManageAutoCommitPermitted = useHasManageAutoCommitPermission(); const isManageAutoCommitPermitted = useHasManageAutoCommitPermission();
const isAutocommitFeatureEnabled = useFeatureFlag(
FEATURE_FLAG.release_git_autocommit_feature_enabled,
);
const isAutocommitToggling = useSelector(getIsAutocommitToggling); const isAutocommitToggling = useSelector(getIsAutocommitToggling);
const isAutocommitEnabled = useSelector(getAutocommitEnabledSelector); const isAutocommitEnabled = useSelector(getAutocommitEnabledSelector);
const gitMetadataLoading = useSelector(getGitMetadataLoadingSelector); const gitMetadataLoading = useSelector(getGitMetadataLoadingSelector);
@ -82,7 +77,7 @@ function DangerZone() {
const currentApp = useSelector(getCurrentApplication); const currentApp = useSelector(getCurrentApplication);
const handleDisconnect = () => { const handleDisconnect = useCallback(() => {
AnalyticsUtil.logEvent("GS_DISCONNECT_GIT_CLICK", { AnalyticsUtil.logEvent("GS_DISCONNECT_GIT_CLICK", {
source: "GIT_CONNECTION_MODAL", source: "GIT_CONNECTION_MODAL",
}); });
@ -94,9 +89,9 @@ function DangerZone() {
}), }),
); );
dispatch(setIsDisconnectGitModalOpen(true)); dispatch(setIsDisconnectGitModalOpen(true));
}; }, [currentApp?.id, currentApp?.name, dispatch]);
const handleToggleAutocommit = () => { const handleToggleAutocommit = useCallback(() => {
if (isAutocommitEnabled) { if (isAutocommitEnabled) {
dispatch(setGitSettingsModalOpenAction({ open: false })); dispatch(setGitSettingsModalOpenAction({ open: false }));
dispatch(setIsAutocommitModalOpen(true)); dispatch(setIsAutocommitModalOpen(true));
@ -104,10 +99,9 @@ function DangerZone() {
dispatch(toggleAutocommitEnabledInit()); dispatch(toggleAutocommitEnabledInit());
AnalyticsUtil.logEvent("GS_AUTO_COMMIT_ENABLED"); AnalyticsUtil.logEvent("GS_AUTO_COMMIT_ENABLED");
} }
}; }, [dispatch, isAutocommitEnabled]);
const showAutoCommit = const showAutoCommit = isManageAutoCommitPermitted;
isAutocommitFeatureEnabled && isManageAutoCommitPermitted;
const showDisconnect = isConnectToGitPermitted; const showDisconnect = isConnectToGitPermitted;
const showDivider = showAutoCommit && showDisconnect; const showDivider = showAutoCommit && showDisconnect;
@ -128,7 +122,7 @@ function DangerZone() {
<Text renderAs="p">{createMessage(AUTOCOMMIT_MESSAGE)}</Text> <Text renderAs="p">{createMessage(AUTOCOMMIT_MESSAGE)}</Text>
</BodyInnerContainer> </BodyInnerContainer>
<Button <Button
data-testid="t--git-disconnect-btn" data-testid="t--git-autocommit-btn"
isLoading={isAutocommitToggling || gitMetadataLoading} isLoading={isAutocommitToggling || gitMetadataLoading}
kind={isAutocommitEnabled ? "error" : "secondary"} kind={isAutocommitEnabled ? "error" : "secondary"}
onClick={handleToggleAutocommit} onClick={handleToggleAutocommit}

View File

@ -1,4 +1,4 @@
import React, { useMemo } from "react"; import React, { useCallback, useMemo } from "react";
import styled from "styled-components"; import styled from "styled-components";
import BranchButton from "./BranchButton"; import BranchButton from "./BranchButton";
@ -44,8 +44,6 @@ import SpinnerLoader from "pages/common/SpinnerLoader";
import { getTypographyByKey } from "@appsmith/ads-old"; import { getTypographyByKey } from "@appsmith/ads-old";
import { Button, Icon, Tooltip } from "@appsmith/ads"; import { Button, Icon, Tooltip } from "@appsmith/ads";
import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import AnalyticsUtil from "ee/utils/AnalyticsUtil";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import AutocommitStatusbar from "./AutocommitStatusbar"; import AutocommitStatusbar from "./AutocommitStatusbar";
import { useHasConnectToGitPermission } from "../hooks/gitPermissionHooks"; import { useHasConnectToGitPermission } from "../hooks/gitPermissionHooks";
import { GitSettingsTab } from "reducers/uiReducers/gitSyncReducer"; import { GitSettingsTab } from "reducers/uiReducers/gitSyncReducer";
@ -262,6 +260,19 @@ function ConnectGitPlaceholder() {
); );
}, [isConnectToGitPermitted]); }, [isConnectToGitPermitted]);
const handleClickOnGitConnect = useCallback(() => {
AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", {
source: "BOTTOM_BAR_GIT_CONNECT_BUTTON",
});
dispatch(
setIsGitSyncModalOpen({
isOpen: true,
tab: GitSyncModalTab.GIT_CONNECTION,
}),
);
}, [dispatch]);
return ( return (
<OuterContainer> <OuterContainer>
<Tooltip content={tooltipContent} isDisabled={!isTooltipEnabled}> <Tooltip content={tooltipContent} isDisabled={!isTooltipEnabled}>
@ -275,18 +286,7 @@ function ConnectGitPlaceholder() {
className="t--connect-git-bottom-bar" className="t--connect-git-bottom-bar"
isDisabled={!isConnectToGitPermitted} isDisabled={!isConnectToGitPermitted}
kind="secondary" kind="secondary"
onClick={() => { onClick={handleClickOnGitConnect}
AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", {
source: "BOTTOM_BAR_GIT_CONNECT_BUTTON",
});
dispatch(
setIsGitSyncModalOpen({
isOpen: true,
tab: GitSyncModalTab.GIT_CONNECTION,
}),
);
}}
size="sm" size="sm"
> >
{createMessage(CONNECT_GIT_BETA)} {createMessage(CONNECT_GIT_BETA)}
@ -314,9 +314,6 @@ export default function QuickGitActions() {
isDiscardInProgress || isPullInProgress || isFetchingGitStatus; isDiscardInProgress || isPullInProgress || isFetchingGitStatus;
const changesToCommit = useSelector(getCountOfChangesToCommit); const changesToCommit = useSelector(getCountOfChangesToCommit);
const isAutocommitFeatureEnabled = useFeatureFlag(
FEATURE_FLAG.release_git_autocommit_feature_enabled,
);
const gitMetadata = useSelector(getGitMetadataSelector); const gitMetadata = useSelector(getGitMetadataSelector);
const isPollingAutocommit = useSelector(getIsPollingAutocommit); const isPollingAutocommit = useSelector(getIsPollingAutocommit);
const isAutocommitEnabled = gitMetadata?.autoCommitConfig?.enabled; const isAutocommitEnabled = gitMetadata?.autoCommitConfig?.enabled;
@ -383,9 +380,7 @@ export default function QuickGitActions() {
return isGitConnected ? ( return isGitConnected ? (
<Container> <Container>
<BranchButton /> <BranchButton />
{isAutocommitFeatureEnabled && {isAutocommitEnabled && isPollingAutocommit ? (
isAutocommitEnabled &&
isPollingAutocommit ? (
<AutocommitStatusbar completed={!isPollingAutocommit} /> <AutocommitStatusbar completed={!isPollingAutocommit} />
) : ( ) : (
quickActionButtons.map((button) => ( quickActionButtons.map((button) => (

View File

@ -134,8 +134,6 @@ import type { Action } from "entities/Action";
import type { JSCollectionDataState } from "ee/reducers/entityReducers/jsActionsReducer"; import type { JSCollectionDataState } from "ee/reducers/entityReducers/jsActionsReducer";
import { toast } from "@appsmith/ads"; import { toast } from "@appsmith/ads";
import { gitExtendedSagas } from "ee/sagas/GitExtendedSagas"; import { gitExtendedSagas } from "ee/sagas/GitExtendedSagas";
import { selectFeatureFlagCheck } from "ee/selectors/featureFlagsSelectors";
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import type { ApplicationPayload } from "entities/Application"; import type { ApplicationPayload } from "entities/Application";
export function* handleRepoLimitReachedError(response?: ApiResponse) { export function* handleRepoLimitReachedError(response?: ApiResponse) {
@ -1352,14 +1350,10 @@ function* pollAutocommitProgressSaga(): any {
} }
function* triggerAutocommitSaga() { function* triggerAutocommitSaga() {
const isAutocommitFeatureEnabled: boolean = yield select(
selectFeatureFlagCheck,
FEATURE_FLAG.release_git_autocommit_feature_enabled,
);
const gitMetadata: GitMetadata = yield select(getGitMetadataSelector); const gitMetadata: GitMetadata = yield select(getGitMetadataSelector);
const isAutocommitEnabled: boolean = !!gitMetadata?.autoCommitConfig?.enabled; const isAutocommitEnabled: boolean = !!gitMetadata?.autoCommitConfig?.enabled;
if (isAutocommitFeatureEnabled && isAutocommitEnabled) { if (isAutocommitEnabled) {
/* @ts-expect-error: not sure how to do typings of this */ /* @ts-expect-error: not sure how to do typings of this */
const pollTask = yield fork(pollAutocommitProgressSaga); const pollTask = yield fork(pollAutocommitProgressSaga);

View File

@ -1,359 +0,0 @@
package com.appsmith.git.files.operations;
import com.appsmith.external.converters.ISOStringToInstantConverter;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.git.constants.GitSpan;
import com.appsmith.external.git.operations.FileOperationsCE;
import com.appsmith.external.helpers.ObservationHelper;
import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.external.models.BaseDomain;
import com.appsmith.external.models.DatasourceStructure;
import com.appsmith.git.configurations.GitServiceConfig;
import com.appsmith.git.constants.CommonConstants;
import com.appsmith.git.converters.GsonDoubleToLongConverter;
import com.appsmith.git.converters.GsonUnorderedToOrderedConverter;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.micrometer.tracing.Span;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.METADATA;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.RESOURCE_TYPE;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.WIDGETS;
@Slf4j
@Getter
@Component
@Import({GitServiceConfig.class})
public class FileOperationsCEImpl implements FileOperationsCE {
private final GitServiceConfig gitServiceConfig;
private final GitExecutor gitExecutor;
private final Gson gson;
protected final ObservationHelper observationHelper;
private static final String EDIT_MODE_URL_TEMPLATE = "{{editModeUrl}}";
private static final String VIEW_MODE_URL_TEMPLATE = "{{viewModeUrl}}";
private static final Pattern ALLOWED_FILE_EXTENSION_PATTERN =
Pattern.compile("(.*?)\\.(md|MD|git|gitignore|github|yml|yaml)$");
private final Scheduler scheduler = Schedulers.boundedElastic();
private static final String CANVAS_WIDGET = "(Canvas)[0-9]*.";
public FileOperationsCEImpl(
GitServiceConfig gitServiceConfig,
GitExecutor gitExecutor,
GsonBuilder gsonBuilder,
ObservationHelper observationHelper) {
this.gitServiceConfig = gitServiceConfig;
this.gitExecutor = gitExecutor;
// Gson to pretty format JSON file
// Keep Long type as is by default GSON have behavior to convert to Double
// Convert unordered set to ordered one
this.gson = gsonBuilder
.registerTypeAdapter(Double.class, new GsonDoubleToLongConverter())
.registerTypeAdapter(Set.class, new GsonUnorderedToOrderedConverter())
.registerTypeAdapter(Map.class, new GsonUnorderedToOrderedConverter())
.registerTypeAdapter(Instant.class, new ISOStringToInstantConverter())
// Instance creator is required while de-serialising using Gson as key instance can't be invoked
// with no-args constructor
.registerTypeAdapter(DatasourceStructure.Key.class, new DatasourceStructure.KeyInstanceCreator())
.disableHtmlEscaping()
.setPrettyPrinting()
.create();
this.observationHelper = observationHelper;
}
@Override
public void saveMetadataResource(ApplicationGitReference applicationGitReference, Path baseRepo) {
JsonObject metadata = gson.fromJson(gson.toJson(applicationGitReference.getMetadata()), JsonObject.class);
metadata.addProperty(CommonConstants.FILE_FORMAT_VERSION, CommonConstants.fileFormatVersion);
saveResource(metadata, baseRepo.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
}
/**
* This method will be used to store the DB resource to JSON file
*
* @param sourceEntity resource extracted from DB to be stored in file
* @param path file path where the resource to be stored
* @return if the file operation is successful
*/
@Override
public boolean saveResource(Object sourceEntity, Path path) {
try {
Files.createDirectories(path.getParent());
return writeToFile(sourceEntity, path);
} catch (IOException e) {
log.error("Error while writing resource to file {} with {}", path, e.getMessage());
log.debug(e.getMessage());
}
return false;
}
@Override
public void saveWidgets(JSONObject sourceEntity, String resourceName, Path path) {
Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
try {
Files.createDirectories(path);
String resourceType = WIDGETS;
span.tag(RESOURCE_TYPE, resourceType);
observationHelper.startSpan(span, true);
writeStringToFile(sourceEntity.toString(4), path.resolve(resourceName + CommonConstants.JSON_EXTENSION));
} catch (IOException e) {
log.debug("Error while writings widgets data to file, {}", e.getMessage());
} finally {
observationHelper.endSpan(span, true);
}
}
@Override
public void writeStringToFile(String sourceEntity, Path path) throws IOException {
try (BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
fileWriter.write(sourceEntity);
}
}
@Override
public boolean writeToFile(Object sourceEntity, Path path) throws IOException {
Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
String resourceType = sourceEntity.getClass().getSimpleName();
if (!(sourceEntity instanceof BaseDomain)) {
resourceType = METADATA;
}
span.tag(RESOURCE_TYPE, resourceType);
observationHelper.startSpan(span, true);
try (BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
gson.toJson(sourceEntity, fileWriter);
return true;
} finally {
observationHelper.endSpan(span, true);
}
}
/**
* This method will delete the JSON resource available in local git directory on subsequent commit made after the
* deletion of respective resource from DB
*
* @param validResources resources those are still available in DB
* @param resourceDirectory directory which needs to be scanned for possible file deletion operations
*/
@Override
public void scanAndDeleteFileForDeletedResources(Set<String> validResources, Path resourceDirectory) {
// Scan resource directory and delete any unwanted file if present
// unwanted file : corresponding resource from DB has been deleted
if (resourceDirectory.toFile().exists()) {
try (Stream<Path> paths = Files.walk(resourceDirectory)) {
paths.filter(pathLocal -> Files.isRegularFile(pathLocal)
&& !validResources.contains(
pathLocal.getFileName().toString()))
.forEach(this::deleteFile);
} catch (IOException e) {
log.error("Error while scanning directory: {}, with error {}", resourceDirectory, e.getMessage());
}
}
}
/**
* This method will delete the JSON resource directory available in local git directory on subsequent commit made after the
* deletion of respective resource from DB
*
* @param validResources resources those are still available in DB
* @param resourceDirectory directory which needs to be scanned for possible file deletion operations
*/
@Override
public void scanAndDeleteDirectoryForDeletedResources(Set<String> validResources, Path resourceDirectory) {
// Scan resource directory and delete any unwanted directory if present
// unwanted directory : corresponding resource from DB has been deleted
if (resourceDirectory.toFile().exists()) {
try (Stream<Path> paths = Files.walk(resourceDirectory, 1)) {
paths.filter(path -> Files.isDirectory(path)
&& !path.equals(resourceDirectory)
&& !validResources.contains(path.getFileName().toString()))
.forEach(this::deleteDirectory);
} catch (IOException e) {
log.error("Error while scanning directory {} with error {}", resourceDirectory, e.getMessage());
}
}
}
/**
* This method will delete the directory and all its contents
*
* @param directory
*/
@Override
public void deleteDirectory(Path directory) {
if (directory.toFile().exists()) {
try {
FileUtils.deleteDirectory(directory.toFile());
} catch (IOException e) {
log.error("Unable to delete directory for path {} with message {}", directory, e.getMessage());
}
}
}
/**
* This method will delete the file from local repo
*
* @param filePath file that needs to be deleted
*/
@Override
public void deleteFile(Path filePath) {
try {
Files.deleteIfExists(filePath);
} catch (DirectoryNotEmptyException e) {
log.error("Unable to delete non-empty directory at {} with cause", filePath, e.getMessage());
} catch (IOException e) {
log.error("Unable to delete file {} with {}", filePath, e.getMessage());
}
}
/**
* This method will be used to read and dehydrate the json file present from the local git repo
*
* @param filePath file on which the read operation will be performed
* @return resource stored in the JSON file
*/
@Override
public Object readFile(Path filePath) {
Span span = observationHelper.createSpan(GitSpan.FILE_READ);
observationHelper.startSpan(span, true);
Object file;
try (FileReader reader = new FileReader(filePath.toFile())) {
file = gson.fromJson(reader, Object.class);
} catch (Exception e) {
log.error("Error while reading file {} with message {} with cause", filePath, e.getMessage(), e.getCause());
return null;
} finally {
observationHelper.endSpan(span, true);
}
return file;
}
/**
* This method will be used to read and dehydrate the json files present from the local git repo
*
* @param directoryPath directory path for files on which read operation will be performed
* @return resources stored in the directory
*/
@Override
public Map<String, Object> readFiles(Path directoryPath, String keySuffix) {
Map<String, Object> resource = new HashMap<>();
File directory = directoryPath.toFile();
if (directory.isDirectory()) {
Arrays.stream(Objects.requireNonNull(directory.listFiles())).forEach(file -> {
try (FileReader reader = new FileReader(file)) {
resource.put(file.getName() + keySuffix, gson.fromJson(reader, Object.class));
} catch (Exception e) {
log.error(
"Error while reading file {} with message {} with cause",
file.toPath(),
e.getMessage(),
e.getCause());
}
});
}
return resource;
}
/**
* This method will read the content of the file as a plain text and does not apply the gson to json transformation
*
* @param filePath file path for files on which read operation will be performed
* @return content of the file in the path
*/
@Override
public String readFileAsString(Path filePath) {
Span span = observationHelper.createSpan(GitSpan.FILE_READ);
observationHelper.startSpan(span, true);
String data = CommonConstants.EMPTY_STRING;
try {
data = FileUtils.readFileToString(filePath.toFile(), "UTF-8");
} catch (IOException e) {
log.error("Error while reading the file from git repo {} ", e.getMessage());
} finally {
observationHelper.endSpan(span, true);
}
return data;
}
@Override
public Integer getFileFormatVersion(Object metadata) {
if (metadata == null) {
return 1;
}
JsonObject json = gson.fromJson(gson.toJson(metadata), JsonObject.class);
JsonElement fileFormatVersion = json.get(CommonConstants.FILE_FORMAT_VERSION);
return fileFormatVersion.getAsInt();
}
@Override
public JSONObject getMainContainer(Object pageJson) {
JSONObject pageJSON = new JSONObject(gson.toJson(pageJson));
JSONArray layouts = pageJSON.getJSONObject("unpublishedPage").getJSONArray("layouts");
return layouts.getJSONObject(0).getJSONObject("dsl");
}
@Override
public Mono<Long> deleteIndexLockFile(Path path, int validTimeInSeconds) {
// Check the time created of the index.lock file
// If the File is stale for more than validTime, then delete the file
try {
BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
FileTime fileTime = attr.creationTime();
Instant now = Instant.now();
Instant validCreateTime = now.minusSeconds(validTimeInSeconds);
if (fileTime.toInstant().isBefore(validCreateTime)) {
// Add base repo path
path = Paths.get(path + ".lock");
deleteFile(path);
return Mono.just(now.minusMillis(fileTime.toMillis()).getEpochSecond());
} else {
return Mono.just(0L);
}
} catch (IOException ex) {
log.error("Error reading index.lock file: {}", ex.getMessage());
return Mono.just(0L);
}
}
}

View File

@ -1,15 +1,11 @@
package com.appsmith.git.files.operations; package com.appsmith.git.files.operations;
import com.appsmith.external.annotations.FeatureFlagged;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.git.constants.GitSpan; import com.appsmith.external.git.constants.GitSpan;
import com.appsmith.external.git.operations.FileOperationsCE; import com.appsmith.external.git.operations.FileOperationsCE;
import com.appsmith.external.helpers.ObservationHelper; import com.appsmith.external.helpers.ObservationHelper;
import com.appsmith.external.models.ApplicationGitReference; import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.external.models.BaseDomain; import com.appsmith.external.models.BaseDomain;
import com.appsmith.external.views.Git; import com.appsmith.external.views.Git;
import com.appsmith.git.configurations.GitServiceConfig;
import com.appsmith.git.constants.CommonConstants; import com.appsmith.git.constants.CommonConstants;
import com.appsmith.util.SerializationUtils; import com.appsmith.util.SerializationUtils;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
@ -20,25 +16,32 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.GsonBuilder;
import io.micrometer.tracing.Span; import io.micrometer.tracing.Span;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.json.JSONObject; import org.json.JSONObject;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.METADATA; import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.METADATA;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.RESOURCE_TYPE; import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricConstantsCE.RESOURCE_TYPE;
@ -47,8 +50,7 @@ import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitMetricCon
@Slf4j @Slf4j
@Getter @Getter
@Component @Component
@Import({GitServiceConfig.class}) public class FileOperationsCEv2Impl implements FileOperationsCE {
public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements FileOperationsCE {
protected final ObjectMapper objectMapper; protected final ObjectMapper objectMapper;
protected final ObjectReader objectReader; protected final ObjectReader objectReader;
@ -56,13 +58,7 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
private final ObservationHelper observationHelper; private final ObservationHelper observationHelper;
public FileOperationsCEv2Impl( public FileOperationsCEv2Impl(PrettyPrinter prettyPrinter, ObservationHelper observationHelper) {
GitServiceConfig gitServiceConfig,
GitExecutor gitExecutor,
GsonBuilder gsonBuilder,
PrettyPrinter prettyPrinter,
ObservationHelper observationHelper) {
super(gitServiceConfig, gitExecutor, gsonBuilder, observationHelper);
this.objectMapper = SerializationUtils.getBasicObjectMapper(prettyPrinter); this.objectMapper = SerializationUtils.getBasicObjectMapper(prettyPrinter);
@ -73,7 +69,6 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
this.observationHelper = observationHelper; this.observationHelper = observationHelper;
} }
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
@Override @Override
public void saveMetadataResource(ApplicationGitReference applicationGitReference, Path baseRepo) { public void saveMetadataResource(ApplicationGitReference applicationGitReference, Path baseRepo) {
ObjectNode metadata = objectMapper.valueToTree(applicationGitReference.getMetadata()); ObjectNode metadata = objectMapper.valueToTree(applicationGitReference.getMetadata());
@ -81,7 +76,6 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
saveResource(metadata, baseRepo.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION)); saveResource(metadata, baseRepo.resolve(CommonConstants.METADATA + CommonConstants.JSON_EXTENSION));
} }
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
@Override @Override
public void saveWidgets(JSONObject sourceEntity, String resourceName, Path path) { public void saveWidgets(JSONObject sourceEntity, String resourceName, Path path) {
Span span = observationHelper.createSpan(GitSpan.FILE_WRITE); Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
@ -101,7 +95,6 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
} }
} }
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
@Override @Override
public boolean writeToFile(Object sourceEntity, Path path) throws IOException { public boolean writeToFile(Object sourceEntity, Path path) throws IOException {
Span span = observationHelper.createSpan(GitSpan.FILE_WRITE); Span span = observationHelper.createSpan(GitSpan.FILE_WRITE);
@ -126,7 +119,6 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
* @param filePath file on which the read operation will be performed * @param filePath file on which the read operation will be performed
* @return resource stored in the JSON file * @return resource stored in the JSON file
*/ */
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
@Override @Override
public Object readFile(Path filePath) { public Object readFile(Path filePath) {
Span span = observationHelper.createSpan(GitSpan.FILE_READ); Span span = observationHelper.createSpan(GitSpan.FILE_READ);
@ -150,7 +142,6 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
* @param directoryPath directory path for files on which read operation will be performed * @param directoryPath directory path for files on which read operation will be performed
* @return resources stored in the directory * @return resources stored in the directory
*/ */
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
@Override @Override
public Map<String, Object> readFiles(Path directoryPath, String keySuffix) { public Map<String, Object> readFiles(Path directoryPath, String keySuffix) {
Map<String, Object> resource = new HashMap<>(); Map<String, Object> resource = new HashMap<>();
@ -171,7 +162,6 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
return resource; return resource;
} }
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
@Override @Override
public Integer getFileFormatVersion(Object metadata) { public Integer getFileFormatVersion(Object metadata) {
if (metadata == null) { if (metadata == null) {
@ -182,7 +172,6 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
return fileFormatVersion; return fileFormatVersion;
} }
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
@Override @Override
public JSONObject getMainContainer(Object pageJson) { public JSONObject getMainContainer(Object pageJson) {
JsonNode pageJSON = objectMapper.valueToTree(pageJson); JsonNode pageJSON = objectMapper.valueToTree(pageJson);
@ -193,4 +182,145 @@ public class FileOperationsCEv2Impl extends FileOperationsCEImpl implements File
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/**
* This method will be used to store the DB resource to JSON file
*
* @param sourceEntity resource extracted from DB to be stored in file
* @param path file path where the resource to be stored
* @return if the file operation is successful
*/
@Override
public boolean saveResource(Object sourceEntity, Path path) {
try {
Files.createDirectories(path.getParent());
return writeToFile(sourceEntity, path);
} catch (IOException e) {
log.error("Error while writing resource to file {} with {}", path, e.getMessage());
log.debug(e.getMessage());
}
return false;
}
/**
* This method will delete the JSON resource available in local git directory on subsequent commit made after the
* deletion of respective resource from DB
*
* @param validResources resources those are still available in DB
* @param resourceDirectory directory which needs to be scanned for possible file deletion operations
*/
@Override
public void scanAndDeleteFileForDeletedResources(Set<String> validResources, Path resourceDirectory) {
// Scan resource directory and delete any unwanted file if present
// unwanted file : corresponding resource from DB has been deleted
if (resourceDirectory.toFile().exists()) {
try (Stream<Path> paths = Files.walk(resourceDirectory)) {
paths.filter(pathLocal -> Files.isRegularFile(pathLocal)
&& !validResources.contains(
pathLocal.getFileName().toString()))
.forEach(this::deleteFile);
} catch (IOException e) {
log.error("Error while scanning directory: {}, with error {}", resourceDirectory, e.getMessage());
}
}
}
/**
* This method will delete the JSON resource directory available in local git directory on subsequent commit made after the
* deletion of respective resource from DB
*
* @param validResources resources those are still available in DB
* @param resourceDirectory directory which needs to be scanned for possible file deletion operations
*/
@Override
public void scanAndDeleteDirectoryForDeletedResources(Set<String> validResources, Path resourceDirectory) {
// Scan resource directory and delete any unwanted directory if present
// unwanted directory : corresponding resource from DB has been deleted
if (resourceDirectory.toFile().exists()) {
try (Stream<Path> paths = Files.walk(resourceDirectory, 1)) {
paths.filter(path -> Files.isDirectory(path)
&& !path.equals(resourceDirectory)
&& !validResources.contains(path.getFileName().toString()))
.forEach(this::deleteDirectory);
} catch (IOException e) {
log.error("Error while scanning directory {} with error {}", resourceDirectory, e.getMessage());
}
}
}
/**
* This method will delete the directory and all its contents
*
* @param directory
*/
@Override
public void deleteDirectory(Path directory) {
if (directory.toFile().exists()) {
try {
FileUtils.deleteDirectory(directory.toFile());
} catch (IOException e) {
log.error("Unable to delete directory for path {} with message {}", directory, e.getMessage());
}
}
}
/**
* This method will delete the file from local repo
*
* @param filePath file that needs to be deleted
*/
@Override
public void deleteFile(Path filePath) {
try {
Files.deleteIfExists(filePath);
} catch (DirectoryNotEmptyException e) {
log.error("Unable to delete non-empty directory at {} with cause", filePath, e.getMessage());
} catch (IOException e) {
log.error("Unable to delete file {} with {}", filePath, e.getMessage());
}
}
/**
* This method will read the content of the file as a plain text and does not apply the gson to json transformation
*
* @param filePath file path for files on which read operation will be performed
* @return content of the file in the path
*/
@Override
public String readFileAsString(Path filePath) {
Span span = observationHelper.createSpan(GitSpan.FILE_READ);
observationHelper.startSpan(span, true);
String data = CommonConstants.EMPTY_STRING;
try {
data = FileUtils.readFileToString(filePath.toFile(), "UTF-8");
} catch (IOException e) {
log.error("Error while reading the file from git repo {} ", e.getMessage());
} finally {
observationHelper.endSpan(span, true);
}
return data;
}
@Override
public Mono<Long> deleteIndexLockFile(Path path, int validTimeInSeconds) {
// Check the time created of the index.lock file
// If the File is stale for more than validTime, then delete the file
try {
BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
FileTime fileTime = attr.creationTime();
Instant now = Instant.now();
Instant validCreateTime = now.minusSeconds(validTimeInSeconds);
if (fileTime.toInstant().isBefore(validCreateTime)) {
// Add base repo path
path = Paths.get(path + ".lock");
deleteFile(path);
return Mono.just(now.minusMillis(fileTime.toMillis()).getEpochSecond());
} else {
return Mono.just(0L);
}
} catch (IOException ex) {
log.error("Error reading index.lock file: {}", ex.getMessage());
return Mono.just(0L);
}
}
} }

View File

@ -1,25 +1,15 @@
package com.appsmith.git.files.operations; package com.appsmith.git.files.operations;
import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.git.operations.FileOperations; import com.appsmith.external.git.operations.FileOperations;
import com.appsmith.external.helpers.ObservationHelper; import com.appsmith.external.helpers.ObservationHelper;
import com.appsmith.git.configurations.GitServiceConfig;
import com.fasterxml.jackson.core.PrettyPrinter; import com.fasterxml.jackson.core.PrettyPrinter;
import com.google.gson.GsonBuilder;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component
@Primary @Primary
@Import({GitServiceConfig.class}) @Component
public class FileOperationsImpl extends FileOperationsCEv2Impl implements FileOperations { public class FileOperationsImpl extends FileOperationsCEv2Impl implements FileOperations {
public FileOperationsImpl( public FileOperationsImpl(PrettyPrinter prettyPrinter, ObservationHelper observationHelper) {
GitServiceConfig gitServiceConfig, super(prettyPrinter, observationHelper);
GitExecutor gitExecutor,
GsonBuilder gsonBuilder,
PrettyPrinter prettyPrinter,
ObservationHelper observationHelper) {
super(gitServiceConfig, gitExecutor, gsonBuilder, prettyPrinter, observationHelper);
} }
} }

View File

@ -7,7 +7,6 @@ import com.appsmith.git.configurations.GitServiceConfig;
import com.appsmith.git.files.FileUtilsImpl; import com.appsmith.git.files.FileUtilsImpl;
import com.appsmith.git.files.operations.FileOperationsImpl; import com.appsmith.git.files.operations.FileOperationsImpl;
import com.appsmith.git.service.GitExecutorImpl; import com.appsmith.git.service.GitExecutorImpl;
import com.google.gson.GsonBuilder;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.GitAPIException;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
@ -42,8 +41,7 @@ public class FileUtilsImplTest {
gitExecutor = Mockito.mock(GitExecutorImpl.class); gitExecutor = Mockito.mock(GitExecutorImpl.class);
GitServiceConfig gitServiceConfig = new GitServiceConfig(); GitServiceConfig gitServiceConfig = new GitServiceConfig();
gitServiceConfig.setGitRootPath(localTestDirectoryPath.toString()); gitServiceConfig.setGitRootPath(localTestDirectoryPath.toString());
FileOperations fileOperations = FileOperations fileOperations = new FileOperationsImpl(null, ObservationHelper.NOOP);
new FileOperationsImpl(gitServiceConfig, gitExecutor, new GsonBuilder(), null, ObservationHelper.NOOP);
fileUtils = new FileUtilsImpl(gitServiceConfig, gitExecutor, fileOperations, ObservationHelper.NOOP); fileUtils = new FileUtilsImpl(gitServiceConfig, gitExecutor, fileOperations, ObservationHelper.NOOP);
} }

View File

@ -14,16 +14,6 @@ public enum FeatureFlagEnum {
APP_NAVIGATION_LOGO_UPLOAD, APP_NAVIGATION_LOGO_UPLOAD,
release_embed_hide_share_settings_enabled, release_embed_hide_share_settings_enabled,
rollout_datasource_test_rate_limit_enabled, rollout_datasource_test_rate_limit_enabled,
release_git_autocommit_feature_enabled,
/**
* Since checking eligibility for autocommit is an expensive operation,
* We want to roll out this feature on cloud in a controlled manner.
* We could have used the autocommit flag itself, however it is on tenant level,
* and it can't be moved to user level due to its usage on non-reactive code paths.
* We would keep the main autocommit flag false on production for the version <= testing versions,
* and turn it to true for later versions
* We would remove this feature flag once the testing is complete.
*/
release_git_autocommit_eligibility_enabled,
// Add EE flags below this line, to avoid conflicts. // Add EE flags below this line, to avoid conflicts.
} }

View File

@ -16,8 +16,6 @@ public interface FileOperationsCE {
void saveWidgets(JSONObject sourceEntity, String resourceName, Path path); void saveWidgets(JSONObject sourceEntity, String resourceName, Path path);
void writeStringToFile(String sourceEntity, Path path) throws IOException;
boolean writeToFile(Object sourceEntity, Path path) throws IOException; boolean writeToFile(Object sourceEntity, Path path) throws IOException;
void scanAndDeleteFileForDeletedResources(Set<String> validResources, Path resourceDirectory); void scanAndDeleteFileForDeletedResources(Set<String> validResources, Path resourceDirectory);

View File

@ -1,37 +0,0 @@
package com.appsmith.server.git.autocommit.helpers;
import com.appsmith.server.domains.GitArtifactMetadata;
import com.appsmith.server.dtos.AutoCommitTriggerDTO;
import com.appsmith.server.dtos.PageDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import static java.lang.Boolean.FALSE;
@Slf4j
@Component
public class AutoCommitEligibilityHelperFallbackImpl implements AutoCommitEligibilityHelper {
@Override
public Mono<Boolean> isServerAutoCommitRequired(String workspaceId, GitArtifactMetadata gitMetadata) {
return Mono.just(FALSE);
}
@Override
public Mono<Boolean> isClientMigrationRequired(PageDTO pageDTO) {
return Mono.just(FALSE);
}
@Override
public Mono<Boolean> isClientMigrationRequiredFSOps(
String workspaceId, GitArtifactMetadata gitMetadata, PageDTO pageDTO) {
return Mono.just(FALSE);
}
@Override
public Mono<AutoCommitTriggerDTO> isAutoCommitRequired(
String workspaceId, GitArtifactMetadata gitArtifactMetadata, PageDTO pageDTO) {
return Mono.just(new AutoCommitTriggerDTO(FALSE, FALSE, FALSE));
}
}

View File

@ -25,8 +25,7 @@ import static java.lang.Boolean.TRUE;
@Primary @Primary
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class AutoCommitEligibilityHelperImpl extends AutoCommitEligibilityHelperFallbackImpl public class AutoCommitEligibilityHelperImpl implements AutoCommitEligibilityHelper {
implements AutoCommitEligibilityHelper {
private final CommonGitFileUtils commonGitFileUtils; private final CommonGitFileUtils commonGitFileUtils;
private final DSLMigrationUtils dslMigrationUtils; private final DSLMigrationUtils dslMigrationUtils;

View File

@ -1,33 +0,0 @@
package com.appsmith.server.git.autocommit.helpers;
import com.appsmith.server.dtos.AutoCommitResponseDTO;
import com.appsmith.server.dtos.AutoCommitTriggerDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Slf4j
@Component
public class GitAutoCommitHelperFallbackImpl implements GitAutoCommitHelper {
@Override
public Mono<Boolean> autoCommitClientMigration(String defaultApplicationId, String branchName) {
return Mono.just(Boolean.FALSE);
}
@Override
public Mono<Boolean> autoCommitServerMigration(String defaultApplicationId, String branchName) {
return Mono.just(Boolean.FALSE);
}
@Override
public Mono<AutoCommitResponseDTO> getAutoCommitProgress(String defaultApplicationId, String branchName) {
return Mono.just(new AutoCommitResponseDTO(AutoCommitResponseDTO.AutoCommitResponse.IDLE));
}
@Override
public Mono<Boolean> publishAutoCommitEvent(
AutoCommitTriggerDTO autoCommitTriggerDTO, String defaultApplicationId, String branchName) {
return Mono.just(Boolean.FALSE);
}
}

View File

@ -1,7 +1,5 @@
package com.appsmith.server.git.autocommit.helpers; package com.appsmith.server.git.autocommit.helpers;
import com.appsmith.external.annotations.FeatureFlagged;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.server.applications.base.ApplicationService; import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.domains.Application; import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.GitArtifactMetadata; import com.appsmith.server.domains.GitArtifactMetadata;
@ -18,7 +16,6 @@ import com.appsmith.server.services.UserDataService;
import com.appsmith.server.solutions.ApplicationPermission; import com.appsmith.server.solutions.ApplicationPermission;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
@ -28,9 +25,8 @@ import static com.appsmith.server.dtos.AutoCommitResponseDTO.AutoCommitResponse.
import static com.appsmith.server.dtos.AutoCommitResponseDTO.AutoCommitResponse.LOCKED; import static com.appsmith.server.dtos.AutoCommitResponseDTO.AutoCommitResponse.LOCKED;
@Slf4j @Slf4j
@Primary
@Service @Service
public class GitAutoCommitHelperImpl extends GitAutoCommitHelperFallbackImpl implements GitAutoCommitHelper { public class GitAutoCommitHelperImpl implements GitAutoCommitHelper {
private final GitPrivateRepoHelper gitPrivateRepoHelper; private final GitPrivateRepoHelper gitPrivateRepoHelper;
private final AutoCommitEventHandler autoCommitEventHandler; private final AutoCommitEventHandler autoCommitEventHandler;
private final UserDataService userDataService; private final UserDataService userDataService;
@ -126,13 +122,11 @@ public class GitAutoCommitHelperImpl extends GitAutoCommitHelperFallbackImpl imp
} }
@Override @Override
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
public Mono<Boolean> autoCommitClientMigration(String defaultApplicationId, String branchName) { public Mono<Boolean> autoCommitClientMigration(String defaultApplicationId, String branchName) {
return autoCommitApplication(defaultApplicationId, branchName, Boolean.TRUE); return autoCommitApplication(defaultApplicationId, branchName, Boolean.TRUE);
} }
@Override @Override
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
public Mono<Boolean> autoCommitServerMigration(String defaultApplicationId, String branchName) { public Mono<Boolean> autoCommitServerMigration(String defaultApplicationId, String branchName) {
return autoCommitApplication(defaultApplicationId, branchName, Boolean.FALSE); return autoCommitApplication(defaultApplicationId, branchName, Boolean.FALSE);
} }
@ -236,7 +230,6 @@ public class GitAutoCommitHelperImpl extends GitAutoCommitHelperFallbackImpl imp
} }
@Override @Override
@FeatureFlagged(featureFlagName = FeatureFlagEnum.release_git_autocommit_feature_enabled)
public Mono<Boolean> publishAutoCommitEvent( public Mono<Boolean> publishAutoCommitEvent(
AutoCommitTriggerDTO autoCommitTriggerDTO, String defaultApplicationId, String branchName) { AutoCommitTriggerDTO autoCommitTriggerDTO, String defaultApplicationId, String branchName) {

View File

@ -1,21 +1,26 @@
package com.appsmith.server.git; package com.appsmith.server.git;
import com.appsmith.external.converters.ISOStringToInstantConverter; import com.appsmith.external.converters.ISOStringToInstantConverter;
import com.appsmith.external.dtos.GitLogDTO;
import com.appsmith.external.dtos.ModifiedResources; import com.appsmith.external.dtos.ModifiedResources;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.external.git.GitExecutor; import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.models.ApplicationGitReference; import com.appsmith.external.models.ApplicationGitReference;
import com.appsmith.server.configurations.ProjectProperties;
import com.appsmith.server.constants.SerialiseArtifactObjective; import com.appsmith.server.constants.SerialiseArtifactObjective;
import com.appsmith.server.domains.Workspace; import com.appsmith.server.domains.Workspace;
import com.appsmith.server.dtos.ApplicationImportDTO; import com.appsmith.server.dtos.ApplicationImportDTO;
import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.events.AutoCommitEvent;
import com.appsmith.server.exports.internal.ExportService; import com.appsmith.server.exports.internal.ExportService;
import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.git.autocommit.AutoCommitEventHandler;
import com.appsmith.server.git.autocommit.AutoCommitEventHandlerImpl;
import com.appsmith.server.helpers.CommonGitFileUtils; import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.MockPluginExecutor;
import com.appsmith.server.helpers.PluginExecutorHelper; import com.appsmith.server.helpers.PluginExecutorHelper;
import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.imports.internal.ImportService; import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.services.FeatureFlagService; import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.WorkspaceService; import com.appsmith.server.services.WorkspaceService;
import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper; import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper;
import com.google.gson.Gson; import com.google.gson.Gson;
@ -30,12 +35,12 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo; import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory;
@ -54,11 +59,12 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import static com.appsmith.server.constants.ArtifactType.APPLICATION; import static com.appsmith.server.constants.ArtifactType.APPLICATION;
import static java.lang.Boolean.FALSE; import static com.appsmith.server.git.autocommit.AutoCommitEventHandlerCEImpl.AUTO_COMMIT_MSG_FORMAT;
import static java.lang.Boolean.TRUE; import static java.lang.Boolean.TRUE;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@ -114,12 +120,29 @@ public class ServerSchemaMigrationEnforcerTest {
@SpyBean @SpyBean
GitExecutor gitExecutor; GitExecutor gitExecutor;
@SpyBean
FeatureFlagService featureFlagService;
@MockBean @MockBean
PluginExecutorHelper pluginExecutorHelper; PluginExecutorHelper pluginExecutorHelper;
AutoCommitEventHandler autoCommitEventHandler;
@Autowired
ProjectProperties projectProperties;
@SpyBean
RedisUtils redisUtils;
@SpyBean
GitRedisUtils gitRedisUtils;
@Autowired
AnalyticsService analyticsService;
@MockBean
DSLMigrationUtils dslMigrationUtils;
@MockBean
ApplicationEventPublisher applicationEventPublisher;
private final Gson gson = new GsonBuilder() private final Gson gson = new GsonBuilder()
.registerTypeAdapter(Instant.class, new ISOStringToInstantConverter()) .registerTypeAdapter(Instant.class, new ISOStringToInstantConverter())
.setPrettyPrinting() .setPrettyPrinting()
@ -290,51 +313,6 @@ public class ServerSchemaMigrationEnforcerTest {
} }
} }
@Test
public void savedFile_reSavedWithDifferentSerialisationLogic_diffOccurs()
throws URISyntaxException, IOException, GitAPIException {
ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("ce-automation-test.json"));
ModifiedResources modifiedResources = new ModifiedResources();
modifiedResources.setAllModified(true);
applicationJson.setModifiedResources(modifiedResources);
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), FALSE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
gitFileSystemTestHelper.setupGitRepository(
WORKSPACE_ID, DEFAULT_APPLICATION_ID, BRANCH_NAME, REPO_NAME, applicationJson);
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Path suffixPath = Paths.get(WORKSPACE_ID, DEFAULT_APPLICATION_ID, REPO_NAME);
Path gitCompletePath = gitExecutor.createRepoPath(suffixPath);
commonGitFileUtils
.saveArtifactToLocalRepo(suffixPath, applicationJson, BRANCH_NAME)
.block();
try (Git gitRepo = Git.open(gitCompletePath.toFile())) {
List<DiffEntry> diffEntries = gitRepo.diff().call();
Set<String> fileChanges = Set.of(
"application.json",
"metadata.json",
"theme.json",
"datasources/JSON typicode API (1).json",
"datasources/TED postgres (1).json",
"datasources/mainGoogleSheetDS.json");
for (DiffEntry diff : diffEntries) {
assertThat(fileChanges).contains(diff.getOldPath());
assertThat(fileChanges).contains(diff.getNewPath());
assertThat(diff.getChangeType()).isEqualTo(DiffEntry.ChangeType.MODIFY);
}
assertThat(diffEntries.size()).isNotZero();
}
}
@Test @Test
public void savedFile_reSavedWithSameSerialisationLogic_noDiffOccurs() public void savedFile_reSavedWithSameSerialisationLogic_noDiffOccurs()
throws URISyntaxException, IOException, GitAPIException { throws URISyntaxException, IOException, GitAPIException {
@ -372,11 +350,6 @@ public class ServerSchemaMigrationEnforcerTest {
modifiedResources.setAllModified(true); modifiedResources.setAllModified(true);
applicationJson.setModifiedResources(modifiedResources); applicationJson.setModifiedResources(modifiedResources);
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
gitFileSystemTestHelper.setupGitRepository( gitFileSystemTestHelper.setupGitRepository(
WORKSPACE_ID, DEFAULT_APPLICATION_ID, BRANCH_NAME, REPO_NAME, applicationJson); WORKSPACE_ID, DEFAULT_APPLICATION_ID, BRANCH_NAME, REPO_NAME, applicationJson);
@ -423,4 +396,73 @@ public class ServerSchemaMigrationEnforcerTest {
} }
} }
} }
@Test
public void autocommitMigration_WhenServerVersionIsBehindDiffOccursAnd_CommitSuccess()
throws URISyntaxException, IOException, GitAPIException {
autoCommitEventHandler = new AutoCommitEventHandlerImpl(
applicationEventPublisher,
gitRedisUtils,
redisUtils,
dslMigrationUtils,
commonGitFileUtils,
gitExecutor,
projectProperties,
analyticsService);
AutoCommitEvent autoCommitEvent = createEvent();
autoCommitEvent.setIsServerSideEvent(TRUE);
ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json"));
Path baseRepoSuffix = Paths.get(
autoCommitEvent.getWorkspaceId(), autoCommitEvent.getApplicationId(), autoCommitEvent.getRepoName());
Mockito.doReturn(Mono.just("success"))
.when(gitExecutor)
.pushApplication(
baseRepoSuffix,
autoCommitEvent.getRepoUrl(),
autoCommitEvent.getPublicKey(),
autoCommitEvent.getPrivateKey(),
autoCommitEvent.getBranchName());
gitFileSystemTestHelper.setupGitRepository(autoCommitEvent, applicationJson);
StepVerifier.create(autoCommitEventHandler
.autoCommitServerMigration(autoCommitEvent)
.zipWhen(a -> redisUtils.getAutoCommitProgress(autoCommitEvent.getApplicationId())))
.assertNext(tuple2 -> {
assertThat(tuple2.getT1()).isTrue();
assertThat(tuple2.getT2()).isEqualTo(100);
})
.verifyComplete();
StepVerifier.create(gitExecutor.getCommitHistory(baseRepoSuffix))
.assertNext(gitLogDTOs -> {
assertThat(gitLogDTOs).isNotEmpty();
assertThat(gitLogDTOs.size()).isEqualTo(3);
Set<String> commitMessages =
gitLogDTOs.stream().map(GitLogDTO::getCommitMessage).collect(Collectors.toSet());
assertThat(commitMessages)
.contains(String.format(AUTO_COMMIT_MSG_FORMAT, projectProperties.getVersion()));
})
.verifyComplete();
}
private AutoCommitEvent createEvent() {
String defaultApplicationId = "default-app-id", branchName = "develop", workspaceId = "test-workspace-id";
AutoCommitEvent autoCommitEvent = new AutoCommitEvent();
autoCommitEvent.setApplicationId(defaultApplicationId + UUID.randomUUID());
autoCommitEvent.setBranchName(branchName);
autoCommitEvent.setRepoName("test-repo");
autoCommitEvent.setAuthorName("test author");
autoCommitEvent.setAuthorEmail("testauthor@example.com");
autoCommitEvent.setWorkspaceId(workspaceId);
autoCommitEvent.setRepoUrl("git@example.com:exampleorg/example-repo.git");
autoCommitEvent.setPrivateKey("private-key");
autoCommitEvent.setPublicKey("public-key");
return autoCommitEvent;
}
} }

View File

@ -1,7 +1,6 @@
package com.appsmith.server.git.autocommit; package com.appsmith.server.git.autocommit;
import com.appsmith.external.dtos.GitLogDTO; import com.appsmith.external.dtos.GitLogDTO;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.external.git.FileInterface; import com.appsmith.external.git.FileInterface;
import com.appsmith.external.git.GitExecutor; import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.helpers.AppsmithBeanUtils; import com.appsmith.external.helpers.AppsmithBeanUtils;
@ -13,7 +12,6 @@ import com.appsmith.server.domains.NewPage;
import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.events.AutoCommitEvent; import com.appsmith.server.events.AutoCommitEvent;
import com.appsmith.server.featureflags.CachedFeatures;
import com.appsmith.server.git.GitRedisUtils; import com.appsmith.server.git.GitRedisUtils;
import com.appsmith.server.helpers.CommonGitFileUtils; import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils; import com.appsmith.server.helpers.DSLMigrationUtils;
@ -21,7 +19,6 @@ import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.migrations.JsonSchemaMigration; import com.appsmith.server.migrations.JsonSchemaMigration;
import com.appsmith.server.migrations.JsonSchemaVersions; import com.appsmith.server.migrations.JsonSchemaVersions;
import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.AnalyticsService;
import com.appsmith.server.services.FeatureFlagService;
import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper; import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject; import net.minidev.json.JSONObject;
@ -30,7 +27,6 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
@ -45,13 +41,11 @@ import java.net.URISyntaxException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.appsmith.server.git.autocommit.AutoCommitEventHandlerCEImpl.AUTO_COMMIT_MSG_FORMAT; import static com.appsmith.server.git.autocommit.AutoCommitEventHandlerCEImpl.AUTO_COMMIT_MSG_FORMAT;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE; import static java.lang.Boolean.TRUE;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@ -89,9 +83,6 @@ public class AutoCommitEventHandlerImplTest {
@SpyBean @SpyBean
GitExecutor gitExecutor; GitExecutor gitExecutor;
@MockBean
FeatureFlagService featureFlagService;
@Autowired @Autowired
GitFileSystemTestHelper gitFileSystemTestHelper; GitFileSystemTestHelper gitFileSystemTestHelper;
@ -474,56 +465,6 @@ public class AutoCommitEventHandlerImplTest {
.verifyComplete(); .verifyComplete();
} }
@Test
public void autocommitServerMigration_WhenSerialisationLogicChanges_CommitSuccess()
throws URISyntaxException, IOException, GitAPIException {
AutoCommitEvent autoCommitEvent = createEvent();
autoCommitEvent.setIsServerSideEvent(TRUE);
ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json"));
Path baseRepoSuffix = Paths.get(
autoCommitEvent.getWorkspaceId(), autoCommitEvent.getApplicationId(), autoCommitEvent.getRepoName());
doReturn(Mono.just("success"))
.when(gitExecutor)
.pushApplication(
baseRepoSuffix,
autoCommitEvent.getRepoUrl(),
autoCommitEvent.getPublicKey(),
autoCommitEvent.getPrivateKey(),
autoCommitEvent.getBranchName());
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), FALSE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
gitFileSystemTestHelper.setupGitRepository(autoCommitEvent, applicationJson);
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
StepVerifier.create(autoCommitEventHandler
.autoCommitServerMigration(autoCommitEvent)
.zipWhen(a -> redisUtils.getAutoCommitProgress(autoCommitEvent.getApplicationId())))
.assertNext(tuple2 -> {
assertThat(tuple2.getT1()).isTrue();
assertThat(tuple2.getT2()).isEqualTo(100);
})
.verifyComplete();
StepVerifier.create(gitExecutor.getCommitHistory(baseRepoSuffix))
.assertNext(gitLogDTOs -> {
assertThat(gitLogDTOs).isNotEmpty();
assertThat(gitLogDTOs.size()).isEqualTo(3);
Set<String> commitMessages =
gitLogDTOs.stream().map(GitLogDTO::getCommitMessage).collect(Collectors.toSet());
assertThat(commitMessages)
.contains(String.format(AUTO_COMMIT_MSG_FORMAT, projectProperties.getVersion()));
})
.verifyComplete();
}
@Test @Test
public void autocommitServerMigration_WhenSerialisationLogicDoesNotChange_CommitFailure() public void autocommitServerMigration_WhenSerialisationLogicDoesNotChange_CommitFailure()
throws URISyntaxException, IOException, GitAPIException { throws URISyntaxException, IOException, GitAPIException {
@ -533,11 +474,6 @@ public class AutoCommitEventHandlerImplTest {
ApplicationJson applicationJson = ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json")); gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json"));
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), FALSE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
gitFileSystemTestHelper.setupGitRepository(autoCommitEvent, applicationJson); gitFileSystemTestHelper.setupGitRepository(autoCommitEvent, applicationJson);
StepVerifier.create(autoCommitEventHandler StepVerifier.create(autoCommitEventHandler
.autoCommitServerMigration(autoCommitEvent) .autoCommitServerMigration(autoCommitEvent)

View File

@ -1,7 +1,6 @@
package com.appsmith.server.git.autocommit; package com.appsmith.server.git.autocommit;
import com.appsmith.external.dtos.GitLogDTO; import com.appsmith.external.dtos.GitLogDTO;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.external.git.GitExecutor; import com.appsmith.external.git.GitExecutor;
import com.appsmith.external.helpers.AppsmithBeanUtils; import com.appsmith.external.helpers.AppsmithBeanUtils;
import com.appsmith.server.acl.AclPermission; import com.appsmith.server.acl.AclPermission;
@ -17,7 +16,6 @@ import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.AutoCommitResponseDTO; import com.appsmith.server.dtos.AutoCommitResponseDTO;
import com.appsmith.server.dtos.AutoCommitTriggerDTO; import com.appsmith.server.dtos.AutoCommitTriggerDTO;
import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.featureflags.CachedFeatures;
import com.appsmith.server.git.autocommit.helpers.AutoCommitEligibilityHelper; import com.appsmith.server.git.autocommit.helpers.AutoCommitEligibilityHelper;
import com.appsmith.server.git.common.CommonGitService; import com.appsmith.server.git.common.CommonGitService;
import com.appsmith.server.helpers.CommonGitFileUtils; import com.appsmith.server.helpers.CommonGitFileUtils;
@ -27,7 +25,6 @@ import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.migrations.JsonSchemaMigration; import com.appsmith.server.migrations.JsonSchemaMigration;
import com.appsmith.server.migrations.JsonSchemaVersions; import com.appsmith.server.migrations.JsonSchemaVersions;
import com.appsmith.server.newpages.base.NewPageService; import com.appsmith.server.newpages.base.NewPageService;
import com.appsmith.server.services.FeatureFlagService;
import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserDataService;
import com.appsmith.server.solutions.PagePermission; import com.appsmith.server.solutions.PagePermission;
import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper; import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper;
@ -39,7 +36,6 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
@ -54,7 +50,6 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.time.Duration; import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -80,9 +75,6 @@ public class AutoCommitServiceTest {
@SpyBean @SpyBean
GitExecutor gitExecutor; GitExecutor gitExecutor;
@MockBean
FeatureFlagService featureFlagService;
@MockBean @MockBean
DSLMigrationUtils dslMigrationUtils; DSLMigrationUtils dslMigrationUtils;
@ -199,21 +191,6 @@ public class AutoCommitServiceTest {
doReturn(Mono.just(new AutoCommitTriggerDTO(isAutocommitRequired, clientMigration, serverMigration))) doReturn(Mono.just(new AutoCommitTriggerDTO(isAutocommitRequired, clientMigration, serverMigration)))
.when(autoCommitEligibilityHelper) .when(autoCommitEligibilityHelper)
.isAutoCommitRequired(anyString(), any(), any()); .isAutoCommitRequired(anyString(), any(), any());
// doReturn(Mono.just(getMockedDsl()))
// .when(commonGitFileUtils)
// .getPageDslVersionNumber(anyString(), any(), any(), anyBoolean(), any());
//
// Integer serverVersion = jsonSchemaVersions.getServerVersion();
// Integer dslVersionNumber = clientMigration ? DSL_VERSION_NUMBER + 1 : DSL_VERSION_NUMBER;
// Integer serverSchemaVersionNumber = serverMigration ? serverVersion - 1 : serverVersion;
//
// doReturn(Mono.just(dslVersionNumber)).when(dslMigrationUtils).getLatestDslVersion();
//
// // server as true
// doReturn(Mono.just(serverSchemaVersionNumber))
// .when(commonGitFileUtils)
// .getMetadataServerSchemaMigrationVersion(anyString(), any(), anyBoolean(), any());
} }
@BeforeEach @BeforeEach
@ -238,15 +215,6 @@ public class AutoCommitServiceTest {
DEFAULT_APP_ID, pagePermission.getEditPermission(), ApplicationMode.PUBLISHED)) DEFAULT_APP_ID, pagePermission.getEditPermission(), ApplicationMode.PUBLISHED))
.thenReturn(Flux.just(pageDTO)); .thenReturn(Flux.just(pageDTO));
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(TRUE));
Mockito.when(commonGitService.fetchRemoteChanges(any(Application.class), any(Application.class), anyBoolean())) Mockito.when(commonGitService.fetchRemoteChanges(any(Application.class), any(Application.class), anyBoolean()))
.thenReturn(Mono.just(branchTrackingStatus)); .thenReturn(Mono.just(branchTrackingStatus));

View File

@ -1,7 +1,6 @@
package com.appsmith.server.git.autocommit.helpers; package com.appsmith.server.git.autocommit.helpers;
import com.appsmith.external.dtos.ModifiedResources; import com.appsmith.external.dtos.ModifiedResources;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.server.constants.ArtifactType; import com.appsmith.server.constants.ArtifactType;
import com.appsmith.server.domains.Application; import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.GitArtifactMetadata; import com.appsmith.server.domains.GitArtifactMetadata;
@ -10,12 +9,10 @@ import com.appsmith.server.domains.Theme;
import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.AutoCommitTriggerDTO; import com.appsmith.server.dtos.AutoCommitTriggerDTO;
import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.featureflags.CachedFeatures;
import com.appsmith.server.git.GitRedisUtils; import com.appsmith.server.git.GitRedisUtils;
import com.appsmith.server.helpers.CommonGitFileUtils; import com.appsmith.server.helpers.CommonGitFileUtils;
import com.appsmith.server.helpers.DSLMigrationUtils; import com.appsmith.server.helpers.DSLMigrationUtils;
import com.appsmith.server.migrations.JsonSchemaVersions; import com.appsmith.server.migrations.JsonSchemaVersions;
import com.appsmith.server.services.FeatureFlagService;
import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper; import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject; import net.minidev.json.JSONObject;
@ -23,7 +20,6 @@ import org.eclipse.jgit.api.errors.GitAPIException;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockBean;
@ -34,10 +30,8 @@ import reactor.test.StepVerifier;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitCommandConstantsCE.AUTO_COMMIT_ELIGIBILITY; import static com.appsmith.external.git.constants.ce.GitConstantsCE.GitCommandConstantsCE.AUTO_COMMIT_ELIGIBILITY;
import static java.lang.Boolean.TRUE;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@Slf4j @Slf4j
@ -53,9 +47,6 @@ public class AutoCommitEligibilityHelperTest {
@MockBean @MockBean
DSLMigrationUtils dslMigrationUtils; DSLMigrationUtils dslMigrationUtils;
@MockBean
FeatureFlagService featureFlagService;
@MockBean @MockBean
GitRedisUtils gitRedisUtils; GitRedisUtils gitRedisUtils;
@ -103,9 +94,6 @@ public class AutoCommitEligibilityHelperTest {
@BeforeEach @BeforeEach
public void beforeEach() { public void beforeEach() {
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(dslMigrationUtils.getLatestDslVersion()).thenReturn(Mono.just(RANDOM_DSL_VERSION_NUMBER)); Mockito.when(dslMigrationUtils.getLatestDslVersion()).thenReturn(Mono.just(RANDOM_DSL_VERSION_NUMBER));
Mockito.when(gitRedisUtils.addFileLock(DEFAULT_APPLICATION_ID, AUTO_COMMIT_ELIGIBILITY)) Mockito.when(gitRedisUtils.addFileLock(DEFAULT_APPLICATION_ID, AUTO_COMMIT_ELIGIBILITY))
@ -209,11 +197,6 @@ public class AutoCommitEligibilityHelperTest {
@Test @Test
public void isAutoCommitRequired_whenOnlyServerIsEligible_verifyDTOReturnTrue() { public void isAutoCommitRequired_whenOnlyServerIsEligible_verifyDTOReturnTrue() {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
GitArtifactMetadata gitArtifactMetadata = createGitMetadata(); GitArtifactMetadata gitArtifactMetadata = createGitMetadata();
PageDTO pageDTO = createPageDTO(RANDOM_DSL_VERSION_NUMBER); PageDTO pageDTO = createPageDTO(RANDOM_DSL_VERSION_NUMBER);
@ -266,12 +249,6 @@ public class AutoCommitEligibilityHelperTest {
public void isServerMigrationRequired_whenJsonSchemaIsAhead_returnsTrue() { public void isServerMigrationRequired_whenJsonSchemaIsAhead_returnsTrue() {
GitArtifactMetadata gitArtifactMetadata = createGitMetadata(); GitArtifactMetadata gitArtifactMetadata = createGitMetadata();
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
// this leads to server migration requirement as true // this leads to server migration requirement as true
Mockito.doReturn(Mono.just(jsonSchemaVersions.getServerVersion() - 1)) Mockito.doReturn(Mono.just(jsonSchemaVersions.getServerVersion() - 1))
.when(commonGitFileUtils) .when(commonGitFileUtils)
@ -377,12 +354,6 @@ public class AutoCommitEligibilityHelperTest {
@Test @Test
public void isServerMigrationRequired_fileSystemOperation_returnsTrue() throws GitAPIException, IOException { public void isServerMigrationRequired_fileSystemOperation_returnsTrue() throws GitAPIException, IOException {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
ApplicationJson applicationJson = new ApplicationJson(); ApplicationJson applicationJson = new ApplicationJson();
Application application = new Application(); Application application = new Application();

View File

@ -1,6 +1,5 @@
package com.appsmith.server.git.autocommit.helpers; package com.appsmith.server.git.autocommit.helpers;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.server.acl.AclPermission; import com.appsmith.server.acl.AclPermission;
import com.appsmith.server.applications.base.ApplicationService; import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.domains.Application; import com.appsmith.server.domains.Application;
@ -14,7 +13,6 @@ import com.appsmith.server.git.autocommit.AutoCommitEventHandler;
import com.appsmith.server.git.common.CommonGitService; import com.appsmith.server.git.common.CommonGitService;
import com.appsmith.server.helpers.GitPrivateRepoHelper; import com.appsmith.server.helpers.GitPrivateRepoHelper;
import com.appsmith.server.helpers.RedisUtils; import com.appsmith.server.helpers.RedisUtils;
import com.appsmith.server.services.FeatureFlagService;
import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.UserDataService;
import com.appsmith.server.solutions.ApplicationPermission; import com.appsmith.server.solutions.ApplicationPermission;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -43,9 +41,6 @@ import static org.mockito.ArgumentMatchers.eq;
@DirtiesContext @DirtiesContext
public class GitAutoCommitHelperImplTest { public class GitAutoCommitHelperImplTest {
@MockBean
FeatureFlagService featureFlagService;
@MockBean @MockBean
AutoCommitEventHandler autoCommitEventHandler; AutoCommitEventHandler autoCommitEventHandler;
@ -80,36 +75,12 @@ public class GitAutoCommitHelperImplTest {
redisUtils.finishAutoCommit(defaultApplicationId).block(); redisUtils.finishAutoCommit(defaultApplicationId).block();
} }
@Test
public void autoCommitApplication_WhenFeatureFlagIsDisabled_AutoCommitNotTriggered() {
Application application = new Application();
application.setGitApplicationMetadata(new GitArtifactMetadata());
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.FALSE));
Mockito.when(applicationService.findById(anyString(), any(AclPermission.class)))
.thenReturn(Mono.just(application));
Mockito.when(gitPrivateRepoHelper.isBranchProtected(any(GitArtifactMetadata.class), anyString()))
.thenReturn(Mono.just(Boolean.FALSE));
Mockito.when(applicationService.findByBranchNameAndBaseApplicationId(
anyString(), anyString(), any(AclPermission.class)))
.thenReturn(Mono.just(application));
StepVerifier.create(gitAutoCommitHelper.autoCommitClientMigration(defaultApplicationId, branchName))
.assertNext(aBoolean -> {
assertThat(aBoolean).isFalse();
})
.verifyComplete();
}
@Test @Test
public void autoCommitApplication_WhenBranchIsProtected_AutoCommitNotTriggered() { public void autoCommitApplication_WhenBranchIsProtected_AutoCommitNotTriggered() {
Application application = new Application(); Application application = new Application();
application.setId(defaultApplicationId); application.setId(defaultApplicationId);
application.setGitApplicationMetadata(new GitArtifactMetadata()); application.setGitApplicationMetadata(new GitArtifactMetadata());
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission())) Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission()))
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));
Mockito.when(gitPrivateRepoHelper.isBranchProtected(any(GitArtifactMetadata.class), eq(branchName))) Mockito.when(gitPrivateRepoHelper.isBranchProtected(any(GitArtifactMetadata.class), eq(branchName)))
@ -132,11 +103,8 @@ public class GitAutoCommitHelperImplTest {
GitArtifactMetadata metadata = new GitArtifactMetadata(); GitArtifactMetadata metadata = new GitArtifactMetadata();
metadata.setAutoCommitConfig(new AutoCommitConfig()); metadata.setAutoCommitConfig(new AutoCommitConfig());
metadata.getAutoCommitConfig().setEnabled(Boolean.FALSE); metadata.getAutoCommitConfig().setEnabled(Boolean.FALSE);
application.setGitApplicationMetadata(metadata); application.setGitApplicationMetadata(metadata);
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission())) Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission()))
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));
Mockito.when(applicationService.findByBranchNameAndBaseApplicationId( Mockito.when(applicationService.findByBranchNameAndBaseApplicationId(
@ -162,8 +130,6 @@ public class GitAutoCommitHelperImplTest {
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));
Mockito.when(gitPrivateRepoHelper.isBranchProtected(any(GitArtifactMetadata.class), eq(branchName))) Mockito.when(gitPrivateRepoHelper.isBranchProtected(any(GitArtifactMetadata.class), eq(branchName)))
.thenReturn(Mono.just(Boolean.FALSE)); .thenReturn(Mono.just(Boolean.FALSE));
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(applicationService.findByBranchNameAndBaseApplicationId( Mockito.when(applicationService.findByBranchNameAndBaseApplicationId(
anyString(), anyString(), any(AclPermission.class))) anyString(), anyString(), any(AclPermission.class)))
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));
@ -190,11 +156,8 @@ public class GitAutoCommitHelperImplTest {
gitAuth.setPrivateKey("private-key"); gitAuth.setPrivateKey("private-key");
gitAuth.setPublicKey("public-key"); gitAuth.setPublicKey("public-key");
metaData.setGitAuth(gitAuth); metaData.setGitAuth(gitAuth);
application.setGitApplicationMetadata(metaData); application.setGitApplicationMetadata(metaData);
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission())) Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission()))
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));
Mockito.when(applicationService.findByBranchNameAndBaseApplicationId( Mockito.when(applicationService.findByBranchNameAndBaseApplicationId(
@ -291,11 +254,8 @@ public class GitAutoCommitHelperImplTest {
GitArtifactMetadata metadata = new GitArtifactMetadata(); GitArtifactMetadata metadata = new GitArtifactMetadata();
metadata.setAutoCommitConfig(new AutoCommitConfig()); metadata.setAutoCommitConfig(new AutoCommitConfig());
metadata.getAutoCommitConfig().setEnabled(Boolean.TRUE); metadata.getAutoCommitConfig().setEnabled(Boolean.TRUE);
application.setGitApplicationMetadata(metadata); application.setGitApplicationMetadata(metadata);
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission())) Mockito.when(applicationService.findById(defaultApplicationId, applicationPermission.getEditPermission()))
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));
Mockito.when(applicationService.findByBranchNameAndBaseApplicationId( Mockito.when(applicationService.findByBranchNameAndBaseApplicationId(
@ -315,31 +275,6 @@ public class GitAutoCommitHelperImplTest {
.verifyComplete(); .verifyComplete();
} }
@Test
public void autoCommitApplication_WhenServerMigrationFlagIsFalse_returnsFalse() {
Application application = new Application();
application.setWorkspaceId("sample-workspace-id");
GitArtifactMetadata metaData = new GitArtifactMetadata();
metaData.setRepoName("test-repo-name");
metaData.setDefaultApplicationId(defaultApplicationId);
metaData.setBranchName(branchName);
GitAuth gitAuth = new GitAuth();
gitAuth.setPrivateKey("private-key");
gitAuth.setPublicKey("public-key");
metaData.setGitAuth(gitAuth);
application.setGitApplicationMetadata(metaData);
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.FALSE));
StepVerifier.create(gitAutoCommitHelper.autoCommitServerMigration(defaultApplicationId, branchName))
.assertNext(isAutoCommitPublished -> {
assertThat(isAutoCommitPublished).isFalse();
});
}
@Test @Test
public void autoCommitApplication_WhenServerRequiresMigration_successIfEverythingIsRight() { public void autoCommitApplication_WhenServerRequiresMigration_successIfEverythingIsRight() {
Application application = new Application(); Application application = new Application();
@ -356,9 +291,6 @@ public class GitAutoCommitHelperImplTest {
application.setGitApplicationMetadata(metaData); application.setGitApplicationMetadata(metaData);
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(applicationService.findById(anyString(), any(AclPermission.class))) Mockito.when(applicationService.findById(anyString(), any(AclPermission.class)))
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));
@ -401,12 +333,8 @@ public class GitAutoCommitHelperImplTest {
gitAuth.setPrivateKey("private-key"); gitAuth.setPrivateKey("private-key");
gitAuth.setPublicKey("public-key"); gitAuth.setPublicKey("public-key");
metaData.setGitAuth(gitAuth); metaData.setGitAuth(gitAuth);
application.setGitApplicationMetadata(metaData); application.setGitApplicationMetadata(metaData);
Mockito.when(featureFlagService.check(FeatureFlagEnum.release_git_autocommit_feature_enabled))
.thenReturn(Mono.just(Boolean.TRUE));
Mockito.when(applicationService.findById(anyString(), any(AclPermission.class))) Mockito.when(applicationService.findById(anyString(), any(AclPermission.class)))
.thenReturn(Mono.just(application)); .thenReturn(Mono.just(application));

View File

@ -1,36 +1,24 @@
package com.appsmith.server.migrations; package com.appsmith.server.migrations;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.ArtifactExchangeJson; import com.appsmith.server.dtos.ArtifactExchangeJson;
import com.appsmith.server.featureflags.CachedFeatures;
import com.appsmith.server.services.FeatureFlagService;
import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper; import com.appsmith.server.testhelpers.git.GitFileSystemTestHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import reactor.test.StepVerifier; import reactor.test.StepVerifier;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.Map;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@Slf4j @Slf4j
@SpringBootTest @SpringBootTest
public class JsonSchemaMigrationTest { public class JsonSchemaMigrationTest {
@MockBean
FeatureFlagService featureFlagService;
@Autowired @Autowired
JsonSchemaMigration jsonSchemaMigration; JsonSchemaMigration jsonSchemaMigration;
@ -43,38 +31,9 @@ public class JsonSchemaMigrationTest {
@Autowired @Autowired
GitFileSystemTestHelper gitFileSystemTestHelper; GitFileSystemTestHelper gitFileSystemTestHelper;
@Test
public void migrateArtifactToLatestSchema_whenFeatureFlagIsOff_returnsFallbackValue()
throws URISyntaxException, IOException {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), FALSE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json"));
ArtifactExchangeJson artifactExchangeJson = jsonSchemaMigration
.migrateArtifactExchangeJsonToLatestSchema(applicationJson, null, null)
.block();
assertThat(artifactExchangeJson.getServerSchemaVersion())
.isEqualTo(jsonSchemaVersionsFallback.getServerVersion());
assertThat(artifactExchangeJson.getServerSchemaVersion()).isEqualTo(jsonSchemaVersions.getServerVersion());
assertThat(artifactExchangeJson.getClientSchemaVersion()).isEqualTo(jsonSchemaVersions.getClientVersion());
assertThat(artifactExchangeJson.getClientSchemaVersion())
.isEqualTo(jsonSchemaVersionsFallback.getClientVersion());
}
@Test @Test
public void migrateArtifactToLatestSchema_whenFeatureFlagIsOn_returnsIncrementedValue() public void migrateArtifactToLatestSchema_whenFeatureFlagIsOn_returnsIncrementedValue()
throws URISyntaxException, IOException { throws URISyntaxException, IOException {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
ApplicationJson applicationJson = ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json")); gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json"));
@ -91,11 +50,6 @@ public class JsonSchemaMigrationTest {
@Test @Test
public void migrateApplicationJsonToLatestSchema_whenFeatureFlagIsOn_returnsIncrementedValue() public void migrateApplicationJsonToLatestSchema_whenFeatureFlagIsOn_returnsIncrementedValue()
throws URISyntaxException, IOException { throws URISyntaxException, IOException {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
ApplicationJson applicationJson = ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json")); gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json"));
@ -111,30 +65,4 @@ public class JsonSchemaMigrationTest {
}) })
.verifyComplete(); .verifyComplete();
} }
@Test
public void migrateApplicationJsonToLatestSchema_whenFeatureFlagIsOff_returnsFallbackValue()
throws URISyntaxException, IOException {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), FALSE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
ApplicationJson applicationJson =
gitFileSystemTestHelper.getApplicationJson(this.getClass().getResource("application.json"));
Mono<ApplicationJson> applicationJsonMono =
jsonSchemaMigration.migrateApplicationJsonToLatestSchema(applicationJson, null, null);
StepVerifier.create(applicationJsonMono)
.assertNext(appJson -> {
assertThat(appJson.getClientSchemaVersion()).isEqualTo(jsonSchemaVersions.getClientVersion());
assertThat(appJson.getClientSchemaVersion())
.isEqualTo(jsonSchemaVersionsFallback.getClientVersion());
assertThat(appJson.getServerSchemaVersion())
.isEqualTo(jsonSchemaVersionsFallback.getServerVersion());
assertThat(appJson.getServerSchemaVersion()).isEqualTo(jsonSchemaVersions.getServerVersion());
})
.verifyComplete();
}
} }

View File

@ -1,55 +1,24 @@
package com.appsmith.server.migrations; package com.appsmith.server.migrations;
import com.appsmith.external.enums.FeatureFlagEnum;
import com.appsmith.server.featureflags.CachedFeatures;
import com.appsmith.server.services.FeatureFlagService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import java.util.Map;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@Slf4j @Slf4j
@SpringBootTest @SpringBootTest
public class JsonSchemaVersionsTest { public class JsonSchemaVersionsTest {
@MockBean
FeatureFlagService featureFlagService;
@Autowired @Autowired
JsonSchemaVersions jsonSchemaVersions; JsonSchemaVersions jsonSchemaVersions;
@Autowired @Autowired
JsonSchemaVersionsFallback jsonSchemaVersionsFallback; JsonSchemaVersionsFallback jsonSchemaVersionsFallback;
@Test
public void getServerVersion_whenFeatureFlagIsOff_returnsFallbackValue() {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), FALSE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
assertThat(jsonSchemaVersions.getServerVersion()).isEqualTo(jsonSchemaVersionsFallback.getServerVersion());
assertThat(jsonSchemaVersions.getClientVersion()).isEqualTo(jsonSchemaVersionsFallback.getClientVersion());
}
@Test @Test
public void getServerVersion_whenFeatureFlagIsOn_returnsIncremented() { public void getServerVersion_whenFeatureFlagIsOn_returnsIncremented() {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.release_git_autocommit_feature_enabled.name(), TRUE));
Mockito.when(featureFlagService.getCachedTenantFeatureFlags())
.thenAnswer((Answer<CachedFeatures>) invocations -> cachedFeatures);
assertThat(jsonSchemaVersions.getServerVersion()).isEqualTo(jsonSchemaVersionsFallback.getServerVersion()); assertThat(jsonSchemaVersions.getServerVersion()).isEqualTo(jsonSchemaVersionsFallback.getServerVersion());
assertThat(jsonSchemaVersions.getClientVersion()).isEqualTo(jsonSchemaVersionsFallback.getClientVersion()); assertThat(jsonSchemaVersions.getClientVersion()).isEqualTo(jsonSchemaVersionsFallback.getClientVersion());
} }

File diff suppressed because one or more lines are too long