toContain('release_host_step_needs') ->and($update)->toContain('release_host_step_needs') ->and($agent)->toContain('release_host_step_needs'); // Und keine nackte Zahl mehr an den beiden alten Stellen. expect($update)->not->toContain('HOST_STEP_NEEDS=3') ->and($agent)->not->toContain('(( have < 3 ))'); }); it('answers the needed contract version from the shell', function () { $result = Process::path(base_path())->timeout(30)->run( 'bash -c '.escapeshellarg('set -Eeuo pipefail; . deploy/lib/release.sh; release_host_step_needs') ); expect($result->exitCode())->toBe(0) ->and(trim($result->output()))->toMatch('/^[0-9]+$/'); }); it('reports the helper as not ok when the host has an older one', function () { File::ensureDirectoryExists(storage_path('app/deploy')); File::put(storage_path('app/deploy/update-status.json'), json_encode([ 'state' => 'idle', 'host_step_contract' => 2, 'host_step_needs' => 3, ])); $state = app(UpdateChannel::class)->state(); expect($state['host_step_ok'])->toBeFalse() ->and($state['host_step_have'])->toBe(2) ->and($state['host_step_needs'])->toBe(3); }); it('reports the helper as ok when it is current', function () { File::ensureDirectoryExists(storage_path('app/deploy')); File::put(storage_path('app/deploy/update-status.json'), json_encode([ 'state' => 'idle', 'host_step_contract' => 3, 'host_step_needs' => 3, ])); expect(app(UpdateChannel::class)->state()['host_step_ok'])->toBeTrue(); }); it('does not cry wolf when the agent has not reported yet', function () { // Ein Wirt, dessen Agent die Zahlen noch nie gemeldet hat (alte Fassung, // erster Lauf), darf nicht als kaputt dastehen. „Ich weiß es nicht" ist // nicht dasselbe wie „zu alt". File::ensureDirectoryExists(storage_path('app/deploy')); File::put(storage_path('app/deploy/update-status.json'), json_encode(['state' => 'idle'])); expect(app(UpdateChannel::class)->state()['host_step_ok'])->toBeTrue(); });