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
This commit is contained in:
parent
64ef0c33dd
commit
41d064fc12
|
|
@ -2,37 +2,9 @@ import { featureFlagIntercept } from "../../../../../support/Objects/FeatureFlag
|
||||||
import * as _ from "../../../../../support/Objects/ObjectsCore";
|
import * as _ from "../../../../../support/Objects/ObjectsCore";
|
||||||
|
|
||||||
let guid: any;
|
let guid: any;
|
||||||
let repoName1: any;
|
let repoName: any;
|
||||||
let repoName2: any;
|
|
||||||
|
|
||||||
describe("Git Branch Protection", function () {
|
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 () {
|
it("Issue 28056 - 2 : Check if protection is enabled when feature flag is enabled", function () {
|
||||||
_.agHelper.GenerateUUID();
|
_.agHelper.GenerateUUID();
|
||||||
cy.get("@guid").then((uid) => {
|
cy.get("@guid").then((uid) => {
|
||||||
|
|
@ -43,7 +15,6 @@ describe("Git Branch Protection", function () {
|
||||||
_.homePage.CreateAppInWorkspace(wsName, appName);
|
_.homePage.CreateAppInWorkspace(wsName, appName);
|
||||||
featureFlagIntercept({
|
featureFlagIntercept({
|
||||||
release_git_connect_v2_enabled: true,
|
release_git_connect_v2_enabled: true,
|
||||||
release_git_branch_protection_enabled: true,
|
|
||||||
});
|
});
|
||||||
cy.wait(1000);
|
cy.wait(1000);
|
||||||
|
|
||||||
|
|
@ -54,7 +25,7 @@ describe("Git Branch Protection", function () {
|
||||||
|
|
||||||
_.gitSync.CreateNConnectToGitV2();
|
_.gitSync.CreateNConnectToGitV2();
|
||||||
cy.get("@gitRepoName").then((repName) => {
|
cy.get("@gitRepoName").then((repName) => {
|
||||||
repoName2 = repName;
|
repoName = repName;
|
||||||
cy.wait("@gitProtectApi").then((res1) => {
|
cy.wait("@gitProtectApi").then((res1) => {
|
||||||
expect(res1.response).to.have.property("statusCode", 200);
|
expect(res1.response).to.have.property("statusCode", 200);
|
||||||
_.agHelper.AssertElementVisibility(
|
_.agHelper.AssertElementVisibility(
|
||||||
|
|
@ -76,7 +47,6 @@ describe("Git Branch Protection", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
_.gitSync.DeleteTestGithubRepo(repoName1);
|
_.gitSync.DeleteTestGithubRepo(repoName);
|
||||||
_.gitSync.DeleteTestGithubRepo(repoName2);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ let ws1Name: string;
|
||||||
let ws2Name: string;
|
let ws2Name: string;
|
||||||
let app1Name: string;
|
let app1Name: string;
|
||||||
let repoName: any;
|
let repoName: any;
|
||||||
|
let branchName: any;
|
||||||
|
|
||||||
describe("Git Connect V2", function () {
|
describe("Git Connect V2", function () {
|
||||||
before(() => {
|
before(() => {
|
||||||
|
|
@ -36,17 +37,21 @@ describe("Git Connect V2", function () {
|
||||||
release_git_connect_v2_enabled: true,
|
release_git_connect_v2_enabled: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
_.entityExplorer.DragDropWidgetNVerify(_.draggableWidgets.TEXT, 300, 300);
|
_.gitSync.CreateGitBranch("test", true);
|
||||||
_.propPane.RenameWidget("Text1", "MyText");
|
cy.get("@gitbranchName").then((bName) => {
|
||||||
_.propPane.UpdatePropertyFieldValue("Text", "Hello World");
|
branchName = bName;
|
||||||
_.gitSync.CommitAndPush();
|
_.entityExplorer.DragDropWidgetNVerify(_.draggableWidgets.TEXT, 300, 300);
|
||||||
|
_.propPane.RenameWidget("Text1", "MyText");
|
||||||
|
_.propPane.UpdatePropertyFieldValue("Text", "Hello World");
|
||||||
|
_.gitSync.CommitAndPush();
|
||||||
|
|
||||||
_.gitSync.ImportAppFromGitV2(ws2Name, repoName);
|
_.gitSync.ImportAppFromGitV2(ws2Name, repoName);
|
||||||
|
_.gitSync.SwitchGitBranch(branchName);
|
||||||
_.entityExplorer.ExpandCollapseEntity("Widgets");
|
_.entityExplorer.ExpandCollapseEntity("Widgets");
|
||||||
_.entityExplorer.AssertEntityPresenceInExplorer("MyText");
|
_.entityExplorer.AssertEntityPresenceInExplorer("MyText");
|
||||||
_.entityExplorer.SelectEntityByName("MyText");
|
_.entityExplorer.SelectEntityByName("MyText");
|
||||||
_.propPane.ValidatePropertyFieldValue("Text", "Hello World");
|
_.propPane.ValidatePropertyFieldValue("Text", "Hello World");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
|
|
||||||
|
|
@ -1033,7 +1033,7 @@ export const ADD_DEPLOY_KEY_STEP_TITLE = () =>
|
||||||
export const HOW_TO_ADD_DEPLOY_KEY = () =>
|
export const HOW_TO_ADD_DEPLOY_KEY = () =>
|
||||||
"How to paste SSH Key in repo and give write access?";
|
"How to paste SSH Key in repo and give write access?";
|
||||||
export const CONSENT_ADDED_DEPLOY_KEY = () =>
|
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 PREVIOUS_STEP = () => "Previous step";
|
||||||
export const GIT_CONNECT_SUCCESS_TITLE = () =>
|
export const GIT_CONNECT_SUCCESS_TITLE = () =>
|
||||||
"Successfully connected to your Git remote repository";
|
"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.";
|
"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_TITLE = () => "🚫 This is a protected branch";
|
||||||
export const BRANCH_TOOLTIP_MESSAGE = () =>
|
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 GO_TO_SETTINGS = () => "Go to settings";
|
||||||
export const NOW_PROTECT_BRANCH = () =>
|
export const NOW_PROTECT_BRANCH = () =>
|
||||||
"You can now protect your default branch.";
|
"You can now protect your default branch.";
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ export const FEATURE_FLAG = {
|
||||||
ab_show_templates_instead_of_blank_canvas_enabled:
|
ab_show_templates_instead_of_blank_canvas_enabled:
|
||||||
"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_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_git_branch_protection_enabled",
|
"license_git_branch_protection_enabled",
|
||||||
license_widget_rtl_support_enabled: "license_widget_rtl_support_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,
|
release_anvil_enabled: false,
|
||||||
ab_show_templates_instead_of_blank_canvas_enabled: false,
|
ab_show_templates_instead_of_blank_canvas_enabled: false,
|
||||||
release_app_sidebar_enabled: false,
|
release_app_sidebar_enabled: false,
|
||||||
release_git_branch_protection_enabled: false,
|
|
||||||
license_git_branch_protection_enabled: false,
|
license_git_branch_protection_enabled: false,
|
||||||
license_widget_rtl_support_enabled: false,
|
license_widget_rtl_support_enabled: false,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,9 @@ export type EventName =
|
||||||
| "GS_GENERATE_KEY_BUTTON_CLICK"
|
| "GS_GENERATE_KEY_BUTTON_CLICK"
|
||||||
| "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK"
|
| "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK"
|
||||||
| "GS_START_USING_GIT"
|
| "GS_START_USING_GIT"
|
||||||
|
| "GS_DEFAULT_BRANCH_UPDATE"
|
||||||
|
| "GS_PROTECTED_BRANCHES_UPDATE"
|
||||||
|
| "GS_OPEN_GIT_SETTINGS"
|
||||||
| "GIT_DISCARD_WARNING"
|
| "GIT_DISCARD_WARNING"
|
||||||
| "GIT_DISCARD_CANCEL"
|
| "GIT_DISCARD_CANCEL"
|
||||||
| "GIT_DISCARD"
|
| "GIT_DISCARD"
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ export const PROVISIONING_SETUP_DOC =
|
||||||
"http://docs.appsmith.com/advanced-concepts/user-provisioning-group-sync";
|
"http://docs.appsmith.com/advanced-concepts/user-provisioning-group-sync";
|
||||||
export const DISCORD_URL = "https://discord.gg/rBTTVJp";
|
export const DISCORD_URL = "https://discord.gg/rBTTVJp";
|
||||||
export const ENTERPRISE_PRICING_PAGE = "https://www.appsmith.com/enterprise";
|
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 = (
|
export const PRICING_PAGE_URL = (
|
||||||
URL: string,
|
URL: string,
|
||||||
|
|
|
||||||
|
|
@ -130,18 +130,11 @@ function QuickActionButton({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPullBtnStatus = (
|
const getPullBtnStatus = (gitStatus: any, pullFailed: boolean) => {
|
||||||
gitStatus: any,
|
|
||||||
pullFailed: boolean,
|
|
||||||
isProtected: boolean,
|
|
||||||
) => {
|
|
||||||
const { behindCount, isClean } = gitStatus || {};
|
const { behindCount, isClean } = gitStatus || {};
|
||||||
let message = createMessage(NO_COMMITS_TO_PULL);
|
let message = createMessage(NO_COMMITS_TO_PULL);
|
||||||
let disabled = behindCount === 0;
|
let disabled = behindCount === 0;
|
||||||
if (isProtected) {
|
if (!isClean) {
|
||||||
disabled = false;
|
|
||||||
message = createMessage(PULL_CHANGES);
|
|
||||||
} else if (!isClean) {
|
|
||||||
disabled = true;
|
disabled = true;
|
||||||
message = createMessage(CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES);
|
message = createMessage(CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES);
|
||||||
} else if (pullFailed) {
|
} else if (pullFailed) {
|
||||||
|
|
@ -322,7 +315,7 @@ export default function QuickGitActions() {
|
||||||
const isProtectedMode = useSelector(protectedModeSelector);
|
const isProtectedMode = useSelector(protectedModeSelector);
|
||||||
|
|
||||||
const { disabled: pullDisabled, message: pullTooltipMessage } =
|
const { disabled: pullDisabled, message: pullTooltipMessage } =
|
||||||
getPullBtnStatus(gitStatus, !!pullFailed, isProtectedMode);
|
getPullBtnStatus(gitStatus, !!pullFailed);
|
||||||
|
|
||||||
const isPullInProgress = useSelector(getPullInProgress);
|
const isPullInProgress = useSelector(getPullInProgress);
|
||||||
const isFetchingGitStatus = useSelector(getIsFetchingGitStatus);
|
const isFetchingGitStatus = useSelector(getIsFetchingGitStatus);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import {
|
||||||
BRANCH_PROTECTION_RULE_1,
|
BRANCH_PROTECTION_RULE_1,
|
||||||
BRANCH_PROTECTION_RULE_2,
|
BRANCH_PROTECTION_RULE_2,
|
||||||
BRANCH_PROTECTION_RULE_3,
|
BRANCH_PROTECTION_RULE_3,
|
||||||
GIT_CONNECT_SUCCESS_MESSAGE,
|
|
||||||
GIT_CONNECT_SUCCESS_TITLE,
|
GIT_CONNECT_SUCCESS_TITLE,
|
||||||
OPEN_GIT_SETTINGS,
|
OPEN_GIT_SETTINGS,
|
||||||
START_USING_GIT,
|
START_USING_GIT,
|
||||||
|
|
@ -21,10 +20,6 @@ import { useDispatch, useSelector } from "react-redux";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getCurrentAppGitMetaData } from "@appsmith/selectors/applicationSelectors";
|
import { getCurrentAppGitMetaData } from "@appsmith/selectors/applicationSelectors";
|
||||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||||
import {
|
|
||||||
getDefaultGitBranchName,
|
|
||||||
getIsGitProtectedFeatureEnabled,
|
|
||||||
} from "selectors/gitSyncSelectors";
|
|
||||||
|
|
||||||
const Container = styled.div``;
|
const Container = styled.div``;
|
||||||
|
|
||||||
|
|
@ -77,10 +72,6 @@ const features = [
|
||||||
|
|
||||||
function ConnectionSuccess() {
|
function ConnectionSuccess() {
|
||||||
const gitMetadata = useSelector(getCurrentAppGitMetaData);
|
const gitMetadata = useSelector(getCurrentAppGitMetaData);
|
||||||
const defaultBranchName = useSelector(getDefaultGitBranchName);
|
|
||||||
const isGitProtectedFeatureEnabled = useSelector(
|
|
||||||
getIsGitProtectedFeatureEnabled,
|
|
||||||
);
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -105,24 +96,20 @@ function ConnectionSuccess() {
|
||||||
tab: GitSyncModalTab.SETTINGS,
|
tab: GitSyncModalTab.SETTINGS,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
AnalyticsUtil.logEvent("GS_START_USING_GIT", {
|
AnalyticsUtil.logEvent("GS_OPEN_GIT_SETTINGS", {
|
||||||
repoUrl: gitMetadata?.remoteUrl,
|
repoUrl: gitMetadata?.remoteUrl,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const preBranchProtectionContent = () => {
|
const branchProtectionContent = () => {
|
||||||
return (
|
|
||||||
<Text renderAs="p">{createMessage(GIT_CONNECT_SUCCESS_MESSAGE)}</Text>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const postBranchProtectionContent = () => {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DefaultBranchMessage renderAs="p">
|
<DefaultBranchMessage renderAs="p">
|
||||||
Right now,{" "}
|
Right now,{" "}
|
||||||
<BranchTag isClosable={false}>{defaultBranchName}</BranchTag> is set
|
<BranchTag isClosable={false}>
|
||||||
as the default branch and it is protected.
|
{gitMetadata?.defaultBranchName}
|
||||||
|
</BranchTag>{" "}
|
||||||
|
is set as the default branch and it is protected.
|
||||||
</DefaultBranchMessage>
|
</DefaultBranchMessage>
|
||||||
<ProtectionRulesTitle renderAs="p">
|
<ProtectionRulesTitle renderAs="p">
|
||||||
{createMessage(BRANCH_PROTECTION_RULES_AS_FOLLOWS)}
|
{createMessage(BRANCH_PROTECTION_RULES_AS_FOLLOWS)}
|
||||||
|
|
@ -144,19 +131,7 @@ function ConnectionSuccess() {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const preBranchProtectionActions = () => {
|
const branchProtectionActions = () => {
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
data-testid="t--start-using-git-button"
|
|
||||||
onClick={handleStartGit}
|
|
||||||
size="md"
|
|
||||||
>
|
|
||||||
{createMessage(START_USING_GIT)}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const postBranchProtectionActions = () => {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -184,16 +159,10 @@ function ConnectionSuccess() {
|
||||||
{createMessage(GIT_CONNECT_SUCCESS_TITLE)}
|
{createMessage(GIT_CONNECT_SUCCESS_TITLE)}
|
||||||
</TitleText>
|
</TitleText>
|
||||||
</TitleContainer>
|
</TitleContainer>
|
||||||
{isGitProtectedFeatureEnabled
|
{branchProtectionContent()}
|
||||||
? postBranchProtectionContent()
|
|
||||||
: preBranchProtectionContent()}
|
|
||||||
</Container>
|
</Container>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>{branchProtectionActions()}</ModalFooter>
|
||||||
{isGitProtectedFeatureEnabled
|
|
||||||
? postBranchProtectionActions()
|
|
||||||
: preBranchProtectionActions()}
|
|
||||||
</ModalFooter>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import styled from "styled-components";
|
||||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||||
import { useAppsmithEnterpriseLink } from "./hooks";
|
import { useAppsmithEnterpriseLink } from "./hooks";
|
||||||
|
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
|
|
@ -70,6 +71,10 @@ function GitDefaultBranch() {
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = () => {
|
||||||
if (selectedValue) {
|
if (selectedValue) {
|
||||||
|
AnalyticsUtil.logEvent("GS_DEFAULT_BRANCH_UPDATE", {
|
||||||
|
old_branch: currentDefaultBranch,
|
||||||
|
new_branch: selectedValue,
|
||||||
|
});
|
||||||
dispatch(updateGitDefaultBranch({ branchName: selectedValue }));
|
dispatch(updateGitDefaultBranch({ branchName: selectedValue }));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,13 @@ import {
|
||||||
APPSMITH_ENTERPRISE,
|
APPSMITH_ENTERPRISE,
|
||||||
BRANCH_PROTECTION,
|
BRANCH_PROTECTION,
|
||||||
BRANCH_PROTECTION_DESC,
|
BRANCH_PROTECTION_DESC,
|
||||||
|
LEARN_MORE,
|
||||||
UPDATE,
|
UPDATE,
|
||||||
createMessage,
|
createMessage,
|
||||||
} from "@appsmith/constants/messages";
|
} from "@appsmith/constants/messages";
|
||||||
import { updateGitProtectedBranchesInit } from "actions/gitSyncActions";
|
import { updateGitProtectedBranchesInit } from "actions/gitSyncActions";
|
||||||
import { Button, Link, Option, Select, Text } from "design-system";
|
import { Button, Link, Option, Select, Text } from "design-system";
|
||||||
import { union, xor } from "lodash";
|
import { xor } from "lodash";
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import {
|
import {
|
||||||
|
|
@ -21,6 +22,8 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||||
import { useAppsmithEnterpriseLink } from "./hooks";
|
import { useAppsmithEnterpriseLink } from "./hooks";
|
||||||
import { REMOTE_BRANCH_PREFIX } from "../../constants";
|
import { REMOTE_BRANCH_PREFIX } from "../../constants";
|
||||||
|
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||||
|
import { DOCS_BRANCH_PROTECTION_URL } from "constants/ThirdPartyConstants";
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
|
|
@ -60,25 +63,25 @@ function GitProtectedBranches() {
|
||||||
const defaultBranch = useSelector(getDefaultGitBranchName);
|
const defaultBranch = useSelector(getDefaultGitBranchName);
|
||||||
|
|
||||||
const branchNames = useMemo(() => {
|
const branchNames = useMemo(() => {
|
||||||
const remoteBranchNames = [];
|
const returnVal: string[] = [];
|
||||||
const localBranchNames = [];
|
|
||||||
for (const unfilteredBranch of unfilteredBranches) {
|
for (const unfilteredBranch of unfilteredBranches) {
|
||||||
if (unfilteredBranch.branchName === defaultBranch) {
|
if (unfilteredBranch.branchName === defaultBranch) {
|
||||||
continue;
|
returnVal.unshift(unfilteredBranch.branchName);
|
||||||
}
|
} else if (unfilteredBranch.branchName.includes(REMOTE_BRANCH_PREFIX)) {
|
||||||
if (unfilteredBranch.branchName.includes(REMOTE_BRANCH_PREFIX)) {
|
const localBranchName = unfilteredBranch.branchName.replace(
|
||||||
remoteBranchNames.push(
|
REMOTE_BRANCH_PREFIX,
|
||||||
unfilteredBranch.branchName.replace(REMOTE_BRANCH_PREFIX, ""),
|
"",
|
||||||
);
|
);
|
||||||
|
if (!returnVal.includes(localBranchName)) {
|
||||||
|
returnVal.push(
|
||||||
|
unfilteredBranch.branchName.replace(REMOTE_BRANCH_PREFIX, ""),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
localBranchNames.push(unfilteredBranch.branchName);
|
returnVal.push(unfilteredBranch.branchName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const branchNames = union(localBranchNames, remoteBranchNames);
|
return returnVal;
|
||||||
if (defaultBranch) {
|
|
||||||
branchNames.unshift(defaultBranch);
|
|
||||||
}
|
|
||||||
return branchNames;
|
|
||||||
}, [unfilteredBranches, defaultBranch]);
|
}, [unfilteredBranches, defaultBranch]);
|
||||||
|
|
||||||
const isGitProtectedFeatureLicensed = useFeatureFlag(
|
const isGitProtectedFeatureLicensed = useFeatureFlag(
|
||||||
|
|
@ -86,7 +89,7 @@ function GitProtectedBranches() {
|
||||||
);
|
);
|
||||||
const protectedBranches = useSelector(getProtectedBranchesSelector);
|
const protectedBranches = useSelector(getProtectedBranchesSelector);
|
||||||
const isUpdateLoading = useSelector(getIsUpdateProtectedBranchesLoading);
|
const isUpdateLoading = useSelector(getIsUpdateProtectedBranchesLoading);
|
||||||
const [selectedValues, setSelectedValues] = useState<string[]>();
|
const [selectedValues, setSelectedValues] = useState<string[]>([]);
|
||||||
|
|
||||||
const enterprisePricingLink = useAppsmithEnterpriseLink(
|
const enterprisePricingLink = useAppsmithEnterpriseLink(
|
||||||
"git_branch_protection",
|
"git_branch_protection",
|
||||||
|
|
@ -103,6 +106,7 @@ function GitProtectedBranches() {
|
||||||
const updateIsDisabled = !areProtectedBranchesDifferent;
|
const updateIsDisabled = !areProtectedBranchesDifferent;
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = () => {
|
||||||
|
sendAnalyticsEvent();
|
||||||
dispatch(
|
dispatch(
|
||||||
updateGitProtectedBranchesInit({
|
updateGitProtectedBranchesInit({
|
||||||
protectedBranches: selectedValues ?? [],
|
protectedBranches: selectedValues ?? [],
|
||||||
|
|
@ -110,6 +114,25 @@ function GitProtectedBranches() {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sendAnalyticsEvent = () => {
|
||||||
|
const eventData = {
|
||||||
|
branches_added: [] as string[],
|
||||||
|
branches_removed: [] as string[],
|
||||||
|
protected_branches: selectedValues,
|
||||||
|
};
|
||||||
|
for (const val of selectedValues) {
|
||||||
|
if (!protectedBranches.includes(val)) {
|
||||||
|
eventData.branches_added.push(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const val of protectedBranches) {
|
||||||
|
if (!selectedValues.includes(val)) {
|
||||||
|
eventData.branches_removed.push(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AnalyticsUtil.logEvent("GS_PROTECTED_BRANCHES_UPDATE", eventData);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<HeadContainer>
|
<HeadContainer>
|
||||||
|
|
@ -117,7 +140,10 @@ function GitProtectedBranches() {
|
||||||
{createMessage(BRANCH_PROTECTION)}
|
{createMessage(BRANCH_PROTECTION)}
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
<SectionDesc kind="body-m" renderAs="p">
|
<SectionDesc kind="body-m" renderAs="p">
|
||||||
{createMessage(BRANCH_PROTECTION_DESC)}
|
{createMessage(BRANCH_PROTECTION_DESC)}{" "}
|
||||||
|
<StyledLink target="_blank" to={DOCS_BRANCH_PROTECTION_URL}>
|
||||||
|
{createMessage(LEARN_MORE)}
|
||||||
|
</StyledLink>
|
||||||
</SectionDesc>
|
</SectionDesc>
|
||||||
{!isGitProtectedFeatureLicensed && (
|
{!isGitProtectedFeatureLicensed && (
|
||||||
<SectionDesc kind="body-m" renderAs="p">
|
<SectionDesc kind="body-m" renderAs="p">
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ import styled from "styled-components";
|
||||||
import { Divider, ModalBody } from "design-system";
|
import { Divider, ModalBody } from "design-system";
|
||||||
import GitDefaultBranch from "./GitDefaultBranch";
|
import GitDefaultBranch from "./GitDefaultBranch";
|
||||||
import GitProtectedBranches from "./GitProtectedBranches";
|
import GitProtectedBranches from "./GitProtectedBranches";
|
||||||
import { useSelector } from "react-redux";
|
|
||||||
import { getIsGitProtectedFeatureEnabled } from "selectors/gitSyncSelectors";
|
|
||||||
import { useIsGitAdmin } from "../../hooks/useIsGitAdmin";
|
import { useIsGitAdmin } from "../../hooks/useIsGitAdmin";
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
|
|
@ -21,16 +19,13 @@ const StyledDivider = styled(Divider)`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function GitSettings() {
|
function GitSettings() {
|
||||||
const isGitProtectedFeatureEnabled = useSelector(
|
|
||||||
getIsGitProtectedFeatureEnabled,
|
|
||||||
);
|
|
||||||
const isGitAdmin = useIsGitAdmin();
|
const isGitAdmin = useIsGitAdmin();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Container>
|
<Container>
|
||||||
<GitUserSettings />
|
<GitUserSettings />
|
||||||
{isGitProtectedFeatureEnabled && isGitAdmin ? (
|
{isGitAdmin ? (
|
||||||
<>
|
<>
|
||||||
<StyledDivider />
|
<StyledDivider />
|
||||||
<GitDefaultBranch />
|
<GitDefaultBranch />
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ import { addBranchParam, GIT_BRANCH_QUERY_KEY } from "constants/routes";
|
||||||
import {
|
import {
|
||||||
getCurrentGitBranch,
|
getCurrentGitBranch,
|
||||||
getDisconnectingGitApplication,
|
getDisconnectingGitApplication,
|
||||||
getIsGitProtectedFeatureEnabled,
|
getIsGitConnectV2Enabled,
|
||||||
getIsGitStatusLiteEnabled,
|
getIsGitStatusLiteEnabled,
|
||||||
} from "selectors/gitSyncSelectors";
|
} from "selectors/gitSyncSelectors";
|
||||||
import { initEditor } from "actions/initActions";
|
import { initEditor } from "actions/initActions";
|
||||||
|
|
@ -221,6 +221,9 @@ function* connectToGitSaga(action: ConnectToGitReduxAction) {
|
||||||
const applicationId: string = yield select(getCurrentApplicationId);
|
const applicationId: string = yield select(getCurrentApplicationId);
|
||||||
const currentPageId: string = yield select(getCurrentPageId);
|
const currentPageId: string = yield select(getCurrentPageId);
|
||||||
response = yield GitSyncAPI.connect(action.payload, applicationId);
|
response = yield GitSyncAPI.connect(action.payload, applicationId);
|
||||||
|
const isGitConnectV2Enabled: boolean = yield select(
|
||||||
|
getIsGitConnectV2Enabled,
|
||||||
|
);
|
||||||
|
|
||||||
const isValidResponse: boolean = yield validateResponse(
|
const isValidResponse: boolean = yield validateResponse(
|
||||||
response,
|
response,
|
||||||
|
|
@ -233,10 +236,7 @@ function* connectToGitSaga(action: ConnectToGitReduxAction) {
|
||||||
yield put(connectToGitSuccess(response?.data));
|
yield put(connectToGitSuccess(response?.data));
|
||||||
const defaultBranch = response?.data?.gitApplicationMetadata?.branchName;
|
const defaultBranch = response?.data?.gitApplicationMetadata?.branchName;
|
||||||
|
|
||||||
const isGitProtectedFeatureEnabled: boolean = yield select(
|
if (isGitConnectV2Enabled) {
|
||||||
getIsGitProtectedFeatureEnabled,
|
|
||||||
);
|
|
||||||
if (isGitProtectedFeatureEnabled) {
|
|
||||||
yield put(
|
yield put(
|
||||||
updateGitProtectedBranchesInit({
|
updateGitProtectedBranchesInit({
|
||||||
protectedBranches: defaultBranch ? [defaultBranch] : [],
|
protectedBranches: defaultBranch ? [defaultBranch] : [],
|
||||||
|
|
@ -1069,12 +1069,6 @@ function* discardChanges({
|
||||||
}
|
}
|
||||||
|
|
||||||
function* fetchGitProtectedBranchesSaga() {
|
function* fetchGitProtectedBranchesSaga() {
|
||||||
const isGitProtectedFeatureEnabled: boolean = yield select(
|
|
||||||
getIsGitProtectedFeatureEnabled,
|
|
||||||
);
|
|
||||||
if (!isGitProtectedFeatureEnabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let response: ApiResponse<string[]>;
|
let response: ApiResponse<string[]>;
|
||||||
try {
|
try {
|
||||||
const appId: string = yield select(getCurrentApplicationId);
|
const appId: string = yield select(getCurrentApplicationId);
|
||||||
|
|
@ -1111,12 +1105,6 @@ function* fetchGitProtectedBranchesSaga() {
|
||||||
function* updateGitProtectedBranchesSaga({
|
function* updateGitProtectedBranchesSaga({
|
||||||
payload,
|
payload,
|
||||||
}: ReduxAction<{ protectedBranches: string[] }>) {
|
}: ReduxAction<{ protectedBranches: string[] }>) {
|
||||||
const isGitProtectedFeatureEnabled: boolean = yield select(
|
|
||||||
getIsGitProtectedFeatureEnabled,
|
|
||||||
);
|
|
||||||
if (!isGitProtectedFeatureEnabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { protectedBranches } = payload;
|
const { protectedBranches } = payload;
|
||||||
const applicationId: string = yield select(getCurrentApplicationId);
|
const applicationId: string = yield select(getCurrentApplicationId);
|
||||||
let response: ApiResponse<string[]>;
|
let response: ApiResponse<string[]>;
|
||||||
|
|
|
||||||
|
|
@ -239,8 +239,3 @@ export const getIsUpdateProtectedBranchesLoading = (state: AppState) => {
|
||||||
state.ui.gitSync.protectedBranchesLoading
|
state.ui.gitSync.protectedBranchesLoading
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getIsGitProtectedFeatureEnabled = createSelector(
|
|
||||||
selectFeatureFlags,
|
|
||||||
(flags) => !!flags?.release_git_branch_protection_enabled,
|
|
||||||
);
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user