From c2025540023c50242998d34f1ddeeef6c61c37fa Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 30 Jan 2025 14:29:46 +0530 Subject: [PATCH 01/59] Store DNS record data for deployments --- packages/backend/src/database.ts | 2 +- packages/backend/src/entity/Deployment.ts | 5 ++++- packages/backend/src/registry.ts | 18 ++++++++++++++++-- packages/backend/src/service.ts | 14 ++++++++++++++ packages/backend/src/types.ts | 8 ++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts index f20eb455..6499b0e1 100644 --- a/packages/backend/src/database.ts +++ b/packages/backend/src/database.ts @@ -60,7 +60,7 @@ export class Database { // Hotfix for updating old DB data if (organizations[0].slug === 'snowball-tools-1') { const [orgEntity] = await getEntities(path.resolve(__dirname, ORGANIZATION_DATA_PATH)); - + await this.updateOrganization( organizations[0].id, { diff --git a/packages/backend/src/entity/Deployment.ts b/packages/backend/src/entity/Deployment.ts index 5c772b32..021cfc75 100644 --- a/packages/backend/src/entity/Deployment.ts +++ b/packages/backend/src/entity/Deployment.ts @@ -14,7 +14,7 @@ import { Project } from './Project'; import { Domain } from './Domain'; import { User } from './User'; import { Deployer } from './Deployer'; -import { AppDeploymentRecordAttributes, AppDeploymentRemovalRecordAttributes } from '../types'; +import { AppDeploymentRecordAttributes, AppDeploymentRemovalRecordAttributes, DNSRecordAttributes } from '../types'; export enum Environment { Production = 'Production', @@ -126,6 +126,9 @@ export class Deployment { @Column('simple-json', { nullable: true }) applicationDeploymentRemovalRecordData!: AppDeploymentRemovalRecordAttributes | null; + @Column('simple-json', { nullable: true }) + dnsRecordData!: DNSRecordAttributes | null; + @ManyToOne(() => Deployer) @JoinColumn({ name: 'deployerLrn' }) deployer!: Deployer; diff --git a/packages/backend/src/registry.ts b/packages/backend/src/registry.ts index 4847bd6d..d5f5ec12 100644 --- a/packages/backend/src/registry.ts +++ b/packages/backend/src/registry.ts @@ -16,7 +16,7 @@ import { ApplicationDeploymentRequest, ApplicationDeploymentRemovalRequest } from './entity/Deployment'; -import { AppDeploymentRecord, AppDeploymentRemovalRecord, AuctionParams, DeployerRecord } from './types'; +import { AppDeploymentRecord, AppDeploymentRemovalRecord, AuctionParams, DeployerRecord, DNSRecordAttributes } from './types'; import { getConfig, getRepoDetails, registryTransactionWithRetry, sleep } from './utils'; const log = debug('snowball:registry'); @@ -27,7 +27,8 @@ const APP_DEPLOYMENT_REQUEST_TYPE = 'ApplicationDeploymentRequest'; const APP_DEPLOYMENT_REMOVAL_REQUEST_TYPE = 'ApplicationDeploymentRemovalRequest'; const APP_DEPLOYMENT_RECORD_TYPE = 'ApplicationDeploymentRecord'; const APP_DEPLOYMENT_REMOVAL_RECORD_TYPE = 'ApplicationDeploymentRemovalRecord'; -const WEBAPP_DEPLOYER_RECORD_TYPE = 'WebappDeployer' +const WEBAPP_DEPLOYER_RECORD_TYPE = 'WebappDeployer'; +const DNS_RECORD_TYPE = 'DnsRecord'; const SLEEP_DURATION = 1000; // TODO: Move registry code to registry-sdk/watcher-ts @@ -442,6 +443,19 @@ export class Registry { ); } + /** + * Fetch deployment DNS Records by filter + */ + async getDNSRecordsByFilter(filter: { [key: string]: any }): Promise { + return this.registry.queryRecords( + { + type: DNS_RECORD_TYPE, + ...filter + }, + true + ); + } + async createApplicationDeploymentRemovalRequest(data: { deploymentId: string; deployerLrn: string; diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index aa8736a0..d3807dfc 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -22,6 +22,7 @@ import { AppDeploymentRemovalRecord, AuctionParams, DeployerRecord, + DNSRecordAttributes, EnvironmentVariables, GitPushEventPayload, } from './types'; @@ -200,11 +201,24 @@ export class Service { log(`Project ${deployment.projectId} not found`); return; } else { + const dnsRecords = await this.laconicRegistry.getDNSRecordsByFilter({ + request: deployment.applicationDeploymentRequestId + }) + + const dnsRecordData: DNSRecordAttributes = { + name: dnsRecords[0].name, + request: dnsRecords[0].request, + resourceType: dnsRecords[0].resourceType, + value: dnsRecords[0].value, + version: dnsRecords[0].version, + } + deployment.applicationDeploymentRecordId = record.id; deployment.applicationDeploymentRecordData = record.attributes; deployment.url = record.attributes.url; deployment.status = DeploymentStatus.Ready; deployment.isCurrent = deployment.environment === Environment.Production; + deployment.dnsRecordData = dnsRecordData; await this.db.updateDeploymentById(deployment.id, deployment); diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 83c810ae..96be83d5 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -40,6 +40,14 @@ export interface AppDeploymentRecordAttributes { version: string; } +export interface DNSRecordAttributes { + name: string; + value: string; + request: string; + resourceType: string; + version: string; +} + export interface AppDeploymentRemovalRecordAttributes { deployment: string; request: string; -- 2.45.2 From 4ae4670dca18a80c10cea368347f78e93e757e00 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Thu, 30 Jan 2025 14:38:29 +0530 Subject: [PATCH 02/59] Remove redirect domain creation while adding custom domain --- packages/backend/src/service.ts | 24 +++---- .../projects/project/settings/SetupDomain.tsx | 62 +++++++++---------- .../org-slug/projects/id/settings/Domains.tsx | 22 ++++--- 3 files changed, 55 insertions(+), 53 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index d3807dfc..80e49874 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1243,7 +1243,7 @@ export class Service { data: { name: string }, ): Promise<{ primaryDomain: Domain; - redirectedDomain: Domain; + // redirectedDomain: Domain; }> { const currentProject = await this.db.getProjectById(projectId); @@ -1259,22 +1259,22 @@ export class Service { const savedPrimaryDomain = await this.db.addDomain(primaryDomainDetails); - const domainArr = data.name.split('www.'); + // const domainArr = data.name.split('www.'); - const redirectedDomainDetails = { - name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`, - branch: currentProject.prodBranch, - project: currentProject, - redirectTo: savedPrimaryDomain, - }; + // const redirectedDomainDetails = { + // name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`, + // branch: currentProject.prodBranch, + // project: currentProject, + // redirectTo: savedPrimaryDomain, + // }; - const savedRedirectedDomain = await this.db.addDomain( - redirectedDomainDetails, - ); + // const savedRedirectedDomain = await this.db.addDomain( + // redirectedDomainDetails, + // ); return { primaryDomain: savedPrimaryDomain, - redirectedDomain: savedRedirectedDomain, + // redirectedDomain: savedRedirectedDomain, }; } diff --git a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx index 03c9b331..e1b5acde 100644 --- a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx +++ b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx @@ -1,12 +1,12 @@ -import { useEffect, useState } from 'react'; +// import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useForm } from 'react-hook-form'; import { Heading } from 'components/shared/Heading'; -import { InlineNotification } from 'components/shared/InlineNotification'; +// import { InlineNotification } from 'components/shared/InlineNotification'; import { Input } from 'components/shared/Input'; import { Button } from 'components/shared/Button'; -import { Radio } from 'components/shared/Radio'; +// import { Radio } from 'components/shared/Radio'; interface SetupDomainFormValues { domainName: string; @@ -18,47 +18,45 @@ const SetupDomain = () => { register, handleSubmit, formState: { isValid }, - watch, - setValue, + // watch, + // setValue, } = useForm({ defaultValues: { domainName: '', - isWWW: 'false', + // isWWW: 'false', }, mode: 'onChange', }); - const [domainStr, setDomainStr] = useState(''); + // const [domainStr, setDomainStr] = useState(''); const navigate = useNavigate(); - const isWWWRadioOptions = [ - { label: domainStr, value: 'false' }, - { label: `www.${domainStr}`, value: 'true' }, - ]; + // const isWWWRadioOptions = [ + // { label: domainStr, value: 'false' }, + // { label: `www.${domainStr}`, value: 'true' }, + // ]; - useEffect(() => { - const subscription = watch((value, { name }) => { - if (name === 'domainName' && value.domainName) { - const domainArr = value.domainName.split('www.'); - const cleanedDomain = - domainArr.length > 1 ? domainArr[1] : domainArr[0]; - setDomainStr(cleanedDomain); + // useEffect(() => { + // const subscription = watch((value, { name }) => { + // if (name === 'domainName' && value.domainName) { + // const domainArr = value.domainName.split('www.'); + // const cleanedDomain = + // domainArr.length > 1 ? domainArr[1] : domainArr[0]; + // setDomainStr(cleanedDomain); - setValue( - 'isWWW', - value.domainName.startsWith('www.') ? 'true' : 'false', - ); - } - }); + // setValue( + // 'isWWW', + // value.domainName.startsWith('www.') ? 'true' : 'false', + // ); + // } + // }); - return () => subscription.unsubscribe(); - }, [watch, setValue]); + // return () => subscription.unsubscribe(); + // }, [watch, setValue]); return (
{ - watch('isWWW') === 'true' - ? navigate(`config?name=www.${domainStr}`) - : navigate(`config?name=${domainStr}`); + onSubmit={handleSubmit((e) => { + navigate(`config?name=${e.domainName}`) })} className="flex flex-col gap-6 w-full" > @@ -80,7 +78,7 @@ const SetupDomain = () => { label="Domain name" /> - {isValid && ( + {/* {isValid && (
Primary domain @@ -99,7 +97,7 @@ const SetupDomain = () => { }. Redirect preferences can be changed later`} />
- )} + )} */}
+ <> + {domains.length == 0 && ( + + )} + } > {domains.map((domain) => { -- 2.45.2 From b5762432e6a7bcda33b8cb83b91514e2e544617d Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Thu, 30 Jan 2025 14:59:12 +0530 Subject: [PATCH 03/59] Remove redirect domain from edit domain form --- .../project/settings/EditDomainDialog.tsx | 89 ++++++++++--------- .../projects/project/settings/SetupDomain.tsx | 2 +- .../org-slug/projects/id/settings/Domains.tsx | 20 ++--- 3 files changed, 59 insertions(+), 52 deletions(-) diff --git a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx index 3607c6b1..45e3a938 100644 --- a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx +++ b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx @@ -1,11 +1,19 @@ -import { useCallback, useEffect, useMemo } from 'react'; -import { Controller, useForm, SubmitHandler } from 'react-hook-form'; +import { + useCallback, + useEffect, + // useMemo +} from 'react'; +import { + // Controller, + useForm, + SubmitHandler, +} from 'react-hook-form'; import { Domain } from 'gql-client'; import { Typography, - Select, - Option, + // Select, + // Option, } from '@snowballtools/material-tailwind-react-fork'; import { useGQLClient } from 'context/GQLClientContext'; @@ -14,7 +22,7 @@ import { Button } from 'components/shared/Button'; import { Input } from 'components/shared/Input'; import { useToast } from 'components/shared/Toast'; -const DEFAULT_REDIRECT_OPTIONS = ['none']; +// const DEFAULT_REDIRECT_OPTIONS = ['none']; interface EditDomainDialogProp { domains: Domain[]; @@ -28,7 +36,7 @@ interface EditDomainDialogProp { type EditDomainValues = { name: string; branch: string; - redirectedTo: string; + // redirectedTo: string; }; const EditDomainDialog = ({ @@ -42,58 +50,58 @@ const EditDomainDialog = ({ const client = useGQLClient(); const { toast, dismiss } = useToast(); - const getRedirectUrl = (domain: Domain) => { - const redirectDomain = domain.redirectTo; + // const getRedirectUrl = (domain: Domain) => { + // const redirectDomain = domain.redirectTo; - if (redirectDomain !== null) { - return redirectDomain?.name; - } else { - return 'none'; - } - }; + // if (redirectDomain !== null) { + // return redirectDomain?.name; + // } else { + // return 'none'; + // } + // }; - const redirectOptions = useMemo(() => { - const domainNames = domains - .filter((domainData) => domainData.id !== domain.id) - .map((domain) => domain.name); - return ['none', ...domainNames]; - }, [domain, domains]); + // const redirectOptions = useMemo(() => { + // const domainNames = domains + // .filter((domainData) => domainData.id !== domain.id) + // .map((domain) => domain.name); + // return ['none', ...domainNames]; + // }, [domain, domains]); - const domainRedirectedFrom = useMemo(() => { - return domains.find( - (domainData) => domainData.redirectTo?.id === domain.id, - ); - }, [domains, domain]); + // const domainRedirectedFrom = useMemo(() => { + // return domains.find( + // (domainData) => domainData.redirectTo?.id === domain.id, + // ); + // }, [domains, domain]); - const isDisableDropdown = useMemo(() => { - return domainRedirectedFrom !== undefined; - }, [domain, domains]); + // const isDisableDropdown = useMemo(() => { + // return domainRedirectedFrom !== undefined; + // }, [domain, domains]); const { handleSubmit, register, - control, - watch, + // control, + // watch, reset, formState: { isValid, isDirty }, } = useForm({ defaultValues: { name: domain.name, branch: domain.branch, - redirectedTo: getRedirectUrl(domain), + // redirectedTo: getRedirectUrl(domain), }, }); const updateDomainHandler: SubmitHandler = useCallback( async (data) => { - const domainRedirectTo = domains.find( - (domainData) => data.redirectedTo === domainData.name, - ); + // const domainRedirectTo = domains.find( + // (domainData) => data.redirectedTo === domainData.name, + // ); const updates = { name: data.name ? data.name : domain.name, branch: data.branch ? data.branch : domain.branch, - redirectToId: domainRedirectTo ? domainRedirectTo.id : null, + // redirectToId: domainRedirectTo ? domainRedirectTo.id : null, }; const { updateDomain } = await client.updateDomain(domain.id, updates); @@ -125,7 +133,7 @@ const EditDomainDialog = ({ reset({ name: domain.name, branch: domain.branch, - redirectedTo: getRedirectUrl(domain), + // redirectedTo: getRedirectUrl(domain), }); }, [domain]); @@ -137,7 +145,7 @@ const EditDomainDialog = ({ Domain name - Redirect to + {/* Redirect to
- )} + )} */} Git branch {!isValid && ( diff --git a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx index e1b5acde..ae157438 100644 --- a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx +++ b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx @@ -65,7 +65,7 @@ const SetupDomain = () => { Setup domain name

- Add your domain and setup redirects + Add your domain {/* and setup redirects */}

diff --git a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx index b4fe6453..39943335 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx @@ -62,17 +62,15 @@ const Domains = () => { headingText="Domains" button={ <> - {domains.length == 0 && ( - - )} + } > -- 2.45.2 From 56eccb48b3bf2771c33543bf2fbc20ba9341101b Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 30 Jan 2025 15:18:28 +0530 Subject: [PATCH 04/59] Add method to fetch DNS data for latest deployment --- packages/backend/src/database.ts | 23 +++++++++++++++++++++++ packages/backend/src/resolvers.ts | 7 +++++++ packages/backend/src/schema.gql | 9 +++++++++ packages/backend/src/service.ts | 5 +++++ packages/gql-client/src/client.ts | 11 +++++++++++ packages/gql-client/src/queries.ts | 12 ++++++++++++ packages/gql-client/src/types.ts | 8 ++++++++ 7 files changed, 75 insertions(+) diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts index 6499b0e1..d91f2ec4 100644 --- a/packages/backend/src/database.ts +++ b/packages/backend/src/database.ts @@ -24,6 +24,7 @@ import { Domain } from './entity/Domain'; import { getEntities, loadAndSaveData } from './utils'; import { UserOrganization } from './entity/UserOrganization'; import { Deployer } from './entity/Deployer'; +import { DNSRecordAttributes } from './types'; const ORGANIZATION_DATA_PATH = '../test/fixtures/organizations.json'; @@ -602,6 +603,28 @@ export class Database { return domains; } + async getLatestDNSDataByProjectId( + projectId: string, + ): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment); + + const deployment = await deploymentRepository.findOne({ + where: { + project: { + id: projectId + }, + }, order: { + createdAt: "DESC", + }, + }); + + if (deployment === null) { + throw new Error(`Error finding DNS data for project with id ${projectId}`); + } + + return deployment.dnsRecordData; + } + async addDeployer(data: DeepPartial): Promise { const deployerRepository = this.dataSource.getRepository(Deployer); const newDomain = await deployerRepository.save(data); diff --git a/packages/backend/src/resolvers.ts b/packages/backend/src/resolvers.ts index e20b7e0c..e21a9d70 100644 --- a/packages/backend/src/resolvers.ts +++ b/packages/backend/src/resolvers.ts @@ -95,6 +95,13 @@ export const createResolvers = async (service: Service): Promise => { ) => { return service.verifyTx(txHash, amount, senderAddress); }, + + getLatestDNSDataByProjectId: async ( + _: any, + { projectId }: { projectId: string }, + ) => { + return service.getLatestDNSDataByProjectId(projectId); + }, }, // TODO: Return error in GQL response diff --git a/packages/backend/src/schema.gql b/packages/backend/src/schema.gql index ff51098a..cf4db3b4 100644 --- a/packages/backend/src/schema.gql +++ b/packages/backend/src/schema.gql @@ -249,6 +249,14 @@ type Auction { bids: [Bid!]! } +type DNSRecordAttributes { + name: string; + value: string; + request: string; + resourceType: string; + version: string; +} + input AuctionParams { maxPrice: String, numProviders: Int, @@ -265,6 +273,7 @@ type Query { projectMembers(projectId: String!): [ProjectMember!] searchProjects(searchText: String!): [Project!] getAuctionData(auctionId: String!): Auction! + getLatestDNSDataByProjectId(projectId: String!): DNSRecordAttributes domains(projectId: String!, filter: FilterDomainsInput): [Domain] deployers: [Deployer] address: String! diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 80e49874..d59052d6 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -447,6 +447,11 @@ export class Service { return dbDeployments; } + async getLatestDNSDataByProjectId(projectId: string): Promise { + const dbDeployments = await this.db.getLatestDNSDataByProjectId(projectId); + return dbDeployments; + } + async getEnvironmentVariablesByProjectId( projectId: string, ): Promise { diff --git a/packages/gql-client/src/client.ts b/packages/gql-client/src/client.ts index c915dde9..1c84a14a 100644 --- a/packages/gql-client/src/client.ts +++ b/packages/gql-client/src/client.ts @@ -453,4 +453,15 @@ export class GQLClient { return data.verifyTx; } + + async getLatestDNSDataByProjectId(projectId: string): Promise { + const { data } = await this.client.query({ + query: queries.getLatestDNSDataByProjectId, + variables: { + projectId, + }, + }); + + return data.dnsRecordData; + } } diff --git a/packages/gql-client/src/queries.ts b/packages/gql-client/src/queries.ts index 48760dbd..d982b276 100644 --- a/packages/gql-client/src/queries.ts +++ b/packages/gql-client/src/queries.ts @@ -343,3 +343,15 @@ query ($txHash: String!, $amount: String!, $senderAddress: String!) { verifyTx(txHash: $txHash, amount: $amount, senderAddress: $senderAddress) } `; + +export const getLatestDNSDataByProjectId = gql` +query($projectId: String!) { + dnsRecordData(projectId: $projectId) { + name + value + request + resourceType + version + } +} +`; diff --git a/packages/gql-client/src/types.ts b/packages/gql-client/src/types.ts index 3c690fc6..c6715af5 100644 --- a/packages/gql-client/src/types.ts +++ b/packages/gql-client/src/types.ts @@ -376,3 +376,11 @@ export type AuctionParams = { maxPrice: string; numProviders: number; }; + +export type DNSRecordAttributes = { + name: string; + value: string; + request: string; + resourceType: string; + version: string; +} -- 2.45.2 From 5d9c965f545b0b52ed54a286bc84296e6b946e9f Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Thu, 30 Jan 2025 16:10:03 +0530 Subject: [PATCH 05/59] Show service provider IP address while creating custom domain --- packages/backend/src/schema.gql | 10 +++--- .../projects/project/settings/DomainCard.tsx | 27 ++++++++++++++-- .../id/settings/domains/add/Config.tsx | 31 ++++++++++++++----- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/packages/backend/src/schema.gql b/packages/backend/src/schema.gql index cf4db3b4..0e78a25e 100644 --- a/packages/backend/src/schema.gql +++ b/packages/backend/src/schema.gql @@ -250,11 +250,11 @@ type Auction { } type DNSRecordAttributes { - name: string; - value: string; - request: string; - resourceType: string; - version: string; + name: String + value: String + request: String + resourceType: String + version: String } input AuctionParams { diff --git a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx index 28775e96..6edbc4d4 100644 --- a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx +++ b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { Domain, DomainStatus, Project } from 'gql-client'; import { @@ -23,6 +23,7 @@ import { } from 'components/shared/CustomIcon'; import { Heading } from 'components/shared/Heading'; import { Button } from 'components/shared/Button'; +import { useParams } from 'react-router-dom'; enum RefreshStatus { IDLE, @@ -56,9 +57,11 @@ const DomainCard = ({ onUpdate, }: DomainCardProps) => { const { toast, dismiss } = useToast(); + const { id } = useParams(); const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false); + const [IPAddress, setIPAddress] = useState(); const client = useGQLClient(); @@ -83,6 +86,26 @@ const DomainCard = ({ } }; + useEffect(() => { + const fetchDNSData = async () => { + if (id === undefined) { + toast({ + id: 'domain_cannot_find_project', + title: 'Cannot find project', + variant: 'error', + onDismiss: dismiss, + }); + return; + } + + const dnsData = await client.getLatestDNSDataByProjectId(id); + + setIPAddress(dnsData.value); + }; + + fetchDNSData(); + }, [id, client]); + return ( <>
@@ -192,7 +215,7 @@ const DomainCard = ({ {DOMAIN_RECORD.type} {DOMAIN_RECORD.name} - {DOMAIN_RECORD.value} + {IPAddress} diff --git a/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx b/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx index d3419c06..bbfe7888 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx @@ -7,6 +7,7 @@ import { InlineNotification } from 'components/shared/InlineNotification'; import { ArrowRightCircleIcon } from 'components/shared/CustomIcon'; import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer'; import { useToast } from 'components/shared/Toast'; +import { useEffect, useState } from 'react'; const Config = () => { const { id, orgSlug } = useParams(); @@ -16,6 +17,8 @@ const Config = () => { const primaryDomainName = searchParams.get('name'); const { toast, dismiss } = useToast(); + const [IPAddress, setIPAddress] = useState(); + const handleSubmitDomain = async () => { if (primaryDomainName === null) { toast({ @@ -59,6 +62,26 @@ const Config = () => { } }; + useEffect(() => { + const fetchDNSData = async () => { + if (id === undefined) { + toast({ + id: 'domain_cannot_find_project', + title: 'Cannot find project', + variant: 'error', + onDismiss: dismiss, + }); + return; + } + + const dnsData = await client.getLatestDNSDataByProjectId(id); + + setIPAddress(dnsData.value); + }; + + fetchDNSData(); + }, [id, client]); + // TODO: Figure out DNS Provider if possible and update appropriatly return ( @@ -79,13 +102,7 @@ const Config = () => { A @ - IP.OF.THE.SP - - - - CNAME - subdomain - domain.of.the.sp + {IPAddress} -- 2.45.2 From 82c4b716943c743d48ebe892e07a32ab2ecd542d Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Thu, 30 Jan 2025 16:13:28 +0530 Subject: [PATCH 06/59] Use oldest custom domain in deployment requests --- packages/backend/src/database.ts | 19 +++++++++++++++++++ packages/backend/src/service.ts | 10 +++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts index d91f2ec4..d35f1fad 100644 --- a/packages/backend/src/database.ts +++ b/packages/backend/src/database.ts @@ -603,6 +603,25 @@ export class Database { return domains; } + async getOldestDomainByProjectId( + projectId: string, + ): Promise { + const domainRepository = this.dataSource.getRepository(Domain); + + const domains = await domainRepository.find({ + where: { + project: { + id: projectId + }, + }, + order: { + createdAt: 'ASC' + } + }); + + return domains; + } + async getLatestDNSDataByProjectId( projectId: string, ): Promise { diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index d59052d6..bd14804b 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -663,6 +663,14 @@ export class Service { const address = await this.getAddress(); const { repo, repoUrl } = await getRepoDetails(octokit, data.project.repository, data.commitHash); const environmentVariablesObj = await this.getEnvVariables(data.project!.id!); + + // If a custom domain is present then use that as the DNS in the deployment request + const domain = await this.db.getOldestDomainByProjectId(data.projectId!); + let dns: string | undefined = undefined; + if (domain) { + dns = domain[0].name; + } + // To set project DNS if (data.environment === Environment.Production) { // On deleting deployment later, project DNS deployment is also deleted @@ -690,7 +698,7 @@ export class Service { lrn: deployer!.deployerLrn!, apiUrl: deployer!.deployerApiUrl!, environmentVariables: environmentVariablesObj, - dns: `${newDeployment.project.name}-${newDeployment.id}`, + dns: dns || `${newDeployment.project.name}-${newDeployment.id}`, payment: data.project.txHash, auctionId: data.project.auctionId, requesterAddress: address, -- 2.45.2 From 624f36155afbb57ad7a23dcbe2886af931e32f95 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Thu, 30 Jan 2025 17:11:18 +0530 Subject: [PATCH 07/59] Fix deploy button disabled for deployers with no min payment --- packages/frontend/src/components/projects/create/Configure.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/projects/create/Configure.tsx b/packages/frontend/src/components/projects/create/Configure.tsx index 98675186..66a9c60a 100644 --- a/packages/frontend/src/components/projects/create/Configure.tsx +++ b/packages/frontend/src/components/projects/create/Configure.tsx @@ -566,7 +566,7 @@ const Configure = () => {
- )} + )} */} -- 2.45.2 From a7190ed804f31b6409e83f5cc31bdb0489c7899f Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Fri, 31 Jan 2025 10:30:46 +0530 Subject: [PATCH 13/59] Show custom domain in overview tabs panel --- packages/backend/src/database.ts | 6 +++--- packages/backend/src/resolvers.ts | 12 +++++++++++ packages/backend/src/schema.gql | 1 + packages/backend/src/service.ts | 8 +++++++- .../pages/org-slug/projects/id/Overview.tsx | 20 +++++++++++++++++-- packages/gql-client/src/client.ts | 15 ++++++++++++++ packages/gql-client/src/queries.ts | 13 ++++++++++++ packages/gql-client/src/types.ts | 4 ++++ 8 files changed, 73 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts index 68d5bd3c..fa8b1c99 100644 --- a/packages/backend/src/database.ts +++ b/packages/backend/src/database.ts @@ -605,10 +605,10 @@ export class Database { async getOldestDomainByProjectId( projectId: string, - ): Promise { + ): Promise { const domainRepository = this.dataSource.getRepository(Domain); - const domains = await domainRepository.find({ + const domain = await domainRepository.findOne({ where: { project: { id: projectId @@ -619,7 +619,7 @@ export class Database { } }); - return domains; + return domain; } async getLatestDNSDataByProjectId( diff --git a/packages/backend/src/resolvers.ts b/packages/backend/src/resolvers.ts index e21a9d70..a34c5f58 100644 --- a/packages/backend/src/resolvers.ts +++ b/packages/backend/src/resolvers.ts @@ -70,6 +70,18 @@ export const createResolvers = async (service: Service): Promise => { return service.getDomainsByProjectId(projectId, filter); }, + oldestDomain: async ( + _: any, + { projectId }: { projectId: string }, + ) => { + try { + return await service.getOldestDomainByProjectId(projectId); + } catch (err) { + log(err); + return false; + } + }, + getAuctionData: async ( _: any, { auctionId }: { auctionId: string }, diff --git a/packages/backend/src/schema.gql b/packages/backend/src/schema.gql index 0e78a25e..dca39278 100644 --- a/packages/backend/src/schema.gql +++ b/packages/backend/src/schema.gql @@ -274,6 +274,7 @@ type Query { searchProjects(searchText: String!): [Project!] getAuctionData(auctionId: String!): Auction! getLatestDNSDataByProjectId(projectId: String!): DNSRecordAttributes + oldestDomain(projectId: String!): Domain domains(projectId: String!, filter: FilterDomainsInput): [Domain] deployers: [Deployer] address: String! diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 5198f6b3..0df4c829 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -674,7 +674,7 @@ export class Service { appName: repo, repository: repoUrl, environmentVariables: environmentVariablesObj, - dns: domain?.[0]?.name ?? `${newDeployment.project.name}`, + dns: domain?.name ?? `${newDeployment.project.name}`, lrn: deployer!.deployerLrn!, apiUrl: deployer!.deployerApiUrl!, payment: data.project.txHash, @@ -1342,6 +1342,12 @@ export class Service { return updateResult; } + async getOldestDomainByProjectId( + projectId: string, + ): Promise { + return await this.db.getOldestDomainByProjectId(projectId) + } + async authenticateGitHub( code: string, user: User, diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index 7732a6e6..7abc0b91 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -32,6 +32,7 @@ const OverviewTabPanel = () => { const [activities, setActivities] = useState([]); const [fetchingActivities, setFetchingActivities] = useState(true); const [liveDomain, setLiveDomain] = useState(); + const [customDomain, setCustomDomain] = useState(null); const client = useGQLClient(); const { project, onUpdate } = useOutletContext(); @@ -124,6 +125,16 @@ const OverviewTabPanel = () => { fetchLiveProdDomain(); }, [project]); + useEffect(() => { + const fetchCustomDomain = async () => { + const { oldestDomain } = await client.oldestDomain(project.id); + + setCustomDomain(oldestDomain); + }; + + fetchCustomDomain(); + }, [project]); + return (
@@ -194,10 +205,15 @@ const OverviewTabPanel = () => { project.deployments.map((deployment) => (
- {`https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`} + {customDomain?.name ?? + `https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`} diff --git a/packages/gql-client/src/client.ts b/packages/gql-client/src/client.ts index 8432da7b..c5deab4e 100644 --- a/packages/gql-client/src/client.ts +++ b/packages/gql-client/src/client.ts @@ -393,6 +393,21 @@ export class GQLClient { return data; } + async oldestDomain( + projectId: string, + ): Promise { + const { data } = await this.client.query({ + query: queries.oldestDomain, + variables: { + projectId, + }, + }); + + console.log({data}) + + return data; + } + async authenticateGitHub( code: string ): Promise { diff --git a/packages/gql-client/src/queries.ts b/packages/gql-client/src/queries.ts index 592bdca8..23b83032 100644 --- a/packages/gql-client/src/queries.ts +++ b/packages/gql-client/src/queries.ts @@ -261,6 +261,19 @@ query ($projectId: String!, $filter: FilterDomainsInput) { } `; +export const oldestDomain = gql` +query ($projectId: String!) { + oldestDomain(projectId: $projectId) { + branch + createdAt + id + name + status + updatedAt + } +} +` + export const getAuctionData = gql` query ($auctionId: String!) { getAuctionData(auctionId: $auctionId){ diff --git a/packages/gql-client/src/types.ts b/packages/gql-client/src/types.ts index c6715af5..7c5414bd 100644 --- a/packages/gql-client/src/types.ts +++ b/packages/gql-client/src/types.ts @@ -236,6 +236,10 @@ export type GetDomainsResponse = { domains: Domain[]; }; +export type OldestDomainResponse = { + oldestDomain: Domain | null; +} + export type GetDeployersResponse = { deployers: Deployer[]; }; -- 2.45.2 From 55500b59143110751f89005177b9857683215723 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Fri, 31 Jan 2025 10:41:53 +0530 Subject: [PATCH 14/59] Display custom domain in project card --- .../projects/ProjectCard/ProjectCard.tsx | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx index c7798279..0f29e572 100644 --- a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx +++ b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx @@ -4,9 +4,15 @@ import { MenuItem, MenuList, } from '@snowballtools/material-tailwind-react-fork'; -import { ComponentPropsWithoutRef, MouseEvent, useCallback } from 'react'; +import { + ComponentPropsWithoutRef, + MouseEvent, + useCallback, + useEffect, + useState, +} from 'react'; import { useNavigate } from 'react-router-dom'; -import { Project } from 'gql-client'; +import { Domain, Project } from 'gql-client'; import { Avatar } from 'components/shared/Avatar'; import { Button } from 'components/shared/Button'; import { @@ -21,6 +27,7 @@ import { WavyBorder } from 'components/shared/WavyBorder'; import { relativeTimeMs } from 'utils/time'; import { getInitials } from 'utils/geInitials'; import { ProjectCardTheme, projectCardTheme } from './ProjectCard.theme'; +import { useGQLClient } from 'context/GQLClientContext'; export interface ProjectCardProps extends ComponentPropsWithoutRef<'div'>, @@ -42,6 +49,9 @@ export const ProjectCard = ({ const hasError = status === 'failure'; const navigate = useNavigate(); + const client = useGQLClient(); + + const [customDomain, setCustomDomain] = useState(null); const handleOptionsClick = ( e: MouseEvent, @@ -63,6 +73,16 @@ export const ProjectCard = ({ [project.id, navigate], ); + useEffect(() => { + const fetchCustomDomain = async () => { + const { oldestDomain } = await client.oldestDomain(project.id); + + setCustomDomain(oldestDomain); + }; + + fetchCustomDomain(); + }, [project]); + return (
{project.name}

- {project.deployments[0]?.domain?.name ?? 'No domain'} + {customDomain && customDomain.name ? customDomain.name : 'No domain'}

{/* Icons */} -- 2.45.2 From 13892015a5ae87b9f14fba525f2365417ec07aa9 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 31 Jan 2025 12:50:15 +0530 Subject: [PATCH 15/59] Store DNS deployment records data in Deployment entity --- packages/backend/src/entity/Deployment.ts | 9 ++++ packages/backend/src/registry.ts | 16 +++--- packages/backend/src/service.ts | 63 ++++++++++++----------- 3 files changed, 51 insertions(+), 37 deletions(-) diff --git a/packages/backend/src/entity/Deployment.ts b/packages/backend/src/entity/Deployment.ts index 021cfc75..f1477f1a 100644 --- a/packages/backend/src/entity/Deployment.ts +++ b/packages/backend/src/entity/Deployment.ts @@ -105,15 +105,24 @@ export class Deployment { @Column('varchar', { nullable: true }) applicationDeploymentRequestId!: string | null; + @Column('varchar', { nullable: true }) + dnsDeploymentRequestId!: string | null; + @Column('simple-json', { nullable: true }) applicationDeploymentRequestData!: ApplicationDeploymentRequest | null; @Column('varchar', { nullable: true }) applicationDeploymentRecordId!: string | null; + @Column('varchar', { nullable: true }) + dnsDeploymentRecordId!: string | null; + @Column('simple-json', { nullable: true }) applicationDeploymentRecordData!: AppDeploymentRecordAttributes | null; + @Column('simple-json', { nullable: true }) + dnsDeploymentRecordData!: AppDeploymentRecordAttributes | null; + @Column('varchar', { nullable: true }) applicationDeploymentRemovalRequestId!: string | null; diff --git a/packages/backend/src/registry.ts b/packages/backend/src/registry.ts index 664f34d1..66f4840f 100644 --- a/packages/backend/src/registry.ts +++ b/packages/backend/src/registry.ts @@ -387,8 +387,8 @@ export class Registry { return records.filter((record: AppDeploymentRecord) => deployments.some( (deployment) => - deployment.applicationDeploymentRequestId === record.attributes.request && - record.attributes.url.includes(deployment.id) + deployment.applicationDeploymentRequestId === record.attributes.request || + deployment.dnsDeploymentRequestId === record.attributes.request ) ); } @@ -443,12 +443,12 @@ export class Registry { ); } - /** - * Fetch deployment DNS Records by Id - */ - async getDNSRecordsById(id: string): Promise { - return this.registry.getRecordsByIds([id]); - } + /** + * Fetch deployment DNS record by Id + */ + async getDNSRecordById(id: string): Promise { + return this.registry.getRecordsByIds([id]); + } async createApplicationDeploymentRemovalRequest(data: { deploymentId: string; diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 0df4c829..656781d8 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -185,23 +185,28 @@ export class Service { }, }); - const recordToDeploymentsMap = deployments.reduce( - (acc: { [key: string]: Deployment }, deployment) => { - acc[deployment.applicationDeploymentRequestId!] = deployment; + const requestIdToRecordsMap = records.reduce( + (acc: { [key: string]: AppDeploymentRecord }, record) => { + acc[record.attributes.request] = record; return acc; }, {}, ); // Update deployment data for ApplicationDeploymentRecords - const deploymentUpdatePromises = records.map(async (record) => { - const deployment = recordToDeploymentsMap[record.attributes.request]; + const deploymentUpdatePromises = deployments.map(async (deployment) => { + const applicationDeploymentRecord = requestIdToRecordsMap[deployment.applicationDeploymentRequestId!] + const dnsDeploymentRecord = requestIdToRecordsMap[deployment.dnsDeploymentRequestId!] + + if (!applicationDeploymentRecord || !dnsDeploymentRecord) { + return; + } if (!deployment.project) { log(`Project ${deployment.projectId} not found`); return; } else { - const dnsRecords = await this.laconicRegistry.getDNSRecordsById(record.attributes.dns); + const dnsRecords = await this.laconicRegistry.getDNSRecordById(applicationDeploymentRecord.attributes.dns); const dnsRecordData: DNSRecordAttributes = { name: dnsRecords[0].attributes.name, @@ -211,9 +216,11 @@ export class Service { version: dnsRecords[0].attributes.version, } - deployment.applicationDeploymentRecordId = record.id; - deployment.applicationDeploymentRecordData = record.attributes; - deployment.url = record.attributes.url; + deployment.applicationDeploymentRecordId = applicationDeploymentRecord.id; + deployment.dnsDeploymentRecordId = dnsDeploymentRecord.id; + deployment.applicationDeploymentRecordData = applicationDeploymentRecord.attributes; + deployment.dnsDeploymentRecordData = dnsDeploymentRecord.attributes; + deployment.url = applicationDeploymentRecord.attributes.url; deployment.status = DeploymentStatus.Ready; deployment.isCurrent = deployment.environment === Environment.Production; deployment.dnsRecordData = dnsRecordData; @@ -233,30 +240,25 @@ export class Service { } log( - `Updated deployment ${deployment.id} with URL ${record.attributes.url}`, + `Updated deployment ${deployment.id} with URL ${applicationDeploymentRecord.attributes.url}`, ); } + + // Set the isCurrent state to false for the old deployments + if (deployment.isCurrent) { + const projectDeployments = await this.db.getDeploymentsByProjectId(deployment.projectId); + const oldDeployments = projectDeployments + .filter(projectDeployment => projectDeployment.deployer.deployerLrn === deployment.deployer.deployerLrn && projectDeployment.id !== deployment.id); + for (const oldDeployment of oldDeployments) { + await this.db.updateDeployment( + { id: oldDeployment.id }, + { isCurrent: false } + ); + } + } }); await Promise.all(deploymentUpdatePromises); - - // Get deployments that are in production environment - const prodDeployments = Object.values(recordToDeploymentsMap).filter(deployment => deployment.isCurrent); - - // Set the isCurrent state to false for the old deployments - for (const deployment of prodDeployments) { - const projectDeployments = await this.db.getDeploymentsByProjectId(deployment.projectId); - const oldDeployments = projectDeployments - .filter(projectDeployment => projectDeployment.deployer.deployerLrn === deployment.deployer.deployerLrn && projectDeployment.id !== deployment.id); - for (const oldDeployment of oldDeployments) { - await this.db.updateDeployment( - { id: oldDeployment.id }, - { isCurrent: false } - ); - } - } - - await Promise.all(deploymentUpdatePromises); } /** @@ -666,10 +668,11 @@ export class Service { const domain = await this.db.getOldestDomainByProjectId(data.project!.id!); // To set project DNS + let dnsDeploymentRequestId = null; if (data.environment === Environment.Production) { // On deleting deployment later, project DNS deployment is also deleted // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later - await this.laconicRegistry.createApplicationDeploymentRequest({ + const dnsRequest = await this.laconicRegistry.createApplicationDeploymentRequest({ deployment: newDeployment, appName: repo, repository: repoUrl, @@ -682,6 +685,7 @@ export class Service { requesterAddress: address, publicKey: deployer!.publicKey! }); + dnsDeploymentRequestId = dnsRequest.applicationDeploymentRequestId; } const { applicationDeploymentRequestId, applicationDeploymentRequestData } = @@ -702,6 +706,7 @@ export class Service { await this.db.updateDeploymentById(newDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData, + dnsDeploymentRequestId }); return newDeployment; -- 2.45.2 From 6df685831f5d175a71374ed5b417b440ee61ab48 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Fri, 31 Jan 2025 12:52:19 +0530 Subject: [PATCH 16/59] Populate domainId while creating deployment --- packages/backend/src/service.ts | 3 ++- .../projects/ProjectCard/ProjectCard.tsx | 20 ++----------------- .../pages/org-slug/projects/id/Overview.tsx | 17 +++------------- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 656781d8..e65fd032 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -706,7 +706,8 @@ export class Service { await this.db.updateDeploymentById(newDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData, - dnsDeploymentRequestId + dnsDeploymentRequestId, + domainId: domain?.id ?? null }); return newDeployment; diff --git a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx index 0f29e572..3312834a 100644 --- a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx +++ b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx @@ -8,11 +8,9 @@ import { ComponentPropsWithoutRef, MouseEvent, useCallback, - useEffect, - useState, } from 'react'; import { useNavigate } from 'react-router-dom'; -import { Domain, Project } from 'gql-client'; +import { Project } from 'gql-client'; import { Avatar } from 'components/shared/Avatar'; import { Button } from 'components/shared/Button'; import { @@ -27,7 +25,6 @@ import { WavyBorder } from 'components/shared/WavyBorder'; import { relativeTimeMs } from 'utils/time'; import { getInitials } from 'utils/geInitials'; import { ProjectCardTheme, projectCardTheme } from './ProjectCard.theme'; -import { useGQLClient } from 'context/GQLClientContext'; export interface ProjectCardProps extends ComponentPropsWithoutRef<'div'>, @@ -49,9 +46,6 @@ export const ProjectCard = ({ const hasError = status === 'failure'; const navigate = useNavigate(); - const client = useGQLClient(); - - const [customDomain, setCustomDomain] = useState(null); const handleOptionsClick = ( e: MouseEvent, @@ -73,16 +67,6 @@ export const ProjectCard = ({ [project.id, navigate], ); - useEffect(() => { - const fetchCustomDomain = async () => { - const { oldestDomain } = await client.oldestDomain(project.id); - - setCustomDomain(oldestDomain); - }; - - fetchCustomDomain(); - }, [project]); - return (
{project.name}

- {customDomain && customDomain.name ? customDomain.name : 'No domain'} + {project.deployments[0]?.domain?.name ?? 'No domain'}

{/* Icons */} diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index 7abc0b91..170661e3 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -32,7 +32,6 @@ const OverviewTabPanel = () => { const [activities, setActivities] = useState([]); const [fetchingActivities, setFetchingActivities] = useState(true); const [liveDomain, setLiveDomain] = useState(); - const [customDomain, setCustomDomain] = useState(null); const client = useGQLClient(); const { project, onUpdate } = useOutletContext(); @@ -125,16 +124,6 @@ const OverviewTabPanel = () => { fetchLiveProdDomain(); }, [project]); - useEffect(() => { - const fetchCustomDomain = async () => { - const { oldestDomain } = await client.oldestDomain(project.id); - - setCustomDomain(oldestDomain); - }; - - fetchCustomDomain(); - }, [project]); - return (
@@ -206,13 +195,13 @@ const OverviewTabPanel = () => {
- {customDomain?.name ?? + {deployment.domain.name ?? `https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`} -- 2.45.2 From 1a5ab4d47e3d1bb0ffaee6640c116a16595aa71e Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Fri, 31 Jan 2025 14:40:59 +0530 Subject: [PATCH 17/59] Remove showing domain status in overview pannel --- .../pages/org-slug/projects/id/Overview.tsx | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index 170661e3..c6001b85 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -1,26 +1,35 @@ import { useEffect, useState } from 'react'; -import { Link, useNavigate, useOutletContext } from 'react-router-dom'; +import { + Link, + // useNavigate, + useOutletContext +} from 'react-router-dom'; import { RequestError } from 'octokit'; import { useOctokit } from 'context/OctokitContext'; import { GitCommitWithBranch, OutletContextType } from '../../../../types'; -import { useGQLClient } from 'context/GQLClientContext'; -import { Button, Heading, Avatar, Tag } from 'components/shared'; +// import { useGQLClient } from 'context/GQLClientContext'; +import { + // Button, + Heading, + Avatar, + // Tag +} from 'components/shared'; import { getInitials } from 'utils/geInitials'; import { BranchStrokeIcon, - CheckRoundFilledIcon, - ClockIcon, + // CheckRoundFilledIcon, + // ClockIcon, CursorBoxIcon, GithubStrokeIcon, - GlobeIcon, + // GlobeIcon, LinkIcon, CalendarDaysIcon, } from 'components/shared/CustomIcon'; import { Activity } from 'components/projects/project/overview/Activity'; import { OverviewInfo } from 'components/projects/project/overview/OverviewInfo'; import { relativeTimeMs } from 'utils/time'; -import { Domain, DomainStatus } from 'gql-client'; +// import { Domain, DomainStatus } from 'gql-client'; import { AuctionCard } from 'components/projects/project/overview/Activity/AuctionCard'; const COMMITS_PER_PAGE = 4; @@ -28,12 +37,12 @@ const PROJECT_UPDATE_WAIT_MS = 5000; const OverviewTabPanel = () => { const { octokit } = useOctokit(); - const navigate = useNavigate(); + // const navigate = useNavigate(); const [activities, setActivities] = useState([]); const [fetchingActivities, setFetchingActivities] = useState(true); - const [liveDomain, setLiveDomain] = useState(); + // const [liveDomain, setLiveDomain] = useState(); - const client = useGQLClient(); + // const client = useGQLClient(); const { project, onUpdate } = useOutletContext(); useEffect(() => { @@ -107,22 +116,22 @@ const OverviewTabPanel = () => { return () => clearInterval(timerId); }, [onUpdate]); - useEffect(() => { - const fetchLiveProdDomain = async () => { - const { domains } = await client.getDomains(project.id, { - branch: project.prodBranch, - status: DomainStatus.Live, - }); + // useEffect(() => { + // const fetchLiveProdDomain = async () => { + // const { domains } = await client.getDomains(project.id, { + // branch: project.prodBranch, + // status: DomainStatus.Live, + // }); - if (domains.length === 0) { - return; - } + // if (domains.length === 0) { + // return; + // } - setLiveDomain(domains[0]); - }; + // setLiveDomain(domains[0]); + // }; - fetchLiveProdDomain(); - }, [project]); + // fetchLiveProdDomain(); + // }, [project]); return (
@@ -153,7 +162,7 @@ const OverviewTabPanel = () => { ))}
- }> + {/* }> {liveDomain ? ( }> Connected @@ -174,7 +183,7 @@ const OverviewTabPanel = () => {
)} - + */} {project.deployments.length !== 0 ? ( <> {/* SOURCE */} @@ -195,13 +204,13 @@ const OverviewTabPanel = () => {
- {deployment.domain.name ?? + {deployment.domain?.name ?? `https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`} -- 2.45.2 From 6e8af82dc2910dcf8aaec097941a8e26f99fdf9e Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Fri, 31 Jan 2025 15:16:59 +0530 Subject: [PATCH 18/59] Make service provider domains non clickable --- packages/frontend/src/pages/org-slug/projects/id/Overview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index c6001b85..ac47fee9 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -153,7 +153,7 @@ const OverviewTabPanel = () => {

{deployment.deployer.baseDomain} -- 2.45.2 From 5be10b6b0ad3a8ea38e02906710548f0cdd987fa Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 31 Jan 2025 15:37:31 +0530 Subject: [PATCH 19/59] Implement functionality to store DNS deployment --- packages/backend/src/entity/Deployment.ts | 12 +- packages/backend/src/registry.ts | 4 +- packages/backend/src/service.ts | 159 +++++++++++++--------- 3 files changed, 98 insertions(+), 77 deletions(-) diff --git a/packages/backend/src/entity/Deployment.ts b/packages/backend/src/entity/Deployment.ts index f1477f1a..8a5aa6b8 100644 --- a/packages/backend/src/entity/Deployment.ts +++ b/packages/backend/src/entity/Deployment.ts @@ -105,24 +105,15 @@ export class Deployment { @Column('varchar', { nullable: true }) applicationDeploymentRequestId!: string | null; - @Column('varchar', { nullable: true }) - dnsDeploymentRequestId!: string | null; - @Column('simple-json', { nullable: true }) applicationDeploymentRequestData!: ApplicationDeploymentRequest | null; @Column('varchar', { nullable: true }) applicationDeploymentRecordId!: string | null; - @Column('varchar', { nullable: true }) - dnsDeploymentRecordId!: string | null; - @Column('simple-json', { nullable: true }) applicationDeploymentRecordData!: AppDeploymentRecordAttributes | null; - @Column('simple-json', { nullable: true }) - dnsDeploymentRecordData!: AppDeploymentRecordAttributes | null; - @Column('varchar', { nullable: true }) applicationDeploymentRemovalRequestId!: string | null; @@ -150,6 +141,9 @@ export class Deployment { @Column('boolean', { default: false }) isCurrent!: boolean; + @Column('boolean', { default: false }) + isDNS!: boolean; + @Column({ enum: DeploymentStatus }) diff --git a/packages/backend/src/registry.ts b/packages/backend/src/registry.ts index 66f4840f..ec9d433b 100644 --- a/packages/backend/src/registry.ts +++ b/packages/backend/src/registry.ts @@ -387,8 +387,8 @@ export class Registry { return records.filter((record: AppDeploymentRecord) => deployments.some( (deployment) => - deployment.applicationDeploymentRequestId === record.attributes.request || - deployment.dnsDeploymentRequestId === record.attributes.request + deployment.applicationDeploymentRequestId === record.attributes.request && + record.attributes.url.includes(deployment.id) ) ); } diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index e65fd032..d905e36f 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -185,28 +185,23 @@ export class Service { }, }); - const requestIdToRecordsMap = records.reduce( - (acc: { [key: string]: AppDeploymentRecord }, record) => { - acc[record.attributes.request] = record; + const recordToDeploymentsMap = deployments.reduce( + (acc: { [key: string]: Deployment }, deployment) => { + acc[deployment.applicationDeploymentRequestId!] = deployment; return acc; }, {}, ); // Update deployment data for ApplicationDeploymentRecords - const deploymentUpdatePromises = deployments.map(async (deployment) => { - const applicationDeploymentRecord = requestIdToRecordsMap[deployment.applicationDeploymentRequestId!] - const dnsDeploymentRecord = requestIdToRecordsMap[deployment.dnsDeploymentRequestId!] - - if (!applicationDeploymentRecord || !dnsDeploymentRecord) { - return; - } + const deploymentUpdatePromises = records.map(async (record) => { + const deployment = recordToDeploymentsMap[record.attributes.request]; if (!deployment.project) { log(`Project ${deployment.projectId} not found`); return; } else { - const dnsRecords = await this.laconicRegistry.getDNSRecordById(applicationDeploymentRecord.attributes.dns); + const dnsRecords = await this.laconicRegistry.getDNSRecordById(record.attributes.dns); const dnsRecordData: DNSRecordAttributes = { name: dnsRecords[0].attributes.name, @@ -216,15 +211,29 @@ export class Service { version: dnsRecords[0].attributes.version, } - deployment.applicationDeploymentRecordId = applicationDeploymentRecord.id; - deployment.dnsDeploymentRecordId = dnsDeploymentRecord.id; - deployment.applicationDeploymentRecordData = applicationDeploymentRecord.attributes; - deployment.dnsDeploymentRecordData = dnsDeploymentRecord.attributes; - deployment.url = applicationDeploymentRecord.attributes.url; + deployment.applicationDeploymentRecordId = record.id; + deployment.applicationDeploymentRecordData = record.attributes; + deployment.url = record.attributes.url; deployment.status = DeploymentStatus.Ready; deployment.isCurrent = deployment.environment === Environment.Production; deployment.dnsRecordData = dnsRecordData; + if (deployment.isDNS) { + // Delete previous DNS deployment + const oldDNSDeployment = await this.db.getDeployment({ + where: { + projectId: deployment.project.id, + deployer: deployment.deployer, + isDNS: true, + isCurrent: true, + } + }); + + if (oldDNSDeployment) { + await this.db.deleteDeploymentById(oldDNSDeployment.id); + } + } + await this.db.updateDeploymentById(deployment.id, deployment); // Release deployer funds on successful deployment @@ -240,25 +249,27 @@ export class Service { } log( - `Updated deployment ${deployment.id} with URL ${applicationDeploymentRecord.attributes.url}`, + `Updated deployment ${deployment.id} with URL ${record.attributes.url}`, ); } - - // Set the isCurrent state to false for the old deployments - if (deployment.isCurrent) { - const projectDeployments = await this.db.getDeploymentsByProjectId(deployment.projectId); - const oldDeployments = projectDeployments - .filter(projectDeployment => projectDeployment.deployer.deployerLrn === deployment.deployer.deployerLrn && projectDeployment.id !== deployment.id); - for (const oldDeployment of oldDeployments) { - await this.db.updateDeployment( - { id: oldDeployment.id }, - { isCurrent: false } - ); - } - } }); await Promise.all(deploymentUpdatePromises); + + // Get deployments that are in production environment + const prodDeployments = Object.values(recordToDeploymentsMap).filter(deployment => deployment.isCurrent); + // Set the isCurrent state to false for the old deployments + for (const deployment of prodDeployments) { + const projectDeployments = await this.db.getDeploymentsByProjectId(deployment.projectId); + const oldDeployments = projectDeployments + .filter(projectDeployment => projectDeployment.deployer.deployerLrn === deployment.deployer.deployerLrn && projectDeployment.id !== deployment.id); + for (const oldDeployment of oldDeployments) { + await this.db.updateDeployment( + { id: oldDeployment.id }, + { isCurrent: false } + ); + } + }; } /** @@ -658,7 +669,8 @@ export class Service { deployer = data.deployer; } - const newDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData); + const deployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, false); + const dnsDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, true); const address = await this.getAddress(); const { repo, repoUrl } = await getRepoDetails(octokit, data.project.repository, data.commitHash); @@ -668,49 +680,53 @@ export class Service { const domain = await this.db.getOldestDomainByProjectId(data.project!.id!); // To set project DNS - let dnsDeploymentRequestId = null; if (data.environment === Environment.Production) { // On deleting deployment later, project DNS deployment is also deleted // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later - const dnsRequest = await this.laconicRegistry.createApplicationDeploymentRequest({ - deployment: newDeployment, - appName: repo, - repository: repoUrl, - environmentVariables: environmentVariablesObj, - dns: domain?.name ?? `${newDeployment.project.name}`, - lrn: deployer!.deployerLrn!, - apiUrl: deployer!.deployerApiUrl!, - payment: data.project.txHash, - auctionId: data.project.auctionId, - requesterAddress: address, - publicKey: deployer!.publicKey! + const { applicationDeploymentRequestData, applicationDeploymentRequestId } = + await this.laconicRegistry.createApplicationDeploymentRequest({ + deployment: dnsDeployment, + appName: repo, + repository: repoUrl, + environmentVariables: environmentVariablesObj, + dns: domain?.name ?? `${dnsDeployment.project.name}`, + lrn: deployer!.deployerLrn!, + apiUrl: deployer!.deployerApiUrl!, + payment: data.project.txHash, + auctionId: data.project.auctionId, + requesterAddress: address, + publicKey: deployer!.publicKey! + }); + + await this.db.updateDeploymentById(dnsDeployment.id, { + applicationDeploymentRequestId, + applicationDeploymentRequestData, + domainId: domain?.id ?? null }); - dnsDeploymentRequestId = dnsRequest.applicationDeploymentRequestId; } const { applicationDeploymentRequestId, applicationDeploymentRequestData } = await this.laconicRegistry.createApplicationDeploymentRequest({ - deployment: newDeployment, + deployment: deployment, appName: repo, repository: repoUrl, lrn: deployer!.deployerLrn!, apiUrl: deployer!.deployerApiUrl!, environmentVariables: environmentVariablesObj, - dns: `${newDeployment.project.name}-${newDeployment.id}`, + dns: `${deployment.project.name}-${deployment.id}`, payment: data.project.txHash, auctionId: data.project.auctionId, requesterAddress: address, publicKey: deployer!.publicKey! }); - await this.db.updateDeploymentById(newDeployment.id, { + await this.db.updateDeploymentById(deployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData, - dnsDeploymentRequestId, domainId: domain?.id ?? null }); - return newDeployment; + return deployment; } async createDeploymentFromAuction( @@ -753,7 +769,8 @@ export class Service { commitMessage: latestCommit.commit.message, }; - const newDeployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData); + const deployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData, false); + const dnsDeployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData, true); const address = await this.getAddress(); const environmentVariablesObj = await this.getEnvVariables(project!.id!); @@ -761,41 +778,47 @@ export class Service { if (deploymentData.environment === Environment.Production) { // On deleting deployment later, project DNS deployment is also deleted // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later - await this.laconicRegistry.createApplicationDeploymentRequest({ - deployment: newDeployment, - appName: repo, - repository: repoUrl, - environmentVariables: environmentVariablesObj, - dns: `${newDeployment.project.name}`, - auctionId: project.auctionId!, - lrn: deployerLrn, - apiUrl: deployer!.deployerApiUrl!, - requesterAddress: address, - publicKey: deployer!.publicKey! + const { applicationDeploymentRequestId, applicationDeploymentRequestData } = + await this.laconicRegistry.createApplicationDeploymentRequest({ + deployment: dnsDeployment, + appName: repo, + repository: repoUrl, + environmentVariables: environmentVariablesObj, + dns: `${dnsDeployment.project.name}`, + auctionId: project.auctionId!, + lrn: deployerLrn, + apiUrl: deployer!.deployerApiUrl!, + requesterAddress: address, + publicKey: deployer!.publicKey! + }); + + await this.db.updateDeploymentById(dnsDeployment.id, { + applicationDeploymentRequestId, + applicationDeploymentRequestData, }); } const { applicationDeploymentRequestId, applicationDeploymentRequestData } = // Create requests for all the deployers await this.laconicRegistry.createApplicationDeploymentRequest({ - deployment: newDeployment, + deployment: deployment, appName: repo, repository: repoUrl, auctionId: project.auctionId!, lrn: deployerLrn, apiUrl: deployer!.deployerApiUrl!, environmentVariables: environmentVariablesObj, - dns: `${newDeployment.project.name}-${newDeployment.id}`, + dns: `${deployment.project.name}-${deployment.id}`, requesterAddress: address, publicKey: deployer!.publicKey! }); - await this.db.updateDeploymentById(newDeployment.id, { + await this.db.updateDeploymentById(deployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData, }); - return newDeployment; + return deployment; } async createDeploymentFromData( @@ -804,6 +827,7 @@ export class Service { deployerLrn: string, applicationRecordId: string, applicationRecordData: ApplicationRecord, + isDNS: boolean, ): Promise { const newDeployment = await this.db.addDeployment({ project: data.project, @@ -821,6 +845,7 @@ export class Service { deployer: Object.assign(new Deployer(), { deployerLrn, }), + isDNS }); log(`Created deployment ${newDeployment.id}`); @@ -1197,6 +1222,8 @@ export class Service { }, }); + // Compare deployer in DNS while deleting + if (deployment && deployment.applicationDeploymentRecordId) { // If deployment is current, remove deployment for project subdomain as well if (deployment.isCurrent) { -- 2.45.2 From 6dcee29487feeb48119c5ca0406a58b3ab04a1d0 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Fri, 31 Jan 2025 15:49:21 +0530 Subject: [PATCH 20/59] Update flow for deleting deployments --- packages/backend/src/service.ts | 35 ++++++++++++--------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index d905e36f..d675dd24 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1222,37 +1222,28 @@ export class Service { }, }); - // Compare deployer in DNS while deleting - if (deployment && deployment.applicationDeploymentRecordId) { // If deployment is current, remove deployment for project subdomain as well if (deployment.isCurrent) { - const currentDeploymentURL = `https://${(deployment.project.name).toLowerCase()}.${deployment.deployer.baseDomain}`; + const dnsDeployment = await this.db.getDeployment({ + where: { + projectId: deployment.project.id, + deployer: deployment.deployer, + isDNS: true + } + }) - // TODO: Store the latest DNS deployment record - const deploymentRecords = - await this.laconicRegistry.getDeploymentRecordsByFilter({ - application: deployment.applicationRecordId, - url: currentDeploymentURL, - }); - - if (!deploymentRecords.length) { - log( - `No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`, - ); + if (!dnsDeployment) { + log(`DNS deployment for deployment with id ${deployment.id} not found`); return false; } - // Multiple records are fetched, take the latest record - const latestRecord = deploymentRecords - .sort((a, b) => new Date(b.createTime).getTime() - new Date(a.createTime).getTime())[0]; - await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ - deploymentId: latestRecord.id, - deployerLrn: deployment.deployer.deployerLrn, - auctionId: deployment.project.auctionId, - payment: deployment.project.txHash + deploymentId: dnsDeployment.id, + deployerLrn: dnsDeployment.deployer.deployerLrn, + auctionId: dnsDeployment.project.auctionId, + payment: dnsDeployment.project.txHash }); } -- 2.45.2 From 90e9260eb63ee72e9e8531921093fab4f0bd275c Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Fri, 31 Jan 2025 16:20:03 +0530 Subject: [PATCH 21/59] Update UI when IP address is unavailable and project is created via auctions --- .../org-slug/projects/id/settings/Domains.tsx | 52 +++++++++++-------- .../id/settings/domains/add/Config.tsx | 21 +++++--- 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx index 39943335..858ac215 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx @@ -62,31 +62,39 @@ const Domains = () => { headingText="Domains" button={ <> - + {!project.auctionId && ( + + )} } > - {domains.map((domain) => { - return ( - - ); - })} + {project.auctionId ? ( +

+ Custom domains not supported for auction driven deployments. +

+ ) : ( + domains.map((domain) => { + return ( + + ); + }) + )} ); }; diff --git a/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx b/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx index a48c1550..1752c66a 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/settings/domains/add/Config.tsx @@ -74,9 +74,9 @@ const Config = () => { return; } - const dnsData = await client.getLatestDNSDataByProjectId(id); + const dnsData = await client.getLatestDNSDataByProjectId(id); - setIPAddress(dnsData.value); + setIPAddress(dnsData.value); }; fetchDNSData(); @@ -102,18 +102,25 @@ const Config = () => { A @ - {IPAddress ?? 'Not Configured'} + +

+ {IPAddress ?? 'Not available'} +

+
- + /> + )} + + ) : ( +

DNS record data not available

)} - ); }; diff --git a/packages/gql-client/src/client.ts b/packages/gql-client/src/client.ts index 872cd02f..207e6942 100644 --- a/packages/gql-client/src/client.ts +++ b/packages/gql-client/src/client.ts @@ -467,14 +467,14 @@ export class GQLClient { return data.verifyTx; } - async getLatestDNSDataByProjectId(projectId: string): Promise { + async getLatestDNSRecordByProjectId(projectId: string): Promise { const { data } = await this.client.query({ - query: queries.getLatestDNSDataByProjectId, + query: queries.getLatestDNSRecordByProjectId, variables: { projectId, }, }); - return data.getLatestDNSDataByProjectId; + return data; } } diff --git a/packages/gql-client/src/queries.ts b/packages/gql-client/src/queries.ts index 23b83032..cd6dc875 100644 --- a/packages/gql-client/src/queries.ts +++ b/packages/gql-client/src/queries.ts @@ -357,9 +357,9 @@ query ($txHash: String!, $amount: String!, $senderAddress: String!) { } `; -export const getLatestDNSDataByProjectId = gql` +export const getLatestDNSRecordByProjectId = gql` query($projectId: String!) { - getLatestDNSDataByProjectId(projectId: $projectId) { + latestDNSRecord(projectId: $projectId) { name value request diff --git a/packages/gql-client/src/types.ts b/packages/gql-client/src/types.ts index e4f15d45..085c33e9 100644 --- a/packages/gql-client/src/types.ts +++ b/packages/gql-client/src/types.ts @@ -381,10 +381,14 @@ export type AuctionParams = { numProviders: number; }; -export type GetLatestDNSDataResponse = { +export type DNSRecordAttributes = { name: string; value: string; request: string; resourceType: string; version: string; } + +export type GetLatestDNSDataResponse = { + latestDNSRecord: DNSRecordAttributes | null +} -- 2.45.2 From d1e6171874bad8859c639ebd3e1a009d8f9324cd Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Mon, 3 Feb 2025 13:26:26 +0530 Subject: [PATCH 38/59] Send DNS deployment removal request on changing custom domain --- packages/backend/src/service.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index c5cb7125..e464c71d 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -234,18 +234,29 @@ export class Service { deployer: deployment.deployer, isDNS: true, isCurrent: true, + }, + relations: { + project: true, + deployer: true, } }); if (oldDNSDeployment) { - // Delete previous DNS deployment + // Send removal request for the previous DNS deployment and delete DB entry + if (oldDNSDeployment.url === deployment.url) { + await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ + deploymentId: oldDNSDeployment.applicationDeploymentRecordId!, + deployerLrn: oldDNSDeployment.deployer.deployerLrn, + auctionId: oldDNSDeployment.project.auctionId, + payment: oldDNSDeployment.project.txHash + }); + } + await this.db.deleteDeploymentById(oldDNSDeployment.id); // Update domain after the previous DNS deployment is deleted due to unique key constraint for domain - // Set the domain for the new current DNS deployment to either the domain of the previous deployment if present - // Or to the custom domain that was added for that project - const domain = oldDNSDeployment.domain - || await this.db.getOldestDomainByProjectId(deployment.project.id); + // Set the domain for the new current DNS deployment to the custom domain that was added for that project + const domain = await this.db.getOldestDomainByProjectId(deployment.project.id); if (domain) { await this.db.updateDeploymentById(deployment.id, { domain }); -- 2.45.2 From b6084008b853470bd377a4b04e4538424ae33c67 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Mon, 3 Feb 2025 13:28:11 +0530 Subject: [PATCH 39/59] Remove unused GQL methods --- packages/backend/src/resolvers.ts | 12 -------- packages/backend/src/schema.gql | 15 +++++++++- packages/backend/src/service.ts | 6 ---- .../projects/ProjectCard/ProjectCard.tsx | 2 +- .../project/settings/EditDomainDialog.tsx | 3 +- .../frontend/src/pages/components/modals.tsx | 2 ++ .../pages/org-slug/projects/id/Overview.tsx | 13 ++------- .../org-slug/projects/id/settings/Domains.tsx | 28 +++++++++---------- .../frontend/src/stories/MockStoriesData.ts | 2 ++ packages/gql-client/src/client.ts | 13 --------- packages/gql-client/src/queries.ts | 19 ++++--------- packages/gql-client/src/types.ts | 18 +++++++++--- 12 files changed, 56 insertions(+), 77 deletions(-) diff --git a/packages/backend/src/resolvers.ts b/packages/backend/src/resolvers.ts index 237cc1ad..47d8f8ff 100644 --- a/packages/backend/src/resolvers.ts +++ b/packages/backend/src/resolvers.ts @@ -70,18 +70,6 @@ export const createResolvers = async (service: Service): Promise => { return service.getDomainsByProjectId(projectId, filter); }, - oldestDomain: async ( - _: any, - { projectId }: { projectId: string }, - ) => { - try { - return await service.getOldestDomainByProjectId(projectId); - } catch (err) { - log(err); - return false; - } - }, - getAuctionData: async ( _: any, { auctionId }: { auctionId: string }, diff --git a/packages/backend/src/schema.gql b/packages/backend/src/schema.gql index d99d84c8..7e2c32cd 100644 --- a/packages/backend/src/schema.gql +++ b/packages/backend/src/schema.gql @@ -108,6 +108,7 @@ type Deployment { environment: Environment! deployer: Deployer applicationDeploymentRequestId: String + applicationDeploymentRecordData: AppDeploymentRecordAttributes isCurrent: Boolean! baseDomain: String status: DeploymentStatus! @@ -257,6 +258,19 @@ type DNSRecordAttributes { version: String } +type AppDeploymentRecordAttributes { + application: String + auction: String + deployer: String + dns: String + meta: String + name: String + request: String + type: String + url: String + version: String +} + input AuctionParams { maxPrice: String, numProviders: Int, @@ -274,7 +288,6 @@ type Query { searchProjects(searchText: String!): [Project!] getAuctionData(auctionId: String!): Auction! latestDNSRecord(projectId: String!): DNSRecordAttributes - oldestDomain(projectId: String!): Domain domains(projectId: String!, filter: FilterDomainsInput): [Domain] deployers: [Deployer] address: String! diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index e464c71d..c0f69ad0 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1407,12 +1407,6 @@ export class Service { return updateResult; } - async getOldestDomainByProjectId( - projectId: string, - ): Promise { - return await this.db.getOldestDomainByProjectId(projectId) - } - async authenticateGitHub( code: string, user: User, diff --git a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx index 3312834a..0a3aa19e 100644 --- a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx +++ b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx @@ -87,7 +87,7 @@ export const ProjectCard = ({

{project.name}

- {project.deployments[0]?.domain?.name ?? 'No domain'} + {project.deployments[0].applicationDeploymentRecordData.url ?? 'No domain'}

{/* Icons */} diff --git a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx index a7f65be5..45bb3777 100644 --- a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx +++ b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx @@ -178,8 +178,7 @@ const EditDomainDialog = ({ })} disabled={ !Boolean(branches.length) - // || - // watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0] + //|| watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0] } /> {!isValid && ( diff --git a/packages/frontend/src/pages/components/modals.tsx b/packages/frontend/src/pages/components/modals.tsx index 1eb60c6c..9161170f 100644 --- a/packages/frontend/src/pages/components/modals.tsx +++ b/packages/frontend/src/pages/components/modals.tsx @@ -10,6 +10,7 @@ import { DeleteVariableDialog } from 'components/projects/Dialog/DeleteVariableD import { DeleteDomainDialog } from 'components/projects/Dialog/DeleteDomainDialog'; import { CancelDeploymentDialog } from 'components/projects/Dialog/CancelDeploymentDialog'; import { + AppDeploymentRecordAttributes, Deployment, DeploymentStatus, Domain, @@ -57,6 +58,7 @@ const deployment: Deployment = { updatedAt: '1677680400', // 2023-03-01T13:00:00Z applicationDeploymentRequestId: 'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize', + applicationDeploymentRecordData: {} as AppDeploymentRecordAttributes, }; const domains: Domain[] = [ diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index 9d55569d..073c60ae 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { Link, // useNavigate, - useOutletContext + useOutletContext, } from 'react-router-dom'; import { RequestError } from 'octokit'; @@ -202,16 +202,9 @@ const OverviewTabPanel = () => { project.deployments.length > 0 && project.deployments.map((deployment) => (
- + - {deployment.domain?.name ?? - `https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`} + {deployment.applicationDeploymentRecordData.url} diff --git a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx index 858ac215..01e98c6c 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/settings/Domains.tsx @@ -60,21 +60,19 @@ const Domains = () => { return ( - {!project.auctionId && ( - - )} - - } + {...(!project.auctionId && { + button: ( + + ), + })} > {project.auctionId ? (

diff --git a/packages/frontend/src/stories/MockStoriesData.ts b/packages/frontend/src/stories/MockStoriesData.ts index 50f11469..262b2207 100644 --- a/packages/frontend/src/stories/MockStoriesData.ts +++ b/packages/frontend/src/stories/MockStoriesData.ts @@ -12,6 +12,7 @@ import { Domain, Environment, Permission, + AppDeploymentRecordAttributes, } from 'gql-client'; export const user: User = { @@ -111,6 +112,7 @@ export const deployment0: Deployment = { }, applicationDeploymentRequestId: 'bafyreiaycvq6imoppnpwdve4smj6t6ql5svt5zl3x6rimu4qwyzgjorize', + applicationDeploymentRecordData: {} as AppDeploymentRecordAttributes, }; export const project: Project = { diff --git a/packages/gql-client/src/client.ts b/packages/gql-client/src/client.ts index 207e6942..49ddbb60 100644 --- a/packages/gql-client/src/client.ts +++ b/packages/gql-client/src/client.ts @@ -393,19 +393,6 @@ export class GQLClient { return data; } - async oldestDomain( - projectId: string, - ): Promise { - const { data } = await this.client.query({ - query: queries.oldestDomain, - variables: { - projectId, - }, - }); - - return data; - } - async authenticateGitHub( code: string ): Promise { diff --git a/packages/gql-client/src/queries.ts b/packages/gql-client/src/queries.ts index cd6dc875..d243a503 100644 --- a/packages/gql-client/src/queries.ts +++ b/packages/gql-client/src/queries.ts @@ -57,6 +57,9 @@ query ($projectId: String!) { commitHash createdAt environment + applicationDeploymentRecordData { + url + } deployer { baseDomain } @@ -112,6 +115,9 @@ query ($organizationSlug: String!) { commitMessage createdAt environment + applicationDeploymentRecordData { + url + } domain { status branch @@ -261,19 +267,6 @@ query ($projectId: String!, $filter: FilterDomainsInput) { } `; -export const oldestDomain = gql` -query ($projectId: String!) { - oldestDomain(projectId: $projectId) { - branch - createdAt - id - name - status - updatedAt - } -} -` - export const getAuctionData = gql` query ($auctionId: String!) { getAuctionData(auctionId: $auctionId){ diff --git a/packages/gql-client/src/types.ts b/packages/gql-client/src/types.ts index 085c33e9..8e40bff8 100644 --- a/packages/gql-client/src/types.ts +++ b/packages/gql-client/src/types.ts @@ -108,6 +108,7 @@ export type Deployment = { environment: Environment; isCurrent: boolean; baseDomain?: string; + applicationDeploymentRecordData: AppDeploymentRecordAttributes; status: DeploymentStatus; createdBy: User; createdAt: string; @@ -236,10 +237,6 @@ export type GetDomainsResponse = { domains: Domain[]; }; -export type OldestDomainResponse = { - oldestDomain: Domain | null; -} - export type GetDeployersResponse = { deployers: Deployer[]; }; @@ -392,3 +389,16 @@ export type DNSRecordAttributes = { export type GetLatestDNSDataResponse = { latestDNSRecord: DNSRecordAttributes | null } + +export interface AppDeploymentRecordAttributes { + application: string; + auction: string; + deployer: string; + dns: string; + meta: string; + name: string; + request: string; + type: string; + url: string; + version: string; +} -- 2.45.2 From fd38127cb5f6b0705c5f2ff82ff412e4ff9ad993 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Mon, 3 Feb 2025 13:39:58 +0530 Subject: [PATCH 40/59] Update query to get latest DNS record --- packages/backend/src/database.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts index 2fd7232a..9e12ff69 100644 --- a/packages/backend/src/database.ts +++ b/packages/backend/src/database.ts @@ -653,7 +653,6 @@ export class Database { id: projectId, }, status: DeploymentStatus.Ready, - isDNS: true }, order: { createdAt: 'DESC' @@ -661,7 +660,7 @@ export class Database { }); if (deployment === null) { - throw new Error(`DNS deployment not found for project ${projectId}`); + throw new Error(`No deployment found for project ${projectId}`); } return deployment.dnsRecordData; -- 2.45.2 From 8322f877c03da0952d896e8ba8d599f77e55e7c7 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Mon, 3 Feb 2025 15:40:05 +0530 Subject: [PATCH 41/59] Fix check for old DNS deployment --- packages/backend/src/service.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index c0f69ad0..0a09c27e 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -253,14 +253,14 @@ export class Service { } await this.db.deleteDeploymentById(oldDNSDeployment.id); + } - // Update domain after the previous DNS deployment is deleted due to unique key constraint for domain - // Set the domain for the new current DNS deployment to the custom domain that was added for that project - const domain = await this.db.getOldestDomainByProjectId(deployment.project.id); + // Update domain after the previous DNS deployment is deleted due to unique key constraint for domain + // Set the domain for the new current DNS deployment to the custom domain that was added for that project + const customDomain = await this.db.getOldestDomainByProjectId(deployment.project.id); - if (domain) { - await this.db.updateDeploymentById(deployment.id, { domain }); - } + if (customDomain) { + await this.db.updateDeploymentById(deployment.id, { domain: customDomain }); } } -- 2.45.2 From 22bb409617359a95ca616f76eb39703edd46e357 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Mon, 3 Feb 2025 15:46:42 +0530 Subject: [PATCH 42/59] Add check for while accessing project URL --- .../src/components/projects/ProjectCard/ProjectCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx index 0a3aa19e..11b28506 100644 --- a/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx +++ b/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx @@ -87,7 +87,7 @@ export const ProjectCard = ({

{project.name}

- {project.deployments[0].applicationDeploymentRecordData.url ?? 'No domain'} + {project.deployments[0]?.applicationDeploymentRecordData?.url ?? 'No domain'}

{/* Icons */} -- 2.45.2 From ced815802ec8f9200d00da4c711fd8e5e87a2552 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Mon, 3 Feb 2025 16:40:03 +0530 Subject: [PATCH 43/59] Update deployment request config value if not env variables are set --- packages/backend/src/registry.ts | 19 ++++++++++--------- packages/backend/src/service.ts | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/backend/src/registry.ts b/packages/backend/src/registry.ts index ac437e25..a342b1a0 100644 --- a/packages/backend/src/registry.ts +++ b/packages/backend/src/registry.ts @@ -265,12 +265,15 @@ export class Registry { throw new Error(`No record found for ${lrn}`); } - const hash = await this.generateConfigHash( - data.environmentVariables, - data.requesterAddress, - data.publicKey, - data.apiUrl, - ); + let hash; + if (Object.keys(data.environmentVariables).length !== 0) { + hash = await this.generateConfigHash( + data.environmentVariables, + data.requesterAddress, + data.publicKey, + data.apiUrl, + ); + } // Create record of type ApplicationDeploymentRequest and publish const applicationDeploymentRequest = { @@ -281,9 +284,7 @@ export class Registry { dns: data.dns, // https://git.vdb.to/cerc-io/laconic-registry-cli/commit/129019105dfb93bebcea02fde0ed64d0f8e5983b - config: JSON.stringify({ - ref: hash, - }), + config: JSON.stringify(hash ? { ref: hash } : {}), meta: JSON.stringify({ note: `Added by Snowball @ ${DateTime.utc().toFormat( "EEE LLL dd HH:mm:ss 'UTC' yyyy" diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 0a09c27e..bdc23ad1 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -243,7 +243,7 @@ export class Service { if (oldDNSDeployment) { // Send removal request for the previous DNS deployment and delete DB entry - if (oldDNSDeployment.url === deployment.url) { + if (oldDNSDeployment.url !== deployment.url) { await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ deploymentId: oldDNSDeployment.applicationDeploymentRecordId!, deployerLrn: oldDNSDeployment.deployer.deployerLrn, -- 2.45.2 From b50efe315b8eb59a93d5e8cdb28ca2aae3267a22 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Mon, 3 Feb 2025 17:14:11 +0530 Subject: [PATCH 44/59] Remove hyperlink from deployer base domains --- .../projects/project/settings/DomainCard.tsx | 30 +++++++--------- .../project/settings/EditDomainDialog.tsx | 14 +++++--- .../projects/project/settings/SetupDomain.tsx | 10 +++--- .../pages/org-slug/projects/id/Overview.tsx | 35 ++++++++++--------- 4 files changed, 47 insertions(+), 42 deletions(-) diff --git a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx index 125b8425..4bbe1161 100644 --- a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx +++ b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx @@ -14,17 +14,19 @@ import EditDomainDialog from './EditDomainDialog'; import { useGQLClient } from 'context/GQLClientContext'; import { DeleteDomainDialog } from 'components/projects/Dialog/DeleteDomainDialog'; import { useToast } from 'components/shared/Toast'; -// import { Tag } from 'components/shared/Tag'; -import { - // CheckIcon, - // CrossIcon, - // LoadingIcon, - GearIcon, -} from 'components/shared/CustomIcon'; +import { GearIcon } from 'components/shared/CustomIcon'; import { Heading } from 'components/shared/Heading'; import { Button } from 'components/shared/Button'; import { useParams } from 'react-router-dom'; +// NOTE: Commented functionality to verify domain +// import { Tag } from 'components/shared/Tag'; +// import { +// CheckIcon, +// CrossIcon, +// LoadingIcon, +// } from 'components/shared/CustomIcon'; + // enum RefreshStatus { // IDLE, // CHECKING, @@ -32,6 +34,8 @@ import { useParams } from 'react-router-dom'; // CHECK_FAIL, // } +// const CHECK_FAIL_TIMEOUT = 5000; // In milliseconds + interface DomainCardProps { domains: Domain[]; domain: Domain; @@ -40,14 +44,6 @@ interface DomainCardProps { onUpdate: () => Promise; } -// const CHECK_FAIL_TIMEOUT = 5000; // In milliseconds - -// TODO: Get domain record -const DOMAIN_RECORD = { - type: 'A', - name: '@', - value: '56.49.19.21', -}; const DomainCard = ({ domains, @@ -58,10 +54,10 @@ const DomainCard = ({ }: DomainCardProps) => { const { toast, dismiss } = useToast(); const { id } = useParams(); - // const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false); const [dnsRecord, setDnsRecord] = useState(null); + // const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE); const client = useGQLClient(); @@ -215,7 +211,7 @@ const DomainCard = ({ {dnsRecord ? ( {dnsRecord.resourceType} - {DOMAIN_RECORD.name} + @ {dnsRecord.value ?? 'Not Configured'} ) : ( diff --git a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx index 45bb3777..8f368ead 100644 --- a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx +++ b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx @@ -1,18 +1,14 @@ import { - // useMemo, useCallback, useEffect, } from 'react'; import { - // Controller, useForm, SubmitHandler, } from 'react-hook-form'; import { Domain } from 'gql-client'; import { - // Select, - // Option, Typography, } from '@snowballtools/material-tailwind-react-fork'; @@ -22,6 +18,14 @@ import { Button } from 'components/shared/Button'; import { Input } from 'components/shared/Input'; import { useToast } from 'components/shared/Toast'; +// NOTE: Commented redirect domain functionality +// import { +// Select, +// Option, +// } from '@snowballtools/material-tailwind-react-fork'; +// import { Controller } from 'react-hook-form'; +// import { useMemo } from 'react'; + // const DEFAULT_REDIRECT_OPTIONS = ['none']; interface EditDomainDialogProp { @@ -178,7 +182,7 @@ const EditDomainDialog = ({ })} disabled={ !Boolean(branches.length) - //|| watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0] + // || watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0] } /> {!isValid && ( diff --git a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx index 39ae042e..8950b955 100644 --- a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx +++ b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx @@ -1,13 +1,15 @@ -// import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useForm } from 'react-hook-form'; -// import { InlineNotification } from 'components/shared/InlineNotification'; -// import { Radio } from 'components/shared/Radio'; import { Heading } from 'components/shared/Heading'; import { Input } from 'components/shared/Input'; import { Button } from 'components/shared/Button'; +// NOTE: Commented redirect domain functionality +// import { useEffect, useState } from 'react'; +// import { InlineNotification } from 'components/shared/InlineNotification'; +// import { Radio } from 'components/shared/Radio'; + interface SetupDomainFormValues { domainName: string; isWWW: string; @@ -28,8 +30,8 @@ const SetupDomain = () => { mode: 'onChange', }); - // const [domainStr, setDomainStr] = useState(''); const navigate = useNavigate(); + // const [domainStr, setDomainStr] = useState(''); // const isWWWRadioOptions = [ // { label: domainStr, value: 'false' }, // { label: `www.${domainStr}`, value: 'true' }, diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index 073c60ae..1f461d73 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -1,29 +1,21 @@ import { useEffect, useState } from 'react'; import { Link, - // useNavigate, useOutletContext, } from 'react-router-dom'; import { RequestError } from 'octokit'; -// import { useGQLClient } from 'context/GQLClientContext'; import { - // Button, - // Tag, Heading, Avatar, } from 'components/shared'; import { - // CheckRoundFilledIcon, - // ClockIcon, - // GlobeIcon, BranchStrokeIcon, CursorBoxIcon, GithubStrokeIcon, LinkIcon, CalendarDaysIcon, } from 'components/shared/CustomIcon'; -// import { Domain, DomainStatus } from 'gql-client'; import { useOctokit } from 'context/OctokitContext'; import { GitCommitWithBranch, OutletContextType } from '../../../../types'; import { getInitials } from 'utils/geInitials'; @@ -32,6 +24,20 @@ import { OverviewInfo } from 'components/projects/project/overview/OverviewInfo' import { relativeTimeMs } from 'utils/time'; import { AuctionCard } from 'components/projects/project/overview/Activity/AuctionCard'; +// NOTE: Commented elements related to domain verification +// import { useGQLClient } from 'context/GQLClientContext'; +// import { Domain, DomainStatus } from 'gql-client'; +// import { +// CheckRoundFilledIcon, +// ClockIcon, +// GlobeIcon, +// } from 'components/shared/CustomIcon'; +// import { +// Button, +// Tag, +// } from 'components/shared'; +// import { useNavigate } from 'react-router-dom'; + const COMMITS_PER_PAGE = 4; const PROJECT_UPDATE_WAIT_MS = 5000; @@ -150,14 +156,11 @@ const OverviewTabPanel = () => { {project.deployments && project.deployments.length > 0 && project.deployments.map((deployment, index) => ( -

- - {deployment.deployer.baseDomain} - +

+ {deployment.deployer.baseDomain}

))} -- 2.45.2 From b409d43e51dbf62331501195ae5a5d2e475a744b Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Mon, 3 Feb 2025 17:49:06 +0530 Subject: [PATCH 45/59] Update flow for deleting deployments --- packages/backend/src/service.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index bdc23ad1..8755e337 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -716,7 +716,7 @@ export class Service { const environmentVariablesObj = await this.getEnvVariables(data.project!.id!); // If a custom domain is present then use that as the DNS in the deployment request - const domain = await this.db.getOldestDomainByProjectId(data.project!.id!); + const customDomain = await this.db.getOldestDomainByProjectId(data.project!.id!); // To set project DNS if (data.environment === Environment.Production) { @@ -728,7 +728,7 @@ export class Service { appName: repo, repository: repoUrl, environmentVariables: environmentVariablesObj, - dns: domain?.name ?? `${dnsDeployment.project.name}`, + dns: customDomain?.name ?? `${dnsDeployment.project.name}`, lrn: deployer!.deployerLrn!, apiUrl: deployer!.deployerApiUrl!, payment: data.project.txHash, @@ -1280,11 +1280,20 @@ export class Service { return false; } - await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ - deploymentId: dnsDeployment.applicationDeploymentRecordId!, - deployerLrn: dnsDeployment.deployer.deployerLrn, - auctionId: dnsDeployment.project.auctionId, - payment: dnsDeployment.project.txHash + const dnsResult = + await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ + deploymentId: dnsDeployment.applicationDeploymentRecordId!, + deployerLrn: dnsDeployment.deployer.deployerLrn, + auctionId: dnsDeployment.project.auctionId, + payment: dnsDeployment.project.txHash + }); + + await this.db.updateDeploymentById(dnsDeployment.id, { + status: DeploymentStatus.Deleting, + applicationDeploymentRemovalRequestId: + dnsResult.applicationDeploymentRemovalRequestId, + applicationDeploymentRemovalRequestData: + dnsResult.applicationDeploymentRemovalRequestData, }); } -- 2.45.2 From 8553c30b0d86459468f48f4069878b072b7f0ada Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Mon, 3 Feb 2025 19:04:41 +0530 Subject: [PATCH 46/59] Update comment note --- .../src/components/projects/project/settings/DomainCard.tsx | 2 +- .../components/projects/project/settings/EditDomainDialog.tsx | 2 +- .../src/components/projects/project/settings/SetupDomain.tsx | 2 +- packages/frontend/src/pages/org-slug/projects/id/Overview.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx index 4bbe1161..2fe0b05d 100644 --- a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx +++ b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx @@ -19,7 +19,7 @@ import { Heading } from 'components/shared/Heading'; import { Button } from 'components/shared/Button'; import { useParams } from 'react-router-dom'; -// NOTE: Commented functionality to verify domain +// NOTE: Commented code for verify domain functionality // import { Tag } from 'components/shared/Tag'; // import { // CheckIcon, diff --git a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx index 8f368ead..a677d0bd 100644 --- a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx +++ b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx @@ -18,7 +18,7 @@ import { Button } from 'components/shared/Button'; import { Input } from 'components/shared/Input'; import { useToast } from 'components/shared/Toast'; -// NOTE: Commented redirect domain functionality +// NOTE: Commented code for redirect domain functionality // import { // Select, // Option, diff --git a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx index 8950b955..ed3ab87d 100644 --- a/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx +++ b/packages/frontend/src/components/projects/project/settings/SetupDomain.tsx @@ -5,7 +5,7 @@ import { Heading } from 'components/shared/Heading'; import { Input } from 'components/shared/Input'; import { Button } from 'components/shared/Button'; -// NOTE: Commented redirect domain functionality +// NOTE: Commented code for redirect domain functionality // import { useEffect, useState } from 'react'; // import { InlineNotification } from 'components/shared/InlineNotification'; // import { Radio } from 'components/shared/Radio'; diff --git a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx index 1f461d73..52618aa8 100644 --- a/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx +++ b/packages/frontend/src/pages/org-slug/projects/id/Overview.tsx @@ -24,7 +24,7 @@ import { OverviewInfo } from 'components/projects/project/overview/OverviewInfo' import { relativeTimeMs } from 'utils/time'; import { AuctionCard } from 'components/projects/project/overview/Activity/AuctionCard'; -// NOTE: Commented elements related to domain verification +// NOTE: Commented code for verify domain functionality // import { useGQLClient } from 'context/GQLClientContext'; // import { Domain, DomainStatus } from 'gql-client'; // import { -- 2.45.2 From 59329c18f609c69950bcf8560b36a7bd5fa483f3 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Mon, 3 Feb 2025 19:33:40 +0530 Subject: [PATCH 47/59] Update method to rollback deployment --- packages/backend/src/registry.ts | 77 ++++++++++++-------------------- packages/backend/src/service.ts | 49 ++++++++++++++++++-- 2 files changed, 73 insertions(+), 53 deletions(-) diff --git a/packages/backend/src/registry.ts b/packages/backend/src/registry.ts index a342b1a0..1a071231 100644 --- a/packages/backend/src/registry.ts +++ b/packages/backend/src/registry.ts @@ -108,19 +108,7 @@ export class Registry { ...(packageJSON.version && { app_version: packageJSON.version }) }; - const fee = parseGasAndFees(this.registryConfig.fee.gas, this.registryConfig.fee.fees); - - const result = await registryTransactionWithRetry(() => - this.registry.setRecord( - { - privateKey: this.registryConfig.privateKey, - record: applicationRecord, - bondId: this.registryConfig.bondId - }, - this.registryConfig.privateKey, - fee - ) - ); + const result = await this.publishRecord(applicationRecord); log(`Published application record ${result.id}`); log('Application record data:', applicationRecord); @@ -129,6 +117,8 @@ export class Registry { const lrn = this.getLrn(repo); log(`Setting name: ${lrn} for record ID: ${result.id}`); + const fee = parseGasAndFees(this.registryConfig.fee.gas, this.registryConfig.fee.fees); + await sleep(SLEEP_DURATION); await registryTransactionWithRetry(() => this.registry.setName( @@ -220,17 +210,7 @@ export class Registry { type: APP_DEPLOYMENT_AUCTION_RECORD_TYPE, }; - const result = await registryTransactionWithRetry(() => - this.registry.setRecord( - { - privateKey: this.registryConfig.privateKey, - record: applicationDeploymentAuction, - bondId: this.registryConfig.bondId - }, - this.registryConfig.privateKey, - fee - ) - ); + const result = await this.publishRecord(applicationDeploymentAuction); log(`Application deployment auction created: ${auctionResult.auction.id}`); log(`Application deployment auction record published: ${result.id}`); @@ -299,19 +279,7 @@ export class Registry { await sleep(SLEEP_DURATION); - const fee = parseGasAndFees(this.registryConfig.fee.gas, this.registryConfig.fee.fees); - - const result = await registryTransactionWithRetry(() => - this.registry.setRecord( - { - privateKey: this.registryConfig.privateKey, - record: applicationDeploymentRequest, - bondId: this.registryConfig.bondId - }, - this.registryConfig.privateKey, - fee - ) - ); + const result = await this.publishRecord(applicationDeploymentRequest); log(`Application deployment request record published: ${result.id}`); log('Application deployment request data:', applicationDeploymentRequest); @@ -472,18 +440,8 @@ export class Registry { ...(data.payment && { payment: data.payment }), }; - const fee = parseGasAndFees(this.registryConfig.fee.gas, this.registryConfig.fee.fees); - - const result = await registryTransactionWithRetry(() => - this.registry.setRecord( - { - privateKey: this.registryConfig.privateKey, - record: applicationDeploymentRemovalRequest, - bondId: this.registryConfig.bondId - }, - this.registryConfig.privateKey, - fee - ) + const result = await this.publishRecord( + applicationDeploymentRemovalRequest, ); log(`Application deployment removal request record published: ${result.id}`); @@ -509,6 +467,27 @@ export class Registry { return completedAuctions; } + async publishRecord(recordData: any): Promise { + const fee = parseGasAndFees( + this.registryConfig.fee.gas, + this.registryConfig.fee.fees, + ); + + const result = await registryTransactionWithRetry(() => + this.registry.setRecord( + { + privateKey: this.registryConfig.privateKey, + record: recordData, + bondId: this.registryConfig.bondId, + }, + this.registryConfig.privateKey, + fee, + ), + ); + + return result; + } + async getRecordsByName(name: string): Promise { return this.registry.resolveNames([name]); } diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 8755e337..de402918 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1,7 +1,8 @@ import assert from 'assert'; import debug from 'debug'; -import { DeepPartial, FindOptionsWhere, IsNull, Not } from 'typeorm'; +import { DeepPartial, FindOptionsWhere } from 'typeorm'; import { Octokit, RequestError } from 'octokit'; +import { DateTime } from 'luxon'; import { OAuthApp } from '@octokit/oauth-app'; @@ -260,7 +261,7 @@ export class Service { const customDomain = await this.db.getOldestDomainByProjectId(deployment.project.id); if (customDomain) { - await this.db.updateDeploymentById(deployment.id, { domain: customDomain }); + deployment.domain = customDomain; } } @@ -1222,17 +1223,20 @@ export class Service { const oldCurrentDeployment = await this.db.getDeployment({ relations: { domain: true, + project: true, + deployer: true, }, where: { project: { id: projectId, }, isCurrent: true, + isDNS: false, }, }); if (!oldCurrentDeployment) { - throw new Error('Current deployment doesnot exist'); + throw new Error('Current deployment does not exist'); } const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById( @@ -1242,9 +1246,46 @@ export class Service { const newCurrentDeploymentUpdate = await this.db.updateDeploymentById( deploymentId, - { isCurrent: true, domain: oldCurrentDeployment?.domain }, + { isCurrent: true, domain: oldCurrentDeployment.domain }, ); + const newCurrentDeployment = await this.db.getDeployment({ where: { id: deploymentId }, relations: { project: true, deployer: true } }); + + if (!newCurrentDeployment) { + throw new Error(`Deployment with Id ${deploymentId} not found`); + } + + // Create a DNS deployment for the new current deployment + const dnsDeployment = await this.createDeploymentFromData( + newCurrentDeployment.project.ownerId, + newCurrentDeployment, + newCurrentDeployment.deployer!.deployerLrn!, + newCurrentDeployment.applicationRecordId, + newCurrentDeployment.applicationRecordData, + true, + ); + + const applicationDeploymentRequestData = newCurrentDeployment.applicationDeploymentRequestData; + + applicationDeploymentRequestData!.version = (Number(applicationDeploymentRequestData?.version) + 1).toString(); + applicationDeploymentRequestData!.meta = JSON.stringify({ + ...JSON.parse(applicationDeploymentRequestData!.meta), + note: `Updated by Snowball @ ${DateTime.utc().toFormat( + "EEE LLL dd HH:mm:ss 'UTC' yyyy" + )}` + }); + + const result = await this.laconicRegistry.publishRecord( + applicationDeploymentRequestData, + ); + + log(`Application deployment request record published: ${result.id}`) + + await this.db.updateDeploymentById(dnsDeployment.id, { + applicationDeploymentRequestId: result.id, + applicationDeploymentRequestData, + }); + return newCurrentDeploymentUpdate && oldCurrentDeploymentUpdate; } -- 2.45.2 From 10cbdf73a39b0f5d9e6dc5f0b1a30d0f1f043521 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Mon, 3 Feb 2025 23:33:35 +0530 Subject: [PATCH 48/59] Fix unique constraint error in rollback deployment --- packages/backend/src/service.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index de402918..efa10a38 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -709,6 +709,8 @@ export class Service { deployer = data.deployer; } + console.log("DATA>DOMAIN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",data.domain) + const deployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, false); const dnsDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, true); @@ -1246,7 +1248,7 @@ export class Service { const newCurrentDeploymentUpdate = await this.db.updateDeploymentById( deploymentId, - { isCurrent: true, domain: oldCurrentDeployment.domain }, + { isCurrent: true, domain: null }, ); const newCurrentDeployment = await this.db.getDeployment({ where: { id: deploymentId }, relations: { project: true, deployer: true } }); @@ -1255,6 +1257,25 @@ export class Service { throw new Error(`Deployment with Id ${deploymentId} not found`); } + const applicationDeploymentRequestData = newCurrentDeployment.applicationDeploymentRequestData; + + const customDomain = await this.db.getOldestDomainByProjectId(projectId); + + if (customDomain) { + await this.db.updateDeployment( + { + domainId: customDomain.id, + }, + { + domain: null, + }, + ); + } + + if(customDomain && applicationDeploymentRequestData) { + newCurrentDeployment.domain = customDomain + } + // Create a DNS deployment for the new current deployment const dnsDeployment = await this.createDeploymentFromData( newCurrentDeployment.project.ownerId, @@ -1265,9 +1286,6 @@ export class Service { true, ); - const applicationDeploymentRequestData = newCurrentDeployment.applicationDeploymentRequestData; - - applicationDeploymentRequestData!.version = (Number(applicationDeploymentRequestData?.version) + 1).toString(); applicationDeploymentRequestData!.meta = JSON.stringify({ ...JSON.parse(applicationDeploymentRequestData!.meta), note: `Updated by Snowball @ ${DateTime.utc().toFormat( -- 2.45.2 From f6b0f95761e2d975634d179a35c25ec3a6a42e63 Mon Sep 17 00:00:00 2001 From: Shreerang Kale Date: Mon, 3 Feb 2025 23:53:11 +0530 Subject: [PATCH 49/59] Add dns while publishing record while publishing record --- packages/backend/src/entity/Deployment.ts | 1 + packages/backend/src/service.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/backend/src/entity/Deployment.ts b/packages/backend/src/entity/Deployment.ts index 1ec328fb..b30f59f9 100644 --- a/packages/backend/src/entity/Deployment.ts +++ b/packages/backend/src/entity/Deployment.ts @@ -39,6 +39,7 @@ export interface ApplicationDeploymentRequest { config: string; meta: string; payment?: string; + dns?: string; } export interface ApplicationDeploymentRemovalRequest { diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index efa10a38..775e9228 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1274,6 +1274,7 @@ export class Service { if(customDomain && applicationDeploymentRequestData) { newCurrentDeployment.domain = customDomain + applicationDeploymentRequestData.dns = customDomain.name } // Create a DNS deployment for the new current deployment -- 2.45.2 From 3ea43eab4214fa2f0cbd2372a1cd88244f93acdb Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 4 Feb 2025 11:59:21 +0530 Subject: [PATCH 50/59] Remove domain relation from deployments table --- packages/backend/src/database.ts | 12 +-- packages/backend/src/entity/Deployment.ts | 10 +-- packages/backend/src/resolvers.ts | 2 +- packages/backend/src/schema.gql | 1 - packages/backend/src/service.ts | 86 ++++--------------- .../project/deployments/DeploymentMenu.tsx | 4 +- .../frontend/src/pages/components/modals.tsx | 13 +-- .../frontend/src/stories/MockStoriesData.ts | 1 - packages/gql-client/src/queries.ts | 24 ------ packages/gql-client/src/types.ts | 1 - 10 files changed, 29 insertions(+), 125 deletions(-) diff --git a/packages/backend/src/database.ts b/packages/backend/src/database.ts index 9e12ff69..82bed68d 100644 --- a/packages/backend/src/database.ts +++ b/packages/backend/src/database.ts @@ -158,10 +158,9 @@ export class Database { .leftJoinAndSelect( 'project.deployments', 'deployments', - 'deployments.isCurrent = true AND deployments.isDNS = true' + 'deployments.isCurrent = true AND deployments.isCanonical = true' ) .leftJoinAndSelect('deployments.createdBy', 'user') - .leftJoinAndSelect('deployments.domain', 'domain') .leftJoinAndSelect('deployments.deployer', 'deployer') .leftJoinAndSelect('project.owner', 'owner') .leftJoinAndSelect('project.deployers', 'deployers') @@ -203,9 +202,8 @@ export class Database { .leftJoinAndSelect( 'project.deployments', 'deployments', - 'deployments.isCurrent = true AND deployments.isDNS = true' + 'deployments.isCurrent = true AND deployments.isCanonical = true' ) - .leftJoinAndSelect('deployments.domain', 'domain') .leftJoin('project.projectMembers', 'projectMembers') .leftJoin('project.organization', 'organization') .where( @@ -236,7 +234,6 @@ export class Database { return this.getDeployments({ relations: { project: true, - domain: true, createdBy: true, deployer: true, }, @@ -251,11 +248,10 @@ export class Database { }); } - async getCommitDeploymentsByProjectId(projectId: string): Promise { + async getNonCanonicalDeploymentsByProjectId(projectId: string): Promise { return this.getDeployments({ relations: { project: true, - domain: true, createdBy: true, deployer: true, }, @@ -263,7 +259,7 @@ export class Database { project: { id: projectId }, - isDNS: false + isCanonical: false }, order: { createdAt: 'DESC' diff --git a/packages/backend/src/entity/Deployment.ts b/packages/backend/src/entity/Deployment.ts index b30f59f9..882233f7 100644 --- a/packages/backend/src/entity/Deployment.ts +++ b/packages/backend/src/entity/Deployment.ts @@ -78,13 +78,6 @@ export class Deployment { @JoinColumn({ name: 'projectId' }) project!: Project; - @Column({ nullable: true }) - domainId!: string | null; - - @OneToOne(() => Domain) - @JoinColumn({ name: 'domainId' }) - domain!: Domain | null; - @Column('varchar') branch!: string; @@ -142,9 +135,8 @@ export class Deployment { @Column('boolean', { default: false }) isCurrent!: boolean; - // TODO: Rename field @Column('boolean', { default: false }) - isDNS!: boolean; + isCanonical!: boolean; @Column({ enum: DeploymentStatus diff --git a/packages/backend/src/resolvers.ts b/packages/backend/src/resolvers.ts index 47d8f8ff..d9f9128d 100644 --- a/packages/backend/src/resolvers.ts +++ b/packages/backend/src/resolvers.ts @@ -38,7 +38,7 @@ export const createResolvers = async (service: Service): Promise => { }, deployments: async (_: any, { projectId }: { projectId: string }) => { - return service.getCommitDeploymentsByProjectId(projectId); + return service.getNonCanonicalDeploymentsByProjectId(projectId); }, environmentVariables: async ( diff --git a/packages/backend/src/schema.gql b/packages/backend/src/schema.gql index 7e2c32cd..400e36ef 100644 --- a/packages/backend/src/schema.gql +++ b/packages/backend/src/schema.gql @@ -100,7 +100,6 @@ type ProjectMember { type Deployment { id: String! - domain: Domain branch: String! commitHash: String! commitMessage: String! diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 775e9228..90fae68b 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -228,12 +228,12 @@ export class Service { deployment.isCurrent = deployment.environment === Environment.Production; deployment.dnsRecordData = dnsRecordData; - if (deployment.isDNS) { + if (deployment.isCanonical) { const oldDNSDeployment = await this.db.getDeployment({ where: { projectId: deployment.project.id, deployer: deployment.deployer, - isDNS: true, + isCanonical: true, isCurrent: true, }, relations: { @@ -255,14 +255,6 @@ export class Service { await this.db.deleteDeploymentById(oldDNSDeployment.id); } - - // Update domain after the previous DNS deployment is deleted due to unique key constraint for domain - // Set the domain for the new current DNS deployment to the custom domain that was added for that project - const customDomain = await this.db.getOldestDomainByProjectId(deployment.project.id); - - if (customDomain) { - deployment.domain = customDomain; - } } await this.db.updateDeploymentById(deployment.id, deployment); @@ -301,7 +293,7 @@ export class Service { projectDeployment.deployer.deployerLrn === deployment.deployer.deployerLrn && projectDeployment.id !== deployment.id && - projectDeployment.isDNS == deployment.isDNS, + projectDeployment.isCanonical == deployment.isCanonical, ); for (const oldDeployment of oldDeployments) { await this.db.updateDeployment( @@ -493,14 +485,14 @@ export class Service { return dbProjects; } - async getCommitDeploymentsByProjectId(projectId: string): Promise { - const commitDeployments = await this.db.getCommitDeploymentsByProjectId(projectId); - return commitDeployments; + async getNonCanonicalDeploymentsByProjectId(projectId: string): Promise { + const nonCanonicalDeployments = await this.db.getNonCanonicalDeploymentsByProjectId(projectId); + return nonCanonicalDeployments; } async getLatestDNSRecordByProjectId(projectId: string): Promise { - const dnsDeployments = await this.db.getLatestDNSRecordByProjectId(projectId); - return dnsDeployments; + const dnsRecord = await this.db.getLatestDNSRecordByProjectId(projectId); + return dnsRecord; } async getEnvironmentVariablesByProjectId( @@ -649,18 +641,12 @@ export class Service { throw new Error('Deployment does not exist'); } - const prodBranchDomains = await this.db.getDomainsByProjectId( - oldDeployment.project.id, - { branch: oldDeployment.project.prodBranch }, - ); - const octokit = await this.getOctokit(user.id); const newDeployment = await this.createDeployment(user.id, octokit, { project: oldDeployment.project, branch: oldDeployment.branch, environment: Environment.Production, - domain: prodBranchDomains[0], commitHash: oldDeployment.commitHash, commitMessage: oldDeployment.commitMessage, deployer: oldDeployment.deployer @@ -689,19 +675,6 @@ export class Service { commitHash: data.commitHash!, }); - // Update previous deployment with prod branch domain - // TODO: Fix unique constraint error for domain - if (data.domain) { - await this.db.updateDeployment( - { - domainId: data.domain.id, - }, - { - domain: null, - }, - ); - } - let deployer; if (deployerLrn) { deployer = await this.db.getDeployerByLRN(deployerLrn); @@ -709,20 +682,19 @@ export class Service { deployer = data.deployer; } - console.log("DATA>DOMAIN!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",data.domain) - const deployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, false); - const dnsDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, true); const address = await this.getAddress(); const { repo, repoUrl } = await getRepoDetails(octokit, data.project.repository, data.commitHash); const environmentVariablesObj = await this.getEnvVariables(data.project!.id!); - // If a custom domain is present then use that as the DNS in the deployment request - const customDomain = await this.db.getOldestDomainByProjectId(data.project!.id!); // To set project DNS if (data.environment === Environment.Production) { + const dnsDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, true); + // If a custom domain is present then use that as the DNS in the deployment request + const customDomain = await this.db.getOldestDomainByProjectId(data.project!.id!); + // On deleting deployment later, project DNS deployment is also deleted // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later const { applicationDeploymentRequestData, applicationDeploymentRequestId } = @@ -867,7 +839,7 @@ export class Service { deployerLrn: string, applicationRecordId: string, applicationRecordData: ApplicationRecord, - isDNS: boolean, + isCanonical: boolean, ): Promise { const newDeployment = await this.db.addDeployment({ project: data.project, @@ -878,14 +850,13 @@ export class Service { status: DeploymentStatus.Building, applicationRecordId, applicationRecordData, - domain: data.domain, createdBy: Object.assign(new User(), { id: userId, }), deployer: Object.assign(new Deployer(), { deployerLrn, }), - isDNS + isCanonical }); log(`Created deployment ${newDeployment.id}`); @@ -1118,9 +1089,6 @@ export class Service { for await (const project of projects) { const octokit = await this.getOctokit(project.ownerId); - const [domain] = await this.db.getDomainsByProjectId(project.id, { - branch, - }); const deployers = project.deployers; if (!deployers) { @@ -1138,7 +1106,6 @@ export class Service { project.prodBranch === branch ? Environment.Production : Environment.Preview, - domain, commitHash: headCommit.id, commitMessage: headCommit.message, deployer: deployer @@ -1180,7 +1147,6 @@ export class Service { const oldDeployment = await this.db.getDeployment({ relations: { project: true, - domain: true, deployer: true, createdBy: true, }, @@ -1206,7 +1172,6 @@ export class Service { // TODO: Put isCurrent field in project branch: oldDeployment.branch, environment: Environment.Production, - domain: oldDeployment.domain, commitHash: oldDeployment.commitHash, commitMessage: oldDeployment.commitMessage, deployer: oldDeployment.deployer @@ -1224,7 +1189,6 @@ export class Service { // TODO: Implement transactions const oldCurrentDeployment = await this.db.getDeployment({ relations: { - domain: true, project: true, deployer: true, }, @@ -1233,7 +1197,7 @@ export class Service { id: projectId, }, isCurrent: true, - isDNS: false, + isCanonical: false, }, }); @@ -1243,12 +1207,12 @@ export class Service { const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById( oldCurrentDeployment.id, - { isCurrent: false, domain: null }, + { isCurrent: false }, ); const newCurrentDeploymentUpdate = await this.db.updateDeploymentById( deploymentId, - { isCurrent: true, domain: null }, + { isCurrent: true }, ); const newCurrentDeployment = await this.db.getDeployment({ where: { id: deploymentId }, relations: { project: true, deployer: true } }); @@ -1261,19 +1225,7 @@ export class Service { const customDomain = await this.db.getOldestDomainByProjectId(projectId); - if (customDomain) { - await this.db.updateDeployment( - { - domainId: customDomain.id, - }, - { - domain: null, - }, - ); - } - - if(customDomain && applicationDeploymentRequestData) { - newCurrentDeployment.domain = customDomain + if (customDomain && applicationDeploymentRequestData) { applicationDeploymentRequestData.dns = customDomain.name } @@ -1326,7 +1278,7 @@ export class Service { where: { projectId: deployment.project.id, deployer: deployment.deployer, - isDNS: true + isCanonical: true }, relations: { project: true, diff --git a/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx b/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx index 118dca39..ee96a588 100644 --- a/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx +++ b/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx @@ -243,7 +243,7 @@ export const DeploymentMenu = ({ setRedeployToProduction((preVal) => !preVal); }} deployment={deployment} - domains={deployment.domain ? [deployment.domain] : []} + domains={[]} isConfirmButtonLoading={isConfirmButtonLoading} /> {Boolean(currentDeployment) && ( @@ -258,7 +258,7 @@ export const DeploymentMenu = ({ }} deployment={currentDeployment} newDeployment={deployment} - domains={currentDeployment.domain ? [currentDeployment.domain] : []} + domains={[]} /> )} { setRedeployToProduction((preVal) => !preVal) } deployment={deployment} - domains={deployment.domain ? [deployment.domain] : []} + domains={[]} /> {/* Rollback to this deployment */} - - - - ); -}; - -export default AssignDomainDialog; diff --git a/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx b/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx index ee96a588..fdf6484c 100644 --- a/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx +++ b/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx @@ -10,7 +10,6 @@ import { import { Deployment, Domain, Environment, Project } from 'gql-client'; import { Button } from 'components/shared/Button'; import { - GlobeIcon, HorizontalDotIcon, LinkIcon, RefreshIcon, @@ -18,7 +17,6 @@ import { UndoIcon, CrossCircleIcon, } from 'components/shared/CustomIcon'; -import AssignDomainDialog from './AssignDomainDialog'; import { useGQLClient } from 'context/GQLClientContext'; import { cn } from 'utils/classnames'; import { ChangeStateToProductionDialog } from 'components/projects/Dialog/ChangeStateToProductionDialog'; @@ -50,7 +48,6 @@ export const DeploymentMenu = ({ const [deleteDeploymentDialog, setDeleteDeploymentDialog] = useState(false); const [isConfirmDeleteLoading, setIsConfirmDeleteLoading] = useState(false); const [rollbackDeployment, setRollbackDeployment] = useState(false); - const [assignDomainDialog, setAssignDomainDialog] = useState(false); const [isConfirmButtonLoading, setConfirmButtonLoadingLoading] = useState(false); @@ -173,12 +170,6 @@ export const DeploymentMenu = ({ Visit - setAssignDomainDialog(!assignDomainDialog)} - > - Assign domain - setChangeToProduction(!changeToProduction)} @@ -243,7 +234,7 @@ export const DeploymentMenu = ({ setRedeployToProduction((preVal) => !preVal); }} deployment={deployment} - domains={[]} + domains={prodBranchDomains} isConfirmButtonLoading={isConfirmButtonLoading} /> {Boolean(currentDeployment) && ( @@ -258,13 +249,9 @@ export const DeploymentMenu = ({ }} deployment={currentDeployment} newDeployment={deployment} - domains={[]} + domains={prodBranchDomains} /> )} - setAssignDomainDialog(!assignDomainDialog)} - /> { -- 2.45.2 From 3931e207118eafa08d0abd4eef10a984d6e22654 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 4 Feb 2025 13:37:20 +0530 Subject: [PATCH 54/59] Fix method to update deployment to production --- packages/backend/src/service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 402e7c75..3a3bd8ce 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -634,6 +634,7 @@ export class Service { where: { id: deploymentId }, relations: { project: true, + deployer: true, }, }); -- 2.45.2 From 6a2a8bb3c4f578151dc1ab9bedf4b3f2cc845dd6 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 4 Feb 2025 14:05:06 +0530 Subject: [PATCH 55/59] Add loaders for action buttons --- .../projects/project/deployments/DeploymentMenu.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx b/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx index fdf6484c..cb87aa98 100644 --- a/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx +++ b/packages/frontend/src/components/projects/project/deployments/DeploymentMenu.tsx @@ -47,6 +47,7 @@ export const DeploymentMenu = ({ const [redeployToProduction, setRedeployToProduction] = useState(false); const [deleteDeploymentDialog, setDeleteDeploymentDialog] = useState(false); const [isConfirmDeleteLoading, setIsConfirmDeleteLoading] = useState(false); + const [isConfirmUpdateLoading, setIsConfirmUpdateLoading] = useState(false); const [rollbackDeployment, setRollbackDeployment] = useState(false); const [isConfirmButtonLoading, setConfirmButtonLoadingLoading] = useState(false); @@ -55,6 +56,8 @@ export const DeploymentMenu = ({ const isUpdated = await client.updateDeploymentToProd(deployment.id); if (isUpdated.updateDeploymentToProd) { await onUpdate(); + setIsConfirmUpdateLoading(false); + toast({ id: 'deployment_changed_to_production', title: 'Deployment changed to production', @@ -99,6 +102,8 @@ export const DeploymentMenu = ({ ); if (isRollbacked.rollbackDeployment) { await onUpdate(); + setIsConfirmUpdateLoading(false); + toast({ id: 'deployment_rolled_back', title: 'Deployment rolled back', @@ -217,9 +222,11 @@ export const DeploymentMenu = ({ handleCancel={() => setChangeToProduction((preVal) => !preVal)} open={changeToProduction} handleConfirm={async () => { + setIsConfirmUpdateLoading(true); await updateDeployment(); setChangeToProduction((preVal) => !preVal); }} + isConfirmButtonLoading={isConfirmUpdateLoading} deployment={deployment} domains={prodBranchDomains} /> @@ -244,12 +251,14 @@ export const DeploymentMenu = ({ open={rollbackDeployment} confirmButtonTitle="Rollback" handleConfirm={async () => { + setIsConfirmUpdateLoading(true); await rollbackDeploymentHandler(); setRollbackDeployment((preVal) => !preVal); }} deployment={currentDeployment} newDeployment={deployment} domains={prodBranchDomains} + isConfirmButtonLoading={isConfirmUpdateLoading} /> )} Date: Tue, 4 Feb 2025 14:50:45 +0530 Subject: [PATCH 56/59] Rename variables for canonical deployments --- packages/backend/src/registry.ts | 8 ++--- packages/backend/src/service.ts | 56 ++++++++++++++++---------------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/packages/backend/src/registry.ts b/packages/backend/src/registry.ts index 1a071231..c7d8b8e0 100644 --- a/packages/backend/src/registry.ts +++ b/packages/backend/src/registry.ts @@ -414,12 +414,8 @@ export class Registry { * Fetch record by Id */ async getRecordById(id: string): Promise { - const record = await this.registry.getRecordsByIds([id]); - if (record.length === 0) { - return null; - } - - return record[0]; + const [record] = await this.registry.getRecordsByIds([id]); + return record ?? null; } async createApplicationDeploymentRemovalRequest(data: { diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 3a3bd8ce..6adb400a 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -229,7 +229,7 @@ export class Service { deployment.dnsRecordData = dnsRecordData; if (deployment.isCanonical) { - const oldDNSDeployment = await this.db.getDeployment({ + const previousCanonicalDeployment = await this.db.getDeployment({ where: { projectId: deployment.project.id, deployer: deployment.deployer, @@ -242,18 +242,18 @@ export class Service { } }); - if (oldDNSDeployment) { - // Send removal request for the previous DNS deployment and delete DB entry - if (oldDNSDeployment.url !== deployment.url) { + if (previousCanonicalDeployment) { + // Send removal request for the previous canonical deployment and delete DB entry + if (previousCanonicalDeployment.url !== deployment.url) { await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ - deploymentId: oldDNSDeployment.applicationDeploymentRecordId!, - deployerLrn: oldDNSDeployment.deployer.deployerLrn, - auctionId: oldDNSDeployment.project.auctionId, - payment: oldDNSDeployment.project.txHash + deploymentId: previousCanonicalDeployment.applicationDeploymentRecordId!, + deployerLrn: previousCanonicalDeployment.deployer.deployerLrn, + auctionId: previousCanonicalDeployment.project.auctionId, + payment: previousCanonicalDeployment.project.txHash }); } - await this.db.deleteDeploymentById(oldDNSDeployment.id); + await this.db.deleteDeploymentById(previousCanonicalDeployment.id); } } @@ -691,7 +691,7 @@ export class Service { // To set project DNS if (data.environment === Environment.Production) { - const dnsDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, true); + const canonicalDeployment = await this.createDeploymentFromData(userId, data, deployer!.deployerLrn!, applicationRecordId, applicationRecordData, true); // If a custom domain is present then use that as the DNS in the deployment request const customDomain = await this.db.getOldestDomainByProjectId(data.project!.id!); @@ -699,11 +699,11 @@ export class Service { // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later const { applicationDeploymentRequestData, applicationDeploymentRequestId } = await this.laconicRegistry.createApplicationDeploymentRequest({ - deployment: dnsDeployment, + deployment: canonicalDeployment, appName: repo, repository: repoUrl, environmentVariables: environmentVariablesObj, - dns: customDomain?.name ?? `${dnsDeployment.project.name}`, + dns: customDomain?.name ?? `${canonicalDeployment.project.name}`, lrn: deployer!.deployerLrn!, apiUrl: deployer!.deployerApiUrl!, payment: data.project.txHash, @@ -712,7 +712,7 @@ export class Service { publicKey: deployer!.publicKey! }); - await this.db.updateDeploymentById(dnsDeployment.id, { + await this.db.updateDeploymentById(canonicalDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData, }); @@ -787,7 +787,7 @@ export class Service { const environmentVariablesObj = await this.getEnvVariables(project!.id!); // To set project DNS if (deploymentData.environment === Environment.Production) { - const dnsDeployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData, true); + const canonicalDeployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData, true); // If a custom domain is present then use that as the DNS in the deployment request const customDomain = await this.db.getOldestDomainByProjectId(project!.id!); @@ -795,11 +795,11 @@ export class Service { // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later const { applicationDeploymentRequestId, applicationDeploymentRequestData } = await this.laconicRegistry.createApplicationDeploymentRequest({ - deployment: dnsDeployment, + deployment: canonicalDeployment, appName: repo, repository: repoUrl, environmentVariables: environmentVariablesObj, - dns: customDomain?.name ?? `${dnsDeployment.project.name}`, + dns: customDomain?.name ?? `${canonicalDeployment.project.name}`, auctionId: project.auctionId!, lrn: deployerLrn, apiUrl: deployer!.deployerApiUrl!, @@ -807,7 +807,7 @@ export class Service { publicKey: deployer!.publicKey! }); - await this.db.updateDeploymentById(dnsDeployment.id, { + await this.db.updateDeploymentById(canonicalDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData, }); @@ -1232,8 +1232,8 @@ export class Service { applicationDeploymentRequestData.dns = customDomain.name } - // Create a DNS deployment for the new current deployment - const dnsDeployment = await this.createDeploymentFromData( + // Create a canonical deployment for the new current deployment + const canonicalDeployment = await this.createDeploymentFromData( newCurrentDeployment.project.ownerId, newCurrentDeployment, newCurrentDeployment.deployer!.deployerLrn!, @@ -1255,7 +1255,7 @@ export class Service { log(`Application deployment request record published: ${result.id}`) - await this.db.updateDeploymentById(dnsDeployment.id, { + await this.db.updateDeploymentById(canonicalDeployment.id, { applicationDeploymentRequestId: result.id, applicationDeploymentRequestData, }); @@ -1277,7 +1277,7 @@ export class Service { if (deployment && deployment.applicationDeploymentRecordId) { // If deployment is current, remove deployment for project subdomain as well if (deployment.isCurrent) { - const dnsDeployment = await this.db.getDeployment({ + const canonicalDeployment = await this.db.getDeployment({ where: { projectId: deployment.project.id, deployer: deployment.deployer, @@ -1289,21 +1289,21 @@ export class Service { }, }) - if (!dnsDeployment) { - log(`DNS deployment for deployment with id ${deployment.id} not found`); + if (!canonicalDeployment) { + log(`Canonical deployment for deployment with id ${deployment.id} not found`); return false; } const dnsResult = await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ - deploymentId: dnsDeployment.applicationDeploymentRecordId!, - deployerLrn: dnsDeployment.deployer.deployerLrn, - auctionId: dnsDeployment.project.auctionId, - payment: dnsDeployment.project.txHash + deploymentId: canonicalDeployment.applicationDeploymentRecordId!, + deployerLrn: canonicalDeployment.deployer.deployerLrn, + auctionId: canonicalDeployment.project.auctionId, + payment: canonicalDeployment.project.txHash }); - await this.db.updateDeploymentById(dnsDeployment.id, { + await this.db.updateDeploymentById(canonicalDeployment.id, { status: DeploymentStatus.Deleting, applicationDeploymentRemovalRequestId: dnsResult.applicationDeploymentRemovalRequestId, -- 2.45.2 From 027c88e1480f25f55e110635c92de24a655850fa Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 4 Feb 2025 15:04:46 +0530 Subject: [PATCH 57/59] Update deletion flow to handle deployments without canonical deployments --- packages/backend/src/service.ts | 56 ++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 6adb400a..1bf7ccbf 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1289,27 +1289,53 @@ export class Service { }, }) + // If the canonical deployment is not present then query the chain for the deployment record for backwards compatibility if (!canonicalDeployment) { - log(`Canonical deployment for deployment with id ${deployment.id} not found`); + log(`Canonical deployment for deployment with id ${deployment.id} not found, querying the chain..`); + const currentDeploymentURL = `https://${(deployment.project.name).toLowerCase()}.${deployment.deployer.baseDomain}`; - return false; - } + const deploymentRecords = + await this.laconicRegistry.getDeploymentRecordsByFilter({ + application: deployment.applicationRecordId, + url: currentDeploymentURL, + }); + + if (!deploymentRecords.length) { + log( + `No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`, + ); + + return false; + } + + // Multiple records are fetched, take the latest record + const latestRecord = deploymentRecords + .sort((a, b) => new Date(b.createTime).getTime() - new Date(a.createTime).getTime())[0]; - const dnsResult = await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ - deploymentId: canonicalDeployment.applicationDeploymentRecordId!, - deployerLrn: canonicalDeployment.deployer.deployerLrn, - auctionId: canonicalDeployment.project.auctionId, - payment: canonicalDeployment.project.txHash + deploymentId: latestRecord.id, + deployerLrn: deployment.deployer.deployerLrn, + auctionId: deployment.project.auctionId, + payment: deployment.project.txHash }); + } else { + // If canonical deployment is found in the DB, then send the removal request with that deployment record Id + const result = + await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ + deploymentId: canonicalDeployment.applicationDeploymentRecordId!, + deployerLrn: canonicalDeployment.deployer.deployerLrn, + auctionId: canonicalDeployment.project.auctionId, + payment: canonicalDeployment.project.txHash + }); - await this.db.updateDeploymentById(canonicalDeployment.id, { - status: DeploymentStatus.Deleting, - applicationDeploymentRemovalRequestId: - dnsResult.applicationDeploymentRemovalRequestId, - applicationDeploymentRemovalRequestData: - dnsResult.applicationDeploymentRemovalRequestData, - }); + await this.db.updateDeploymentById(canonicalDeployment.id, { + status: DeploymentStatus.Deleting, + applicationDeploymentRemovalRequestId: + result.applicationDeploymentRemovalRequestId, + applicationDeploymentRemovalRequestData: + result.applicationDeploymentRemovalRequestData, + }); + } } const result = -- 2.45.2 From 720411d5d2beb2a2e35f4016e0ecdba551caa5f7 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 4 Feb 2025 15:38:53 +0530 Subject: [PATCH 58/59] Update comment for backward compatibility --- packages/backend/src/service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 1bf7ccbf..86dd6bef 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -1289,7 +1289,7 @@ export class Service { }, }) - // If the canonical deployment is not present then query the chain for the deployment record for backwards compatibility + // If the canonical deployment is not present then query the chain for the deployment record for backward compatibility if (!canonicalDeployment) { log(`Canonical deployment for deployment with id ${deployment.id} not found, querying the chain..`); const currentDeploymentURL = `https://${(deployment.project.name).toLowerCase()}.${deployment.deployer.baseDomain}`; -- 2.45.2 From 21334df4cb2af48ae2262a5893e1c338e96fd058 Mon Sep 17 00:00:00 2001 From: IshaVenikar Date: Tue, 4 Feb 2025 17:36:45 +0530 Subject: [PATCH 59/59] Update method to rollback to previous version --- packages/backend/src/service.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/service.ts b/packages/backend/src/service.ts index 86dd6bef..0321df01 100644 --- a/packages/backend/src/service.ts +++ b/packages/backend/src/service.ts @@ -695,8 +695,8 @@ export class Service { // If a custom domain is present then use that as the DNS in the deployment request const customDomain = await this.db.getOldestDomainByProjectId(data.project!.id!); - // On deleting deployment later, project DNS deployment is also deleted - // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later + // On deleting deployment later, project canonical deployment is also deleted + // So publish project canonical deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later const { applicationDeploymentRequestData, applicationDeploymentRequestId } = await this.laconicRegistry.createApplicationDeploymentRequest({ deployment: canonicalDeployment, @@ -791,8 +791,8 @@ export class Service { // If a custom domain is present then use that as the DNS in the deployment request const customDomain = await this.db.getOldestDomainByProjectId(project!.id!); - // On deleting deployment later, project DNS deployment is also deleted - // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later + // On deleting deployment later, project canonical deployment is also deleted + // So publish project canonical deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later const { applicationDeploymentRequestId, applicationDeploymentRequestData } = await this.laconicRegistry.createApplicationDeploymentRequest({ deployment: canonicalDeployment, @@ -1218,6 +1218,10 @@ export class Service { { isCurrent: true }, ); + if (!newCurrentDeploymentUpdate || !oldCurrentDeploymentUpdate){ + return false; + } + const newCurrentDeployment = await this.db.getDeployment({ where: { id: deploymentId }, relations: { project: true, deployer: true } }); if (!newCurrentDeployment) { @@ -1255,12 +1259,12 @@ export class Service { log(`Application deployment request record published: ${result.id}`) - await this.db.updateDeploymentById(canonicalDeployment.id, { + const updateResult = await this.db.updateDeploymentById(canonicalDeployment.id, { applicationDeploymentRequestId: result.id, applicationDeploymentRequestData, }); - return newCurrentDeploymentUpdate && oldCurrentDeploymentUpdate; + return updateResult; } async deleteDeployment(deploymentId: string): Promise { -- 2.45.2