oto/lib/oto/application.dart

184 lines
5.8 KiB
Dart

// ignore_for_file: depend_on_referenced_packages
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:dart_framework/log/log.dart';
import 'package:dart_framework/platform/process.dart';
import 'package:dart_framework/utils/string_util.dart';
import 'package:dart_framework/utils/system_util.dart';
import 'package:oto/cli/cli.dart';
import 'package:oto/oto/commands/command.dart';
import 'package:oto/oto/commands/command_registry.dart';
import 'package:oto/oto/core/defined_data.dart';
import 'package:oto/oto/pipeline/pipeline.dart';
import 'package:oto/oto/data/command_data.dart';
import 'package:oto/oto/core/data_composer.dart';
import 'package:yaml/yaml.dart';
import 'package:path/path.dart' as path;
enum BuildType { jenkins, test, file, scheduler }
enum CommandState { ready, progress, complete }
class Application {
Application._privateConstructor();
static final Application _instance = Application._privateConstructor();
static Application get instance => _instance;
static String get current {
if (Application.instance.buildType == BuildType.jenkins) {
return Platform.environment['WORKSPACE']!;
} else {
return path.current;
}
}
static File? _logFile;
static bool _logEnable = true;
static String get enter {
return _logFile == null ? '' : '\n';
}
final Map<BuildType, DataComposer Function()> _mapComposer = {
BuildType.test: () => DataComposerTest(),
BuildType.jenkins: () => DataComposerJenkins(),
BuildType.file: () => DataComposerFile()
};
DataCommon? commonData;
Map<String, dynamic> property = {};
Map<String, CommandState> commandStates = {};
Map<String, DataCommand> dataCommandMap = {};
late Pipeline pipeline;
late BuildType _buildType;
BuildType get buildType {
return _buildType;
}
Future build(BuildType buildType,
{String? yamlContent,
DataBuild? buildData,
bool logEnable = true,
String? logPath}) async {
_buildType = buildType;
_logEnable = logEnable;
setUTF8();
registerAllCommands();
DataBuild build;
DataComposer? composer;
// var envArgs = envArguments(arguments);
// bool isTest = envArgs.containsKey('isTest'); //for Unit Test
try {
if (_buildType == BuildType.scheduler) {
commonData = DataCommon.fromJson(FileData.jenkinsMap!);
build = buildData!;
_logFile = File(logPath!);
CLI.logFunc = log;
} else {
composer = _mapComposer[buildType]!();
await composer.compose(yamlContent, printBuildStep);
commonData = composer.commonData;
build = DataBuild.fromJson(getMapFromYamlA(composer.buildYaml)!);
}
if (_logEnable) {
await CLI.printString(
'$enter********************************* Build Data *************************************',
color: Color.magenta);
if (composer != null) log(composer.buildYaml);
}
property = build.property ?? {};
if (!property.containsKey('workspace')) {
property['workspace'] = current;
}
property = Command.replaceAllTagsMap(property, replace: true);
// Register commands; filter out duplicate command IDs
for (var command in build.commands) {
if (dataCommandMap.containsKey(command.id)) {
var ex = ExceptionData();
ex.phase = 'Validate command list';
ex.message = 'Duplicate command id exists: "${command.id}"';
throw Exception(ex);
} else {
dataCommandMap[command.id] = command;
}
}
//Parse pipeline & validate
var validateResult =
Pipeline.pipelineInitialize(build.pipeline!.workflow);
if (!validateResult.enable) {
var ex = ExceptionData();
ex.phase = 'Validate Pipeline';
ex.message = validateResult.message;
throw Exception(ex);
}
pipeline = validateResult.pipeline!;
//start build
await pipeline.execute();
} catch (e, stacktrace) {
await CLI.printString(e.toString(), color: Color.redStrong);
await CLI.printString(stacktrace.toString(), color: Color.yellowStrong);
await printBuildStep('Build Failed', Color.redStrong);
exit(10);
}
if (logEnable) {
await printBuildStep('Build Successfully Complete', Color.cyan);
}
if (buildType != BuildType.scheduler) {
exit(0);
}
}
Future setUTF8() async {
if (Platform.isWindows) {
var data = await ProcessExecutor.start(StringBuffer('chcp 65001'),
logHandler: logWithType);
var exitCode = await data.process.exitCode;
log('Set Korean: ${exitCode == 0}');
}
return simpleFuture;
}
static void logWithType(String message, LogType logType) {
log(message, logType: logType);
}
static void log(String message, {LogType logType = LogType.verbose}) {
if (_logFile == null) {
print(message);
} else {
if (_logEnable || logType == LogType.error) {
_logFile?.writeAsStringSync('[${getDates()}] $message\n',
mode: FileMode.append, flush: true);
}
}
}
static Map<String, dynamic>? getMapFromYamlA(String yamlStr) {
Map<String, dynamic>? map;
if (yamlStr.length > 5) {
YamlMap data = loadYaml(yamlStr);
map = jsonDecode(jsonEncode(data));
}
return map;
}
void updateCommandState(String target, CommandState state) {
commandStates[target] = state;
}
Future printBuildStep(String name, Color? color) async {
var message =
'''$enter*********************************************************************************************
* $name
*********************************************************************************************''';
await CLI.printString(message, color: color ?? Color.green);
return simpleFuture;
}
}