Skip to content

Commit

Permalink
馃搧 Automatic plugins sync (#2781)
Browse files Browse the repository at this point in the history
* feat: created plugins api

* fix: lint

* feat: updated plugins sync

* feat: updated plugin id and secret

* fix: option pluginRepo

* Rename camelcase field

---------

Co-authored-by: Romaric Mourgues <rmourgues@linagora.com>
  • Loading branch information
MontaGhanmy and RomaricMourgues committed Mar 28, 2023
1 parent f375d46 commit 89b5368
Show file tree
Hide file tree
Showing 17 changed files with 233 additions and 1 deletion.
3 changes: 2 additions & 1 deletion twake/backend/node/config/default.json
Expand Up @@ -141,7 +141,8 @@
}
},
"plugins": {
"server": "plugins:3100"
"server": "plugins:3100",
"api": "http://localhost:6000/api"
},
"knowledge-graph": {
"endpoint": "http://host-gateway:8888",
Expand Down
Expand Up @@ -109,6 +109,7 @@ export type ApplicationIdentity = {
website: string;
categories: string[];
compatibility: "twake"[];
repository?: string;
};

export type ApplicationPublication = {
Expand Down
Expand Up @@ -23,6 +23,8 @@ import { ApplicationEventRequestBody } from "../types";
import { logger as log } from "../../../../core/platform/framework";
import { hasCompanyAdminLevel } from "../../../../utils/company";
import gr from "../../../global-resolver";
import config from "../../../../core/config";
import axios from "axios";

export class ApplicationController
implements
Expand Down Expand Up @@ -83,6 +85,7 @@ export class ApplicationController
try {
const app = request.body.resource;
const now = new Date().getTime();
const pluginsEndpoint = config.get("plugins.api");

let entity: Application;

Expand Down Expand Up @@ -144,6 +147,34 @@ export class ApplicationController
entity = res.entity;
}

// SYNC PLUGINS
if (app.identity.repository) {
try {
axios
.post(
`${pluginsEndpoint}/add`,
{
gitRepo: app.identity.repository,
pluginId: entity.getApplicationObject().id,
pluginSecret: entity.getApplicationObject().api.private_key,
},
{
headers: {
"Content-Type": "application/json",
},
},
)
.then(response => {
log.info(response.data);
})
.catch(error => {
log.error(error);
});
} catch (error) {
console.error(error);
}
}

return {
resource: entity.getApplicationObject(),
};
Expand Down
2 changes: 2 additions & 0 deletions twake/docker-compose.dev.mongo.yml
Expand Up @@ -18,11 +18,13 @@ services:
volumes:
- ./plugins/plugins:/usr/src/app/plugins
- ./plugins/plugins.json:/usr/src/app/plugins.json
- ./plugins/api:/usr/src/app/api
build:
context: .
dockerfile: ./docker/twake-plugins/Dockerfile
ports:
- 8080:8080
- 6000:6000
networks:
- twake_network

Expand Down
6 changes: 6 additions & 0 deletions twake/docker/twake-plugins/Dockerfile
Expand Up @@ -16,6 +16,12 @@ RUN mv scripts/* /bin
RUN apk update
RUN apk add git

# SYNC API
WORKDIR /usr/src/app/api
RUN npm install
#RUN npm run build
ENTRYPOINT ["npm", "run", "start:dev"]




Expand Down
21 changes: 21 additions & 0 deletions twake/plugins/api/package.json
@@ -0,0 +1,21 @@
{
"name": "api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "tsc",
"start:dev": "node dist/index.js",
"start": "ts-node src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/express": "^4.17.17",
"express": "^4.18.2",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
}
}
18 changes: 18 additions & 0 deletions twake/plugins/api/src/handlers/addHandler.ts
@@ -0,0 +1,18 @@
import { Request, Response } from "express";
import { runCommand } from "./utils/runCommand";

export const addPluginHandler = async (req: Request, res: Response) => {
const { gitRepo, pluginId, pluginSecret, envVar } = req.body;

if (!gitRepo || !pluginId || !pluginSecret) {
return res.status(400).send("Missing required parameters");
}

try {
await runCommand("add", [gitRepo, pluginId, pluginSecret, envVar]);
res.send("Plugin added successfully");
} catch (err:any) {
console.error(err);
res.status(500).send("Error adding plugin");
}
};
17 changes: 17 additions & 0 deletions twake/plugins/api/src/handlers/buildHandler.ts
@@ -0,0 +1,17 @@
import { Request, Response } from "express";
import { runCommand } from "./utils/runCommand";

export const buildPluginHandler = async (req: Request, res: Response) => {
const { gitRepo } = req.body;

if (!gitRepo) {
return res.status(400).send("Missing required parameters");
}

try {
await runCommand("build", [gitRepo]);
res.send("Plugin built successfully");
} catch (err:any) {
res.status(500).send(`Error building plugin: ${err.message}`);
}
};
13 changes: 13 additions & 0 deletions twake/plugins/api/src/handlers/deleteHandler.ts
@@ -0,0 +1,13 @@
import { Request, Response } from "express";
import { runCommand } from "./utils/runCommand";

export const deletePluginHandler = async (req: Request, res: Response) => {
const pluginName = req.params.pluginName;

try {
await runCommand("delete", [pluginName]);
res.send(`Plugin ${pluginName} deleted successfully`);
} catch (err:any) {
res.status(500).send(`Error deleting plugin ${pluginName}: ${err.message}`);
}
}
6 changes: 6 additions & 0 deletions twake/plugins/api/src/handlers/index.ts
@@ -0,0 +1,6 @@
export { addPluginHandler } from './addHandler';
export { startPluginHandler } from './startHandler';
export { buildPluginHandler } from './buildHandler';
export { updatePluginHandler } from './updateHandler';
export { deletePluginHandler } from './deleteHandler';
export { listPluginHandler } from './listHandler';
11 changes: 11 additions & 0 deletions twake/plugins/api/src/handlers/listHandler.ts
@@ -0,0 +1,11 @@
import { Request, Response } from "express";
import { runCommand } from "./utils/runCommand";

export const listPluginHandler = async (req: Request, res: Response) => {
try {
const output = await runCommand("list", []);
res.send(output);
} catch (err:any) {
res.status(500).send(`Error listing plugins: ${err.message}`);
}
}
11 changes: 11 additions & 0 deletions twake/plugins/api/src/handlers/startHandler.ts
@@ -0,0 +1,11 @@
import { Request, Response } from "express";
import { runCommand } from "./utils/runCommand";

export const startPluginHandler = async (req: Request, res: Response) => {
try {
await runCommand("start", []);
res.send("Plugins started successfully");
} catch (err:any) {
res.status(500).send(`Error starting plugins: ${err.message}`);
}
};
13 changes: 13 additions & 0 deletions twake/plugins/api/src/handlers/updateHandler.ts
@@ -0,0 +1,13 @@
import { Request, Response } from "express";
import { runCommand } from "./utils/runCommand";

export const updatePluginHandler = async (req: Request, res: Response) => {
const pluginName = req.params.pluginName;

try {
await runCommand("update", [pluginName]);
res.send(`Plugin ${pluginName} updated successfully`);
} catch (err:any) {
res.status(500).send(`Error updating plugin ${pluginName}: ${err.message}`);
}
}
28 changes: 28 additions & 0 deletions twake/plugins/api/src/handlers/utils/runCommand.ts
@@ -0,0 +1,28 @@
import { spawn } from "child_process";

export const runCommand = (
command: string,
args: string[]
): Promise<string> => {
return new Promise((resolve, reject) => {
const cmd = spawn(command, args);

let output = "";

cmd.stdout.on("data", (data) => {
output += data;
});

cmd.stderr.on("data", (data) => {
console.error(`stderr: ${data}`);
});

cmd.on("close", (code) => {
if (code === 0) {
resolve(output);
} else {
reject(new Error(`Command ${command} failed with code ${code}`));
}
});
});
};
15 changes: 15 additions & 0 deletions twake/plugins/api/src/index.ts
@@ -0,0 +1,15 @@
import express from "express";
import bodyParser from "body-parser";
import pluginRoutes from "./routes";

const app = express();

app.use(bodyParser.json());

app.use("/api", pluginRoutes);

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

app.listen(port, () => {
console.log(`Listening on port ${port} 馃殌`);
});
25 changes: 25 additions & 0 deletions twake/plugins/api/src/routes.ts
@@ -0,0 +1,25 @@
import express from "express";
import {
addPluginHandler,
startPluginHandler,
buildPluginHandler,
updatePluginHandler,
deletePluginHandler,
listPluginHandler,
} from "./handlers/";

const router = express.Router();

router.post("/add", addPluginHandler);

router.post("/start", startPluginHandler);

router.post("/build", buildPluginHandler);

router.post("/update/:pluginName", updatePluginHandler);

router.post("/delete/:pluginName", deletePluginHandler);

router.get("/list", listPluginHandler);

export default router;
13 changes: 13 additions & 0 deletions twake/plugins/api/tsconfig.json
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2018",
"module": "CommonJS",
"esModuleInterop": true,
"strict": true,
"moduleResolution": "node",
"outDir": "dist",
"sourceMap": true
},
"include": ["src/**/*"]
}

0 comments on commit 89b5368

Please sign in to comment.