Display deployment build logs #8
@ -1,16 +1,16 @@
|
|||||||
import { Entity, PrimaryColumn, Column, OneToMany } from 'typeorm';
|
import { Entity, PrimaryColumn, Column } from 'typeorm';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Deployer {
|
export class Deployer {
|
||||||
@PrimaryColumn()
|
@PrimaryColumn('varchar')
|
||||||
deployerId!: string;
|
deployerId!: string;
|
||||||
|
|
||||||
@Column()
|
@Column('varchar')
|
||||||
deployerLrn!: string;
|
deployerLrn!: string;
|
||||||
|
|
||||||
@Column()
|
@Column('varchar')
|
||||||
deployerApiUrl!: string;
|
deployerApiUrl!: string;
|
||||||
|
|
||||||
@Column()
|
@Column('varchar')
|
||||||
baseDomain!: string;
|
baseDomain!: string;
|
||||||
}
|
}
|
||||||
|
@ -140,9 +140,6 @@ export class Deployment {
|
|||||||
@Column('boolean', { default: false })
|
@Column('boolean', { default: false })
|
||||||
isCurrent!: boolean;
|
isCurrent!: boolean;
|
||||||
|
|
||||||
@Column('varchar', { nullable: true })
|
|
||||||
baseDomain!: string | null;
|
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
enum: DeploymentStatus
|
enum: DeploymentStatus
|
||||||
})
|
})
|
||||||
|
@ -117,7 +117,7 @@ export class Registry {
|
|||||||
this.registryConfig.privateKey,
|
this.registryConfig.privateKey,
|
||||||
fee
|
fee
|
||||||
);
|
);
|
||||||
log("Result: ", result);
|
|
||||||
log(`Published application record ${result.id}`);
|
log(`Published application record ${result.id}`);
|
||||||
log('Application record data:', applicationRecord);
|
log('Application record data:', applicationRecord);
|
||||||
|
|
||||||
@ -302,13 +302,9 @@ export class Registry {
|
|||||||
const { winnerAddresses } = auctionResult;
|
const { winnerAddresses } = auctionResult;
|
||||||
|
|
||||||
for (const auctionWinner of winnerAddresses) {
|
for (const auctionWinner of winnerAddresses) {
|
||||||
const records = await this.registry.queryRecords(
|
const records = await this.getDeployerRecordsByFilter({
|
||||||
{
|
|
||||||
paymentAddress: auctionWinner,
|
paymentAddress: auctionWinner,
|
||||||
type: WEBAPP_DEPLOYER_RECORD_TYPE,
|
});
|
||||||
},
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const record of records) {
|
for (const record of records) {
|
||||||
if (record.id) {
|
if (record.id) {
|
||||||
@ -361,6 +357,19 @@ export class Registry {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch WebappDeployer Records by filter
|
||||||
|
*/
|
||||||
|
async getDeployerRecordsByFilter(filter: { [key: string]: any }): Promise<DeployerRecord[]> {
|
||||||
|
return this.registry.queryRecords(
|
||||||
|
{
|
||||||
|
type: WEBAPP_DEPLOYER_RECORD_TYPE,
|
||||||
|
...filter
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch ApplicationDeploymentRecords by filter
|
* Fetch ApplicationDeploymentRecords by filter
|
||||||
*/
|
*/
|
||||||
|
@ -176,6 +176,7 @@ export class Service {
|
|||||||
})),
|
})),
|
||||||
relations: {
|
relations: {
|
||||||
deployer: true,
|
deployer: true,
|
||||||
|
project: true,
|
||||||
},
|
},
|
||||||
order: {
|
order: {
|
||||||
createdAt: 'DESC',
|
createdAt: 'DESC',
|
||||||
@ -194,17 +195,19 @@ export class Service {
|
|||||||
const deploymentUpdatePromises = records.map(async (record) => {
|
const deploymentUpdatePromises = records.map(async (record) => {
|
||||||
const deployment = recordToDeploymentsMap[record.attributes.request];
|
const deployment = recordToDeploymentsMap[record.attributes.request];
|
||||||
|
|
||||||
const parts = record.attributes.url.replace('https://', '').split('.');
|
if (!deployment.project) {
|
||||||
const baseDomain = parts.slice(1).join('.');
|
log(`Project ${deployment.projectId} not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
deployment.applicationDeploymentRecordId = record.id;
|
deployment.applicationDeploymentRecordId = record.id;
|
||||||
deployment.applicationDeploymentRecordData = record.attributes;
|
deployment.applicationDeploymentRecordData = record.attributes;
|
||||||
deployment.url = record.attributes.url;
|
deployment.url = record.attributes.url;
|
||||||
deployment.baseDomain = baseDomain;
|
|
||||||
deployment.status = DeploymentStatus.Ready;
|
deployment.status = DeploymentStatus.Ready;
|
||||||
deployment.isCurrent = deployment.environment === Environment.Production;
|
deployment.isCurrent = deployment.environment === Environment.Production;
|
||||||
|
|
||||||
await this.db.updateDeploymentById(deployment.id, deployment);
|
await this.db.updateDeploymentById(deployment.id, deployment);
|
||||||
|
}
|
||||||
|
|
||||||
log(
|
log(
|
||||||
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`,
|
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`,
|
||||||
@ -314,27 +317,27 @@ export class Service {
|
|||||||
|
|
||||||
for (const record of deployerRecords) {
|
for (const record of deployerRecords) {
|
||||||
const deployerId = record.id;
|
const deployerId = record.id;
|
||||||
const deployerLrn = record.names[0]
|
const deployerLrn = record.names[0];
|
||||||
const deployerApiUrl = record.attributes.apiUrl;
|
|
||||||
|
|
||||||
deployerIds.push(deployerId);
|
deployerIds.push(deployerId);
|
||||||
deployerLrns.push(deployerLrn);
|
deployerLrns.push(deployerLrn);
|
||||||
|
|
||||||
|
const deployerApiUrl = record.attributes.apiUrl;
|
||||||
|
const apiURL = new URL(deployerApiUrl);
|
||||||
|
const baseDomain = apiURL.hostname.split('.').slice(-3).join('.');
|
||||||
|
|
||||||
const deployerData = {
|
const deployerData = {
|
||||||
deployerId,
|
deployerId,
|
||||||
deployerLrn,
|
deployerLrn,
|
||||||
deployerApiUrl,
|
deployerApiUrl,
|
||||||
|
baseDomain
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store the deployer in the DB
|
// Store the deployer in the DB
|
||||||
|
// TODO: Update project with deployer
|
||||||
await this.db.addDeployer(deployerData);
|
await this.db.addDeployer(deployerData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:Update project with deployer LRNs
|
|
||||||
// await this.db.updateProjectById(project.id!, {
|
|
||||||
// deployerLrns
|
|
||||||
// });
|
|
||||||
|
|
||||||
for (const deployer of deployerIds) {
|
for (const deployer of deployerIds) {
|
||||||
log(`Creating deployment for deployer LRN ${deployer}`);
|
log(`Creating deployment for deployer LRN ${deployer}`);
|
||||||
await this.createDeploymentFromAuction(project, deployer);
|
await this.createDeploymentFromAuction(project, deployer);
|
||||||
@ -676,6 +679,19 @@ export class Service {
|
|||||||
applicationDeploymentRequestData,
|
applicationDeploymentRequestData,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// const deployerRecord = await this.laconicRegistry.getDeployerRecordsByFilter({
|
||||||
|
// name: deployerLrn,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// TODO: Store deployer data
|
||||||
|
// newDeployment.project.deployers.push({
|
||||||
|
// deployerId: deployerRecord[0].id,
|
||||||
|
// deployerApiUrl: deployerRecord[0].attributes.apiUrl,
|
||||||
|
// })
|
||||||
|
// await this.updateProject(newDeployment.project.id, {
|
||||||
|
// deployers:
|
||||||
|
// });
|
||||||
|
|
||||||
return newDeployment;
|
return newDeployment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -886,7 +902,7 @@ export class Service {
|
|||||||
|
|
||||||
if (auctionParams) {
|
if (auctionParams) {
|
||||||
const { applicationDeploymentAuctionId } = await this.laconicRegistry.createApplicationDeploymentAuction(repo, octokit, auctionParams!, deploymentData);
|
const { applicationDeploymentAuctionId } = await this.laconicRegistry.createApplicationDeploymentAuction(repo, octokit, auctionParams!, deploymentData);
|
||||||
await this.updateProject(project.id, { auctionId: applicationDeploymentAuctionId })
|
await this.updateProject(project.id, { auctionId: applicationDeploymentAuctionId });
|
||||||
} else {
|
} else {
|
||||||
await this.createDeployment(user.id, octokit, deploymentData);
|
await this.createDeployment(user.id, octokit, deploymentData);
|
||||||
// await this.updateProject(project.id, { deployerLrns: [lrn!] })
|
// await this.updateProject(project.id, { deployerLrns: [lrn!] })
|
||||||
@ -966,6 +982,9 @@ export class Service {
|
|||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
const deployers = project.deployers;
|
||||||
|
if (!deployers) return;
|
||||||
|
|
||||||
// for (const deployer of deployers) {
|
// for (const deployer of deployers) {
|
||||||
// Create deployment with branch and latest commit in GitHub data
|
// Create deployment with branch and latest commit in GitHub data
|
||||||
await this.createDeployment(project.ownerId, octokit,
|
await this.createDeployment(project.ownerId, octokit,
|
||||||
@ -1101,7 +1120,7 @@ export class Service {
|
|||||||
if (deployment && deployment.applicationDeploymentRecordId) {
|
if (deployment && deployment.applicationDeploymentRecordId) {
|
||||||
// If deployment is current, remove deployment for project subdomain as well
|
// If deployment is current, remove deployment for project subdomain as well
|
||||||
if (deployment.isCurrent) {
|
if (deployment.isCurrent) {
|
||||||
const currentDeploymentURL = `https://${(deployment.project.name).toLowerCase()}.${deployment.baseDomain}`;
|
const currentDeploymentURL = `https://${(deployment.project.name).toLowerCase()}.${deployment.deployer.baseDomain}`;
|
||||||
|
|
||||||
// TODO: Store the latest DNS deployment record
|
// TODO: Store the latest DNS deployment record
|
||||||
const deploymentRecords =
|
const deploymentRecords =
|
||||||
|
@ -6,6 +6,14 @@ import {
|
|||||||
Environment,
|
Environment,
|
||||||
Project,
|
Project,
|
||||||
} from 'gql-client';
|
} from 'gql-client';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
} from '@mui/material';
|
||||||
|
|
||||||
import { Avatar } from 'components/shared/Avatar';
|
import { Avatar } from 'components/shared/Avatar';
|
||||||
import {
|
import {
|
||||||
BranchStrokeIcon,
|
BranchStrokeIcon,
|
||||||
@ -15,12 +23,6 @@ import {
|
|||||||
LoadingIcon,
|
LoadingIcon,
|
||||||
WarningIcon,
|
WarningIcon,
|
||||||
} from 'components/shared/CustomIcon';
|
} from 'components/shared/CustomIcon';
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogTitle,
|
|
||||||
DialogContent,
|
|
||||||
DialogActions,
|
|
||||||
} from '@mui/material';
|
|
||||||
import { Heading } from 'components/shared/Heading';
|
import { Heading } from 'components/shared/Heading';
|
||||||
import { OverflownText } from 'components/shared/OverflownText';
|
import { OverflownText } from 'components/shared/OverflownText';
|
||||||
import { Tag, TagTheme } from 'components/shared/Tag';
|
import { Tag, TagTheme } from 'components/shared/Tag';
|
||||||
@ -66,10 +68,10 @@ const DeploymentDetailsCard = ({
|
|||||||
prodBranchDomains,
|
prodBranchDomains,
|
||||||
}: DeployDetailsCardProps) => {
|
}: DeployDetailsCardProps) => {
|
||||||
const [openDialog, setOpenDialog] = useState<boolean>(false);
|
const [openDialog, setOpenDialog] = useState<boolean>(false);
|
||||||
const handleOpenDialog = () => setOpenDialog(true);
|
|
||||||
const handleCloseDialog = () => setOpenDialog(false);
|
|
||||||
const [deploymentLogs, setDeploymentLogs] = useState<string>();
|
const [deploymentLogs, setDeploymentLogs] = useState<string>();
|
||||||
|
|
||||||
|
const handleOpenDialog = () => setOpenDialog(true);
|
||||||
|
const handleCloseDialog = () => setOpenDialog(false);
|
||||||
|
|
||||||
const getIconByDeploymentStatus = (status: DeploymentStatus) => {
|
const getIconByDeploymentStatus = (status: DeploymentStatus) => {
|
||||||
if (
|
if (
|
||||||
@ -89,7 +91,7 @@ const DeploymentDetailsCard = ({
|
|||||||
|
|
||||||
const fetchDeploymentLogs = useCallback(async () => {
|
const fetchDeploymentLogs = useCallback(async () => {
|
||||||
let url = `${deployment.deployer.deployerApiUrl}/log/${deployment.applicationDeploymentRequestId}`;
|
let url = `${deployment.deployer.deployerApiUrl}/log/${deployment.applicationDeploymentRequestId}`;
|
||||||
const res = await fetch(url);
|
const res = await fetch(url, { cache: 'no-store' });
|
||||||
const logs = await res.text();
|
const logs = await res.text();
|
||||||
setDeploymentLogs(logs);
|
setDeploymentLogs(logs);
|
||||||
handleOpenDialog();
|
handleOpenDialog();
|
||||||
|
Loading…
Reference in New Issue
Block a user