Skip to content

Commit

Permalink
test: add database migration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
KernelDeimos committed Jul 28, 2024
1 parent d0e461e commit 0250469
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 104 deletions.
23 changes: 21 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@
"uuid": "^9.0.0",
"validator": "^13.9.0",
"winston": "^3.9.0",
"winston-daily-rotate-file": "^4.7.1"
"winston-daily-rotate-file": "^4.7.1",
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/node": "^20.5.3",
Expand Down
6 changes: 6 additions & 0 deletions src/backend/src/CoreModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,12 @@ const install = async ({ services, app, useapi }) => {

const { SUService } = require('./services/SUService');
services.registerService('su', SUService);

const { ShutdownService } = require('./services/ShutdownService');
services.registerService('shutdown', ShutdownService);

const { BootScriptService } = require('./services/BootScriptService');
services.registerService('boot-script', BootScriptService);
}

const install_legacy = async ({ services }) => {
Expand Down
8 changes: 7 additions & 1 deletion src/backend/src/Kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const { AdvancedBase } = require("@heyputer/puter-js-common");
const { Context } = require('./util/context');
const BaseService = require("./services/BaseService");
const useapi = require('useapi');
const yargs = require('yargs/yargs')
const { hideBin } = require('yargs/helpers')


class Kernel extends AdvancedBase {
constructor ({ entry_path } = {}) {
Expand Down Expand Up @@ -67,7 +70,9 @@ class Kernel extends AdvancedBase {
}

boot () {
this._runtime_init();
const args = yargs(hideBin(process.argv)).argv

this._runtime_init({ args });

// const express = require('express')
// const app = express();
Expand Down Expand Up @@ -111,6 +116,7 @@ class Kernel extends AdvancedBase {
services,
config,
logger: this.bootLogger,
args,
}, 'app');
globalThis.root_context = root_context;

Expand Down
42 changes: 42 additions & 0 deletions src/backend/src/services/BootScriptService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const { Context } = require("../util/context");
const BaseService = require("./BaseService");

class BootScriptService extends BaseService {
static MODULES = {
fs: require('fs'),
}
async ['__on_boot.ready'] () {
const args = Context.get('args');
if ( ! args['boot-script'] ) return;
const script_name = args['boot-script'];

const require = this.require;
const fs = require('fs');
const boot_json_raw = fs.readFileSync(script_name, 'utf8');
const boot_json = JSON.parse(boot_json_raw);
await this.run_script(boot_json);
}

async run_script (boot_json) {
const scope = {
runner: 'boot-script',
['end-puter-process']: ({ args }) => {
const svc_shutdown = this.services.get('shutdown');
svc_shutdown.shutdown(args[0]);
}
};

for ( let i=0 ; i < boot_json.length ; i++ ) {
const statement = boot_json[i];
const [cmd, ...args] = statement;
if ( ! scope[cmd] ) {
throw new Error(`Unknown command: ${cmd}`);
}
await scope[cmd]({ scope, args });
}
}
}

module.exports = {
BootScriptService
};
11 changes: 11 additions & 0 deletions src/backend/src/services/ShutdownService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const BaseService = require("./BaseService");

class ShutdownService extends BaseService {
shutdown ({ reason, code } = {}) {
this.log.info(`Puter is shutting down: ${reason ?? 'no reason provided'}`);
process.stdout.write('\x1B[0m\r\n');
process.exit(code ?? 0);
}
}

module.exports = { ShutdownService };
196 changes: 96 additions & 100 deletions src/backend/src/services/database/SqliteDatabaseAccessService.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
const { es_import_promise } = require("../../fun/dev-console-ui-utils");
const { surrounding_box } = require("../../fun/dev-console-ui-utils");
const { Context } = require("../../util/context");
const { CompositeError } = require("../../util/errorutil");
const structutil = require("../../util/structutil");
const { BaseDatabaseAccessService } = require("./BaseDatabaseAccessService");
Expand All @@ -44,7 +45,14 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {
this.db = new Database(this.config.path);

// Database upgrade logic
const TARGET_VERSION = 24;
const HIGHEST_VERSION = 24;
const TARGET_VERSION = (() => {
const args = Context.get('args');
if ( args['database-target-version'] ) {
return parseInt(args['database-target-version']);
}
return HIGHEST_VERSION;
})();

const [{ user_version }] = do_setup
? [{ user_version: -1 }]
Expand All @@ -53,105 +61,93 @@ class SqliteDatabaseAccessService extends BaseDatabaseAccessService {

const upgrade_files = [];

if ( user_version === -1 ) {
upgrade_files.push('0001_create-tables.sql');
upgrade_files.push('0002_add-default-apps.sql');
}

if ( user_version <= 0 ) {
upgrade_files.push('0003_user-permissions.sql');
}

if ( user_version <= 1 ) {
upgrade_files.push('0004_sessions.sql');
}

if ( user_version <= 2 ) {
upgrade_files.push('0005_background-apps.sql');
}

if ( user_version <= 3 ) {
upgrade_files.push('0006_update-apps.sql');
}

if ( user_version <= 4 ) {
upgrade_files.push('0007_sessions.sql');
}

if ( user_version <= 5 ) {
upgrade_files.push('0008_otp.sql');
}

if ( user_version <= 6 ) {
upgrade_files.push('0009_app-prefix-fix.sql');
}

if ( user_version <= 7 ) {
upgrade_files.push('0010_add-git-app.sql');
}

if ( user_version <= 8 ) {
upgrade_files.push('0011_notification.sql');
}

if ( user_version <= 9 ) {
upgrade_files.push('0012_appmetadata.sql');
}

if ( user_version <= 10 ) {
upgrade_files.push('0013_protected-apps.sql');
}

if ( user_version <= 11 ) {
upgrade_files.push('0014_share.sql');
}

if ( user_version <= 12 ) {
upgrade_files.push('0015_group.sql');
}

if ( user_version <= 13 ) {
upgrade_files.push('0016_group-permissions.sql');
}

if ( user_version <= 14 ) {
upgrade_files.push('0017_publicdirs.sql');
}

if ( user_version <= 15 ) {
upgrade_files.push('0018_fix-0003.sql');
}

if ( user_version <= 16 ) {
upgrade_files.push('0019_fix-0016.sql');
}

if ( user_version <= 17 ) {
upgrade_files.push('0020_dev-center.sql');
}

if ( user_version <= 18 ) {
upgrade_files.push('0021_app-owner-id.sql');
}

if ( user_version <= 19 ) {
upgrade_files.push('0022_dev-center-max.sql');
}

if ( user_version <= 20 ) {
upgrade_files.push('0023_fix-kv.sql');
}

if ( user_version <= 21 ) {
upgrade_files.push('0024_default-groups.sql');
}

if ( user_version <= 22 ) {
upgrade_files.push('0025_system-user.dbmig.js');
}

if ( user_version <= 23 ) {
upgrade_files.push('0026_user-groups.dbmig.js');
const available_migrations = [
[-1, [
'0001_create-tables.sql',
'0002_add-default-apps.sql',
]],
[0, [
'0003_user-permissions.sql',
]],
[1, [
'0004_sessions.sql',
]],
[2, [
'0005_background-apps.sql',
]],
[3, [
'0006_update-apps.sql',
]],
[4, [
'0007_sessions.sql',
]],
[5, [
'0008_otp.sql',
]],
[6, [
'0009_app-prefix-fix.sql',
]],
[7, [
'0010_add-git-app.sql',
]],
[8, [
'0011_notification.sql',
]],
[9, [
'0012_appmetadata.sql',
]],
[10, [
'0013_protected-apps.sql',
]],
[11, [
'0014_share.sql',
]],
[12, [
'0015_group.sql',
]],
[13, [
'0016_group-permissions.sql',
]],
[14, [
'0017_publicdirs.sql',
]],
[15, [
'0018_fix-0003.sql',
]],
[16, [
'0019_fix-0016.sql',
]],
[17, [
'0020_dev-center.sql',
]],
[18, [
'0021_app-owner-id.sql',
]],
[19, [
'0022_dev-center-max.sql',
]],
[20, [
'0023_fix-kv.sql',
]],
[21, [
'0024_default-groups.sql',
]],
[22, [
'0025_system-user.dbmig.js',
]],
[23, [
'0026_user-groups.dbmig.js',
]],
];

for ( const [v_lt_or_eq, files] of available_migrations ) {
if ( v_lt_or_eq + 1 >= TARGET_VERSION && TARGET_VERSION !== HIGHEST_VERSION ) {
this.log.noticeme(`Early exit: target version set to ${TARGET_VERSION}`);
break;
}
if ( user_version <= v_lt_or_eq ) {
upgrade_files.push(...files);
}
}

if ( upgrade_files.length > 0 ) {
Expand Down
10 changes: 10 additions & 0 deletions src/backend/src/services/runtime-analysis/AlarmService.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const { generate_identifier } = require('../../util/identifier.js');
const { stringify_log_entry } = require('./LogService.js');
const BaseService = require('../BaseService.js');
const { split_lines } = require('../../util/stdioutil.js');
const { Context } = require('../../util/context.js');

class AlarmService extends BaseService {
async _construct () {
Expand Down Expand Up @@ -251,6 +252,15 @@ class AlarmService extends BaseService {
svc_devConsole.add_widget(this.alarm_widget);
}

const args = Context.get('args');
if ( args['quit-on-alarm'] ) {
const svc_shutdown = this.services.get('shutdown');
svc_shutdown.shutdown({
reason: '--quit-on-alarm is set',
code: 1,
});
}

if ( alarm.no_alert ) return;

const severity = alarm.severity ?? 'critical';
Expand Down
Loading

0 comments on commit 0250469

Please sign in to comment.