Add GQL mutation for rollback deployment (#46)

* Show project owner in member tab panel

* Implement mutation for rollback deployment

* Fix project members count

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
Nabarun Gogoi 2024-01-29 17:39:51 +05:30 committed by Ashwin Phatak
parent 1ae1564878
commit 8c38d4788e
8 changed files with 70 additions and 4 deletions

View File

@ -303,4 +303,18 @@ export class Database {
return false;
}
}
async rollbackDeploymentById (projectId: string, deploymentId: string): Promise<boolean> {
const deploymentRepository = this.dataSource.getRepository(Deployment);
// TODO: Implement transactions
const oldCurrentDeploymentUpdate = await deploymentRepository.update({ project: { id: projectId }, isCurrent: true }, { isCurrent: false });
const newCurrentDeploymentUpdate = await deploymentRepository.update({ id: Number(deploymentId) }, { isCurrent: true });
if (oldCurrentDeploymentUpdate.affected && newCurrentDeploymentUpdate.affected) {
return oldCurrentDeploymentUpdate.affected > 0 && newCurrentDeploymentUpdate.affected > 0;
} else {
return false;
}
}
}

View File

@ -169,6 +169,15 @@ export const createResolvers = async (db: Database): Promise<any> => {
log(err);
return false;
}
},
rollbackDeployment: async (_: any, { projectId, deploymentId }: {deploymentId: string, projectId: string }) => {
try {
return db.rollbackDeploymentById(projectId, deploymentId);
} catch (err) {
log(err);
return false;
}
}
}
};

View File

@ -131,6 +131,7 @@ type Mutation {
updateProject(projectId: String!, updateProject: UpdateProjectInput): Boolean!
redeployToProd(deploymentId: String!): Boolean!
deleteProject(projectId: String!): Boolean!
rollbackDeployment(projectId: String!, deploymentId: String!): Boolean!
}
input AddEnvironmentVariableInput {

View File

@ -29,6 +29,16 @@
"branch": "prod",
"commitHash": "testXyz"
},
{
"projectIndex": 0,
"domainIndex": null,
"title": "nextjs-boilerplate-4",
"status": "Ready",
"environment": "Production",
"isCurrent": false,
"branch": "prod",
"commitHash": "testXyz"
},
{
"projectIndex": 1,
"domainIndex":3,

View File

@ -1,6 +1,7 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useOutletContext, useParams } from 'react-router-dom';
import toast, { Toaster } from 'react-hot-toast';
import { Project } from 'gql-client';
import { Chip, Button, Typography } from '@material-tailwind/react';
@ -15,7 +16,7 @@ import { useGQLClient } from '../../../../context/GQLClientContext';
const FIRST_MEMBER_CARD = 0;
const MembersTabPanel = () => {
const MembersTabPanel = ({ project }: { project: Project }) => {
const { id } = useParams();
const client = useGQLClient();
@ -69,7 +70,7 @@ const MembersTabPanel = () => {
<Chip
className="normal-case ml-3 font-normal"
size="sm"
value={projectMembers.length}
value={projectMembers.length + 1}
/>
</div>
</div>
@ -82,6 +83,15 @@ const MembersTabPanel = () => {
</Button>
</div>
</div>
<MemberCard
member={project.owner}
isFirstCard={true}
isOwner={true}
isPending={false}
permissions={[]}
handleDeletePendingMember={() => {}}
removeMemberHandler={async () => {}}
/>
{projectMembers.map((projectMember, index) => {
return (
<MemberCard

View File

@ -1,8 +1,8 @@
import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client';
import { getUser, getOrganizations, getDeployments, getProjectMembers, searchProjects, getEnvironmentVariables, getProject, getProjectsInOrganization } from './queries';
import { AddEnvironmentVariableInput, AddEnvironmentVariablesResponse, GetDeploymentsResponse, GetEnvironmentVariablesResponse, GetOrganizationsResponse, GetProjectMembersResponse, SearchProjectsResponse, GetUserResponse, RemoveMemberResponse, UpdateDeploymentToProdResponse, GetProjectResponse, UpdateProjectResponse, UpdateProjectInput, RedeployToProdResponse, DeleteProjectResponse, GetProjectsInOrganizationResponse } from './types';
import { removeMember, addEnvironmentVariables, updateDeploymentToProd, updateProjectMutation, redeployToProd, deleteProject } from './mutations';
import { AddEnvironmentVariableInput, AddEnvironmentVariablesResponse, GetDeploymentsResponse, GetEnvironmentVariablesResponse, GetOrganizationsResponse, GetProjectMembersResponse, SearchProjectsResponse, GetUserResponse, RemoveMemberResponse, UpdateDeploymentToProdResponse, GetProjectResponse, UpdateProjectResponse, UpdateProjectInput, RedeployToProdResponse, DeleteProjectResponse, GetProjectsInOrganizationResponse, RollbackDeploymentResponse } from './types';
import { removeMember, addEnvironmentVariables, updateDeploymentToProd, updateProjectMutation, redeployToProd, deleteProject, rollbackDeployment } from './mutations';
export interface GraphQLConfig {
gqlEndpoint: string;
@ -180,4 +180,16 @@ export class GQLClient {
return data;
}
async rollbackDeployment (projectId: string, deploymentId: string): Promise<RollbackDeploymentResponse> {
const { data } = await this.client.mutate({
mutation: rollbackDeployment,
variables: {
projectId,
deploymentId
}
});
return data;
}
}

View File

@ -34,3 +34,9 @@ mutation ($projectId: String!) {
deleteProject(projectId: $projectId)
}
`;
export const rollbackDeployment = gql`
mutation ($projectId: String! ,$deploymentId: String!) {
rollbackDeployment(proejctId: $projectId, deploymentId: $deploymentId)
}
`;

View File

@ -195,3 +195,7 @@ export type UpdateProjectInput = {
export type RedeployToProdResponse = {
redeployToProd: boolean
}
export type RollbackDeploymentResponse = {
rollbackDeployment: boolean
}