32 lines
3.3 KiB
PHP
32 lines
3.3 KiB
PHP
<?php
|
|
// Offline additive migration; no rights, credentials, contacts or activation are provisioned.
|
|
use Illuminate\Contracts\Console\Kernel;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Symfony\Component\Process\Process;
|
|
use Tempo\Purchasing\Delivery\Installation;
|
|
use Tempo\Purchasing\Delivery\CodeDeployment;
|
|
use Tempo\Purchasing\SgfSourcing\Schema;
|
|
$root=dirname(__DIR__);$action=$argv[1]??'';$host=realpath($argv[2]??'');
|
|
try{
|
|
if(!$host||!in_array($action,['plan','migrate'],true))throw new RuntimeException('Usage: plan <host> | migrate <host> <target-sha> <backup-file> <backup-sha> <operator> <manifest-sha>');
|
|
$host=str_replace('\\','/',$host);$manifestText=file_get_contents($root.'/manifest.json');$manifest=json_decode($manifestText,true,64,JSON_THROW_ON_ERROR);$manifestHash=hash('sha256',$manifestText);
|
|
foreach($manifest['support_files'] as $file=>$hash)if(str_contains($file,'..')||!preg_match('~^[A-Za-z0-9_./-]+$~D',$file)||is_link($root.'/'.$file)||!hash_equals($hash,hash_file('sha256',$root.'/'.$file)))throw new RuntimeException('Bundle integrity failed');
|
|
require $host.'/vendor/autoload.php';$app=require $host.'/bootstrap/app.php';$app->make(Kernel::class)->bootstrap();
|
|
if(!class_exists(Installation::class))require_once $root.'/integrations/sgf/operational/bootstrap.php';
|
|
if(!class_exists(Schema::class))require_once $root.'/integrations/sgf/sourcing/Schema.php';
|
|
require_once $root.'/integrations/sgf/operational/CodeDeployment.php';
|
|
$db=DB::connection();$current=json_decode(file_get_contents($host.'/storage/app/private/module-deployments/current.json'),true,32,JSON_THROW_ON_ERROR);
|
|
(new CodeDeployment($host))->plan($host.'/packages/internal-requisitions',$current['manifest_sha256']);
|
|
$plan=['target_sha256'=>Installation::target($db),'manifest_sha256'=>$manifestHash,'schema_changes'=>Schema::TABLES,'new_rights'=>Schema::RIGHTS,'grant_performed'=>false,'activated'=>false];
|
|
if($action==='plan'){echo json_encode($plan,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR);exit;}
|
|
$backup=$argv[4]??'';$backupHash=$argv[5]??'';$operator=$argv[6]??'';
|
|
if(!hash_equals($plan['target_sha256'],$argv[3]??'')||!hash_equals($manifestHash,$argv[7]??'')||!is_file($backup)||!hash_equals($backupHash,hash_file('sha256',$backup))||trim($operator)===''||!is_file($host.'/storage/framework/down'))throw new RuntimeException('Target, manifest, backup, operator and maintenance are required');
|
|
(new Process([getenv('PG_RESTORE_BINARY')?:'pg_restore','--list',$backup],null,null,null,60))->mustRun();
|
|
$result=Schema::migrate($db,$backupHash,$operator);
|
|
$old=json_decode(file_get_contents($host.'/packages/internal-requisitions/manifest.json'),true,64,JSON_THROW_ON_ERROR);
|
|
$receipt=['host'=>$host,'from_manifest_sha256'=>$current['manifest_sha256'],'to_manifest_sha256'=>$manifestHash,'schema_verified'=>Schema::compatible($db),'changes'=>[]];
|
|
foreach($manifest['support_files'] as $file=>$hash)if(($old['support_files'][$file]??null)!==$hash)$receipt['changes'][$file]=['before'=>$old['support_files'][$file]??null,'after'=>$hash];
|
|
file_put_contents($host.'/storage/app/private/module-deployments/schema-transition-'.$manifestHash.'.json',json_encode($receipt,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR));
|
|
echo json_encode($result+['activated'=>false,'rights_granted'=>false],JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR);
|
|
}catch(Throwable $e){fwrite(STDERR,$e->getMessage()."\n");exit(1);}
|