Add method deployment requests after auction completion

This commit is contained in:
IshaVenikar 2024-10-04 16:06:29 +05:30 committed by Nabarun
parent 2a3c5de132
commit 8c824f065b
4 changed files with 93 additions and 102 deletions

View File

@ -49,6 +49,9 @@ export class Project {
@Column('varchar', { nullable: true }) @Column('varchar', { nullable: true })
auctionId?: string | null; auctionId?: string | null;
@Column('varchar', { nullable: true })
auctionStatus?: string | null;
@Column('varchar', { nullable: true }) @Column('varchar', { nullable: true })
deployerLrn?: string[] | null; deployerLrn?: string[] | null;

View File

@ -2,6 +2,8 @@ import debug from 'debug';
import assert from 'assert'; import assert from 'assert';
import { inc as semverInc } from 'semver'; import { inc as semverInc } from 'semver';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { DeepPartial } from 'typeorm';
import { Octokit } from 'octokit';
import { Registry as LaconicRegistry, parseGasAndFees } from '@cerc-io/registry-sdk'; import { Registry as LaconicRegistry, parseGasAndFees } from '@cerc-io/registry-sdk';
@ -151,17 +153,56 @@ export class Registry {
}; };
} }
async createApplicationDeploymentAuction (data: { async createApplicationDeploymentAuction (
deployment: Deployment,
appName: string, appName: string,
}, octokit: Octokit,
auctionData: AuctionData, auctionData: AuctionData,
): Promise<{ data: DeepPartial<Deployment>,
): Promise<{
applicationDeploymentAuctionId: string; applicationDeploymentAuctionId: string;
applicationDeploymentAuctionData: ApplicationDeploymentAuction;
deployerLrns: string[];
}> { }> {
const lrn = this.getLrn(data.appName); // TODO: If data.domain is present then call createDeployment (don't need auction)
assert(data.project?.repository, 'Project repository not found');
const [owner, repo] = data.project.repository.split('/');
const { data: packageJSONData } = await octokit.rest.repos.getContent({
owner,
repo,
path: 'package.json',
ref: data.commitHash,
});
if (!packageJSONData) {
throw new Error('Package.json file not found');
}
assert(!Array.isArray(packageJSONData) && packageJSONData.type === 'file');
const packageJSON: PackageJSON = JSON.parse(atob(packageJSONData.content));
assert(packageJSON.name, "name field doesn't exist in package.json");
const repoUrl = (
await octokit.rest.repos.get({
owner,
repo,
})
).data.html_url;
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
const { applicationRecordId, applicationRecordData } =
await this.createApplicationRecord({
appName: repo,
packageJSON,
appType: data.project!.template!,
commitHash: data.commitHash!,
repoUrl,
});
log(
`Published application record ${applicationRecordId}`,
);
const lrn = this.getLrn(appName);
const records = await this.registry.resolveNames([lrn]); const records = await this.registry.resolveNames([lrn]);
const applicationRecord = records[0]; const applicationRecord = records[0];
@ -198,8 +239,6 @@ export class Registry {
type: APP_DEPLOYMENT_AUCTION_RECORD_TYPE, type: APP_DEPLOYMENT_AUCTION_RECORD_TYPE,
}; };
await sleep(SLEEP_DURATION);
const result = await this.registry.setRecord( const result = await this.registry.setRecord(
{ {
privateKey: this.registryConfig.privateKey, privateKey: this.registryConfig.privateKey,
@ -212,25 +251,8 @@ export class Registry {
log(`Application deployment auction record published: ${result.id}`); log(`Application deployment auction record published: ${result.id}`);
log('Application deployment auction data:', applicationDeploymentAuction); log('Application deployment auction data:', applicationDeploymentAuction);
let deployerLrns = [];
const { winnerAddresses } = auctionResult.auction;
for (const auctionWinner of winnerAddresses) {
const deployerRecord = await this.registry.queryRecords(
{
paymentAddress: auctionWinner,
},
true
);
const lrn = deployerRecord.names.length > 0 ? deployerRecord.names[0] : null;
deployerLrns.push(lrn);
}
return { return {
applicationDeploymentAuctionId: auctionResult.auction.id, applicationDeploymentAuctionId: auctionResult.auction.id,
applicationDeploymentAuctionData: applicationDeploymentAuction,
deployerLrns
}; };
} }
@ -300,6 +322,30 @@ export class Registry {
}; };
} }
async getAuctionWinners(
auctionId: string
): Promise<string[]> {
const records = await this.registry.getAuctionsByIds([auctionId]);
const auctionResult = records[0];
let deployerLrns = [];
const { winnerAddresses } = auctionResult.auction;
for (const auctionWinner of winnerAddresses) {
const deployerRecord = await this.registry.queryRecords(
{
paymentAddress: auctionWinner,
},
true
);
const lrn = deployerRecord.names.length > 0 ? deployerRecord.names[0] : null;
deployerLrns.push(lrn);
}
return deployerLrns;
}
/** /**
* Fetch ApplicationDeploymentRecords for deployments * Fetch ApplicationDeploymentRecords for deployments
*/ */

View File

@ -67,6 +67,7 @@ type Project {
description: String description: String
deployerLrn: [String] deployerLrn: [String]
auctionId: String auctionId: String
auctionStatus: String
template: String template: String
framework: String framework: String
webhooks: [String!] webhooks: [String!]

View File

@ -657,62 +657,11 @@ export class Service {
async createDeploymentFromAuction( async createDeploymentFromAuction(
userId: string, userId: string,
octokit: Octokit, auctionId: string,
// take project data
data: DeepPartial<Deployment>, data: DeepPartial<Deployment>,
auctionData: AuctionData ) {
): Promise<Deployment> { // TODO: If data.domain is present then call createDeployment (don't need auction)
assert(data.project?.repository, 'Project repository not found');
log(
`Creating deployment in project ${data.project.name} from branch ${data.branch}`,
);
const [owner, repo] = data.project.repository.split('/');
const { data: packageJSONData } = await octokit.rest.repos.getContent({
owner,
repo,
path: 'package.json',
ref: data.commitHash,
});
if (!packageJSONData) {
throw new Error('Package.json file not found');
}
assert(!Array.isArray(packageJSONData) && packageJSONData.type === 'file');
const packageJSON: PackageJSON = JSON.parse(atob(packageJSONData.content));
assert(packageJSON.name, "name field doesn't exist in package.json");
const repoUrl = (
await octokit.rest.repos.get({
owner,
repo,
})
).data.html_url;
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
const { applicationRecordId, applicationRecordData } =
await this.registry.createApplicationRecord({
appName: repo,
packageJSON,
appType: data.project!.template!,
commitHash: data.commitHash!,
repoUrl,
});
// 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,
},
);
}
const newDeployment = await this.db.addDeployment({ const newDeployment = await this.db.addDeployment({
project: data.project, project: data.project,
branch: data.branch, branch: data.branch,
@ -720,8 +669,6 @@ export class Service {
commitMessage: data.commitMessage, commitMessage: data.commitMessage,
environment: data.environment, environment: data.environment,
status: DeploymentStatus.Building, status: DeploymentStatus.Building,
applicationRecordId,
applicationRecordData,
domain: data.domain, domain: data.domain,
createdBy: Object.assign(new User(), { createdBy: Object.assign(new User(), {
id: userId, id: userId,
@ -729,19 +676,11 @@ export class Service {
}); });
log( log(
`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`, `Created deployment ${newDeployment.id}`,
); );
const deploymentAuctionData = await this.registry.createApplicationDeploymentAuction({
deployment: newDeployment,
appName: repo
}, auctionData
);
const deploymentAuctionId = deploymentAuctionData.applicationDeploymentAuctionId;
const environmentVariables = const environmentVariables =
await this.db.getEnvironmentVariablesByProjectId(data.project.id!, { await this.db.getEnvironmentVariablesByProjectId(data.project!.id!, {
environment: Environment.Production, environment: Environment.Production,
}); });
@ -760,21 +699,23 @@ export class Service {
// So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later
await this.registry.createApplicationDeploymentRequest({ await this.registry.createApplicationDeploymentRequest({
deployment: newDeployment, deployment: newDeployment,
appName: repo, appName: data.project!.name!,
repository: repoUrl, repository: data.url!,
environmentVariables: environmentVariablesObj, environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}`, dns: `${newDeployment.project.name}`,
}); });
} }
for (const deployer in deploymentAuctionData.deployerLrns) { const deployerLrns = await this.registry.getAuctionWinners(auctionId);
for (const deployer in deployerLrns) {
const { applicationDeploymentRequestId, applicationDeploymentRequestData } = const { applicationDeploymentRequestId, applicationDeploymentRequestData } =
// Create requests for all the deployers // Create requests for all the deployers
await this.registry.createApplicationDeploymentRequest({ await this.registry.createApplicationDeploymentRequest({
deployment: newDeployment, deployment: newDeployment,
appName: repo, appName: data.project!.name!,
repository: repoUrl, repository: data.url!,
auctionId: deploymentAuctionId, auctionId,
lrn: deployer, lrn: deployer,
environmentVariables: environmentVariablesObj, environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`, dns: `${newDeployment.project.name}-${newDeployment.id}`,
@ -843,7 +784,7 @@ export class Service {
organizationSlug: string, organizationSlug: string,
data: DeepPartial<Project>, data: DeepPartial<Project>,
lrn?: string, lrn?: string,
auctiondata?: AuctionData auctionData?: AuctionData
): Promise<Project | undefined> { ): Promise<Project | undefined> {
const organization = await this.db.getOrganization({ const organization = await this.db.getOrganization({
where: { where: {
@ -878,8 +819,8 @@ export class Service {
commitMessage: latestCommit.commit.message, commitMessage: latestCommit.commit.message,
}; };
const deployment = auctiondata const deployment = auctionData
? await this.createDeploymentFromAuction(user.id, octokit, deploymentData, auctiondata) ? await this.registry.createApplicationDeploymentAuction(repo, octokit, auctionData!, deploymentData)
: await this.createDeployment(user.id, octokit, deploymentData, lrn); : await this.createDeployment(user.id, octokit, deploymentData, lrn);
await this.createRepoHook(octokit, project); await this.createRepoHook(octokit, project);