PromucFlow_constructor/app/client/src/api/GitSyncAPI.tsx
Rudraprasad Das cda27eb6f3
feat: branch protection (#28526)
## Description
- 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

#### PR fixes following issue(s)
Fixes #28434, #28056

#### Media
Protected View -
<img width="1728" alt="image"
src="https://github.com/appsmithorg/appsmith/assets/8724051/4fb26450-61e1-4fc0-a66d-0ebaa28ff90c">

Branch Protection Settings -
<img width="1728" alt="image"
src="https://github.com/appsmithorg/appsmith/assets/8724051/fb6d16b6-0a3c-42fd-be1a-9b3677048663">


#### Type of change
- New feature (non-breaking change which adds functionality)

## 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
- [ ] 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

---------

Co-authored-by: Nayan <nayan@appsmith.com>
2023-11-03 22:43:36 +05:30

222 lines
5.5 KiB
TypeScript

import type { AxiosPromise } from "axios";
import Api from "api/Api";
import type { ApiResponse } from "./ApiResponses";
import type { GitConfig } from "entities/GitSync";
import ApplicationApi from "@appsmith/api/ApplicationApi";
export interface CommitPayload {
applicationId: string;
commitMessage: string;
doPush: boolean;
branch: string;
}
export interface MergeBranchPayload {
applicationId: string;
sourceBranch: string;
destinationBranch: string;
}
export interface MergeStatusPayload {
applicationId: string;
sourceBranch: string;
destinationBranch: string;
}
export interface ConnectToGitPayload {
remoteUrl: string;
gitProfile?: {
authorName: string;
authorEmail: string;
useDefaultProfile?: boolean;
};
}
interface GitStatusParam {
applicationId: string;
branch: string;
compareRemote: "true" | "false";
}
interface GitRemoteStatusParam {
applicationId: string;
branch: string;
}
class GitSyncAPI extends Api {
static baseURL = `/v1/git`;
static async commit({
applicationId,
branch,
commitMessage,
doPush,
}: CommitPayload): Promise<AxiosPromise<ApiResponse>> {
return Api.post(
`${GitSyncAPI.baseURL}/commit/app/${applicationId}?branchName=${branch}`,
{
commitMessage,
doPush,
},
);
}
static async merge({
applicationId,
destinationBranch,
sourceBranch,
}: MergeBranchPayload): Promise<AxiosPromise<ApiResponse>> {
return Api.post(`${GitSyncAPI.baseURL}/merge/app/${applicationId}`, {
sourceBranch,
destinationBranch,
});
}
static async getMergeStatus({
applicationId,
destinationBranch,
sourceBranch,
}: MergeStatusPayload) {
return Api.post(`${GitSyncAPI.baseURL}/merge/status/app/${applicationId}`, {
sourceBranch,
destinationBranch,
});
}
static async pull({ applicationId }: { applicationId: string }) {
return Api.get(`${GitSyncAPI.baseURL}/pull/app/${applicationId}`);
}
static async connect(payload: ConnectToGitPayload, applicationId: string) {
return Api.post(
`${GitSyncAPI.baseURL}/connect/app/${applicationId}`,
payload,
);
}
static async getGlobalConfig() {
return Api.get(`${GitSyncAPI.baseURL}/profile/default`);
}
static async setGlobalConfig(payload: GitConfig) {
return Api.post(`${GitSyncAPI.baseURL}/profile/default`, payload);
}
static async fetchBranches(applicationId: string, pruneBranches?: boolean) {
const queryParams = {} as { pruneBranches?: boolean };
if (pruneBranches) queryParams.pruneBranches = true;
return Api.get(
`${GitSyncAPI.baseURL}/branch/app/${applicationId}`,
queryParams,
);
}
static async checkoutBranch(applicationId: string, branch: string) {
return Api.get(
`${GitSyncAPI.baseURL}/checkout-branch/app/${applicationId}`,
{
branchName: branch,
},
);
}
static async createNewBranch(applicationId: string, branch: string) {
return Api.post(
`${GitSyncAPI.baseURL}/create-branch/app/${applicationId}`,
{
branchName: branch,
},
);
}
static async getLocalConfig(applicationId: string) {
return Api.get(`${GitSyncAPI.baseURL}/profile/app/${applicationId}`);
}
static async setLocalConfig(payload: GitConfig, applicationId: string) {
return Api.put(
`${GitSyncAPI.baseURL}/profile/app/${applicationId}`,
payload,
);
}
static async getGitStatus({
applicationId,
branch,
compareRemote = "true",
}: GitStatusParam) {
return Api.get(
`${GitSyncAPI.baseURL}/status/app/${applicationId}`,
{ compareRemote },
{ headers: { branchName: branch } },
);
}
static async getGitRemoteStatus({
applicationId,
branch,
}: GitRemoteStatusParam) {
return Api.get(
`${GitSyncAPI.baseURL}/fetch/remote/app/${applicationId}`,
{},
{ headers: { branchName: branch } },
);
}
static async revokeGit({ applicationId }: { applicationId: string }) {
return Api.post(`${GitSyncAPI.baseURL}/disconnect/app/${applicationId}`);
}
static async importApp(payload: ConnectToGitPayload, workspaceId: string) {
return Api.post(`${GitSyncAPI.baseURL}/import/${workspaceId}`, payload);
}
static async getSSHKeyPair(
applicationId: string,
): Promise<AxiosPromise<ApiResponse>> {
return Api.get(ApplicationApi.baseURL + "/ssh-keypair/" + applicationId);
}
static async generateSSHKeyPair(
applicationId: string,
keyType: string,
isImporting?: boolean,
): Promise<AxiosPromise<ApiResponse>> {
const url = isImporting
? `v1/git/import/keys?keyType=${keyType}`
: `${ApplicationApi.baseURL}/ssh-keypair/${applicationId}?keyType=${keyType}`;
return isImporting ? Api.get(url) : Api.post(url);
}
static async deleteBranch(
applicationId: string,
branchName: string,
): Promise<AxiosPromise<ApiResponse>> {
return Api.delete(GitSyncAPI.baseURL + "/branch/app/" + applicationId, {
branchName,
});
}
static async discardChanges(applicationId: string) {
return Api.put(`${GitSyncAPI.baseURL}/discard/app/${applicationId}`);
}
static async getProtectedBranches(applicationId: string) {
return Api.get(
`${GitSyncAPI.baseURL}/branch/app/${applicationId}/protected`,
);
}
static async updateProtectedBranches(
applicationId: string,
branchNames: string[],
) {
return Api.post(
`${GitSyncAPI.baseURL}/branch/app/${applicationId}/protected`,
{ branchNames },
);
}
}
export default GitSyncAPI;