From d24a0bf4b90a8d6b843290d021249a2381e8e493 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 3 Nov 2023 22:43:36 +0530 Subject: [PATCH 1/9] feat: branch protection (#28526) - Adds server endpoints for getting and setting protected branches - Adds protected canvas view for branch protection - Adds default branch and protected branch in git modal settings Fixes #28434, #28056 Protected View - image Branch Protection Settings - image - New feature (non-breaking change which adds functionality) > > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > > Add Testsmith test cases links that relate to this PR > > > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --------- Co-authored-by: Nayan --- app/client/src/actions/gitSyncActions.ts | 35 +++++ app/client/src/ce/constants/messages.ts | 5 +- app/client/src/ce/entities/FeatureFlag.ts | 3 - app/client/src/pages/Editor/EditorHeader.tsx | 1 + .../WidgetsEditor/MainContainerWrapper.tsx | 5 +- .../Editor/gitSync/QuickGitActions/index.tsx | 2 +- .../Editor/gitSync/Tabs/ConnectionSuccess.tsx | 129 +++++------------- .../Tabs/GitSettings/GitDefaultBranch.tsx | 43 +++--- .../Tabs/GitSettings/GitProtectedBranches.tsx | 45 ++---- app/client/src/sagas/GitSyncSagas.ts | 61 ++------- .../server/services/ce/GitServiceCEImpl.java | 5 +- .../server/services/ce/GitServiceCETest.java | 31 +---- 12 files changed, 125 insertions(+), 240 deletions(-) diff --git a/app/client/src/actions/gitSyncActions.ts b/app/client/src/actions/gitSyncActions.ts index c08068a911..9ea9d84675 100644 --- a/app/client/src/actions/gitSyncActions.ts +++ b/app/client/src/actions/gitSyncActions.ts @@ -474,6 +474,25 @@ export const fetchGitProtectedBranchesInit = () => { }; }; +export const fetchGitProtectedBranchesSuccess = ( + protectedBranches: string[], +) => { + return { + type: ReduxActionTypes.GIT_FETCH_PROTECTED_BRANCHES_SUCCESS, + payload: { protectedBranches }, + }; +}; + +export const fetchGitProtectedBranchesError = ( + error: any, + show: boolean = true, +) => { + return { + type: ReduxActionTypes.GIT_FETCH_PROTECTED_BRANCHES_ERROR, + payload: { error, show }, + }; +}; + export const updateGitProtectedBranchesInit = (payload: { protectedBranches: string[]; }) => { @@ -482,3 +501,19 @@ export const updateGitProtectedBranchesInit = (payload: { payload, }; }; + +export const updateGitProtectedBranchesSuccess = () => { + return { + type: ReduxActionTypes.GIT_UPDATE_PROTECTED_BRANCHES_SUCCESS, + }; +}; + +export const updateGitProtectedBranchesError = ( + error: any, + show: boolean = true, +) => { + return { + type: ReduxActionTypes.GIT_UPDATE_PROTECTED_BRANCHES_ERROR, + payload: { error, show }, + }; +}; diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 958fa34d65..6f77ffceee 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -508,7 +508,6 @@ export const PAGE_SERVER_UNAVAILABLE_ERROR_MESSAGES = ( export const POST = () => "Post"; export const CANCEL = () => "Cancel"; export const REMOVE = () => "Remove"; -export const CREATE = () => "Create"; // Showcase Carousel export const NEXT = () => "NEXT"; @@ -1038,7 +1037,7 @@ export const PREVIOUS_STEP = () => "Previous step"; export const GIT_CONNECT_SUCCESS_TITLE = () => "Successfully connected to your Git remote repository"; export const GIT_CONNECT_SUCCESS_MESSAGE = () => - "Now you can start collaborating with your team members by committing, merging and deploying your app"; + "Right now, {branch} is set as the default branch and it is protected."; export const START_USING_GIT = () => "Start using Git"; export const OPEN_GIT_SETTINGS = () => "Open Git settings"; export const GIT_AUTHOR = () => "Git author"; @@ -1087,8 +1086,6 @@ export const GO_TO_SETTINGS = () => "Go to settings"; export const NOW_PROTECT_BRANCH = () => "You can now protect your default branch."; export const APPSMITH_ENTERPRISE = () => "Appsmith Enterprise"; -export const PROTECT_BRANCH_SUCCESS = () => "Changed protected branches"; -export const UPDATE_DEFAULT_BRANCH_SUCCESS = () => "Updated default branch"; // Git Branch Protection end export const NAV_DESCRIPTION = () => diff --git a/app/client/src/ce/entities/FeatureFlag.ts b/app/client/src/ce/entities/FeatureFlag.ts index 06cbf116fc..9e8b3a55b7 100644 --- a/app/client/src/ce/entities/FeatureFlag.ts +++ b/app/client/src/ce/entities/FeatureFlag.ts @@ -30,8 +30,6 @@ export const FEATURE_FLAG = { release_app_sidebar_enabled: "release_app_sidebar_enabled", release_git_branch_protection_enabled: "release_git_branch_protection_enabled", - license_git_branch_protection_enabled: - "license_git_branch_protection_enabled", license_widget_rtl_support_enabled: "license_widget_rtl_support_enabled", } as const; @@ -62,7 +60,6 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = { ab_show_templates_instead_of_blank_canvas_enabled: false, release_app_sidebar_enabled: false, release_git_branch_protection_enabled: false, - license_git_branch_protection_enabled: false, license_widget_rtl_support_enabled: false, }; diff --git a/app/client/src/pages/Editor/EditorHeader.tsx b/app/client/src/pages/Editor/EditorHeader.tsx index 554e196081..06b66af263 100644 --- a/app/client/src/pages/Editor/EditorHeader.tsx +++ b/app/client/src/pages/Editor/EditorHeader.tsx @@ -115,6 +115,7 @@ export function EditorHeader() { ); const isPreviewingApp = isPreviewMode || isAppSettingsPaneWithNavigationTabOpen; + const isProtectedMode = useSelector(protectedModeSelector); const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [showModal, setShowModal] = useState(false); diff --git a/app/client/src/pages/Editor/WidgetsEditor/MainContainerWrapper.tsx b/app/client/src/pages/Editor/WidgetsEditor/MainContainerWrapper.tsx index 4a424ea098..57d96ec9cf 100644 --- a/app/client/src/pages/Editor/WidgetsEditor/MainContainerWrapper.tsx +++ b/app/client/src/pages/Editor/WidgetsEditor/MainContainerWrapper.tsx @@ -136,7 +136,7 @@ function MainContainerWrapper(props: MainCanvasWrapperProps) { const selectedTheme = useSelector(getSelectedAppTheme); const params = useParams<{ applicationId: string; pageId: string }>(); const shouldHaveTopMargin = - !(isPreviewMode || isProtectedMode) || + (!isPreviewMode && !isProtectedMode) || !isAppSettingsPaneWithNavigationTabOpen || pages.length > 1; const isAppThemeChanging = useSelector(getAppThemeIsChanging); @@ -185,7 +185,7 @@ function MainContainerWrapper(props: MainCanvasWrapperProps) { } const isPreviewingNavigation = - isPreviewMode || isProtectedMode || isAppSettingsPaneWithNavigationTabOpen; + isPreviewMode || isAppSettingsPaneWithNavigationTabOpen; /** * calculating exact height to not allow scroll at this component, @@ -231,6 +231,7 @@ function MainContainerWrapper(props: MainCanvasWrapperProps) { shouldHaveTopMargin && !showCanvasTopSection && !isPreviewingNavigation && + !isProtectedMode && !showAnonymousDataPopup, "mt-24": shouldShowSnapShotBanner, })} diff --git a/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx index a41259d97c..0c0bce361e 100644 --- a/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx +++ b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx @@ -179,7 +179,7 @@ const getQuickActionButtons = ({ { className: "t--bottom-bar-commit", disabled: isProtectedMode, - count: isProtectedMode ? undefined : changesToCommit, + count: changesToCommit, icon: "plus", loading: isFetchingGitStatus, onClick: commit, diff --git a/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx b/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx index 83f86190bf..cf9ebc777b 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx @@ -8,7 +8,6 @@ import { BRANCH_PROTECTION_RULE_1, BRANCH_PROTECTION_RULE_2, BRANCH_PROTECTION_RULE_3, - GIT_CONNECT_SUCCESS_MESSAGE, GIT_CONNECT_SUCCESS_TITLE, OPEN_GIT_SETTINGS, START_USING_GIT, @@ -21,10 +20,7 @@ import { useDispatch, useSelector } from "react-redux"; import styled from "styled-components"; import { getCurrentAppGitMetaData } from "@appsmith/selectors/applicationSelectors"; import AnalyticsUtil from "utils/AnalyticsUtil"; -import { - getDefaultGitBranchName, - getIsGitProtectedFeatureEnabled, -} from "selectors/gitSyncSelectors"; +import { getDefaultGitBranchName } from "selectors/gitSyncSelectors"; const Container = styled.div``; @@ -57,18 +53,6 @@ const FeatureIcon = styled(Icon)` margin-right: 4px; `; -const BranchTag = styled(Tag)` - display: inline-flex; -`; - -const DefaultBranchMessage = styled(Text)` - margin-bottom: 16px; -`; - -const ProtectionRulesTitle = styled(Text)` - margin-bottom: 8px; -`; - const features = [ createMessage(BRANCH_PROTECTION_RULE_1), createMessage(BRANCH_PROTECTION_RULE_2), @@ -78,9 +62,6 @@ const features = [ function ConnectionSuccess() { const gitMetadata = useSelector(getCurrentAppGitMetaData); const defaultBranchName = useSelector(getDefaultGitBranchName); - const isGitProtectedFeatureEnabled = useSelector( - getIsGitProtectedFeatureEnabled, - ); const dispatch = useDispatch(); useEffect(() => { @@ -110,55 +91,42 @@ function ConnectionSuccess() { }); }; - const preBranchProtectionContent = () => { - return ( - {createMessage(GIT_CONNECT_SUCCESS_MESSAGE)} - ); - }; - - const postBranchProtectionContent = () => { - return ( - <> - - Right now,{" "} - {defaultBranchName} is set - as the default branch and it is protected. - - - {createMessage(BRANCH_PROTECTION_RULES_AS_FOLLOWS)} - - - {features.map((feature) => ( - - - {feature} - - ))} - - {createMessage(BRANCH_PROTECTION_CHANGE_RULE)} - - ); - }; - - const preBranchProtectionActions = () => { - return ( - - ); - }; - - const postBranchProtectionActions = () => { - return ( - <> + return ( + <> + + + + + + {createMessage(GIT_CONNECT_SUCCESS_TITLE)} + + + + Right now,{" "} + + {defaultBranchName} + {" "} + is set as the default branch and it is protected. + + + {createMessage(BRANCH_PROTECTION_RULES_AS_FOLLOWS)} + + + {features.map((feature) => ( + + + {feature} + + ))} + + {createMessage(BRANCH_PROTECTION_CHANGE_RULE)} + + + - - ); - }; - - return ( - <> - - - - - - {createMessage(GIT_CONNECT_SUCCESS_TITLE)} - - - {isGitProtectedFeatureEnabled - ? postBranchProtectionContent() - : preBranchProtectionContent()} - - - - {isGitProtectedFeatureEnabled - ? postBranchProtectionActions() - : preBranchProtectionActions()} ); diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx index 8c7691351e..a84833fb76 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx @@ -6,14 +6,12 @@ import { createMessage, } from "@appsmith/constants/messages"; import { updateGitDefaultBranch } from "actions/gitSyncActions"; +import { isCEMode } from "@appsmith/utils"; import { Button, Link, Option, Select, Text } from "design-system"; import React, { useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { getGitBranches } from "selectors/gitSyncSelectors"; import styled from "styled-components"; -import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; -import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; -import { useAppsmithEnterpriseLink } from "./hooks"; const Container = styled.div` padding-top: 16px; @@ -43,10 +41,9 @@ const StyledSelect = styled(Select)` `; function GitDefaultBranch() { + const isCE = isCEMode(); + const dispatch = useDispatch(); - const isGitProtectedFeatureLicensed = useFeatureFlag( - FEATURE_FLAG.license_git_branch_protection_enabled, - ); const unfilteredBranches = useSelector(getGitBranches); const [selectedValue, setSelectedValue] = useState(); @@ -55,10 +52,6 @@ function GitDefaultBranch() { return defaultBranch?.branchName; }, [unfilteredBranches]); - const enterprisePricingLink = useAppsmithEnterpriseLink( - "git_branch_protection", - ); - useEffect(() => { const defaultBranch = unfilteredBranches.find((b) => b.default); setSelectedValue(defaultBranch?.branchName); @@ -75,7 +68,7 @@ function GitDefaultBranch() { }; const updateIsDisabled = - !selectedValue || selectedValue === currentDefaultBranch; + isCE && (!selectedValue || selectedValue === currentDefaultBranch); return ( @@ -86,24 +79,21 @@ function GitDefaultBranch() { {createMessage(DEFAULT_BRANCH_DESC)} - {!isGitProtectedFeatureLicensed && ( - - To change your default branch, try{" "} - - {createMessage(APPSMITH_ENTERPRISE)} - - - )} + + To change your default branch, try{" "} + + {createMessage(APPSMITH_ENTERPRISE)} + + setSelectedValue(v)} value={selectedValue} > @@ -114,7 +104,6 @@ function GitDefaultBranch() { ))} + ); + }; + + const postBranchProtectionActions = () => { + return ( + <> + + ); + }; + + return ( + <> + + + + + + {createMessage(GIT_CONNECT_SUCCESS_TITLE)} + + + {isGitProtectedFeatureEnabled + ? postBranchProtectionContent() + : preBranchProtectionContent()} + + + + {isGitProtectedFeatureEnabled + ? postBranchProtectionActions() + : preBranchProtectionActions()} ); diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx index a84833fb76..8c7691351e 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx @@ -6,12 +6,14 @@ import { createMessage, } from "@appsmith/constants/messages"; import { updateGitDefaultBranch } from "actions/gitSyncActions"; -import { isCEMode } from "@appsmith/utils"; import { Button, Link, Option, Select, Text } from "design-system"; import React, { useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { getGitBranches } from "selectors/gitSyncSelectors"; import styled from "styled-components"; +import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; +import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; +import { useAppsmithEnterpriseLink } from "./hooks"; const Container = styled.div` padding-top: 16px; @@ -41,9 +43,10 @@ const StyledSelect = styled(Select)` `; function GitDefaultBranch() { - const isCE = isCEMode(); - const dispatch = useDispatch(); + const isGitProtectedFeatureLicensed = useFeatureFlag( + FEATURE_FLAG.license_git_branch_protection_enabled, + ); const unfilteredBranches = useSelector(getGitBranches); const [selectedValue, setSelectedValue] = useState(); @@ -52,6 +55,10 @@ function GitDefaultBranch() { return defaultBranch?.branchName; }, [unfilteredBranches]); + const enterprisePricingLink = useAppsmithEnterpriseLink( + "git_branch_protection", + ); + useEffect(() => { const defaultBranch = unfilteredBranches.find((b) => b.default); setSelectedValue(defaultBranch?.branchName); @@ -68,7 +75,7 @@ function GitDefaultBranch() { }; const updateIsDisabled = - isCE && (!selectedValue || selectedValue === currentDefaultBranch); + !selectedValue || selectedValue === currentDefaultBranch; return ( @@ -79,21 +86,24 @@ function GitDefaultBranch() { {createMessage(DEFAULT_BRANCH_DESC)} - - To change your default branch, try{" "} - - {createMessage(APPSMITH_ENTERPRISE)} - - + {!isGitProtectedFeatureLicensed && ( + + To change your default branch, try{" "} + + {createMessage(APPSMITH_ENTERPRISE)} + + + )} setSelectedValue(v)} value={selectedValue} > @@ -104,6 +114,7 @@ function GitDefaultBranch() { ))} diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/index.test.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/index.test.tsx new file mode 100644 index 0000000000..97cfecd713 --- /dev/null +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/index.test.tsx @@ -0,0 +1,19 @@ +/* eslint-disable jest/no-focused-tests */ +import React from "react"; +import { render, screen } from "test/testUtils"; +import GitSettings from "."; +import type { AppState } from "@appsmith/reducers"; + +jest.mock("../../hooks/useIsGitAdmin", () => ({ + useIsGitAdmin: () => false, +})); + +describe("GitSettings test for git admin disabled", () => { + it("Branch protection, default branch and disconnect disabled when not ", () => { + const initialState: Partial = {}; + render(, { initialState }); + expect(screen.queryByTestId("t--git-protected-branches-select")).toBe(null); + expect(screen.queryByTestId("t--git-default-branch-select")).toBe(null); + expect(screen.queryByTestId("t--git-disconnect-btn")).toBe(null); + }); +}); diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/index.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/index.tsx index ce72c2db9f..48f7eaf01d 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/index.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/index.tsx @@ -7,6 +7,7 @@ import GitDefaultBranch from "./GitDefaultBranch"; import GitProtectedBranches from "./GitProtectedBranches"; import { useSelector } from "react-redux"; import { getIsGitProtectedFeatureEnabled } from "selectors/gitSyncSelectors"; +import { useIsGitAdmin } from "../../hooks/useIsGitAdmin"; const Container = styled.div` overflow: auto; @@ -23,18 +24,20 @@ function GitSettings() { const isGitProtectedFeatureEnabled = useSelector( getIsGitProtectedFeatureEnabled, ); + const isGitAdmin = useIsGitAdmin(); + return ( - {isGitProtectedFeatureEnabled ? ( + {isGitProtectedFeatureEnabled && isGitAdmin ? ( <> ) : null} - + {isGitAdmin && } ); diff --git a/app/client/src/pages/Editor/gitSync/hooks/useIsGitAdmin.ts b/app/client/src/pages/Editor/gitSync/hooks/useIsGitAdmin.ts new file mode 100644 index 0000000000..b78282426a --- /dev/null +++ b/app/client/src/pages/Editor/gitSync/hooks/useIsGitAdmin.ts @@ -0,0 +1,15 @@ +import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; +import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors"; +import { getHasCreateWorkspacePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers"; +import { useSelector } from "react-redux"; +import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; + +export const useIsGitAdmin = () => { + const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); + const tenantPermissions = useSelector(getTenantPermissions); + const canCreateWorkspace = getHasCreateWorkspacePermission( + isFeatureEnabled, + tenantPermissions, + ); + return canCreateWorkspace; +}; From 64ef0c33dd94b53e49824f16e23e99e2cd19f572 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 9 Nov 2023 16:58:04 +0530 Subject: [PATCH 4/9] fix: git branch protection bug fixes (#28749) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Fixes a couple of issues with branch protection - #28727 Toast message issues - #28726 Pull count on pull icon - #28748 Display remote branches in list - #28697 Pulling protected branch shows discard toast - Added branch name to default branch toast - #28698 Select not scrolling bug #### PR fixes following issue(s) Mentioned above #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change - Bug fix (non-breaking change which fixes an issue) > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [x] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --- app/client/cypress/support/Pages/GitSync.ts | 2 +- app/client/src/actions/gitSyncActions.ts | 5 ++- app/client/src/ce/constants/messages.ts | 4 +- app/client/src/ce/sagas/ApplicationSagas.tsx | 7 --- .../Editor/gitSync/QuickGitActions/index.tsx | 16 +++++-- .../Tabs/GitSettings/GitDefaultBranch.tsx | 2 + .../Tabs/GitSettings/GitProtectedBranches.tsx | 43 ++++++++++++++----- .../src/pages/Editor/gitSync/constants.ts | 2 + .../Editor/gitSync/hooks/useIsGitAdmin.ts | 15 ++----- app/client/src/sagas/GitSyncSagas.ts | 19 +++++--- 10 files changed, 74 insertions(+), 41 deletions(-) diff --git a/app/client/cypress/support/Pages/GitSync.ts b/app/client/cypress/support/Pages/GitSync.ts index 40dd9f1a76..99139d7211 100644 --- a/app/client/cypress/support/Pages/GitSync.ts +++ b/app/client/cypress/support/Pages/GitSync.ts @@ -474,9 +474,9 @@ export class GitSync { this.agHelper.AssertContains( Cypress.env("MESSAGES").DISCARDING_AND_PULLING_CHANGES(), ); + this.agHelper.AssertContains("Discarded changes successfully"); this.assertHelper.AssertNetworkStatus("@discardChanges"); this.assertHelper.AssertNetworkStatus("@gitStatus"); - this.agHelper.AssertContains("Discarded changes successfully"); this.agHelper.AssertElementExist(this._bottomBarCommit, 0, 30000); } diff --git a/app/client/src/actions/gitSyncActions.ts b/app/client/src/actions/gitSyncActions.ts index c08068a911..1427ac984b 100644 --- a/app/client/src/actions/gitSyncActions.ts +++ b/app/client/src/actions/gitSyncActions.ts @@ -196,8 +196,11 @@ export const fetchGitRemoteStatusSuccess = (payload: GitRemoteStatusData) => ({ payload, }); -export const discardChanges = () => ({ +export const discardChanges = ( + payload: { successToastMessage?: string } | undefined | null = {}, +) => ({ type: ReduxActionTypes.GIT_DISCARD_CHANGES, + payload, }); export const discardChangesSuccess = (payload: any) => ({ diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 834c749f47..72a4d68ab7 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -842,6 +842,7 @@ export const COMMITTING_AND_PUSHING_CHANGES = () => export const DISCARDING_AND_PULLING_CHANGES = () => "Discarding and pulling changes..."; export const DISCARD_SUCCESS = () => "Discarded changes successfully."; +export const DISCARD_AND_PULL_SUCCESS = () => "Pulled from remote successfully"; export const IS_MERGING = () => "Merging changes..."; @@ -1087,7 +1088,8 @@ export const NOW_PROTECT_BRANCH = () => "You can now protect your default branch."; export const APPSMITH_ENTERPRISE = () => "Appsmith Enterprise"; export const PROTECT_BRANCH_SUCCESS = () => "Changed protected branches"; -export const UPDATE_DEFAULT_BRANCH_SUCCESS = () => "Updated default branch"; +export const UPDATE_DEFAULT_BRANCH_SUCCESS = (branchName: string) => + `Updated default branch ${!!branchName ? `to ${branchName}` : ""}`; export const CONTACT_ADMIN_FOR_GIT = () => "Please contact your workspace admin to connect your app to a git repo"; // Git Branch Protection end diff --git a/app/client/src/ce/sagas/ApplicationSagas.tsx b/app/client/src/ce/sagas/ApplicationSagas.tsx index f2a50f6ccb..23a7ce406c 100644 --- a/app/client/src/ce/sagas/ApplicationSagas.tsx +++ b/app/client/src/ce/sagas/ApplicationSagas.tsx @@ -65,7 +65,6 @@ import { createMessage, DELETING_APPLICATION, DELETING_MULTIPLE_APPLICATION, - DISCARD_SUCCESS, ERROR_IMPORTING_APPLICATION_TO_WORKSPACE, } from "@appsmith/constants/messages"; import { APP_MODE } from "entities/App"; @@ -300,12 +299,6 @@ export function* fetchAppAndPagesSaga( }, }); - if (localStorage.getItem("GIT_DISCARD_CHANGES") === "success") { - toast.show(createMessage(DISCARD_SUCCESS), { - kind: "success", - }); - localStorage.setItem("GIT_DISCARD_CHANGES", ""); - } yield put({ type: ReduxActionTypes.SET_APP_VERSION_ON_WORKER, payload: response.data.application?.evaluationVersion, diff --git a/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx index ad0740799b..5ef6f74b52 100644 --- a/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx +++ b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx @@ -13,6 +13,7 @@ import { CONNECTING_TO_REPO_DISABLED, CONTACT_ADMIN_FOR_GIT, createMessage, + DISCARD_AND_PULL_SUCCESS, DURING_ONBOARDING_TOUR, GIT_SETTINGS, MERGE, @@ -136,8 +137,11 @@ const getPullBtnStatus = ( ) => { const { behindCount, isClean } = gitStatus || {}; let message = createMessage(NO_COMMITS_TO_PULL); - let disabled = isProtected ? false : behindCount === 0; - if (!isClean) { + let disabled = behindCount === 0; + if (isProtected) { + disabled = false; + message = createMessage(PULL_CHANGES); + } else if (!isClean) { disabled = true; message = createMessage(CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES); } else if (pullFailed) { @@ -189,7 +193,7 @@ const getQuickActionButtons = ({ }, { className: "t--bottom-bar-pull", - count: isProtectedMode ? undefined : gitStatus?.behindCount, + count: gitStatus?.behindCount, icon: "down-arrow-2", onClick: () => !pullDisabled && pull(), tooltipText: pullTooltipMessage, @@ -360,7 +364,11 @@ export default function QuickGitActions() { source: "BOTTOM_BAR_GIT_PULL_BUTTON", }); if (isProtectedMode) { - dispatch(discardChanges()); + dispatch( + discardChanges({ + successToastMessage: createMessage(DISCARD_AND_PULL_SUCCESS), + }), + ); } else { dispatch(gitPullInit({ triggeredFromBottomBar: true })); } diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx index 8c7691351e..0380b181f8 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitDefaultBranch.tsx @@ -103,6 +103,8 @@ function GitDefaultBranch() { triggerNode.parentNode} isDisabled={!isGitProtectedFeatureLicensed} onChange={(v) => setSelectedValue(v)} value={selectedValue} diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitProtectedBranches.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitProtectedBranches.tsx index 123a247191..dc6fd581a3 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitProtectedBranches.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitSettings/GitProtectedBranches.tsx @@ -7,7 +7,7 @@ import { } from "@appsmith/constants/messages"; import { updateGitProtectedBranchesInit } from "actions/gitSyncActions"; import { Button, Link, Option, Select, Text } from "design-system"; -import { xor } from "lodash"; +import { union, xor } from "lodash"; import React, { useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { @@ -20,6 +20,7 @@ import styled from "styled-components"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; import { useAppsmithEnterpriseLink } from "./hooks"; +import { REMOTE_BRANCH_PREFIX } from "../../constants"; const Container = styled.div` padding-top: 16px; @@ -56,13 +57,33 @@ function GitProtectedBranches() { const dispatch = useDispatch(); const unfilteredBranches = useSelector(getGitBranches); - const branches = unfilteredBranches.filter( - (b) => !b.branchName.includes("origin/"), - ); + const defaultBranch = useSelector(getDefaultGitBranchName); + + const branchNames = useMemo(() => { + const remoteBranchNames = []; + const localBranchNames = []; + for (const unfilteredBranch of unfilteredBranches) { + if (unfilteredBranch.branchName === defaultBranch) { + continue; + } + if (unfilteredBranch.branchName.includes(REMOTE_BRANCH_PREFIX)) { + remoteBranchNames.push( + unfilteredBranch.branchName.replace(REMOTE_BRANCH_PREFIX, ""), + ); + } else { + localBranchNames.push(unfilteredBranch.branchName); + } + } + const branchNames = union(localBranchNames, remoteBranchNames); + if (defaultBranch) { + branchNames.unshift(defaultBranch); + } + return branchNames; + }, [unfilteredBranches, defaultBranch]); + const isGitProtectedFeatureLicensed = useFeatureFlag( FEATURE_FLAG.license_git_branch_protection_enabled, ); - const defaultBranch = useSelector(getDefaultGitBranchName); const protectedBranches = useSelector(getProtectedBranchesSelector); const isUpdateLoading = useSelector(getIsUpdateProtectedBranchesLoading); const [selectedValues, setSelectedValues] = useState(); @@ -114,20 +135,22 @@ function GitProtectedBranches() { triggerNode.parentNode} isMultiSelect maxTagTextLength={8} onChange={(v) => setSelectedValues(v)} value={selectedValues} > - {branches.map((b) => ( + {branchNames.map((branchName) => ( ))} diff --git a/app/client/src/pages/Editor/gitSync/constants.ts b/app/client/src/pages/Editor/gitSync/constants.ts index 8b0b3fd65e..34f93d730d 100644 --- a/app/client/src/pages/Editor/gitSync/constants.ts +++ b/app/client/src/pages/Editor/gitSync/constants.ts @@ -22,3 +22,5 @@ export enum CREDENTIAL_MODE { MANUALLY = "MANUALLY", IMPORT_JSON = "IMPORT_JSON", } + +export const REMOTE_BRANCH_PREFIX = "origin/"; diff --git a/app/client/src/pages/Editor/gitSync/hooks/useIsGitAdmin.ts b/app/client/src/pages/Editor/gitSync/hooks/useIsGitAdmin.ts index b78282426a..172d0b6bad 100644 --- a/app/client/src/pages/Editor/gitSync/hooks/useIsGitAdmin.ts +++ b/app/client/src/pages/Editor/gitSync/hooks/useIsGitAdmin.ts @@ -1,15 +1,8 @@ -import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; -import { getTenantPermissions } from "@appsmith/selectors/tenantSelectors"; -import { getHasCreateWorkspacePermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers"; import { useSelector } from "react-redux"; -import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; +import { getCurrentAppWorkspace } from "@appsmith/selectors/workspaceSelectors"; +import { hasCreateNewAppPermission } from "@appsmith/utils/permissionHelpers"; export const useIsGitAdmin = () => { - const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled); - const tenantPermissions = useSelector(getTenantPermissions); - const canCreateWorkspace = getHasCreateWorkspacePermission( - isFeatureEnabled, - tenantPermissions, - ); - return canCreateWorkspace; + const workspace = useSelector(getCurrentAppWorkspace); + return hasCreateNewAppPermission(workspace.userPermissions); }; diff --git a/app/client/src/sagas/GitSyncSagas.ts b/app/client/src/sagas/GitSyncSagas.ts index ee685cdf16..8a0c5a8850 100644 --- a/app/client/src/sagas/GitSyncSagas.ts +++ b/app/client/src/sagas/GitSyncSagas.ts @@ -10,6 +10,7 @@ import { import { actionChannel, call, + delay, fork, put, select, @@ -84,6 +85,7 @@ import { import { createMessage, DELETE_BRANCH_SUCCESS, + DISCARD_SUCCESS, ERROR_GIT_AUTH_FAIL, ERROR_GIT_INVALID_REMOTE, GIT_USER_UPDATED_SUCCESSFULLY, @@ -1024,11 +1026,13 @@ export function* deleteBranch({ payload }: ReduxAction) { yield put(fetchBranchesInit({ pruneBranches: true })); } } catch (error) { - yield put(deleteBranchError(error)); + yield put(deleteBranchError({ error, show: true })); } } -function* discardChanges() { +function* discardChanges({ + payload, +}: ReduxAction<{ successToastMessage: string } | null | undefined>) { let response: ApiResponse; try { const appId: string = yield select(getCurrentApplicationId); @@ -1040,10 +1044,15 @@ function* discardChanges() { ); if (isValidResponse) { yield put(discardChangesSuccess(response.data)); - // const applicationId: string = response.data.id; + const successToastMessage = + payload?.successToastMessage ?? createMessage(DISCARD_SUCCESS); + toast.show(successToastMessage, { + kind: "success", + }); + // adding delay to show toast animation before reloading + yield delay(500); const pageId: string = response.data?.pages?.find((page: any) => page.isDefault)?.id || ""; - localStorage.setItem("GIT_DISCARD_CHANGES", "success"); const branch = response.data.gitApplicationMetadata.branchName; window.open(builderURL({ pageId, branch }), "_self"); } else { @@ -1053,11 +1062,9 @@ function* discardChanges() { show: true, }), ); - localStorage.setItem("GIT_DISCARD_CHANGES", "failure"); } } catch (error) { yield put(discardChangesFailure({ error, show: true })); - localStorage.setItem("GIT_DISCARD_CHANGES", "failure"); } } From 41d064fc1287e39cd0b8a556273780352e4a35af Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 13 Nov 2023 13:37:18 +0530 Subject: [PATCH 5/9] fix: remove feature flag and minor fixes for git branch protection (#28770) ## Description Fixes minor issues and remove feature flag `release_git_branch_protection_enabled` #### PR fixes following issue(s) Fixes #28771 #### Type of change - Bug fix (non-breaking change which fixes an issue) ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [x] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --- .../Git/GitSync/GitBranchProtect_spec.ts | 36 +----------- .../Git/GitSync/GitConnectV2_spec.ts | 25 ++++---- app/client/src/ce/constants/messages.ts | 4 +- app/client/src/ce/entities/FeatureFlag.ts | 3 - app/client/src/ce/utils/analyticsUtilTypes.ts | 3 + .../src/constants/ThirdPartyConstants.tsx | 4 ++ .../Editor/gitSync/QuickGitActions/index.tsx | 13 +---- .../Editor/gitSync/Tabs/ConnectionSuccess.tsx | 49 +++------------- .../Tabs/GitSettings/GitDefaultBranch.tsx | 5 ++ .../Tabs/GitSettings/GitProtectedBranches.tsx | 58 ++++++++++++++----- .../Editor/gitSync/Tabs/GitSettings/index.tsx | 7 +-- app/client/src/sagas/GitSyncSagas.ts | 22 ++----- app/client/src/selectors/gitSyncSelectors.tsx | 5 -- 13 files changed, 92 insertions(+), 142 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitBranchProtect_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitBranchProtect_spec.ts index 91f342963c..5f53ebffac 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitBranchProtect_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitBranchProtect_spec.ts @@ -2,37 +2,9 @@ import { featureFlagIntercept } from "../../../../../support/Objects/FeatureFlag import * as _ from "../../../../../support/Objects/ObjectsCore"; let guid: any; -let repoName1: any; -let repoName2: any; +let repoName: any; describe("Git Branch Protection", function () { - it("Issue 28056 - 1 : Check if protection is not enabled when feature flag is disabled", function () { - _.agHelper.GenerateUUID(); - cy.get("@guid").then((uid) => { - guid = uid; - const wsName = "GitBranchProtect-1" + uid; - const appName = "GitBranchProtect-1" + uid; - _.homePage.CreateNewWorkspace(wsName, true); - _.homePage.CreateAppInWorkspace(wsName, appName); - featureFlagIntercept({ - release_git_connect_v2_enabled: true, - release_git_branch_protection_enabled: false, - }); - cy.wait(1000); - _.gitSync.CreateNConnectToGitV2(); - cy.get("@gitRepoName").then((repName) => { - repoName1 = repName; - _.agHelper.AssertElementExist(_.entityExplorer._entityExplorerWrapper); - _.agHelper.AssertElementExist(_.propPane._propertyPaneSidebar); - _.agHelper.AssertElementEnabledDisabled( - _.gitSync._bottomBarCommit, - 0, - false, - ); - }); - }); - }); - it("Issue 28056 - 2 : Check if protection is enabled when feature flag is enabled", function () { _.agHelper.GenerateUUID(); cy.get("@guid").then((uid) => { @@ -43,7 +15,6 @@ describe("Git Branch Protection", function () { _.homePage.CreateAppInWorkspace(wsName, appName); featureFlagIntercept({ release_git_connect_v2_enabled: true, - release_git_branch_protection_enabled: true, }); cy.wait(1000); @@ -54,7 +25,7 @@ describe("Git Branch Protection", function () { _.gitSync.CreateNConnectToGitV2(); cy.get("@gitRepoName").then((repName) => { - repoName2 = repName; + repoName = repName; cy.wait("@gitProtectApi").then((res1) => { expect(res1.response).to.have.property("statusCode", 200); _.agHelper.AssertElementVisibility( @@ -76,7 +47,6 @@ describe("Git Branch Protection", function () { }); after(() => { - _.gitSync.DeleteTestGithubRepo(repoName1); - _.gitSync.DeleteTestGithubRepo(repoName2); + _.gitSync.DeleteTestGithubRepo(repoName); }); }); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitConnectV2_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitConnectV2_spec.ts index 79950ddb47..cfcc878870 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitConnectV2_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitConnectV2_spec.ts @@ -5,6 +5,7 @@ let ws1Name: string; let ws2Name: string; let app1Name: string; let repoName: any; +let branchName: any; describe("Git Connect V2", function () { before(() => { @@ -36,17 +37,21 @@ describe("Git Connect V2", function () { release_git_connect_v2_enabled: true, }); - _.entityExplorer.DragDropWidgetNVerify(_.draggableWidgets.TEXT, 300, 300); - _.propPane.RenameWidget("Text1", "MyText"); - _.propPane.UpdatePropertyFieldValue("Text", "Hello World"); - _.gitSync.CommitAndPush(); + _.gitSync.CreateGitBranch("test", true); + cy.get("@gitbranchName").then((bName) => { + branchName = bName; + _.entityExplorer.DragDropWidgetNVerify(_.draggableWidgets.TEXT, 300, 300); + _.propPane.RenameWidget("Text1", "MyText"); + _.propPane.UpdatePropertyFieldValue("Text", "Hello World"); + _.gitSync.CommitAndPush(); - _.gitSync.ImportAppFromGitV2(ws2Name, repoName); - - _.entityExplorer.ExpandCollapseEntity("Widgets"); - _.entityExplorer.AssertEntityPresenceInExplorer("MyText"); - _.entityExplorer.SelectEntityByName("MyText"); - _.propPane.ValidatePropertyFieldValue("Text", "Hello World"); + _.gitSync.ImportAppFromGitV2(ws2Name, repoName); + _.gitSync.SwitchGitBranch(branchName); + _.entityExplorer.ExpandCollapseEntity("Widgets"); + _.entityExplorer.AssertEntityPresenceInExplorer("MyText"); + _.entityExplorer.SelectEntityByName("MyText"); + _.propPane.ValidatePropertyFieldValue("Text", "Hello World"); + }); }); after(() => { diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 72a4d68ab7..865e2c916f 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -1033,7 +1033,7 @@ export const ADD_DEPLOY_KEY_STEP_TITLE = () => export const HOW_TO_ADD_DEPLOY_KEY = () => "How to paste SSH Key in repo and give write access?"; export const CONSENT_ADDED_DEPLOY_KEY = () => - "I've added deploy key and gave it write access"; + "I've added the deploy key and gave it write access"; export const PREVIOUS_STEP = () => "Previous step"; export const GIT_CONNECT_SUCCESS_TITLE = () => "Successfully connected to your Git remote repository"; @@ -1082,7 +1082,7 @@ export const BRANCH_PROTECTION_CHANGE_RULE = () => "You can remove protection on your default branch in Git settings."; export const BRANCH_TOOLTIP_TITLE = () => "🚫 This is a protected branch"; export const BRANCH_TOOLTIP_MESSAGE = () => - "You can remove protection on your default branch in Git settings."; + "Please create a new branch or checkout an existing one to edit the app."; export const GO_TO_SETTINGS = () => "Go to settings"; export const NOW_PROTECT_BRANCH = () => "You can now protect your default branch."; diff --git a/app/client/src/ce/entities/FeatureFlag.ts b/app/client/src/ce/entities/FeatureFlag.ts index 06cbf116fc..4660a6118a 100644 --- a/app/client/src/ce/entities/FeatureFlag.ts +++ b/app/client/src/ce/entities/FeatureFlag.ts @@ -28,8 +28,6 @@ export const FEATURE_FLAG = { ab_show_templates_instead_of_blank_canvas_enabled: "ab_show_templates_instead_of_blank_canvas_enabled", release_app_sidebar_enabled: "release_app_sidebar_enabled", - release_git_branch_protection_enabled: - "release_git_branch_protection_enabled", license_git_branch_protection_enabled: "license_git_branch_protection_enabled", license_widget_rtl_support_enabled: "license_widget_rtl_support_enabled", @@ -61,7 +59,6 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = { release_anvil_enabled: false, ab_show_templates_instead_of_blank_canvas_enabled: false, release_app_sidebar_enabled: false, - release_git_branch_protection_enabled: false, license_git_branch_protection_enabled: false, license_widget_rtl_support_enabled: false, }; diff --git a/app/client/src/ce/utils/analyticsUtilTypes.ts b/app/client/src/ce/utils/analyticsUtilTypes.ts index d78da69057..cafbf8ad91 100644 --- a/app/client/src/ce/utils/analyticsUtilTypes.ts +++ b/app/client/src/ce/utils/analyticsUtilTypes.ts @@ -185,6 +185,9 @@ export type EventName = | "GS_GENERATE_KEY_BUTTON_CLICK" | "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK" | "GS_START_USING_GIT" + | "GS_DEFAULT_BRANCH_UPDATE" + | "GS_PROTECTED_BRANCHES_UPDATE" + | "GS_OPEN_GIT_SETTINGS" | "GIT_DISCARD_WARNING" | "GIT_DISCARD_CANCEL" | "GIT_DISCARD" diff --git a/app/client/src/constants/ThirdPartyConstants.tsx b/app/client/src/constants/ThirdPartyConstants.tsx index 2c995eab26..f03e68f827 100644 --- a/app/client/src/constants/ThirdPartyConstants.tsx +++ b/app/client/src/constants/ThirdPartyConstants.tsx @@ -27,6 +27,10 @@ export const PROVISIONING_SETUP_DOC = "http://docs.appsmith.com/advanced-concepts/user-provisioning-group-sync"; export const DISCORD_URL = "https://discord.gg/rBTTVJp"; export const ENTERPRISE_PRICING_PAGE = "https://www.appsmith.com/enterprise"; +export const DOCS_BRANCH_PROTECTION_URL = + "https://docs.appsmith.com/advanced-concepts/version-control-with-git/working-with-branches#branch-protection"; +export const DOCS_DEFAULT_BRANCH_URL = + "https://docs.appsmith.com/advanced-concepts/version-control-with-git/working-with-branches#default-branch"; export const PRICING_PAGE_URL = ( URL: string, diff --git a/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx index 5ef6f74b52..a2176be174 100644 --- a/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx +++ b/app/client/src/pages/Editor/gitSync/QuickGitActions/index.tsx @@ -130,18 +130,11 @@ function QuickActionButton({ ); } -const getPullBtnStatus = ( - gitStatus: any, - pullFailed: boolean, - isProtected: boolean, -) => { +const getPullBtnStatus = (gitStatus: any, pullFailed: boolean) => { const { behindCount, isClean } = gitStatus || {}; let message = createMessage(NO_COMMITS_TO_PULL); let disabled = behindCount === 0; - if (isProtected) { - disabled = false; - message = createMessage(PULL_CHANGES); - } else if (!isClean) { + if (!isClean) { disabled = true; message = createMessage(CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES); } else if (pullFailed) { @@ -322,7 +315,7 @@ export default function QuickGitActions() { const isProtectedMode = useSelector(protectedModeSelector); const { disabled: pullDisabled, message: pullTooltipMessage } = - getPullBtnStatus(gitStatus, !!pullFailed, isProtectedMode); + getPullBtnStatus(gitStatus, !!pullFailed); const isPullInProgress = useSelector(getPullInProgress); const isFetchingGitStatus = useSelector(getIsFetchingGitStatus); diff --git a/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx b/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx index 83f86190bf..6dca220f0a 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/ConnectionSuccess.tsx @@ -8,7 +8,6 @@ import { BRANCH_PROTECTION_RULE_1, BRANCH_PROTECTION_RULE_2, BRANCH_PROTECTION_RULE_3, - GIT_CONNECT_SUCCESS_MESSAGE, GIT_CONNECT_SUCCESS_TITLE, OPEN_GIT_SETTINGS, START_USING_GIT, @@ -21,10 +20,6 @@ import { useDispatch, useSelector } from "react-redux"; import styled from "styled-components"; import { getCurrentAppGitMetaData } from "@appsmith/selectors/applicationSelectors"; import AnalyticsUtil from "utils/AnalyticsUtil"; -import { - getDefaultGitBranchName, - getIsGitProtectedFeatureEnabled, -} from "selectors/gitSyncSelectors"; const Container = styled.div``; @@ -77,10 +72,6 @@ const features = [ function ConnectionSuccess() { const gitMetadata = useSelector(getCurrentAppGitMetaData); - const defaultBranchName = useSelector(getDefaultGitBranchName); - const isGitProtectedFeatureEnabled = useSelector( - getIsGitProtectedFeatureEnabled, - ); const dispatch = useDispatch(); useEffect(() => { @@ -105,24 +96,20 @@ function ConnectionSuccess() { tab: GitSyncModalTab.SETTINGS, }), ); - AnalyticsUtil.logEvent("GS_START_USING_GIT", { + AnalyticsUtil.logEvent("GS_OPEN_GIT_SETTINGS", { repoUrl: gitMetadata?.remoteUrl, }); }; - const preBranchProtectionContent = () => { - return ( - {createMessage(GIT_CONNECT_SUCCESS_MESSAGE)} - ); - }; - - const postBranchProtectionContent = () => { + const branchProtectionContent = () => { return ( <> Right now,{" "} - {defaultBranchName} is set - as the default branch and it is protected. + + {gitMetadata?.defaultBranchName} + {" "} + is set as the default branch and it is protected. {createMessage(BRANCH_PROTECTION_RULES_AS_FOLLOWS)} @@ -144,19 +131,7 @@ function ConnectionSuccess() { ); }; - const preBranchProtectionActions = () => { - return ( - - ); - }; - - const postBranchProtectionActions = () => { + const branchProtectionActions = () => { return ( <>