Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto Deploy refactored and sync methods removed #48

Merged
merged 3 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"request": "launch",
"name": "Launch Program",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/dist/server.js",
"program": "${workspaceFolder}/dist/index.js",
"preLaunchTask": "npm: buildDebug",
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
Expand Down
5 changes: 2 additions & 3 deletions src/controller/delete.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextFunction, Request, Response } from 'express';

import { ChildProcess } from 'child_process';
import { rmSync } from 'fs';
import { rm } from 'fs/promises';
import { join } from 'path';

import { allApplications, childProcesses } from '../constants';
Expand Down Expand Up @@ -29,7 +29,6 @@ type DeleteBody = {
version: string;
};

// TODO: Refactor this, do not use sync methods
export const deployDelete = catchAsync(
async (
req: Omit<Request, 'body'> & { body: DeleteBody },
Expand Down Expand Up @@ -65,7 +64,7 @@ export const deployDelete = catchAsync(
const appLocation = join(appsDirectory, app);

// Delete the directory of the application
rmSync(appLocation, { recursive: true, force: true });
await rm(appLocation, { recursive: true, force: true });

if (!(await ensureFolderExists(appLocation))) {
isError = true;
Expand Down
8 changes: 2 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import colors from 'colors';
import dotenv from 'dotenv';

import app from './app';
import { findJsonFilesRecursively } from './utils/autoDeploy';
import { autoDeployApps } from './utils/autoDeploy';
import { appsDirectory } from './utils/config';
import { ensureFolderExists } from './utils/utils';

Expand All @@ -14,11 +14,7 @@ void (async (): Promise<void> => {

await ensureFolderExists(appsDirectory);

// TODO: Refactor this
await findJsonFilesRecursively(appsDirectory);

console.log('Previously deployed applications deployed successfully');
// END-TODO
await autoDeployApps(appsDirectory);

const port = process.env.PORT || 9000;

Expand Down
113 changes: 68 additions & 45 deletions src/utils/autoDeploy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { pathIsMetaCallJson } from '@metacall/protocol/package';
import { MetaCallJSON, pathIsMetaCallJson } from '@metacall/protocol';
import { spawn } from 'child_process';
import * as fs from 'fs';
import * as fs from 'fs/promises';
import * as path from 'path';
import {
Deployment,
Expand All @@ -13,57 +13,80 @@ import {
} from '../constants';
import { isIAllApps, logProcessOutput } from './utils';

// TODO: Refactor this
export const findJsonFilesRecursively = async (
appsDir: string
): Promise<void> => {
// TODO: Avoid sync commands
const files = fs.readdirSync(appsDir, { withFileTypes: true });
for (const file of files) {
if (file.isDirectory()) {
await findJsonFilesRecursively(path.join(appsDir, file.name));
} else if (pathIsMetaCallJson(file.name)) {
const filePath = path.join(appsDir, file.name);
const desiredPath = path.join(
path.resolve(__dirname, '..'),
'worker',
'index.js'
);
const id = path.basename(appsDir);
export const autoDeployApps = async (appsDir: string): Promise<void> => {
const allDirectories = await fs.readdir(appsDir, { withFileTypes: true });

const deployment: Deployment = {
id,
type: 'application/x-zip-compressed',
path: appsDir,
jsons: []
};
let directoryProcessed = false;

const proc = spawn('metacall', [desiredPath, filePath], {
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
for (const directory of allDirectories) {
if (directory.isDirectory()) {
const directoryPath = path.join(appsDir, directory.name);
const directoryFiles = await fs.readdir(directoryPath, {
withFileTypes: true
});

const message: WorkerMessage<Deployment> = {
type: ProtocolMessageType.Load,
data: deployment
};
const jsonFiles = directoryFiles
.filter(file => file.isFile() && pathIsMetaCallJson(file.name))
.map(file => path.join(directoryPath, file.name));

proc.send(message);
if (jsonFiles.length > 0) {
directoryProcessed = true;

logProcessOutput(proc.stdout, proc.pid, deployment.id);
logProcessOutput(proc.stderr, proc.pid, deployment.id);
const desiredPath = path.join(
path.resolve(__dirname, '..'),
'worker',
'index.js'
);

proc.on('message', (payload: WorkerMessageUnknown) => {
if (payload.type === ProtocolMessageType.MetaData) {
const message = payload as WorkerMessage<
Record<string, IAppWithFunctions>
>;
if (isIAllApps(message.data)) {
const appName = Object.keys(message.data)[0];
childProcesses[appName] = proc;
allApplications[appName] = message.data[appName];
const jsonContent: MetaCallJSON[] = await Promise.all(
jsonFiles.map(async file => {
const content = await fs.readFile(file, 'utf-8');

// map method returns array.That's why didn't passed MetaCallJSON[]
return JSON.parse(content) as MetaCallJSON;
})
);

const deployment: Deployment = {
id: directory.name,
type: 'application/x-zip-compressed',
path: directoryPath,
jsons: jsonContent
};

const proc = spawn('metacall', [desiredPath, ...jsonFiles], {
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
});

const message: WorkerMessage<Deployment> = {
type: ProtocolMessageType.Load,
data: deployment
};

proc.send(message);

logProcessOutput(proc.stdout, proc.pid, deployment.id);
logProcessOutput(proc.stderr, proc.pid, deployment.id);

proc.on('message', (payload: WorkerMessageUnknown) => {
if (payload.type === ProtocolMessageType.MetaData) {
const message = payload as WorkerMessage<
Record<string, IAppWithFunctions>
>;
if (isIAllApps(message.data)) {
const appName = Object.keys(message.data)[0];
childProcesses[appName] = proc;
allApplications[appName] = message.data[appName];
}
}
}
});
});
}
}
}

if (directoryProcessed) {
console.log(
'Previously deployed applications deployed successfully'.green
);
}
};
Loading