create(['status' => 'error']); $run = ProvisioningRun::factory()->create([ 'subject_type' => Host::class, 'subject_id' => $host->id, 'pipeline' => 'host', 'status' => ProvisioningRun::STATUS_FAILED, 'attempt' => 3, 'current_step' => 4, 'error' => 'boom', ]); Livewire::actingAs(admin(), 'operator')->test(Provisioning::class)->call('retry', $run->uuid); $run->refresh(); expect($run->status)->toBe(ProvisioningRun::STATUS_RUNNING) ->and($run->attempt)->toBe(0) ->and($run->error)->toBeNull() ->and($host->fresh()->status)->toBe('onboarding'); Queue::assertPushed(AdvanceRunJob::class); }); it('leaves a live customer alone when the run being retried is a maintenance one', function () { // The retry set the order to `provisioning` for ANY pipeline, and only the // `customer` pipeline ever puts it back to `active` (CompleteProvisioning). // So retrying a failed address, restart, storage, quota or plan-change run // left a paying customer's order reading `provisioning` for ever: nothing in // the product would move it again, the customer saw nothing wrong, and the // console's view of them was simply false. Same reasoning as RunRunner's // failRun() on the way down — a maintenance run must not condemn what it // maintains. Queue::fake(); $order = Order::factory()->create(['status' => 'active']); $instance = Instance::factory()->create([ 'order_id' => $order->id, 'customer_id' => $order->customer_id, 'status' => 'active', ]); $run = ProvisioningRun::factory()->create([ 'subject_type' => Order::class, 'subject_id' => $order->id, 'pipeline' => 'address', 'status' => ProvisioningRun::STATUS_FAILED, 'error' => 'boom', ]); Livewire::actingAs(admin(), 'operator')->test(Provisioning::class)->call('retry', $run->uuid); expect($run->fresh()->status)->toBe(ProvisioningRun::STATUS_RUNNING) ->and($order->fresh()->status)->toBe('active') ->and($instance->fresh()->status)->toBe('active'); Queue::assertPushed(AdvanceRunJob::class); }); it('does put a customer build back into provisioning when that is the run being retried', function () { Queue::fake(); $order = Order::factory()->create(['status' => 'failed']); $instance = Instance::factory()->create([ 'order_id' => $order->id, 'customer_id' => $order->customer_id, 'status' => 'failed', ]); $run = ProvisioningRun::factory()->create([ 'subject_type' => Order::class, 'subject_id' => $order->id, 'pipeline' => 'customer', 'status' => ProvisioningRun::STATUS_FAILED, 'error' => 'boom', ]); Livewire::actingAs(admin(), 'operator')->test(Provisioning::class)->call('retry', $run->uuid); expect($order->fresh()->status)->toBe('provisioning') ->and($instance->fresh()->status)->toBe('provisioning'); }); it('ignores retry on a run that is not failed', function () { Queue::fake(); $host = Host::factory()->active()->create(); $run = ProvisioningRun::factory()->create([ 'subject_type' => Host::class, 'subject_id' => $host->id, 'pipeline' => 'host', 'status' => ProvisioningRun::STATUS_RUNNING, ]); Livewire::actingAs(admin(), 'operator')->test(Provisioning::class)->call('retry', $run->uuid); expect($run->fresh()->status)->toBe(ProvisioningRun::STATUS_RUNNING); Queue::assertNotPushed(AdvanceRunJob::class); });