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

feat: version control #967

Draft
wants to merge 18 commits into
base: develop
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions core/components/AdminVault/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export default class AdminVault {
'control.server': 'Start/Stop Server + Scheduler',
'commands.resources': 'Start/Stop Resources',
'server.cfg.editor': 'Read/Write server.cfg',
'version_control': 'Version Control: Manage',
'txadmin.log.view': 'View System Logs', //FIXME: rename to system.log.view

'menu.vehicle': 'Spawn / Fix Vehicles',
Expand Down
18 changes: 18 additions & 0 deletions core/components/ConfigVault.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export default class ConfigVault {
let cfgData = this.getConfigFromFile();
this.configFile = this.setupConfigStructure(cfgData);
this.config = this.setupConfigDefaults(this.configFile);
if (globals.versionControl) {
globals.versionControl.configUpdated();
}
this.setupFolderStructure();
} catch (error) {
console.error(error);
Expand Down Expand Up @@ -100,6 +103,7 @@ export default class ConfigVault {
logger: null,
monitor: null,
playerDatabase: null,
versionControl: null,
webServer: null,
discordBot: null,
fxRunner: null,
Expand All @@ -110,6 +114,7 @@ export default class ConfigVault {
// this entire config vault is stupid.
// use convict, lodash defaults or something like that
cfg.playerDatabase = cfg.playerDatabase ?? cfg.playerController ?? {};
cfg.versionControl = cfg.versionControl ?? {};

try {
out.global = {
Expand All @@ -123,6 +128,11 @@ export default class ConfigVault {
hideDefaultWarning: toDefault(cfg.global.hideDefaultWarning, false),
hideDefaultScheduledRestartWarning: toDefault(cfg.global.hideDefaultScheduledRestartWarning, false),
};
out.versionControl = {
githubAuthKey: toDefault(cfg.versionControl.githubAuthKey, null),
githubOwner: toDefault(cfg.versionControl.githubAuthKey, null),
githubParentRepo: toDefault(cfg.versionControl.githubParentRepo, null)
};
out.logger = toDefault(cfg.logger, {}); //not in template
out.monitor = {
restarterSchedule: toDefault(cfg.monitor.restarterSchedule, []),
Expand Down Expand Up @@ -221,6 +231,10 @@ export default class ConfigVault {
cfg.logger.admin = toDefault(cfg.logger.admin, {});
cfg.logger.console = toDefault(cfg.logger.console, {});

//Version Control
cfg.versionControl.githubAuthKey = toDefault(cfg.versionControl.githubAuthKey, null);
cfg.versionControl.githubOwner = toDefault(cfg.versionControl.githubOwner, null);

//Monitor
cfg.monitor.restarterSchedule = cfg.monitor.restarterSchedule || [];
cfg.monitor.cooldown = parseInt(cfg.monitor.cooldown) || 60; //not in template - 45 > 60 > 90 -> 60 after fixing the "extra time" logic
Expand Down Expand Up @@ -346,5 +360,9 @@ export default class ConfigVault {
fs.writeFileSync(this.configFilePath, JSON.stringify(toSave, null, 2), 'utf8');
this.configFile = toSave;
this.config = this.setupConfigDefaults(this.configFile);

if (scope == 'versionControl' && globals.versionControl) {
globals.versionControl.configUpdated();
}
}
};
17 changes: 9 additions & 8 deletions core/components/FxRunner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export default class FXRunner {
async spawnServer(announce) {
//If the server is already alive
if (this.fxChild !== null) {
const msg = `The server is already started.`;
const msg = 'The server is already started.';
console.error(msg);
return msg;
}
Expand All @@ -166,13 +166,13 @@ export default class FXRunner {
|| typeof this.spawnVariables.command == 'undefined'
|| typeof this.spawnVariables.args == 'undefined'
) {
const msg = `this.spawnVariables is not set.`;
const msg = 'this.spawnVariables is not set.';
console.error(msg);
return msg;
}
//If there is any FXServer configuration missing
if (this.config.serverDataPath === null || this.config.cfgPath === null) {
const msg = `Cannot start the server with missing configuration (serverDataPath || cfgPath).`;
const msg = 'Cannot start the server with missing configuration (serverDataPath || cfgPath).';
console.error(msg);
return msg;
}
Expand Down Expand Up @@ -218,8 +218,8 @@ export default class FXRunner {
type: 'success',
description: {
key: 'server_actions.spawning_discord',
data: { servername: globals.txAdmin.globalConfig.serverName }
}
data: { servername: globals.txAdmin.globalConfig.serverName },
},
});
}

Expand Down Expand Up @@ -335,7 +335,7 @@ export default class FXRunner {
//Start server again :)
return this.spawnServer();
} catch (error) {
const errMsg = `Couldn't restart the server.`;
const errMsg = 'Couldn\'t restart the server.';
console.error(errMsg);
console.verbose.dir(error);
return errMsg;
Expand Down Expand Up @@ -377,8 +377,8 @@ export default class FXRunner {
type: messageColor,
description: {
key: `server_actions.${messageType}_discord`,
data: tOptions
}
data: tOptions,
},
});

//Awaiting restart delay
Expand All @@ -394,6 +394,7 @@ export default class FXRunner {
globals.resourcesManager.handleServerStop();
globals.playerlistManager.handleServerStop(this.currentMutex);
globals.statsManager.svRuntime.logServerClose(reasonString);
globals.versionControl.svRuntime.handleServerStop(reasonString);
return null;
} catch (error) {
const msg = "Couldn't kill the server. Perhaps What Is Dead May Never Die.";
Expand Down
1 change: 1 addition & 0 deletions core/components/HealthMonitor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export default class HealthMonitor {
this.hasServerStartedYet = true;
globals.statsManager.txRuntime.registerFxserverBoot(processUptime);
globals.statsManager.svRuntime.logServerBoot(processUptime);
globals.versionControl.svRuntime.handleServerBoot(processUptime);
}
return;
}
Expand Down
5 changes: 1 addition & 4 deletions core/components/Logger/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
const modulename = 'Logger';
import AdminLogger from './handlers/admin';
import FXServerLogger from './handlers/fxserver';
import ServerLogger from './handlers/server';
import { getLogSizes } from './loggerUtils.js'
import consoleFactory from '@extras/console';
const console = consoleFactory(modulename);
import { getLogSizes } from './loggerUtils.js';

// NOTE: to turn this into an universal class outside txAdmin() instance
// when a txAdmin profile starts, it does universal.logger.start(profilename)
Expand Down
15 changes: 7 additions & 8 deletions core/components/Scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default class Scheduler {
this.calculatedNextRestartMinuteFloorTs = false;
this.checkSchedule();

//Cron Function
//Cron Function
setInterval(() => {
this.checkSchedule();
globals.webServer?.webSocket.pushRefresh('status');
Expand Down Expand Up @@ -101,7 +101,7 @@ export default class Scheduler {
//Dispatch `txAdmin:events:skippedNextScheduledRestart`
globals.fxRunner.sendEvent('skippedNextScheduledRestart', {
secondsRemaining: Math.floor((prevMinuteFloorTs - Date.now()) / 1000),
temporary
temporary,
});
} else {
this.nextSkip = false;
Expand Down Expand Up @@ -193,7 +193,7 @@ export default class Scheduler {

//Checking if skipped
if (this.nextSkip === this.calculatedNextRestartMinuteFloorTs) {
console.verbose.log(`Skipping next scheduled restart`);
console.verbose.log('Skipping next scheduled restart');
return;
}

Expand All @@ -212,7 +212,6 @@ export default class Scheduler {

//reset next scheduled
this.nextTempSchedule = false;

} else if (scheduleWarnings.includes(nextDistMins)) {
const tOptions = {
smart_count: nextDistMins,
Expand All @@ -224,14 +223,14 @@ export default class Scheduler {
type: 'warning',
description: {
key: 'restarter.schedule_warn_discord',
data: tOptions
}
data: tOptions,
},
});

//Dispatch `txAdmin:events:scheduledRestart`
//Dispatch `txAdmin:events:scheduledRestart`
globals.fxRunner.sendEvent('scheduledRestart', {
secondsRemaining: nextDistMins * 60,
translatedMessage: globals.translator.t('restarter.schedule_warn', tOptions)
translatedMessage: globals.translator.t('restarter.schedule_warn', tOptions),
});
}
}
Expand Down
157 changes: 157 additions & 0 deletions core/components/VersionControl/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
const modulename = "VersionControl";
import consoleFactory from "@extras/console";
import type TxAdmin from "@core/txAdmin.js";
import SvRuntimeVersionControl from "./svRuntime";
import { Octokit } from "octokit";
import fetch from "node-fetch";

const console = consoleFactory(modulename);

/**
* Module responsible for handling version control
*/
export default class VersionControl {
readonly #txAdmin: TxAdmin;
public readonly svRuntime: SvRuntimeVersionControl;
public octokit: Octokit | null;
private githubAuthKey: string | null;
private githubOwner: string | null;
private githubParentRepo: string | null;

private async updateGithubAuthKey(newValue: string | null) {
this.githubAuthKey = newValue;
await this.updateOctokitValue();
}

public async createGithubRepo(
repoName: string,
ownerName: string,
isOrganization: boolean
): Promise<[boolean, any?]> {
console.log({
repoName,
ownerName,
isOrganization
});
if (this.octokit) {
if (isOrganization === true) {
const resp = this.octokit.request("POST /orgs/{org}/repos", {
org: ownerName,
name: repoName,
description: "Server repository created by txAdmin",
private: true,
has_issues: true,
has_projects: true,
has_wiki: true,
is_template: false
});
console.log("resp", JSON.stringify(resp));

if (resp.status === 200) {
return [true, resp.data];
}
} else {
const resp = this.octokit.request("POST /user/repos", {
name: repoName,
description: "Server repository created by txAdmin",
private: true,
has_issues: true,
has_projects: true,
has_wiki: true,
is_template: false
});

if (resp.status === 200) {
return [true, resp.data];
}
}
}

return [false];
}

public async isAuthKeyValid(key: string) {
try {
const val = await new Octokit({
auth: key,
request: {
fetch: fetch
}
}).rest.users.getAuthenticated();

return val.status === 200;
} catch (err) {
console.verbose.warn(err);
return false;
}
}

public async getUsername() {
if (this.octokit) {
const { data } = await this.octokit.rest.users.getAuthenticated();

if (data) {
return data.login;
}
}

return null;
}

private async updateOctokitValue() {
if (this.githubAuthKey !== null) {
if ((await this.isAuthKeyValid(this.githubAuthKey)) === true) {
this.octokit = new Octokit({
auth: this.githubAuthKey,
request: {
fetch: fetch
}
});
console.verbose.log("Valid github auth key");
} else {
console.info("Invalid github auth key");
}
} else {
this.octokit = null;
}
}

public configUpdated() {
const cfg = this.#txAdmin.configVault.getScoped("versionControl");

this.updateGithubAuthKey(cfg.githubAuthKey);
this.githubOwner = cfg.githubOwner;
this.githubParentRepo = cfg.githubParentRepo;
}

public async getOwners() {
const resp: string[] = [];

if (this.octokit !== null) {
const orgsResp = await this.octokit.request("GET /user/orgs");

const { data: userResp } =
await this.octokit.rest.users.getAuthenticated();

if (userResp) {
resp.push(userResp.login);
}

if (orgsResp && orgsResp.status === 200) {
orgsResp.data.forEach((v: { login: string }) => {
resp.push(v.login);
});
}
}

return resp;
}

constructor(txAdmin: TxAdmin) {
this.#txAdmin = txAdmin;
this.githubAuthKey = null;
this.githubOwner = null;
this.configUpdated();
this.svRuntime = new SvRuntimeVersionControl(txAdmin);
}
}
6 changes: 6 additions & 0 deletions core/components/VersionControl/svRuntime/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { VcFileType } from "./perfSchemas";

export const defaultData: VcFileType = {
resources: [],
repository: null
};
Loading