Add method deployment requests after auction completion
This commit is contained in:
parent
5bde36228d
commit
5bba3c7f5c
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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!]
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user