Files
SGF/scripts/modular-development-host.mjs
2026-11-02 08:06:45 +02:00

32 lines
3.9 KiB
JavaScript

// Separate development database/role/app: regression resets cannot erase it.
import fs from 'node:fs';import path from 'node:path';import crypto from 'node:crypto';import {spawnSync} from 'node:child_process';
const pointer='C:/laragon/data/sgf-tempo/run/modular-regression-current.json';
const state=JSON.parse(fs.readFileSync(pointer,'utf8'));
if(!/^[a-f0-9]{12}$/.test(state.id)||path.basename(state.root)!=='modular-regression-'+state.id||state.port!==55439)throw Error('Unexpected isolated host');
if(state.development)throw Error('Development host already configured; preserve it.');
const database='sgf_modules_dev_'+state.id,role='sgf_modules_qa_'+state.id,password=crypto.randomBytes(30).toString('hex');
const app=path.join(state.root,'development-app'),pg='C:/Program Files/PostgreSQL/17/bin';
const admin=fs.readFileSync(path.join(state.root,'private/admin-password.txt'),'utf8');
function run(exe,args,options={}){const r=spawnSync(exe,args,{encoding:'utf8',windowsHide:true,maxBuffer:8*1024*1024,...options});if(r.status!==0)throw Error((r.stdout||'')+(r.stderr||''));return r.stdout;}
const identity=run(path.join(pg,'psql.exe'),['-h','127.0.0.1','-p',String(state.port),'-U','sgf_regression_owner','-d','postgres','-At','-c',"SELECT current_setting('cluster_name')"],{env:{...process.env,PGPASSWORD:admin}}).trim();
if(identity!=='sgf_modular_regression_'+state.id)throw Error('Unexpected database cluster');
fs.cpSync(state.app,app,{recursive:true,filter:p=>!['storage','.env','.env.testing','.env.browser-testing'].includes(path.relative(state.app,p).split(path.sep)[0])&&!p.includes(path.join('bootstrap','cache')+path.sep)});
for(const dir of ['storage/framework/cache/data','storage/framework/sessions','storage/framework/views','storage/logs','bootstrap/cache'])fs.mkdirSync(path.join(app,dir),{recursive:true});
if(fs.existsSync(path.join(app,'public/hot')))fs.unlinkSync(path.join(app,'public/hot'));
function files(dir){return fs.readdirSync(dir,{withFileTypes:true}).flatMap(e=>e.isDirectory()?files(path.join(dir,e.name)):[path.join(dir,e.name)]);}
const adaptations=[];
for(const dir of ['app','database','config','tests','scripts'])for(const p of files(path.join(app,dir)).filter(p=>/\.(php|sql|mjs)$/.test(p))){
const text=fs.readFileSync(p,'utf8'),next=text.replaceAll('sgf_tempo_test',database).replaceAll('sgf_test_runner',role);
if(next!==text){fs.writeFileSync(p,next);adaptations.push(path.relative(app,p));}
}
fs.writeFileSync(path.join(state.root,'development-identity-adaptations.json'),JSON.stringify(adaptations,null,2));
run(path.join(pg,'psql.exe'),['-h','127.0.0.1','-p',String(state.port),'-U','sgf_regression_owner','-d','postgres','-v','ON_ERROR_STOP=1'],{env:{...process.env,PGPASSWORD:admin},input:`CREATE ROLE ${role} LOGIN PASSWORD '${password}' NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;\nCREATE DATABASE ${database} OWNER ${role};\nREVOKE ALL ON DATABASE ${database} FROM PUBLIC;\n`});
const env=`APP_NAME=SGF-Modular-Development\nAPP_KEY=base64:${crypto.randomBytes(32).toString('base64')}\nAPP_DEBUG=false\nAPP_URL=http://127.0.0.1:${state.web_port}\nAPP_ENV=testing\nDB_CONNECTION=pgsql\nDB_HOST=127.0.0.1\nDB_PORT=${state.port}\nDB_DATABASE=${database}\nDB_USERNAME=${role}\nDB_PASSWORD=${password}\nDB_URL=\nSESSION_DRIVER=array\nCACHE_STORE=array\nBCRYPT_ROUNDS=4\n`;
fs.writeFileSync(path.join(app,'.env.testing'),env);
fs.writeFileSync(path.join(app,'.env'),env.replace('APP_ENV=testing','APP_ENV=local'));
run('php',['artisan','migrate','--env=testing','--force','--no-interaction'],{cwd:app});
const provision=run('php',['scripts/modular-development-profiles.php',path.join(state.root,'private/development.json')],{cwd:app});
state.development={app,database,role,port:state.port,url:`http://127.0.0.1:${state.web_port}`};
fs.writeFileSync(pointer,JSON.stringify(state,null,2));fs.writeFileSync(path.join(state.root,'development-provision.json'),provision);
console.log(JSON.stringify({configured:true,...state.development,credentials_printed:false}));