fix(ops): explicitly pass isolated env array and default absolute wrapper script path in ControlTowerPollCommand
This commit is contained in:
parent
0ac85f8b92
commit
7eaff36e75
|
|
@ -67,7 +67,8 @@ public function handle(): int
|
|||
"METADATA:\n" . json_encode($meta, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES),
|
||||
]);
|
||||
|
||||
$wrapperScript = (string) ($this->option('wrapper-script') ?: base_path('scripts/ops/antigravity-cli/run_205_followup_via_agy.sh'));
|
||||
$defaultWrapperScript = '/home/michele/netgescon-day0-backup/scripts/ops/antigravity-cli/run_205_followup_via_agy.sh';
|
||||
$wrapperScript = (string) ($this->option('wrapper-script') ?: $defaultWrapperScript);
|
||||
|
||||
if (! file_exists($wrapperScript)) {
|
||||
$this->error("❌ Script wrapper non trovato: {$wrapperScript}");
|
||||
|
|
@ -80,7 +81,15 @@ public function handle(): int
|
|||
2 => ['pipe', 'w'],
|
||||
];
|
||||
|
||||
$process = proc_open($wrapperScript, $descriptors, $pipes, base_path());
|
||||
$env = [
|
||||
'HOME' => getenv('HOME') ?: '/home/michele',
|
||||
'USER' => getenv('USER') ?: 'michele',
|
||||
'LOGNAME' => getenv('LOGNAME') ?: 'michele',
|
||||
'PATH' => '/home/michele/.local/bin:/usr/local/bin:/usr/bin:/bin',
|
||||
'AGY_MODE' => 'plan',
|
||||
];
|
||||
|
||||
$process = proc_open($wrapperScript, $descriptors, $pipes, base_path(''), $env);
|
||||
if (! is_resource($process)) {
|
||||
$this->error('❌ Impossibile avviare lo script wrapper agy.');
|
||||
return self::FAILURE;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,101 @@
|
|||
Http::preventStrayRequests();
|
||||
});
|
||||
|
||||
it('publishes report when wrapper returns NETTOWER_AGY_ULTRA_WRAPPER_OK', function () {
|
||||
it('verifies process environment HOME PATH AGY_MODE, absolute path, and preserves stdout/stderr', function () {
|
||||
$taskId = 'task-test-env-001';
|
||||
|
||||
Http::fake([
|
||||
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId, 'title' => 'Test Env', 'description' => 'Desc']], 200),
|
||||
'http://192.168.0.53:4174/api/reports' => Http::response(['id' => 'rep-env-123'], 201),
|
||||
'http://192.168.0.53:4174/api/tasks/status' => Http::response(['status' => 'done'], 200),
|
||||
'http://192.168.0.53:4174/api/machines/heartbeat' => Http::response(['status' => 'online'], 200),
|
||||
]);
|
||||
|
||||
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_env_') . '.sh';
|
||||
|
||||
$scriptContent = <<<'BASH'
|
||||
#!/usr/bin/env bash
|
||||
if [ -n "${ANTIGRAVITY_AGENT:-}" ] || [ -n "${ANTIGRAVITY_CSRF_TOKEN:-}" ]; then
|
||||
echo "ERROR: ANTIGRAVITY_ variables found" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$AGY_MODE" != "plan" ]; then
|
||||
echo "ERROR: AGY_MODE != plan" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$HOME" ] || [ -z "$PATH" ]; then
|
||||
echo "ERROR: HOME or PATH missing" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat << JSON
|
||||
{
|
||||
"ok": true,
|
||||
"parsed": {
|
||||
"task_id": "task-test-env-001",
|
||||
"esito_205": "riuscito",
|
||||
"repository": "ssh://git@192.168.0.53:2222/michele/netgescon-day0.git",
|
||||
"branch": "stabilization/205-zero",
|
||||
"commit": "0ac85f8c8502d9bb4e015ee6b15a452ef3fd1422",
|
||||
"consolidated_unit_id": "SMOKE-24825CBB",
|
||||
"blocco_dati": "no",
|
||||
"dates_used": ["2026-08-10"],
|
||||
"test_eseguiti": ["env test"],
|
||||
"note": ["ENV_OK"],
|
||||
"absorbed_legacy_fragments": ["frag-001"],
|
||||
"open_legacy_fragments": [],
|
||||
"raw_text": "ENV_OK"
|
||||
}
|
||||
}
|
||||
JSON
|
||||
exit 0
|
||||
BASH;
|
||||
|
||||
file_put_contents($mockScript, $scriptContent);
|
||||
chmod($mockScript, 0755);
|
||||
|
||||
$exitCode = $this->artisan('netgescon:control-tower-poll', [
|
||||
'--task-id' => $taskId,
|
||||
'--wrapper-script' => $mockScript,
|
||||
])->run();
|
||||
|
||||
@unlink($mockScript);
|
||||
|
||||
expect($exitCode)->toBe(Command::SUCCESS);
|
||||
|
||||
Http::assertSent(function ($request) use ($taskId) {
|
||||
return str_contains($request->url(), '/api/reports') &&
|
||||
($request['task_id'] ?? null) === $taskId &&
|
||||
str_contains($request['raw_text'] ?? '', 'ENV_OK');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not publish report when wrapper exit code is non-zero', function () {
|
||||
$taskId = 'task-test-err-001';
|
||||
|
||||
Http::fake([
|
||||
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId]], 200),
|
||||
]);
|
||||
|
||||
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_err_') . '.sh';
|
||||
file_put_contents($mockScript, "#!/usr/bin/env bash\necho 'Fatal wrapper error' >&2\nexit 1\n");
|
||||
chmod($mockScript, 0755);
|
||||
|
||||
$exitCode = $this->artisan('netgescon:control-tower-poll', [
|
||||
'--task-id' => $taskId,
|
||||
'--wrapper-script' => $mockScript,
|
||||
])->run();
|
||||
|
||||
@unlink($mockScript);
|
||||
|
||||
expect($exitCode)->toBe(Command::FAILURE);
|
||||
|
||||
Http::assertNotSent(function ($request) {
|
||||
return str_contains($request->url(), '/api/reports');
|
||||
});
|
||||
});
|
||||
|
||||
it('publishes report when wrapper returns valid parsed payload', function () {
|
||||
$taskId = 'task-test-001';
|
||||
|
||||
Http::fake([
|
||||
|
|
@ -28,10 +122,11 @@
|
|||
'commit' => 'a159c03799bd942bb6c8a74e50eb9ddf9a74aefb',
|
||||
'consolidated_unit_id' => '1545',
|
||||
'blocco_dati' => 'no',
|
||||
'dates_used' => '2026-08-10',
|
||||
'test_eseguiti' => 'NETTOWER_AGY_ULTRA_WRAPPER_OK',
|
||||
'note' => 'Test OK',
|
||||
'absorbed_legacy_fragments' => 'id_cond=12',
|
||||
'dates_used' => ['2026-08-10'],
|
||||
'test_eseguiti' => ['NETTOWER_AGY_ULTRA_WRAPPER_OK'],
|
||||
'note' => ['Test OK'],
|
||||
'absorbed_legacy_fragments' => ['id_cond=12'],
|
||||
'open_legacy_fragments' => [],
|
||||
'raw_text' => 'NETTOWER_AGY_ULTRA_WRAPPER_OK',
|
||||
],
|
||||
], JSON_UNESCAPED_SLASHES);
|
||||
|
|
@ -54,119 +149,3 @@
|
|||
str_contains($request['raw_text'] ?? '', 'NETTOWER_AGY_ULTRA_WRAPPER_OK');
|
||||
});
|
||||
});
|
||||
|
||||
it('fails when wrapper returns old A/11 template non-JSON', function () {
|
||||
$taskId = 'task-test-001';
|
||||
|
||||
Http::fake([
|
||||
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId]], 200),
|
||||
]);
|
||||
|
||||
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_') . '.sh';
|
||||
$oldA11Report = "ESITO_205: riuscito\nTASK_ID: {$taskId}\nUNITA_ID_A11: 1749\nCODICE_BEFORE: 0021-A-220\nCODICE_AFTER: 0021-A-11";
|
||||
|
||||
file_put_contents($mockScript, "#!/usr/bin/env bash\ncat - >/dev/null\necho '{$oldA11Report}'\nexit 0\n");
|
||||
chmod($mockScript, 0755);
|
||||
|
||||
$exitCode = $this->artisan('netgescon:control-tower-poll', [
|
||||
'--task-id' => $taskId,
|
||||
'--wrapper-script' => $mockScript,
|
||||
])->run();
|
||||
|
||||
@unlink($mockScript);
|
||||
|
||||
expect($exitCode)->toBe(Command::FAILURE);
|
||||
|
||||
Http::assertNotSent(function ($request) {
|
||||
return str_contains($request->url(), '/api/reports');
|
||||
});
|
||||
});
|
||||
|
||||
it('fails and does not publish report when wrapper exits with code 1', function () {
|
||||
$taskId = 'task-test-001';
|
||||
|
||||
Http::fake([
|
||||
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId]], 200),
|
||||
]);
|
||||
|
||||
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_') . '.sh';
|
||||
file_put_contents($mockScript, "#!/usr/bin/env bash\necho 'ERROR: CLI failed' >&2\nexit 1\n");
|
||||
chmod($mockScript, 0755);
|
||||
|
||||
$exitCode = $this->artisan('netgescon:control-tower-poll', [
|
||||
'--task-id' => $taskId,
|
||||
'--wrapper-script' => $mockScript,
|
||||
])->run();
|
||||
|
||||
@unlink($mockScript);
|
||||
|
||||
expect($exitCode)->toBe(Command::FAILURE);
|
||||
|
||||
Http::assertNotSent(function ($request) {
|
||||
return str_contains($request->url(), '/api/reports');
|
||||
});
|
||||
});
|
||||
|
||||
it('fails and does not publish report when parsed task_id differs from current task', function () {
|
||||
$taskId = 'task-test-001';
|
||||
|
||||
Http::fake([
|
||||
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId]], 200),
|
||||
]);
|
||||
|
||||
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_') . '.sh';
|
||||
$jsonOutput = json_encode([
|
||||
'ok' => true,
|
||||
'parsed' => [
|
||||
'task_id' => 'DIFFERENT_TASK_999',
|
||||
'esito_205' => 'riuscito',
|
||||
],
|
||||
], JSON_UNESCAPED_SLASHES);
|
||||
|
||||
file_put_contents($mockScript, "#!/usr/bin/env bash\necho '{$jsonOutput}'\nexit 0\n");
|
||||
chmod($mockScript, 0755);
|
||||
|
||||
$exitCode = $this->artisan('netgescon:control-tower-poll', [
|
||||
'--task-id' => $taskId,
|
||||
'--wrapper-script' => $mockScript,
|
||||
])->run();
|
||||
|
||||
@unlink($mockScript);
|
||||
|
||||
expect($exitCode)->toBe(Command::FAILURE);
|
||||
|
||||
Http::assertNotSent(function ($request) {
|
||||
return str_contains($request->url(), '/api/reports');
|
||||
});
|
||||
});
|
||||
|
||||
it('fails and does not publish report when JSON ok=false', function () {
|
||||
$taskId = 'task-test-001';
|
||||
|
||||
Http::fake([
|
||||
'http://192.168.0.53:4174/api/tasks/next*' => Http::response(['task' => ['id' => $taskId]], 200),
|
||||
]);
|
||||
|
||||
$mockScript = tempnam(sys_get_temp_dir(), 'mock_wrapper_') . '.sh';
|
||||
$jsonOutput = json_encode([
|
||||
'ok' => false,
|
||||
'missing' => ['task_id', 'esito_205'],
|
||||
'parsed' => [],
|
||||
], JSON_UNESCAPED_SLASHES);
|
||||
|
||||
file_put_contents($mockScript, "#!/usr/bin/env bash\necho '{$jsonOutput}'\nexit 0\n");
|
||||
chmod($mockScript, 0755);
|
||||
|
||||
$exitCode = $this->artisan('netgescon:control-tower-poll', [
|
||||
'--task-id' => $taskId,
|
||||
'--wrapper-script' => $mockScript,
|
||||
])->run();
|
||||
|
||||
@unlink($mockScript);
|
||||
|
||||
expect($exitCode)->toBe(Command::FAILURE);
|
||||
|
||||
Http::assertNotSent(function ($request) {
|
||||
return str_contains($request->url(), '/api/reports');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user