something something git

This commit is contained in:
peter
2019-08-20 00:34:24 +02:00
parent 940f2f439d
commit 79c832e463
5 changed files with 202 additions and 52 deletions
+121 -28
View File
@@ -1,15 +1,15 @@
'use strict'
import * as Logger from 'log4js'
import { socketioRPC, ConfigLoader } from 'frontblock-generic/Plugin';
import { socketioRPC, ConfigLoader, Plugin } from 'frontblock-generic/Plugin';
import { ErrorResponse, SuccessResponse } from 'frontblock-generic/Types';
import express = require('express');
import http = require('http');
import bsock = require('bsock');
import { FrontblockCherryPicker } from "git-cherrypicker"
import { promises as fs } from "fs"
import { GitUpdater } from "./GitUpdater";
import * as git from "simple-git/promise"
import { GitUpdater, RepoFolderStatus, } from "./GitUpdater";
import * as path from "path"
const kfs = require("key-file-storage").default('kfs')
@@ -70,7 +70,12 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
private httpServer
private io = bsock.createServer()
private wsServer = http.createServer()
private pm
private dashboardUpdater:GitUpdater
private adminUpdater:GitUpdater
private pluginUpdaters:{[name in string]:GitUpdater} = {}
private loadedPlugins:{[name in string]:Plugin} = {}
constructor(){
super("FrontblockAdmin")
@@ -83,29 +88,82 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
}
private async updateFrontblockLib(){
logger.warn("Picking FrontblockLib...")
await (new FrontblockCherryPicker("fb-dist/admin", "master", "FrontblockLib.js")).write("./static/FrontblockLib.js")
}
private async updateDashboard(){
const dashboard = new GitUpdater("./static")
const status = await dashboard.cloneRepo("https://gitea.frontblock.me/fb-dist/dashboard.git", true)
console.log(status)
private async updateDashboard():Promise<RepoFolderStatus>{
logger.warn("Cloning dashboard...")
this.dashboardUpdater = new GitUpdater("./static")
const status = await this.dashboardUpdater.cloneRepo("https://gitea.frontblock.me/fb-dist/dashboard.git", true)
return(status)
}
private async updatePluginmanager(){
const dashboard = new GitUpdater("./plugins/PluginManager")
const status = await dashboard.cloneRepo("https://gitea.frontblock.me/fb-dist/pluginmanager.git", true)
console.log(status)
private async installPlugin(name: string):Promise<RepoFolderStatus>{
logger.warn("Cloning "+name+"...")
this.pluginUpdaters[name] = new GitUpdater("./plugins/"+name)
const status = await this.pluginUpdaters[name].cloneRepo("https://gitea.frontblock.me/fb-dist/"+name.toLowerCase()+".git", true)
return status
}
private async startPlugin(name:string):Promise<boolean>{
if(!this.pluginUpdaters[name]) return false
const status = await this.pluginUpdaters[name].getStatus()
if(!status.exists || status.empty || !status.tags || status.tags.length === 0){
logger.error("Bad repo status", name, status)
return false
}
if(this.loadedPlugins[name]){
logger.error("Plugin", name, "is already started")
return false
}
let str = "../plugins/"+name+"/Plugin"
const pluginClass = await import(str)
const pluginObj = new pluginClass.default()
await pluginObj.start()
this.loadedPlugins[name] = pluginObj
return true
}
private async updatePlugin(name:string):Promise<boolean>{
if(!this.pluginUpdaters[name]) return false
const status = await this.pluginUpdaters[name].getStatus()
if(!status.exists || status.empty || !status.tags || status.tags.length === 0){
logger.error("Bad repo status", name, status)
return false
}
if(status.currentTag == status.latestTag){
logger.warn(name, "already at latest tag")
return false
}
if(this.loadedPlugins[name]){
logger.error("Plugin", name, "is running. Stop it first")
return false
}
this.pluginUpdaters[name].checkoutTag(status.latestTag!)
return true
}
private async setPluginVersion(pluginName:string, tag:string):Promise<RepoFolderStatus>{
const status = await this.pluginUpdaters[pluginName].getStatus()
if(!status.exists || !status.tags || status.tags.length === 0 || !status.tags.includes(tag)){
logger.error("Bad repo status", pluginName, status)
return status
}
return await this.pluginUpdaters[pluginName].checkoutTag(tag)
}
private async initialize(){
await this.updateDashboard()
await this.updateFrontblockLib()
await this.updatePluginmanager()
let str = "../plugins/PluginManager/Plugin"
const PM = await import(str)
this.pm = new PM.default()
await this.installPlugin("PluginManager")
//await this.updatePluginmanager()
this.startWebsocket()
this.startWebserver()
@@ -132,20 +190,55 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
}
},{
owner: 'Admin',
name: 'installPluginManager',
name: 'installPlugin',
args: 'name',
info: {
type: 'call',
fn: async (name:string) => {
return await this.installPlugin(name)
}
}
},{
owner: 'Admin',
name: 'startPlugin',
args: 'name',
info: {
type: 'call',
fn: async (name:string) => {
return await this.startPlugin(name)
}
}
},{
owner: 'PluginManager',
name: 'getLoadedPluginNames',
args: '',
info: {
type: 'call',
fn: () => {}
fn: () => Object.keys(this.loadedPlugins)
}
},{
owner: 'Admin',
name: 'updatePlugin',
args: 'name',
info: {
type: 'call',
fn: async (name) => {return await this.updatePlugin(name)}
}
},{
owner: 'Admin',
name: 'setPluginVersion',
args: 'name, tag',
info: {
type: 'call',
fn: async (name, tag) => {return await this.setPluginVersion(name, tag)}
}
}
]
//translate RPCs to socket-bound function metadata
const loadedPlugins = this.pm.getLoadedPlugins()
const loadedPlugins = this.loadedPlugins
for(const name in loadedPlugins){
loadedPlugins[name].backend.exportRPCs().forEach(rpc => {
loadedPlugins[name].exportRPCs().forEach(rpc => {
const info = this.rpcToRpcInfo(name, rpc)
rpcInfos.push(info)
})
@@ -207,10 +300,6 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
})
})
}
private installPluginManager(){
}
private startWebserver(){
if(this.httpServer != null || this.express != null){
@@ -225,8 +314,12 @@ export class FrontblockAdmin extends ConfigLoader<AdminConf>{
/**
* get the compiled FrontendPlugins.js
*/
this.express.get('/plugins/:id'+".js", (request, response) => {
let frontend = this.pm.getFrontend(request.params.id)
this.express.get('/plugins/:id'+".js", async (request, response) => {
const pth = path.resolve("plugins/"+request.params.id, "FrontendPlugin.js");
logger.info("Loading frontend plugin from fs", pth)
const file = await fs.readFile(pth)
const frontend = file.toString()
response.status(200)
response.set('Content-Type', 'application/javascript')
response.send(frontend)
+3 -1
View File
@@ -11,7 +11,7 @@ const rmrf = (path:string, options = {}) => {
return new Promise((acc, _) => rimraf(path, options, acc))
}
type RepoFolderStatus = {
export type RepoFolderStatus = {
exists: boolean
empty: boolean
currentTag?: string
@@ -53,6 +53,8 @@ export class GitUpdater{
}
async cloneRepo(from:string, force:boolean = false):Promise<RepoFolderStatus> {
if(this.folderPath === "." && force)
throw new Error("refusing to `rm -rf .`: \ncloneRepo(from: "+from+", force: "+force+")")
if(force){
await rmrf(this.folderPath)
await fs.mkdir(this.folderPath, { recursive: true });
+47
View File
@@ -0,0 +1,47 @@
const TerserPlugin = require('terser-webpack-plugin');
const path = require('path');
module.exports = {
optimization: {
minimize: false
},
mode: 'production',
target: "node",
entry: path.resolve(__dirname, '../../dist/FrontblockLib.js'),
output: {
path: path.resolve(__dirname, '../../dist'),
filename: 'FrontblockLib.js',
libraryTarget: 'commonjs',
},
optimization: {
minimizer: [new TerserPlugin({
cache: true,
parallel: true,
terserOptions:{
mangle: false,
keep_classnames: true
}
})],
splitChunks: {
cacheGroups: {
common: {
chunks: 'all',
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
name: 'common'
},
vendor: {
test: /node_modules/,
chunks: 'all',
name: 'vendor',
priority: 10,
enforce: true,
minChunks: 2
}
}
}
}
}