make:driver
Scaffold a driver, its conformance test, and an optional installable split package with vortos:make:driver.
make:driver
Writing a driver by hand means remembering the attribute, the capability descriptor skeleton, and the conformance test boilerplate every time. vortos:make:driver generates all of it from two arguments: the concern and the driver's key.
php bin/console vortos:make:driver deploy k8s \
--port="App\Deploy\Target\DeployTargetInterface" \
--tck="App\Deploy\Testing\DeployTargetConformanceTestCase"This creates:
src/Deploy/Target/K8s/
├── K8sDriver.php
└── Tests/
└── K8sDriverConformanceTest.phpOptions
| Option | Default | Purpose |
|---|---|---|
--port | Vortos\OpsKit\Driver\DriverInterface | FQCN of the port interface the driver implements |
--namespace | App\<Concern>\Driver | Parent namespace for the generated class |
--tck | Vortos\OpsKit\Testing\ConformanceTestCase | FQCN of the conformance base class the test extends |
--tag | vortos.<concern>.driver | DI tag used by the concern's compiler pass |
--dir | derived from namespace | Output directory |
--order | 150 | extra.vortos.order written into a split package's composer.json |
--split | off | Also scaffold a full installable Composer package |
Step-by-step
Generate the driver against your concern's actual port and TCK:
php bin/console vortos:make:driver backup s3-glacier \
--port="App\Backup\Target\BackupTargetInterface" \
--tck="App\Backup\Testing\BackupTargetConformanceTestCase"Fill in capabilities() with what the driver honestly supports:
public function capabilities(): CapabilityDescriptor
{
return CapabilityDescriptor::create(capabilities: [
'point_in_time_restore' => false,
'object_lock' => true,
]);
}Implement the port's actual methods (deploy(), store(), notify() — whatever your port declares).
Wire registerForAutoconfiguration() in your concern's DI extension if this is the first driver for that port — the scaffolder prints the exact line to add:
$container->registerForAutoconfiguration(BackupTargetInterface::class)
->addTag('vortos.backup.target');Run the generated conformance test. It already inherits the full TCK for that port — no test code to write beyond createDriver() and expectedKey(), which the scaffolder fills in for you:
./vendor/bin/phpunit src/Backup/Target/S3Glacier/Tests/S3GlacierDriverConformanceTest.phpShipping a driver as its own package
Pass --split to scaffold a complete installable Composer package alongside the driver — useful when a driver depends on a provider SDK you don't want as a hard dependency of the core concern.
php bin/console vortos:make:driver analytics mixpanel --splitpackages/Vortos/src/AnalyticsMixpanel/
├── composer.json
├── DependencyInjection/
│ ├── AnalyticsMixpanelPackage.php
│ └── AnalyticsMixpanelExtension.php
└── MixpanelDriver.phpThe generated Extension calls setAutoconfigured(true) so the core concern's registerForAutoconfiguration() rule picks up the driver the moment the package is installed — there's no manual registration step on the consuming application's side. This is exactly the pattern AnalyticsPosthog and DeployK8s use.
Existing files are never overwritten
DriverScaffolder::write() skips any file that already exists rather than overwriting it. Re-running make:driver after hand-editing the generated class is safe.
Ops Kit
The swappable-driver pattern shared by every Vortos operations concern — ports, drivers, capabilities, and registries with zero runtime reflection.
Testing & the Agnosticism Lint
The conformance test suite (TCK) every driver inherits, and the static check that keeps provider names out of core engine code.