run method
Runs this command.
The return value is wrapped in a Future if necessary and returned by
CommandRunner.runCommand.
Implementation
@override
Future<int> run() async {
final rootPath = argResults?['root'] as String? ?? fs.currentDirectory.path;
final root = fs.directory(rootPath);
if (!root.existsSync()) {
logger.err('No such directory: $rootPath');
return 1;
}
final basePort = int.tryParse(argResults?['base-port'] as String? ?? '');
if (basePort == null) {
logger.err('--base-port must be a number');
return 1;
}
final services = const ServiceDiscovery().find(root);
if (services.isEmpty) {
logger.err(
'No Revali services found under $rootPath.\n'
'A service is a package with a routes/ directory that depends on '
'revali_router.',
);
return 1;
}
final content = composeFile(services, basePort: basePort);
if (argResults?['stdout'] as bool? ?? false) {
io.stdout.write(content);
return 0;
}
final outputPath =
argResults?['output'] as String? ??
p.join(root.path, 'docker-compose.yaml');
final output = fs.file(outputPath);
output.parent.createSync(recursive: true);
output.writeAsStringSync(content);
logger.success('Wrote ${services.length} service(s) to $outputPath');
final missing = services.where((s) => !s.hasDockerfile).toList();
if (missing.isNotEmpty) {
// Worth saying out loud: `docker compose up` would fail on these, and
// the reason is in a comment in a generated file nobody reads.
final paths = missing.map((s) => s.relativePath).join(', ');
logger.warn(
'${missing.length} service(s) have no Dockerfile yet. '
'Run `revali build` in: $paths',
);
}
return 0;
}