Keep deployment logging available on formatting errors

This commit is contained in:
Andras Bacsai
2026-09-24 09:36:59 +02:00
parent b37d24d258
commit 50643a44f8
3 changed files with 114 additions and 76 deletions
+39 -35
View File
@@ -179,43 +179,47 @@ class ApplicationDeploymentQueue extends Model
private function redactSensitiveInfo($text)
{
$text = remove_iip($text);
try {
$text = remove_iip($text);
$app = $this->application;
if (! $app) {
return $text;
$app = $this->application;
if (! $app) {
return $text;
}
$lockedVars = collect([]);
if ($app->environment_variables) {
$lockedVars = $lockedVars->merge(
$app->environment_variables
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
if ($this->pull_request_id !== 0 && $app->environment_variables_preview) {
$lockedVars = $lockedVars->merge(
$app->environment_variables_preview
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
foreach ($lockedVars as $key => $value) {
$escapedValue = preg_quote($value, '/');
$text = preg_replace(
'/'.$escapedValue.'/',
REDACTED,
$text
);
}
return is_string($text) ? $text : REDACTED;
} catch (\Throwable) {
return REDACTED;
}
$lockedVars = collect([]);
if ($app->environment_variables) {
$lockedVars = $lockedVars->merge(
$app->environment_variables
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
if ($this->pull_request_id !== 0 && $app->environment_variables_preview) {
$lockedVars = $lockedVars->merge(
$app->environment_variables_preview
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
foreach ($lockedVars as $key => $value) {
$escapedValue = preg_quote($value, '/');
$text = preg_replace(
'/'.$escapedValue.'/',
REDACTED,
$text
);
}
return $text;
}
public function addLogEntry(string $message, string $type = 'stdout', bool $hidden = false)
+45 -41
View File
@@ -22,49 +22,53 @@ trait ExecuteRemoteCommand
private function redact_sensitive_info($text)
{
$text = remove_iip($text);
try {
$text = remove_iip($text);
if (! isset($this->application)) {
return $text;
if (! isset($this->application)) {
return $text;
}
$lockedVars = collect([]);
if (isset($this->application->environment_variables)) {
$lockedVars = $lockedVars->merge(
$this->application->environment_variables
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
if (isset($this->pull_request_id) && $this->pull_request_id !== 0 && isset($this->application->environment_variables_preview)) {
$lockedVars = $lockedVars->merge(
$this->application->environment_variables_preview
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
if (isset($this->remote_secrets_cache)) {
$lockedVars = $lockedVars->merge(array_values(array_filter(
$this->remote_secrets_cache,
static fn (mixed $value): bool => is_string($value) && $value !== ''
)));
}
foreach ($lockedVars as $key => $value) {
$escapedValue = preg_quote($value, '/');
$text = preg_replace(
'/'.$escapedValue.'/',
REDACTED,
$text
);
}
return is_string($text) ? $text : REDACTED;
} catch (\Throwable) {
return REDACTED;
}
$lockedVars = collect([]);
if (isset($this->application->environment_variables)) {
$lockedVars = $lockedVars->merge(
$this->application->environment_variables
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
if (isset($this->pull_request_id) && $this->pull_request_id !== 0 && isset($this->application->environment_variables_preview)) {
$lockedVars = $lockedVars->merge(
$this->application->environment_variables_preview
->where('is_shown_once', true)
->flatMap(fn (EnvironmentVariable $variable): array => $variable->logRedactionValues())
->filter()
);
}
if (isset($this->remote_secrets_cache)) {
$lockedVars = $lockedVars->merge(array_values(array_filter(
$this->remote_secrets_cache,
static fn (mixed $value): bool => is_string($value) && $value !== ''
)));
}
foreach ($lockedVars as $key => $value) {
$escapedValue = preg_quote($value, '/');
$text = preg_replace(
'/'.$escapedValue.'/',
REDACTED,
$text
);
}
return $text;
}
public function execute_remote_command(...$commands)
@@ -134,6 +134,36 @@ it('redacts generated multiline forms in remote command and output logging', fun
}
});
it('keeps deployment logging available if value formatting fails', function () {
[$application, $server] = makeDeploymentControlVarFixture();
$variable = new class extends EnvironmentVariable
{
public function logRedactionValues(): array
{
throw new RuntimeException('Harmless formatting failure');
}
};
$variable->is_shown_once = true;
$application->setRelation('environment_variables', collect([$variable]));
$deployment = ApplicationDeploymentQueue::create([
'deployment_uuid' => 'harmless-formatting-failure',
'application_id' => $application->id,
'server_id' => $server->id,
]);
$deployment->setRelation('application', $application);
$deployment->addLogEntry('Harmless log text');
expect(json_decode($deployment->fresh()->logs, true)[0]['output'])->toBe(REDACTED);
[$job, $reflection] = makeControlVarFilteringJob($application, $server);
readDeploymentJobProperty($job, $reflection, 'application')
->setRelation('environment_variables', collect([$variable]));
expect(invokeDeploymentJobMethod($job, $reflection, 'redact_sensitive_info', 'Harmless command text'))
->toBe(REDACTED);
});
it('ignores empty and non-string remote secrets when redacting command output', function () {
[$application, $server] = makeDeploymentControlVarFixture();
[$job, $reflection] = makeControlVarFilteringJob($application, $server, [