fix(service): write compose .env files atomically via temp rename
Replace direct .env overwrite with a unique temp file and mv so a partial write cannot leave a truncated environment file on disk.
This commit is contained in:
parent
d85a7800fa
commit
0134401f7c
2 changed files with 17 additions and 3 deletions
|
|
@ -1587,7 +1587,7 @@ public function saveComposeConfigs()
|
||||||
Storage::disk('local')->delete("tmp/{$filename}");
|
Storage::disk('local')->delete("tmp/{$filename}");
|
||||||
|
|
||||||
$commands[] = "cd $workdir";
|
$commands[] = "cd $workdir";
|
||||||
$commands[] = 'rm -f .env || true';
|
$environmentFilename = new_public_id().'.env.tmp';
|
||||||
|
|
||||||
$envs = collect([]);
|
$envs = collect([]);
|
||||||
|
|
||||||
|
|
@ -1618,10 +1618,10 @@ public function saveComposeConfigs()
|
||||||
$envs->push("{$env->key}={$env->real_value}");
|
$envs->push("{$env->key}={$env->real_value}");
|
||||||
}
|
}
|
||||||
if ($envs->count() === 0) {
|
if ($envs->count() === 0) {
|
||||||
$commands[] = 'touch .env';
|
$commands[] = "touch {$environmentFilename} && mv {$environmentFilename} .env";
|
||||||
} else {
|
} else {
|
||||||
$envs_base64 = base64_encode($envs->implode("\n"));
|
$envs_base64 = base64_encode($envs->implode("\n"));
|
||||||
$commands[] = "echo '$envs_base64' | base64 -d | tee .env > /dev/null";
|
$commands[] = "echo '$envs_base64' | base64 -d | tee {$environmentFilename} > /dev/null && mv {$environmentFilename} .env";
|
||||||
}
|
}
|
||||||
|
|
||||||
instant_remote_process($commands, $this->server);
|
instant_remote_process($commands, $this->server);
|
||||||
|
|
|
||||||
14
tests/Unit/ServiceComposeConfigAtomicWriteTest.php
Normal file
14
tests/Unit/ServiceComposeConfigAtomicWriteTest.php
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
it('publishes the service environment file atomically', function () {
|
||||||
|
$source = file_get_contents(__DIR__.'/../../app/Models/Service.php');
|
||||||
|
$methodStart = strpos($source, 'public function saveComposeConfigs()');
|
||||||
|
$methodEnd = strpos($source, 'public function parse(', $methodStart);
|
||||||
|
$method = substr($source, $methodStart, $methodEnd - $methodStart);
|
||||||
|
|
||||||
|
expect($method)
|
||||||
|
->not->toContain("'rm -f .env || true'")
|
||||||
|
->toContain("new_public_id().'.env.tmp'")
|
||||||
|
->toContain('tee {$environmentFilename} > /dev/null && mv {$environmentFilename} .env')
|
||||||
|
->toContain('touch {$environmentFilename} && mv {$environmentFilename} .env');
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue