Add managed registry provisioning, pruning, and readiness tracking
This commit is contained in:
@@ -5,6 +5,7 @@ use App\Actions\Applications\GenerateDeployKey;
|
||||
use App\Actions\Environments\BuildApplicationArtifact;
|
||||
use App\Actions\Environments\PlanBuildArtifact;
|
||||
use App\Enums\BuildArtifactStatus;
|
||||
use App\Enums\BuildStrategy;
|
||||
use App\Enums\RegistryType;
|
||||
use App\Models\Application;
|
||||
use App\Models\Network;
|
||||
@@ -23,7 +24,7 @@ beforeEach(function () {
|
||||
{
|
||||
$this->scripts[] = $script;
|
||||
|
||||
return str_contains($script, 'docker manifest inspect')
|
||||
return str_contains($script, 'docker buildx imagetools inspect') || str_contains($script, 'push_output=$(docker push')
|
||||
? "image_digest=sha256:registrydigest\n"
|
||||
: "image_digest=billing-api:aaaaaaaaaaaa@sha256:localdigest\n";
|
||||
}
|
||||
@@ -80,13 +81,64 @@ it('resolves external registry artifacts without building locally', function ()
|
||||
|
||||
expect($built->registry_ref)->toBe('ghcr.io/example/billing-api:bbbbbbbbbbbb')
|
||||
->and($built->image_digest)->toBe('sha256:registrydigest')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('docker manifest inspect')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('docker buildx imagetools inspect')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('ghcr.io/example/billing-api:bbbbbbbbbbbb')
|
||||
->and($this->remoteRunner->scripts[0])->not->toContain('docker build')
|
||||
->and($this->remoteRunner->scripts[0])->not->toContain('docker build --file')
|
||||
->and($this->remoteRunner->scripts[0])->not->toContain('git clone');
|
||||
});
|
||||
|
||||
function buildServerFor(Organisation $organisation): Server
|
||||
it('builds and pushes managed registry artifacts without embedding registry credentials', function () {
|
||||
$organisation = Organisation::factory()->create();
|
||||
$server = buildServerFor($organisation, true);
|
||||
$organisation->registries()->create([
|
||||
'name' => 'Managed',
|
||||
'type' => RegistryType::MANAGED,
|
||||
'url' => 'registry.example.com',
|
||||
'credentials' => [
|
||||
'build_username' => 'keystone-build',
|
||||
'build_password' => 'super-secret-password',
|
||||
'runtime_username' => 'keystone-runtime',
|
||||
'runtime_password' => 'runtime-secret',
|
||||
],
|
||||
'control_server_id' => $server->id,
|
||||
'health_status' => 'healthy',
|
||||
'readiness_checks' => ['control_https' => 'passed', 'build_push' => 'passed'],
|
||||
'ready_at' => now(),
|
||||
]);
|
||||
$application = Application::factory()->for($organisation)->create([
|
||||
'name' => 'Billing API',
|
||||
'repository_url' => 'git@example.com:org/repo.git',
|
||||
]);
|
||||
app(GenerateDeployKey::class)->execute($application, [
|
||||
'public' => 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAITestPublicKey keystone',
|
||||
'private' => "-----BEGIN OPENSSH PRIVATE KEY-----\ntest\n-----END OPENSSH PRIVATE KEY-----",
|
||||
'fingerprint' => 'SHA256:test',
|
||||
]);
|
||||
$environment = app(CreateLaravelEnvironment::class)->execute($application->refresh(), 'production');
|
||||
$environment->services()->first()->update([
|
||||
'server_id' => $server->id,
|
||||
'desired_replicas' => 2,
|
||||
]);
|
||||
$artifact = app(PlanBuildArtifact::class)->execute($environment, str_repeat('c', 40));
|
||||
|
||||
$built = app(BuildApplicationArtifact::class)->execute($artifact);
|
||||
|
||||
expect($built->registry_ref)->toBe("registry.example.com/keystone/{$application->uuid}/{$environment->uuid}:cccccccccccc")
|
||||
->and($built->metadata['build_strategy'])->toBe(BuildStrategy::DEDICATED_BUILDER->value)
|
||||
->and($built->image_digest)->toBe('sha256:registrydigest')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('flock 9')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('docker login')
|
||||
->and($this->remoteRunner->scripts[0])->toContain(base64_encode('super-secret-password'))
|
||||
->and($this->remoteRunner->scripts[0])->toContain('docker build --file Dockerfile.keystone')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('push_output=$(docker push')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('digest: \\(sha256:')
|
||||
->and($this->remoteRunner->scripts[0])->not->toContain('docker manifest inspect')
|
||||
->and($this->remoteRunner->scripts[0])->not->toContain('"digest"')
|
||||
->and($this->remoteRunner->scripts[0])->not->toContain('super-secret-password')
|
||||
->and($this->remoteRunner->scripts[0])->toContain('DOCKER_CONFIG=\'/root/.docker\'');
|
||||
});
|
||||
|
||||
function buildServerFor(Organisation $organisation, bool $buildEnabled = false): Server
|
||||
{
|
||||
$provider = Provider::factory()->forOrganisation($organisation)->create();
|
||||
$network = Network::create([
|
||||
@@ -100,5 +152,8 @@ function buildServerFor(Organisation $organisation): Server
|
||||
->forOrganisation($organisation->id)
|
||||
->forProvider($provider->id)
|
||||
->forNetwork($network->id)
|
||||
->create();
|
||||
->create([
|
||||
'is_control_node' => $buildEnabled,
|
||||
'build_enabled' => $buildEnabled,
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user