diff --git a/.vscode/launch.json b/.vscode/launch.json index d8517e7..0bc7838 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -100,14 +100,14 @@ "request": "launch", "type": "dart", "program": "./bin/main.dart", - "args": ["scheduler", "-r", "./assets/scheduler.yaml"] + "args": ["scheduler", "-r", "./assets/scheduler2.yaml"] }, { "name": "scheduler unregist", "request": "launch", "type": "dart", "program": "./bin/main.dart", - "args": ["scheduler", "-u", "test"] + "args": ["scheduler", "-u", "test2"] }, { "name": "scheduler background", @@ -115,6 +115,13 @@ "type": "dart", "program": "./bin/main.dart", "args": ["scheduler", "-s"] + }, + { + "name": "scheduler enable", + "request": "launch", + "type": "dart", + "program": "./bin/main.dart", + "args": ["scheduler", "-e", "test2", "true"] } ] } \ No newline at end of file diff --git a/assets/scheduler.yaml b/assets/scheduler.yaml index 069cdff..e81b03c 100644 --- a/assets/scheduler.yaml +++ b/assets/scheduler.yaml @@ -7,7 +7,7 @@ scheduler: property: - workspace: /Users/toki/works/oto_cli + workspace: /home/deck/work/oto_cli pipeline: @@ -25,10 +25,10 @@ commands: id: diff param: paths: - - /Users/toki/works/oto_cli/lib/oto/data/command_data.dart - - /Users/toki/works/oto_cli/lib/oto/data/jenkins_data.dart - - /Users/toki/works/oto_cli/lib/oto/data/jira_data.dart - - /Users/toki/works/oto_cli/lib/oto/data/pipeline_data.dart + - /lib/oto/data/command_data.dart + - /lib/oto/data/jenkins_data.dart + - /lib/oto/data/jira_data.dart + - /lib/oto/data/pipeline_data.dart setDiff: <@property.isDiff> - command: Shell diff --git a/lib/cli/commands/scheduler/scheduler_linux.dart b/lib/cli/commands/scheduler/scheduler_linux.dart index ffb0984..eb970b1 100644 --- a/lib/cli/commands/scheduler/scheduler_linux.dart +++ b/lib/cli/commands/scheduler/scheduler_linux.dart @@ -1,5 +1,10 @@ +import 'dart:io'; import 'package:oto_cli/cli/commands/scheduler/scheduler_manager.dart'; class SchedulerLinux extends SchedulerManager { -} \ No newline at end of file + @override + String get exePath { + return Platform.resolvedExecutable; + } +} diff --git a/lib/cli/commands/scheduler/scheduler_manager.dart b/lib/cli/commands/scheduler/scheduler_manager.dart index e14f71e..53d4ec6 100644 --- a/lib/cli/commands/scheduler/scheduler_manager.dart +++ b/lib/cli/commands/scheduler/scheduler_manager.dart @@ -1,4 +1,3 @@ - import 'dart:collection'; import 'dart:convert'; import 'dart:io'; @@ -18,7 +17,6 @@ import 'package:oto_cli/oto/data/command_data.dart'; import 'package:path/path.dart' as path; class SchedulerManager { - static String get _schedulerPath { var debugPath = isDebug ? '.debug' : ''; return '$dataPath$debugPath/scheduler'; @@ -30,7 +28,12 @@ class SchedulerManager { ProcessInfo? _currentScheduler; final Map _map = {}; - final logFile = File('$_logsPath/scheduler_${getDate()}_${getTime().replaceAll(':', '')}_[$pid].txt'); + final logFile = File( + '$_logsPath/scheduler_${getDate()}_${getTime().replaceAll(':', '')}_[$pid].txt'); + + String get exePath { + return throw UnimplementedError('Unimplemented exePath'); + } String get _settingsPath { return '$_schedulerPath/settings.json'; @@ -38,7 +41,7 @@ class SchedulerManager { SchedulerListData get _localData { var file = File(_settingsPath); - if(!file.existsSync()) { + if (!file.existsSync()) { _localData = SchedulerListData(); } return SchedulerListData.fromJson(jsonDecode(file.readAsStringSync())); @@ -46,7 +49,8 @@ class SchedulerManager { set _localData(SchedulerListData data) { var file = File(_settingsPath); - file.writeAsStringSync(JsonEncoder.withIndent(' ').convert(data.toJson()), mode: FileMode.write, flush: true); + file.writeAsStringSync(JsonEncoder.withIndent(' ').convert(data.toJson()), + mode: FileMode.write, flush: true); } String get _startupID { @@ -56,11 +60,11 @@ class SchedulerManager { HashSet get _schedulers { HashSet hash = HashSet(); var dir = Directory(_schedulerPath); - if(dir.existsSync()) { + if (dir.existsSync()) { var fileList = dir.listSync(); - for(var item in fileList) { - if(item is File) { - if(path.extension(item.path).toLowerCase().contains('.yaml')) { + for (var item in fileList) { + if (item is File) { + if (path.extension(item.path).toLowerCase().contains('.yaml')) { hash.add(path.basenameWithoutExtension(item.path)); } } @@ -70,13 +74,13 @@ class SchedulerManager { } SchedulerManager(); - + factory SchedulerManager.create() { - if(Platform.isMacOS) { + if (Platform.isMacOS) { return SchedulerOsx(); - } else if(Platform.isWindows) { + } else if (Platform.isWindows) { return SchedulerWindows(); - } else if(Platform.isLinux) { + } else if (Platform.isLinux) { return SchedulerLinux(); } else { throw UnsupportedError('This platform not supported.'); @@ -85,7 +89,7 @@ class SchedulerManager { Future regist(String filePath) async { var file = File(filePath); - if(!file.existsSync()) { + if (!file.existsSync()) { return throw Exception("The file '$filePath' does not exist."); } Map? map; @@ -93,26 +97,28 @@ class SchedulerManager { try { map = Application.getMapFromYamlA(await file.readAsString()); build = DataBuild.fromJson(map!); - } on Exception catch(e, stacktace) { + } on Exception catch (e, stacktace) { print(stacktace); - return throw Exception("The file '$filePath' is not in yaml format or is an unsupported build format."); + return throw Exception( + "The file '$filePath' is not in yaml format or is an unsupported build format."); } - if(build.scheduler == null) { + if (build.scheduler == null) { return throw Exception('Scheduler entry does not exist within yaml.'); } var dirLogs = Directory(_logsPath); var alias = build.scheduler!.alias; var hash = _schedulers; - if(hash.contains(alias)) { - return throw Exception('A scheduler with the same alias is registered. Please do it with a different alias.'); + if (hash.contains(alias)) { + return throw Exception( + 'A scheduler with the same alias is registered. Please do it with a different alias.'); } await _checkStartup(); await _checkProcess(); await _startProcess(); - - if(!dirLogs.existsSync()) { + + if (!dirLogs.existsSync()) { dirLogs.createSync(recursive: true); } var newPath = '$_schedulerPath/$alias.yaml'; @@ -135,7 +141,7 @@ class SchedulerManager { } Future unregist(String alias) async { - if(_schedulers.contains(alias)) { + if (_schedulers.contains(alias)) { var file = File('$_schedulerPath/$alias.yaml'); file.deleteSync(); } else { @@ -143,7 +149,7 @@ class SchedulerManager { } var local = _localData; - if(local.map.containsKey(alias)) { + if (local.map.containsKey(alias)) { local.map.remove(alias); _localData = local; } @@ -156,7 +162,7 @@ class SchedulerManager { Future showList() async { print(''); var scheduleList = _schedulers; - if(scheduleList.isEmpty) { + if (scheduleList.isEmpty) { print(':::: There are no registered schedulers.'); print(''); } else { @@ -164,12 +170,13 @@ class SchedulerManager { print(''); print('${' [Enable]'.padRight(20)}${'[Alias]'.padRight(20)}[Path]'); var local = _localData; - for(var item in _schedulers) { + for (var item in _schedulers) { var enable = true; - if(local.map.containsKey(item)) { + if (local.map.containsKey(item)) { enable = local.map[item]!.enable; } - print('${' - $enable'.padRight(20)}${item.padRight(20)}$_schedulerPath/$item.yaml'); + print( + '${' - $enable'.padRight(20)}${item.padRight(20)}$_schedulerPath/$item.yaml'); } print(''); } @@ -179,7 +186,7 @@ class SchedulerManager { Future enableScheduler(String alias, bool enable) async { var local = _localData; - if(_schedulers.contains(alias)) { + if (_schedulers.contains(alias)) { var data = SchedulerData(); data.alias = alias; data.enable = enable; @@ -189,11 +196,11 @@ class SchedulerManager { print(''); print("Scheduler '$alias' has been $activate."); print(''); - + await _checkStartup(); await _checkProcess(); await _startProcess(); - + exit(0); } else { return throw Exception("There is no scheduler called '$alias'."); @@ -202,7 +209,7 @@ class SchedulerManager { Future terminate() async { await _checkProcess(); - if(_currentScheduler != null) { + if (_currentScheduler != null) { Process.killPid(_currentScheduler!.pid); print('Scheduler operation stopped.'); } @@ -210,7 +217,7 @@ class SchedulerManager { } Future _checkTerminate() async { - if(_schedulers.isEmpty) { + if (_schedulers.isEmpty) { await _unregistStartup(); await terminate(); } @@ -219,12 +226,16 @@ class SchedulerManager { Future _startProcess() async { //Launchd로 자동 실행이 되지 않은경우 직접실행 - if(_currentScheduler == null) { + if (_currentScheduler == null) { var script = isDebug ? ' $scriptPath' : ''; var shell = StringBuffer(); shell.writeln('nohup $executablePath$script scheduler -s &'); - shell.writeln('disown'); - ProcessExecutor.run(shell, workspace: Directory.systemTemp.path, printStdout: false); + // shell.writeln('disown'); + print(shell.toString()); + ProcessExecutor.run(shell, + workspace: Directory.systemTemp.path, + printStdout: false, + logHandler: (p0, p1) => print(p0)); await _checkProcess(); } return simpleFuture; @@ -233,9 +244,10 @@ class SchedulerManager { Future _checkProcess() async { //process check var processes = await findProcess('scheduler -s'); - for(var process in processes) { + for (var process in processes) { var processName = process.name; - if(processName.contains('main.dart scheduler -s') || processName.contains('$appName scheduler -s')) { + if (processName.contains('main.dart scheduler -s') || + processName.contains('$appName scheduler -s')) { _currentScheduler = process; print('Scheduler is running on pid [${_currentScheduler!.pid}].'); break; @@ -245,30 +257,24 @@ class SchedulerManager { } Future _checkStartup() async { - if(!await OSStartup.isRegistedStartup(_startupID)) { + if (!await OSStartup.isRegistedStartup(_startupID)) { List param = []; var exe = Platform.resolvedExecutable; - if(isDebug) { + if (isDebug) { param.add(scriptPath); } else { - //homebrew로 설치시 예외 처리 - if(exe.startsWith('/usr/local')) { - //intel mac - exe = '/usr/local/bin/${path.basenameWithoutExtension(exe)}'; - } else if(exe.startsWith('/opt/homebrew')) { - //sillicon mac - exe = '/opt/homebrew/bin/${path.basenameWithoutExtension(exe)}'; - } + exe = exePath; } param.add('scheduler'); param.add('-s'); - await OSStartup.registStartup(exe, _startupID, arguments: param, logErrorFilePath: '$_schedulerPath/launch_err.log'); + await OSStartup.registStartup(exe, _startupID, + arguments: param, logErrorFilePath: '$_schedulerPath/launch_err.log'); } return simpleFuture; } Future _unregistStartup() async { - if(await OSStartup.isRegistedStartup(_startupID)) { + if (await OSStartup.isRegistedStartup(_startupID)) { await OSStartup.unregistStartup(_startupID); } return simpleFuture; @@ -277,20 +283,22 @@ class SchedulerManager { //======================== other process ========================// Future start() async { _log('Scheduler is running on pid [$pid].'); - while(true) { + while (true) { //매초 마다 등록된 파일이 있나 체크 await Future.delayed(Duration(seconds: 1)); var settings = _localData.map; - for(var alias in _schedulers) { - var enable = settings.containsKey(alias) ? settings[alias]!.enable : true; - if(!_map.containsKey(alias) && enable) { + for (var alias in _schedulers) { + var enable = + settings.containsKey(alias) ? settings[alias]!.enable : true; + if (!_map.containsKey(alias) && enable) { _log('Schduler found: $alias'); - var handler = IsolateManager.create(IsolateScheduler({'alias': alias, 'root': _schedulerPath, 'logs': _logsPath})); - handler.addListener('terminated', _onTerminated ); + var handler = IsolateManager.create(IsolateScheduler( + {'alias': alias, 'root': _schedulerPath, 'logs': _logsPath})); + handler.addListener('terminated', _onTerminated); handler.addListener('log', _onLog); _map[alias] = handler; } - if(_map.containsKey(alias) && !enable) { + if (_map.containsKey(alias) && !enable) { _removeHandler(alias); } } @@ -308,7 +316,7 @@ class SchedulerManager { var type = map['type'] as String; var message = map['message'] as String; _removeHandler(alias); - switch(type) { + switch (type) { case 'error': _log('[Error] $message'); break; @@ -316,15 +324,15 @@ class SchedulerManager { var local = _localData; var list = _schedulers; - if(list.isEmpty) { + if (list.isEmpty) { _log('Scheduler operation stopped.'); - if(local.map.containsKey(alias)) { + if (local.map.containsKey(alias)) { local.map.remove(alias); } } else { list.contains(alias); SchedulerData data = SchedulerData(); - if(local.map.containsKey(alias)) { + if (local.map.containsKey(alias)) { data = local.map[alias]!; } data.alias = alias; @@ -340,10 +348,11 @@ class SchedulerManager { } void _log(String message) { - logFile.writeAsStringSync('[${getDates()}] $message\n', mode: FileMode.append, flush: true); + logFile.writeAsStringSync('[${getDates()}] $message\n', + mode: FileMode.append, flush: true); } void _logError(Exception e, StackTrace stacktace) { _log('[${e.toString()}]\n${stacktace.toString()}'); } -} \ No newline at end of file +} diff --git a/lib/cli/commands/scheduler/scheduler_osx.dart b/lib/cli/commands/scheduler/scheduler_osx.dart index 56fdf6f..9dfa1ac 100644 --- a/lib/cli/commands/scheduler/scheduler_osx.dart +++ b/lib/cli/commands/scheduler/scheduler_osx.dart @@ -1,5 +1,20 @@ +import 'dart:io'; + import 'package:oto_cli/cli/commands/scheduler/scheduler_manager.dart'; +import 'package:path/path.dart' as path; class SchedulerOsx extends SchedulerManager { - -} \ No newline at end of file + @override + String get exePath { + var exe = Platform.resolvedExecutable; + //homebrew로 설치시 예외 처리 + if (exe.startsWith('/usr/local')) { + //intel mac + exe = '/usr/local/bin/${path.basenameWithoutExtension(exe)}'; + } else if (exe.startsWith('/opt/homebrew')) { + //sillicon mac + exe = '/opt/homebrew/bin/${path.basenameWithoutExtension(exe)}'; + } + return exe; + } +} diff --git a/lib/oto/data/command_data.dart b/lib/oto/data/command_data.dart index 7e61a3b..ccf51be 100644 --- a/lib/oto/data/command_data.dart +++ b/lib/oto/data/command_data.dart @@ -546,7 +546,7 @@ class DataJiraUser extends DataParam { //Zip @JsonSerializable() -class DataZip extends DataParam { +class DataZip extends DataFile { DataZip(); late String zipFile;