Integrate SP auctions for app deployment #2

Merged
nabarun merged 42 commits from ng-integrate-auction into main 2024-10-18 12:37:01 +00:00
4 changed files with 93 additions and 102 deletions
Showing only changes of commit 8c824f065b - Show all commits

View File

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

View File

@ -2,6 +2,8 @@ import debug from 'debug';
import assert from 'assert';
import { inc as semverInc } from 'semver';
import { DateTime } from 'luxon';
import { DeepPartial } from 'typeorm';
import { Octokit } from 'octokit';
import { Registry as LaconicRegistry, parseGasAndFees } from '@cerc-io/registry-sdk';
@ -151,17 +153,56 @@ export class Registry {
};
}
async createApplicationDeploymentAuction (data: {
deployment: Deployment,
async createApplicationDeploymentAuction (
appName: string,
},
octokit: Octokit,
auctionData: AuctionData,
): Promise<{
data: DeepPartial<Deployment>,
): Promise<{
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 applicationRecord = records[0];
@ -198,8 +239,6 @@ export class Registry {
type: APP_DEPLOYMENT_AUCTION_RECORD_TYPE,
};
await sleep(SLEEP_DURATION);
const result = await this.registry.setRecord(
{
privateKey: this.registryConfig.privateKey,
@ -212,25 +251,8 @@ export class Registry {
log(`Application deployment auction record published: ${result.id}`);
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 {
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
*/

View File

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

View File

@ -657,62 +657,11 @@ export class Service {
async createDeploymentFromAuction(
userId: string,
octokit: Octokit,
auctionId: string,
// take project data
data: DeepPartial<Deployment>,
auctionData: AuctionData
): Promise<Deployment> {
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,
},
);
}
) {
// TODO: If data.domain is present then call createDeployment (don't need auction)
const newDeployment = await this.db.addDeployment({
project: data.project,
branch: data.branch,
@ -720,8 +669,6 @@ export class Service {
commitMessage: data.commitMessage,
environment: data.environment,
status: DeploymentStatus.Building,
applicationRecordId,
applicationRecordData,
domain: data.domain,
createdBy: Object.assign(new User(), {
id: userId,
@ -729,19 +676,11 @@ export class Service {
});
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 =
await this.db.getEnvironmentVariablesByProjectId(data.project.id!, {
await this.db.getEnvironmentVariablesByProjectId(data.project!.id!, {
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
await this.registry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
appName: data.project!.name!,
repository: data.url!,
environmentVariables: environmentVariablesObj,
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 } =
// Create requests for all the deployers
await this.registry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
auctionId: deploymentAuctionId,
appName: data.project!.name!,
repository: data.url!,
auctionId,
lrn: deployer,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`,
@ -843,7 +784,7 @@ export class Service {
organizationSlug: string,
data: DeepPartial<Project>,
lrn?: string,
auctiondata?: AuctionData
auctionData?: AuctionData
): Promise<Project | undefined> {
const organization = await this.db.getOrganization({
where: {
@ -878,8 +819,8 @@ export class Service {
commitMessage: latestCommit.commit.message,
};
const deployment = auctiondata
? await this.createDeploymentFromAuction(user.id, octokit, deploymentData, auctiondata)
const deployment = auctionData
? await this.registry.createApplicationDeploymentAuction(repo, octokit, auctionData!, deploymentData)
: await this.createDeployment(user.id, octokit, deploymentData, lrn);
await this.createRepoHook(octokit, project);