Integrate SP auctions for app deployment #2
@ -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;
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -67,6 +67,7 @@ type Project {
|
||||
description: String
|
||||
deployerLrn: [String]
|
||||
auctionId: String
|
||||
auctionStatus: String
|
||||
template: String
|
||||
framework: String
|
||||
webhooks: [String!]
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user