diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts index 4c0f39e7..84ed518e 100644 --- a/packages/backend/src/database.ts +++ b/packages/backend/src/database.ts @@ -303,4 +303,18 @@ export class Database { return false; } } + + async rollbackDeploymentById (projectId: string, deploymentId: string): Promise { + 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; + } + } } diff --git a/packages/backend/src/resolvers.ts b/packages/backend/src/resolvers.ts index d28dbae4..8d99c3c8 100644 --- a/packages/backend/src/resolvers.ts +++ b/packages/backend/src/resolvers.ts @@ -169,6 +169,15 @@ export const createResolvers = async (db: Database): Promise => { 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; + } } } }; diff --git a/packages/backend/src/schema.gql b/packages/backend/src/schema.gql index 2c9814eb..c07d5289 100644 --- a/packages/backend/src/schema.gql +++ b/packages/backend/src/schema.gql @@ -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 { diff --git a/packages/backend/test/fixtures/deployments.json b/packages/backend/test/fixtures/deployments.json index d55da5a9..9ae78457 100644 --- a/packages/backend/test/fixtures/deployments.json +++ b/packages/backend/test/fixtures/deployments.json @@ -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, diff --git a/packages/frontend/src/components/projects/project/settings/MembersTabPanel.tsx b/packages/frontend/src/components/projects/project/settings/MembersTabPanel.tsx index 68d14675..0ffecfad 100644 --- a/packages/frontend/src/components/projects/project/settings/MembersTabPanel.tsx +++ b/packages/frontend/src/components/projects/project/settings/MembersTabPanel.tsx @@ -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 = () => { @@ -82,6 +83,15 @@ const MembersTabPanel = () => { + {}} + removeMemberHandler={async () => {}} + /> {projectMembers.map((projectMember, index) => { return ( { + const { data } = await this.client.mutate({ + mutation: rollbackDeployment, + variables: { + projectId, + deploymentId + } + }); + + return data; + } } diff --git a/packages/gql-client/src/mutations.ts b/packages/gql-client/src/mutations.ts index e4eae6a7..a14db98a 100644 --- a/packages/gql-client/src/mutations.ts +++ b/packages/gql-client/src/mutations.ts @@ -34,3 +34,9 @@ mutation ($projectId: String!) { deleteProject(projectId: $projectId) } `; + +export const rollbackDeployment = gql` +mutation ($projectId: String! ,$deploymentId: String!) { + rollbackDeployment(proejctId: $projectId, deploymentId: $deploymentId) +} +`; diff --git a/packages/gql-client/src/types.ts b/packages/gql-client/src/types.ts index 098728d4..2baaa980 100644 --- a/packages/gql-client/src/types.ts +++ b/packages/gql-client/src/types.ts @@ -195,3 +195,7 @@ export type UpdateProjectInput = { export type RedeployToProdResponse = { redeployToProd: boolean } + +export type RollbackDeploymentResponse = { + rollbackDeployment: boolean +}