main.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. const path_ = require('node:path');
  2. const fs = require('node:fs');
  3. const { spawnSync } = require('node:child_process');
  4. const prompt = require('prompt-sync')({sigint: true});
  5. const ind_str = () => Array(ind).fill(' --').join('');
  6. let ind = 0;
  7. const log = {
  8. // log with unicode warning symbols in yellow
  9. warn: (msg) => {
  10. console.log(`\x1b[33;1m[!]${ind_str()} ${msg}\x1b[0m`);
  11. },
  12. crit: (msg) => {
  13. console.log(`\x1b[31;1m[!]${ind_str()} ${msg}\x1b[0m`);
  14. },
  15. info: (msg) => {
  16. console.log(`\x1B[36;1m[i]\x1B[0m${ind_str()} ${msg}`);
  17. },
  18. named: (name, value) => {
  19. console.log(`\x1B[36;1m[i]${ind_str()} ${name}\x1B[0m ${value}`);
  20. },
  21. error: e => {
  22. if ( e instanceof UserError ) {
  23. log.crit(e.message);
  24. } else {
  25. console.error(e);
  26. }
  27. },
  28. indent () { ind++; },
  29. dedent () { ind--; },
  30. heading (title) {
  31. const circle = '🔵';
  32. console.log(`\n\x1b[36;1m${circle} ${title} ${circle}\x1b[0m`);
  33. }
  34. };
  35. const areyousure = (message, options = {}) => {
  36. const { crit } = options;
  37. const logfn = crit ? log.crit : log.warn;
  38. logfn(message);
  39. const answer = prompt(`\x1B[35;1m[?]\x1B[0m ${ options?.prompt ?? 'Are you sure?' } (y/n): `);
  40. if ( answer !== 'y' ) {
  41. if ( options.fail_hint ) {
  42. log.info(options.fail_hint);
  43. }
  44. console.log(`\x1B[31;21;1mAborted.\x1B[0m`);
  45. process.exit(1);
  46. }
  47. }
  48. if ( ! fs.existsSync('.is_puter_repository') ) {
  49. throw new Error('This script must be run from the root of a puter repository');
  50. }
  51. areyousure(
  52. 'This script will delete all data in the database. Are you sure you want to proceed?',
  53. { crit: true }
  54. )
  55. let backup_created = false;
  56. const DBPATH = 'volatile/runtime/puter-database.sqlite';
  57. const delete_db = () => {
  58. if ( ! fs.existsSync(DBPATH) ) {
  59. log.info('No database file to remove');
  60. // no need to create a backup if the database doesn't exist
  61. backup_created = true;
  62. return;
  63. }
  64. if ( ! backup_created ) {
  65. log.info(`Creating a backup of the database...`);
  66. const RANDOM = Math.floor(Math.random() * 1000000);
  67. const DATE = new Date().toISOString().replace(/:/g, '-');
  68. fs.renameSync(DBPATH, `${DBPATH}_${DATE}_${RANDOM}.bak`);
  69. backup_created = true;
  70. return;
  71. }
  72. log.info('Removing database file');
  73. fs.unlinkSync(DBPATH);
  74. }
  75. const pwd = process.cwd();
  76. const boot_script_path = path_.join(pwd, 'tools/migrations-test/noop.puter.json');
  77. const launch_puter = (args) => {
  78. const ret = spawnSync(
  79. 'node',
  80. ['tools/run-selfhosted.js', ...args],
  81. {
  82. stdio: 'inherit',
  83. env: {
  84. ...process.env,
  85. NO_VAR_RUNTIME: '1',
  86. },
  87. }
  88. );
  89. ret.ok = ret.status === 0;
  90. return ret;
  91. };
  92. {
  93. delete_db();
  94. log.info(`Test case: fresh install`);
  95. if ( ! launch_puter([
  96. '--quit-on-alarm',
  97. `--boot-script=${boot_script_path}`,
  98. ]).ok ) {
  99. log.crit('Migration to v21 raised alarm');
  100. process.exit(1);
  101. }
  102. }
  103. {
  104. delete_db();
  105. log.info(`Test case: migrate to 21, then migrate to 24`);
  106. if ( ! launch_puter([
  107. `--database-target-version=21`,
  108. '--quit-on-alarm',
  109. `--boot-script=${boot_script_path}`,
  110. ]).ok ) {
  111. log.crit('Migration to v21 raised alarm');
  112. process.exit(1);
  113. }
  114. if ( ! launch_puter([
  115. `--database-target-version=24`,
  116. '--quit-on-alarm',
  117. `--boot-script=${boot_script_path}`,
  118. ]).ok ) {
  119. log.crit('Migration to v24 raised alarm');
  120. process.exit(1);
  121. }
  122. }
  123. log.info('No migration scripts produced any obvious errors.');
  124. log.warn('This is not a substitute for release candidate migration testing!');