build_manager 코드 추가
This commit is contained in:
parent
d60768a63d
commit
9c92c64e0b
26 changed files with 2732 additions and 0 deletions
|
|
@ -3,8 +3,10 @@ import 'package:oto_cli/cli/commands/command_start.dart';
|
|||
|
||||
import 'package:oto_cli/cli/cli.dart';
|
||||
import 'package:oto_cli/cli/commands/command_template.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
|
||||
void main(List<String> arguments) async {
|
||||
var app = Application.to;
|
||||
CLI.initialize('OTO', arguments, [
|
||||
CommandTemplate(),
|
||||
CommandInstall(),
|
||||
|
|
|
|||
151
lib/oto/application.dart
Normal file
151
lib/oto/application.dart
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:dart_framework/utils/system_util.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:oto_cli/oto/data/jenkins_data.dart';
|
||||
import 'package:oto_cli/oto/test_data.dart';
|
||||
|
||||
class Application {
|
||||
Application._privateConstructor();
|
||||
static final Application _instance = Application._privateConstructor();
|
||||
static Application get to => _instance;
|
||||
|
||||
Map<String, dynamic>? _property;
|
||||
Map<String, dynamic>? get property {
|
||||
return _property;
|
||||
}
|
||||
|
||||
DataJenkins? _jenkinsData;
|
||||
DataJenkins? get jenkinsData {
|
||||
return _jenkinsData;
|
||||
}
|
||||
|
||||
Future<void> build(List<String> arguments) async {
|
||||
// await test();
|
||||
// return;
|
||||
|
||||
Map<String, dynamic>? buildMap;
|
||||
Map<String, dynamic>? jenkinsMap;
|
||||
var envArgs = envArguments(arguments);
|
||||
bool isTest = envArgs.containsKey('isTest'); //for Unit Test
|
||||
if (isTest) {
|
||||
//Test map
|
||||
buildMap = TestData.buildMap;
|
||||
jenkinsMap = TestData.jenkinsMap!;
|
||||
print('Start test build...');
|
||||
} else {
|
||||
String os = Platform.operatingSystem;
|
||||
var enable = true;
|
||||
print('Current OS: $os');
|
||||
print('Start build...');
|
||||
String jsonStr = '';
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
await Process.run('zsh', ['./lib/shell/jenkins_env_params.sh'])
|
||||
.then((ProcessResult result) => jsonStr = result.stdout);
|
||||
jenkinsMap = getMapFromJson(jsonStr)!;
|
||||
} else if (Platform.isWindows) {
|
||||
print('Win Test!!');
|
||||
await Process.run('cmd', [
|
||||
'/C',
|
||||
'${Directory.current.path}/lib/shell/jenkins_env_params.bat'
|
||||
]).then((ProcessResult result) => jsonStr = result.stdout);
|
||||
jenkinsMap = getMapFromJson(jsonStr);
|
||||
} else {
|
||||
enable = false;
|
||||
print(
|
||||
'is not Mac/Windows/Linux. build must be execute in Mac/Windows os system');
|
||||
}
|
||||
if (enable) {
|
||||
printBuildStep('Jenkins Variables');
|
||||
print(jsonStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (jenkinsMap != null) {
|
||||
_jenkinsData = DataJenkins.fromJson(jenkinsMap);
|
||||
if (!isTest) {
|
||||
var buildStr = await getBuildData();
|
||||
buildMap = getMapFromYaml(buildStr);
|
||||
}
|
||||
|
||||
execute(buildMap!);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> execute(Map<String, dynamic> buildMap) async {
|
||||
var c = Completer();
|
||||
DataBuild? build;
|
||||
build = DataBuild.fromJson(buildMap);
|
||||
|
||||
_property = build.common;
|
||||
for (var command in build.commands) {
|
||||
String commandStr =
|
||||
command.command.toString().replaceAll('CommandType.', '');
|
||||
printBuildStep('Phase Start: $commandStr');
|
||||
if (!await Command(command.command).execute(command)) {
|
||||
exit(10);
|
||||
}
|
||||
}
|
||||
|
||||
c.complete();
|
||||
printBuildStep('Build Successfully Complete');
|
||||
exit(0);
|
||||
return c.future;
|
||||
}
|
||||
|
||||
void printBuildStep(String name) {
|
||||
print(
|
||||
'************************************************************************************');
|
||||
print('* $name');
|
||||
print(
|
||||
'************************************************************************************');
|
||||
}
|
||||
|
||||
Future<String> getBuildData() async {
|
||||
var c = Completer<String>();
|
||||
var file = File('${_jenkinsData!.workspace}/build_data.conf');
|
||||
var content = '';
|
||||
if (Platform.isWindows) {
|
||||
content = file
|
||||
.readAsStringSync(encoding: SystemEncoding())
|
||||
.replaceAll('BuildData=', '');
|
||||
var regEx = RegExp(r'(%)([a-zA-Z0-9]+)(%)');
|
||||
var list = regEx.allMatches(content);
|
||||
var params = <String>[];
|
||||
for (var match in list) {
|
||||
var param = match.group(2);
|
||||
if (!params.contains(param)) {
|
||||
params.add(param!);
|
||||
}
|
||||
}
|
||||
|
||||
var temp = File('${_jenkinsData!.workspace}/param_temp.bat');
|
||||
var bat = '';
|
||||
for (var param in params) {
|
||||
bat += '@echo %$param%\n';
|
||||
}
|
||||
temp.writeAsStringSync(bat);
|
||||
|
||||
var resultParam = '';
|
||||
await Process.run('cmd', ['/C', temp.path])
|
||||
.then((ProcessResult result) => resultParam = result.stdout);
|
||||
var values = resultParam.split('\n');
|
||||
var length = params.length;
|
||||
for (var i = 0; i < length; ++i) {
|
||||
var value = values[i]
|
||||
.toString()
|
||||
.replaceAll('\\', '/')
|
||||
.replaceAll(RegExp('\r|\n'), '');
|
||||
content = content.replaceAll('%${params[i]}%', value);
|
||||
}
|
||||
temp.deleteSync();
|
||||
} else {
|
||||
content = await file.readAsString();
|
||||
}
|
||||
print(content);
|
||||
|
||||
c.complete(content);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
26
lib/oto/build/app_data_creator.dart
Normal file
26
lib/oto/build/app_data_creator.dart
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:dart_framework/core/app_data_manager.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class CreateAppData implements Command {
|
||||
Function? get error => null;
|
||||
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var jenkins = Application.to.jenkinsData!;
|
||||
var data = DataAppDataCreator.fromJson(command.param);
|
||||
var workspace = data.workspace ?? jenkins.workspace;
|
||||
workspace = workspace.replaceAll('\\', '/');
|
||||
var appData = await AppDataManager.to
|
||||
.create(data.scm, workspace, data.relativeAssetPath, data.name);
|
||||
Command.setReturnValue(data.returnVersion, appData.version);
|
||||
Command.setReturnValue(data.returnHash, appData.gitHash.substring(0, 7));
|
||||
|
||||
c.complete(true);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
45
lib/oto/build/build_dart.dart
Normal file
45
lib/oto/build/build_dart.dart
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import 'dart:async';
|
||||
import 'package:dart_framework/platform/process.dart';
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class BuildDart implements Command {
|
||||
Function? get error => null;
|
||||
|
||||
Future<StringBuffer> appendShell(
|
||||
StringBuffer shell, DataCommand command) async {
|
||||
var c = Completer<StringBuffer>();
|
||||
c.complete(shell);
|
||||
return c.future;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var data = DataBuildDart.fromJson(command.param);
|
||||
var workspace = Path.getNormal(Application.to.jenkinsData!.workspace);
|
||||
var targetPath =
|
||||
Path.getNormal(Command.replaceTag(data.targetPath ?? workspace));
|
||||
|
||||
var shell = StringBuffer();
|
||||
shell.write('cd $targetPath');
|
||||
shell.write(' && flutter clean');
|
||||
shell.write(' && flutter packages upgrade');
|
||||
shell.write(' && flutter pub get');
|
||||
if (data.executeBuildRunner == null ? true : data.executeBuildRunner!) {
|
||||
shell.write(
|
||||
' && flutter pub run build_runner build --delete-conflicting-outputs');
|
||||
}
|
||||
|
||||
var process = await ProcessExecutor.run(await appendShell(shell, command),
|
||||
workspace: workspace);
|
||||
print('#### Exit Code: ${process.exitCode.toString()}');
|
||||
var passCode = [0, 64];
|
||||
//exitCode 65: package not defiend in pubspec.yaml
|
||||
var success = passCode.contains(process.exitCode);
|
||||
c.complete(success);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
63
lib/oto/build/build_dart_compile.dart
Normal file
63
lib/oto/build/build_dart_compile.dart
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:oto_cli/oto/build/build_dart.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../application.dart';
|
||||
|
||||
class BuildDartCompile extends BuildDart {
|
||||
@override
|
||||
Future<StringBuffer> appendShell(
|
||||
StringBuffer shell, DataCommand command) async {
|
||||
var c = Completer<StringBuffer>();
|
||||
var data = DataBuildDartCompile.fromJson(command.param);
|
||||
var extension = getExeExtension();
|
||||
var workspace = Path.getNormal(Application.to.jenkinsData!.workspace);
|
||||
var targetPath =
|
||||
Path.getNormal(Command.replaceTag(data.targetPath ?? workspace));
|
||||
var binPath = path.join(targetPath, 'bin');
|
||||
|
||||
//find build target
|
||||
var targetDir = Directory(binPath);
|
||||
var findedDartFile = '';
|
||||
var fileList = targetDir.listSync();
|
||||
for (var file in fileList) {
|
||||
findedDartFile = path.basename(file.path);
|
||||
break;
|
||||
}
|
||||
findedDartFile = path.join(targetPath, 'bin', findedDartFile);
|
||||
var targetDartFile =
|
||||
Command.replaceTag(data.targetDartFile ?? findedDartFile);
|
||||
|
||||
//clear build path
|
||||
var buildFolderName = 'release';
|
||||
var buildPath = path.join(targetPath, buildFolderName);
|
||||
var buildDir = Directory(buildPath);
|
||||
var buildFileName = data.buildFileName ?? 'release';
|
||||
if (!buildDir.existsSync()) {
|
||||
buildDir.createSync();
|
||||
}
|
||||
buildPath =
|
||||
path.join(targetPath, buildFolderName, '$buildFileName$extension');
|
||||
var preBuildFile = File(buildPath);
|
||||
if (preBuildFile.existsSync()) {
|
||||
preBuildFile.deleteSync();
|
||||
}
|
||||
|
||||
shell.write(' && dart compile exe "$targetDartFile" -o "$buildPath"');
|
||||
c.complete(shell);
|
||||
return c.future;
|
||||
}
|
||||
|
||||
String getExeExtension() {
|
||||
if (Platform.isWindows) {
|
||||
return '.exe';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
26
lib/oto/build/build_dot_net.dart
Normal file
26
lib/oto/build/build_dot_net.dart
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import 'dart:async';
|
||||
import 'package:dart_framework/platform/process.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class BuildDotNet implements Command {
|
||||
Function? get error => null;
|
||||
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var data = DataBuildDotNet.fromJson(command.param);
|
||||
var workspace = Application.to.jenkinsData!.workspace;
|
||||
var shell = StringBuffer();
|
||||
// shell.writeln('C:\\Windows\\System32\\chcp.com 65001');
|
||||
shell.writeln('cd $workspace');
|
||||
shell.writeln(
|
||||
'MSBuild ${data.projectFile} /t:build /p:Configuration=Release;Platform=x86');
|
||||
var process = await ProcessExecutor.run(shell, workspace: workspace);
|
||||
// var exitCode = await process.process.exitCode;
|
||||
// c.complete(process.isSuccess);
|
||||
c.complete(process.exitCode == 0);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
22
lib/oto/build/build_flutter.dart
Normal file
22
lib/oto/build/build_flutter.dart
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:oto_cli/oto/build/build_dart.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
// ignore: constant_identifier_names
|
||||
enum BuildPlatform { Windows, Macos, Web, Apk, Appbundle, iOS, Linux }
|
||||
|
||||
class BuildFlutter extends BuildDart {
|
||||
@override
|
||||
Future<StringBuffer> appendShell(
|
||||
StringBuffer shell, DataCommand command) async {
|
||||
var c = Completer<StringBuffer>();
|
||||
var data = DataBuildFlutter.fromJson(command.param);
|
||||
var platform =
|
||||
data.platform.toString().replaceAll('BuildPlatform.', '').toLowerCase();
|
||||
var additional = data.additional == null ? '' : ' ${data.additional!}';
|
||||
shell.write(' && flutter build $platform$additional');
|
||||
c.complete(shell);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
102
lib/oto/build/build_ios.dart
Normal file
102
lib/oto/build/build_ios.dart
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:dart_framework/platform/process.dart';
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
|
||||
class BuildiOS implements Command {
|
||||
Function? get error => null;
|
||||
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var data = DataBuildiOS.fromJson(command.param);
|
||||
var workspace = Path.getNormal(Application.to.jenkinsData!.workspace);
|
||||
var workspacePath = Path.getNormal(Command.replaceTag(data.workspacePath));
|
||||
var destination = data.destination ?? 'generic/platform=iOS build';
|
||||
var cleanPod = data.cleanPod ?? false;
|
||||
|
||||
var shell = StringBuffer();
|
||||
shell.write('security unlock-keychain -pr0bins');
|
||||
shell.write(' && cd $workspace/ios');
|
||||
shell.write(' && export LANG=en_US.UTF-8');
|
||||
shell.write(' && rm -rf Pods');
|
||||
shell.write(' && rm -rf Podfile.lock');
|
||||
if (cleanPod) {
|
||||
shell.write(' && pod cache clean --all');
|
||||
shell.write(' && pod repo update');
|
||||
shell.write(' && pod install --repo-update');
|
||||
} else {
|
||||
shell.write(' && pod install');
|
||||
}
|
||||
shell.write(
|
||||
' && xcodebuild -workspace $workspacePath -scheme ${data.scheme} -destination $destination');
|
||||
|
||||
var process = await ProcessExecutor.run(shell, workspace: workspace);
|
||||
print('#### Exit Code: ${process.exitCode.toString()}');
|
||||
var success = process.exitCode == 0;
|
||||
if (success) {
|
||||
c.complete(success);
|
||||
return c.future;
|
||||
} else {
|
||||
if (process.exitCode == 31) {
|
||||
data.cleanPod = true;
|
||||
command.param = data.toJson();
|
||||
return await execute(command);
|
||||
} else {
|
||||
c.complete(success);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ArchiveiOS implements Command {
|
||||
Function? get error => null;
|
||||
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var data = DataArchiveiOS.fromJson(command.param);
|
||||
var workspace = Path.getNormal(Application.to.jenkinsData!.workspace);
|
||||
var workspacePath = Path.getNormal(Command.replaceTag(data.workspacePath));
|
||||
var archivePath = Path.getNormal(Command.replaceTag(data.archivePath));
|
||||
|
||||
var shell = StringBuffer();
|
||||
shell.write(
|
||||
'xcodebuild -workspace $workspacePath -scheme ${data.scheme} -archivePath $archivePath archive');
|
||||
|
||||
var process = await ProcessExecutor.run(shell, workspace: workspace);
|
||||
print('#### Exit Code: ${process.exitCode.toString()}');
|
||||
var success = process.exitCode == 0;
|
||||
c.complete(success);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
|
||||
class ExportiOS implements Command {
|
||||
Function? get error => null;
|
||||
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var data = DataExportiOS.fromJson(command.param);
|
||||
var workspace = Path.getNormal(Application.to.jenkinsData!.workspace);
|
||||
var archivePath = Path.getNormal(Command.replaceTag(data.archivePath));
|
||||
var exportPath = Path.getNormal(Command.replaceTag(data.exportPath));
|
||||
var exportOptionPlistPath =
|
||||
Path.getNormal(Command.replaceTag(data.exportOptionPlistPath));
|
||||
|
||||
var shell = StringBuffer();
|
||||
shell.write(
|
||||
'xcodebuild -exportArchive -archivePath $archivePath -exportPath $exportPath -exportOptionsPlist $exportOptionPlistPath');
|
||||
|
||||
var process = await ProcessExecutor.run(shell, workspace: workspace);
|
||||
print('#### Exit Code: ${process.exitCode.toString()}');
|
||||
var success = process.exitCode == 0;
|
||||
c.complete(success);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
137
lib/oto/command.dart
Normal file
137
lib/oto/command.dart
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import 'dart:async';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/build/app_data_creator.dart';
|
||||
import 'package:oto_cli/oto/build/build_dart.dart';
|
||||
import 'package:oto_cli/oto/build/build_dart_compile.dart';
|
||||
import 'package:oto_cli/oto/build/build_dot_net.dart';
|
||||
import 'package:oto_cli/oto/build/build_flutter.dart';
|
||||
import 'package:oto_cli/oto/build/build_ios.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:oto_cli/oto/file/delete.dart';
|
||||
import 'package:oto_cli/oto/file/rename.dart';
|
||||
import 'package:oto_cli/oto/shell/shell.dart';
|
||||
import 'package:oto_cli/oto/file/copy.dart';
|
||||
import 'package:oto_cli/oto/util/execute_app.dart';
|
||||
import 'package:oto_cli/oto/util/publish_ios.dart';
|
||||
import 'package:oto_cli/oto/util/slack.dart';
|
||||
import 'package:oto_cli/oto/util/zip.dart';
|
||||
import 'package:oto_cli/oto/uploader/uploader.dart';
|
||||
|
||||
enum CommandType {
|
||||
SimpleCommand,
|
||||
CreateAppData,
|
||||
BuildDart,
|
||||
BuildFlutter,
|
||||
BuildDartCompile,
|
||||
BuildDotNet,
|
||||
BuildiOS,
|
||||
ArchiveiOS,
|
||||
ExportiOS,
|
||||
PublishiOS,
|
||||
ExecuteApp,
|
||||
Upload,
|
||||
Copy,
|
||||
Rename,
|
||||
Delete,
|
||||
Slack,
|
||||
SlackBuild,
|
||||
Zip,
|
||||
Shell
|
||||
}
|
||||
|
||||
abstract class Command {
|
||||
static final Map<CommandType, Command> _commandMap = {
|
||||
CommandType.SimpleCommand: SimpleCommand(),
|
||||
CommandType.CreateAppData: CreateAppData(),
|
||||
CommandType.BuildDart: BuildDart(),
|
||||
CommandType.BuildFlutter: BuildFlutter(),
|
||||
CommandType.BuildDartCompile: BuildDartCompile(),
|
||||
CommandType.BuildDotNet: BuildDotNet(),
|
||||
CommandType.BuildiOS: BuildiOS(),
|
||||
CommandType.ArchiveiOS: ArchiveiOS(),
|
||||
CommandType.ExportiOS: ExportiOS(),
|
||||
CommandType.PublishiOS: PublishiOS(),
|
||||
CommandType.ExecuteApp: ExecuteApp(),
|
||||
CommandType.Upload: Uploader(),
|
||||
CommandType.Copy: Copy(),
|
||||
CommandType.Rename: Rename(),
|
||||
CommandType.Delete: Delete(),
|
||||
CommandType.Slack: Slack(),
|
||||
CommandType.SlackBuild: SlackBuild(),
|
||||
CommandType.Zip: Zip(),
|
||||
CommandType.Shell: Shell()
|
||||
};
|
||||
|
||||
factory Command(CommandType type) {
|
||||
return _commandMap[type]!;
|
||||
}
|
||||
|
||||
static final Map<String, dynamic> _cache = <String, dynamic>{};
|
||||
static String replaceTag(String raw) {
|
||||
var regEx = RegExp(r'(<!)([a-zA-Z0-9.]+)(>)');
|
||||
var list = regEx.allMatches(raw);
|
||||
for (var match in list) {
|
||||
var param = match.group(2);
|
||||
if (!_cache.containsKey(param)) {
|
||||
_cache[param!] = _getTagValue(param);
|
||||
}
|
||||
var target = '<!${param!}>';
|
||||
raw = raw.replaceAll(target, _cache[param]);
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
static void setReturnValue(String tag, dynamic value) {
|
||||
var regEx = RegExp(r'(<!)([a-zA-Z0-9.]+)(>)');
|
||||
var match = regEx.firstMatch(tag);
|
||||
tag = match!.group(2)!;
|
||||
if (tag.startsWith('common')) {
|
||||
var key = tag.replaceFirst('common.', '');
|
||||
Application.to.property![key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
static dynamic _getTagValue(String value) {
|
||||
var setted = false;
|
||||
dynamic data;
|
||||
if (value.startsWith('common.')) {
|
||||
var map = Application.to.property;
|
||||
var param = value.replaceFirst('common.', '');
|
||||
if (map!.containsKey(param)) {
|
||||
data = map[param];
|
||||
setted = true;
|
||||
} else {
|
||||
print('"$value" is not exist in common');
|
||||
data = '';
|
||||
setted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!setted) {
|
||||
throw Exception(
|
||||
'Command.getTagValue: "$value" is not defined in common.');
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
// ignore: missing_return
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
var c = Completer<bool>();
|
||||
c.complete(true);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
|
||||
//Templete
|
||||
class SimpleCommand implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
print(command.param);
|
||||
//Start here
|
||||
c.complete(true);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
300
lib/oto/data/data.dart
Normal file
300
lib/oto/data/data.dart
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
import 'package:dart_framework/utils/slack/slack_sender.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:dart_framework/core/app_data_manager.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
part 'data.g.dart';
|
||||
|
||||
/// ***************************** Base Data ****************************///
|
||||
@JsonSerializable()
|
||||
class DataBuild {
|
||||
late Map<String, dynamic> common;
|
||||
late List<DataCommand> commands;
|
||||
|
||||
DataBuild();
|
||||
|
||||
factory DataBuild.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataBuildFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataBuildToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class DataCommand {
|
||||
DataCommand();
|
||||
|
||||
late CommandType command;
|
||||
late dynamic param;
|
||||
|
||||
factory DataCommand.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataCommandFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataCommandToJson(this);
|
||||
}
|
||||
|
||||
/// ***************************** Command List ****************************///
|
||||
//SimpleCommand
|
||||
@JsonSerializable()
|
||||
class DataSimpleCommand {
|
||||
DataSimpleCommand();
|
||||
|
||||
late String message;
|
||||
|
||||
factory DataSimpleCommand.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataSimpleCommandFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataSimpleCommandToJson(this);
|
||||
}
|
||||
|
||||
//AppDataCreator
|
||||
@JsonSerializable()
|
||||
class DataAppDataCreator {
|
||||
DataAppDataCreator();
|
||||
|
||||
late SCMType scm;
|
||||
late String? workspace;
|
||||
late String relativeAssetPath;
|
||||
late String returnVersion;
|
||||
late String returnHash;
|
||||
late String name;
|
||||
|
||||
factory DataAppDataCreator.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataAppDataCreatorFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataAppDataCreatorToJson(this);
|
||||
}
|
||||
|
||||
//BuildDart
|
||||
@JsonSerializable()
|
||||
class DataBuildDart {
|
||||
DataBuildDart();
|
||||
|
||||
late String? targetPath;
|
||||
late bool? executeBuildRunner;
|
||||
|
||||
factory DataBuildDart.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataBuildDartFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataBuildDartToJson(this);
|
||||
}
|
||||
|
||||
//BuildFlutter
|
||||
@JsonSerializable()
|
||||
class DataBuildFlutter extends DataBuildDart {
|
||||
DataBuildFlutter();
|
||||
|
||||
late String platform;
|
||||
late String? additional;
|
||||
|
||||
factory DataBuildFlutter.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataBuildFlutterFromJson(json);
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$DataBuildFlutterToJson(this);
|
||||
}
|
||||
|
||||
//BuildDartCompile
|
||||
@JsonSerializable()
|
||||
class DataBuildDartCompile extends DataBuildDart {
|
||||
DataBuildDartCompile();
|
||||
|
||||
late String? targetDartFile;
|
||||
late String? buildFileName;
|
||||
|
||||
factory DataBuildDartCompile.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataBuildDartCompileFromJson(json);
|
||||
@override
|
||||
Map<String, dynamic> toJson() => _$DataBuildDartCompileToJson(this);
|
||||
}
|
||||
|
||||
//BuildDotNet
|
||||
@JsonSerializable()
|
||||
class DataBuildDotNet {
|
||||
DataBuildDotNet();
|
||||
|
||||
late String projectFile;
|
||||
|
||||
factory DataBuildDotNet.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataBuildDotNetFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataBuildDotNetToJson(this);
|
||||
}
|
||||
|
||||
//BuildiOS
|
||||
@JsonSerializable()
|
||||
class DataBuildiOS {
|
||||
DataBuildiOS();
|
||||
|
||||
late String workspacePath;
|
||||
late String scheme;
|
||||
late String? destination;
|
||||
late bool? cleanPod;
|
||||
|
||||
factory DataBuildiOS.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataBuildiOSFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataBuildiOSToJson(this);
|
||||
}
|
||||
|
||||
//ArchiveiOS
|
||||
@JsonSerializable()
|
||||
class DataArchiveiOS {
|
||||
DataArchiveiOS();
|
||||
|
||||
late String workspacePath;
|
||||
late String scheme;
|
||||
late String archivePath;
|
||||
|
||||
factory DataArchiveiOS.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataArchiveiOSFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataArchiveiOSToJson(this);
|
||||
}
|
||||
|
||||
//ExportiOS
|
||||
@JsonSerializable()
|
||||
class DataExportiOS {
|
||||
DataExportiOS();
|
||||
|
||||
late String archivePath;
|
||||
late String exportOptionPlistPath;
|
||||
late String exportPath;
|
||||
|
||||
factory DataExportiOS.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataExportiOSFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataExportiOSToJson(this);
|
||||
}
|
||||
|
||||
//PublishiOS
|
||||
@JsonSerializable()
|
||||
class DataPublishiOS {
|
||||
DataPublishiOS();
|
||||
|
||||
late String bundleID;
|
||||
late String version;
|
||||
late String appName;
|
||||
late String ipaURL;
|
||||
late String menifestURL;
|
||||
late String displayImageURL;
|
||||
late String fullSizeImageURL;
|
||||
late String destinationPath;
|
||||
|
||||
factory DataPublishiOS.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataPublishiOSFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataPublishiOSToJson(this);
|
||||
}
|
||||
|
||||
//ExecuteApp
|
||||
@JsonSerializable()
|
||||
class DataExecuteApp {
|
||||
DataExecuteApp();
|
||||
|
||||
late String executable;
|
||||
late String desktopServicePath;
|
||||
|
||||
factory DataExecuteApp.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataExecuteAppFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataExecuteAppToJson(this);
|
||||
}
|
||||
|
||||
//Uploader
|
||||
@JsonSerializable()
|
||||
class DataUploader {
|
||||
DataUploader();
|
||||
|
||||
late bool sftp;
|
||||
late int port;
|
||||
late String host;
|
||||
late String user;
|
||||
late String password;
|
||||
late Map<String, String> uploadMap;
|
||||
|
||||
factory DataUploader.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataUploaderFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataUploaderToJson(this);
|
||||
}
|
||||
|
||||
class DataFile {
|
||||
DataFile();
|
||||
late List<String>? ignorePattern;
|
||||
}
|
||||
|
||||
//Copy & Move
|
||||
@JsonSerializable()
|
||||
class DataCopy extends DataFile {
|
||||
DataCopy();
|
||||
|
||||
late bool? isMove;
|
||||
late Map<String, String> copyMap;
|
||||
|
||||
factory DataCopy.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataCopyFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataCopyToJson(this);
|
||||
}
|
||||
|
||||
//Delete
|
||||
@JsonSerializable()
|
||||
class DataDelete extends DataFile {
|
||||
DataDelete();
|
||||
|
||||
late List<String> list;
|
||||
|
||||
factory DataDelete.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataDeleteFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataDeleteToJson(this);
|
||||
}
|
||||
|
||||
//Rename
|
||||
@JsonSerializable()
|
||||
class DataRename extends DataFile {
|
||||
DataRename();
|
||||
|
||||
late Map<String, String> renameMap;
|
||||
|
||||
factory DataRename.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataRenameFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataRenameToJson(this);
|
||||
}
|
||||
|
||||
//Slack
|
||||
@JsonSerializable()
|
||||
class DataSlack {
|
||||
DataSlack();
|
||||
|
||||
factory DataSlack.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataSlackFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataSlackToJson(this);
|
||||
}
|
||||
|
||||
//Slack Build
|
||||
@JsonSerializable()
|
||||
class DataSlackBuild {
|
||||
DataSlackBuild();
|
||||
|
||||
late String appName;
|
||||
late SlackBuildType type;
|
||||
late String color;
|
||||
late String version;
|
||||
late String downloadURL;
|
||||
late String? channel;
|
||||
|
||||
factory DataSlackBuild.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataSlackBuildFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataSlackBuildToJson(this);
|
||||
}
|
||||
|
||||
//Zip
|
||||
@JsonSerializable()
|
||||
class DataZip {
|
||||
DataZip();
|
||||
|
||||
late String zipFile;
|
||||
late List<String> zipList;
|
||||
|
||||
factory DataZip.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataZipFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataZipToJson(this);
|
||||
}
|
||||
|
||||
//Shell
|
||||
@JsonSerializable()
|
||||
class DataShell {
|
||||
DataShell();
|
||||
|
||||
late String? workspace;
|
||||
late String path;
|
||||
|
||||
factory DataShell.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataShellFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataShellToJson(this);
|
||||
}
|
||||
313
lib/oto/data/data.g.dart
Normal file
313
lib/oto/data/data.g.dart
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'data.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
DataBuild _$DataBuildFromJson(Map<String, dynamic> json) => DataBuild()
|
||||
..common = json['common'] as Map<String, dynamic>
|
||||
..commands = (json['commands'] as List<dynamic>)
|
||||
.map((e) => DataCommand.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
|
||||
Map<String, dynamic> _$DataBuildToJson(DataBuild instance) => <String, dynamic>{
|
||||
'common': instance.common,
|
||||
'commands': instance.commands,
|
||||
};
|
||||
|
||||
DataCommand _$DataCommandFromJson(Map<String, dynamic> json) => DataCommand()
|
||||
..command = $enumDecode(_$CommandTypeEnumMap, json['command'])
|
||||
..param = json['param'];
|
||||
|
||||
Map<String, dynamic> _$DataCommandToJson(DataCommand instance) =>
|
||||
<String, dynamic>{
|
||||
'command': _$CommandTypeEnumMap[instance.command]!,
|
||||
'param': instance.param,
|
||||
};
|
||||
|
||||
const _$CommandTypeEnumMap = {
|
||||
CommandType.SimpleCommand: 'SimpleCommand',
|
||||
CommandType.CreateAppData: 'CreateAppData',
|
||||
CommandType.BuildDart: 'BuildDart',
|
||||
CommandType.BuildFlutter: 'BuildFlutter',
|
||||
CommandType.BuildDartCompile: 'BuildDartCompile',
|
||||
CommandType.BuildDotNet: 'BuildDotNet',
|
||||
CommandType.BuildiOS: 'BuildiOS',
|
||||
CommandType.ArchiveiOS: 'ArchiveiOS',
|
||||
CommandType.ExportiOS: 'ExportiOS',
|
||||
CommandType.PublishiOS: 'PublishiOS',
|
||||
CommandType.ExecuteApp: 'ExecuteApp',
|
||||
CommandType.Upload: 'Upload',
|
||||
CommandType.Copy: 'Copy',
|
||||
CommandType.Rename: 'Rename',
|
||||
CommandType.Delete: 'Delete',
|
||||
CommandType.Slack: 'Slack',
|
||||
CommandType.SlackBuild: 'SlackBuild',
|
||||
CommandType.Zip: 'Zip',
|
||||
CommandType.Shell: 'Shell',
|
||||
};
|
||||
|
||||
DataSimpleCommand _$DataSimpleCommandFromJson(Map<String, dynamic> json) =>
|
||||
DataSimpleCommand()..message = json['message'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataSimpleCommandToJson(DataSimpleCommand instance) =>
|
||||
<String, dynamic>{
|
||||
'message': instance.message,
|
||||
};
|
||||
|
||||
DataAppDataCreator _$DataAppDataCreatorFromJson(Map<String, dynamic> json) =>
|
||||
DataAppDataCreator()
|
||||
..scm = $enumDecode(_$SCMTypeEnumMap, json['scm'])
|
||||
..workspace = json['workspace'] as String?
|
||||
..relativeAssetPath = json['relativeAssetPath'] as String
|
||||
..returnVersion = json['returnVersion'] as String
|
||||
..returnHash = json['returnHash'] as String
|
||||
..name = json['name'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataAppDataCreatorToJson(DataAppDataCreator instance) =>
|
||||
<String, dynamic>{
|
||||
'scm': _$SCMTypeEnumMap[instance.scm]!,
|
||||
'workspace': instance.workspace,
|
||||
'relativeAssetPath': instance.relativeAssetPath,
|
||||
'returnVersion': instance.returnVersion,
|
||||
'returnHash': instance.returnHash,
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
const _$SCMTypeEnumMap = {
|
||||
SCMType.Svn: 'Svn',
|
||||
SCMType.Git: 'Git',
|
||||
};
|
||||
|
||||
DataBuildDart _$DataBuildDartFromJson(Map<String, dynamic> json) =>
|
||||
DataBuildDart()
|
||||
..targetPath = json['targetPath'] as String?
|
||||
..executeBuildRunner = json['executeBuildRunner'] as bool?;
|
||||
|
||||
Map<String, dynamic> _$DataBuildDartToJson(DataBuildDart instance) =>
|
||||
<String, dynamic>{
|
||||
'targetPath': instance.targetPath,
|
||||
'executeBuildRunner': instance.executeBuildRunner,
|
||||
};
|
||||
|
||||
DataBuildFlutter _$DataBuildFlutterFromJson(Map<String, dynamic> json) =>
|
||||
DataBuildFlutter()
|
||||
..targetPath = json['targetPath'] as String?
|
||||
..executeBuildRunner = json['executeBuildRunner'] as bool?
|
||||
..platform = json['platform'] as String
|
||||
..additional = json['additional'] as String?;
|
||||
|
||||
Map<String, dynamic> _$DataBuildFlutterToJson(DataBuildFlutter instance) =>
|
||||
<String, dynamic>{
|
||||
'targetPath': instance.targetPath,
|
||||
'executeBuildRunner': instance.executeBuildRunner,
|
||||
'platform': instance.platform,
|
||||
'additional': instance.additional,
|
||||
};
|
||||
|
||||
DataBuildDartCompile _$DataBuildDartCompileFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
DataBuildDartCompile()
|
||||
..targetPath = json['targetPath'] as String?
|
||||
..executeBuildRunner = json['executeBuildRunner'] as bool?
|
||||
..targetDartFile = json['targetDartFile'] as String?
|
||||
..buildFileName = json['buildFileName'] as String?;
|
||||
|
||||
Map<String, dynamic> _$DataBuildDartCompileToJson(
|
||||
DataBuildDartCompile instance) =>
|
||||
<String, dynamic>{
|
||||
'targetPath': instance.targetPath,
|
||||
'executeBuildRunner': instance.executeBuildRunner,
|
||||
'targetDartFile': instance.targetDartFile,
|
||||
'buildFileName': instance.buildFileName,
|
||||
};
|
||||
|
||||
DataBuildDotNet _$DataBuildDotNetFromJson(Map<String, dynamic> json) =>
|
||||
DataBuildDotNet()..projectFile = json['projectFile'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataBuildDotNetToJson(DataBuildDotNet instance) =>
|
||||
<String, dynamic>{
|
||||
'projectFile': instance.projectFile,
|
||||
};
|
||||
|
||||
DataBuildiOS _$DataBuildiOSFromJson(Map<String, dynamic> json) => DataBuildiOS()
|
||||
..workspacePath = json['workspacePath'] as String
|
||||
..scheme = json['scheme'] as String
|
||||
..destination = json['destination'] as String?
|
||||
..cleanPod = json['cleanPod'] as bool?;
|
||||
|
||||
Map<String, dynamic> _$DataBuildiOSToJson(DataBuildiOS instance) =>
|
||||
<String, dynamic>{
|
||||
'workspacePath': instance.workspacePath,
|
||||
'scheme': instance.scheme,
|
||||
'destination': instance.destination,
|
||||
'cleanPod': instance.cleanPod,
|
||||
};
|
||||
|
||||
DataArchiveiOS _$DataArchiveiOSFromJson(Map<String, dynamic> json) =>
|
||||
DataArchiveiOS()
|
||||
..workspacePath = json['workspacePath'] as String
|
||||
..scheme = json['scheme'] as String
|
||||
..archivePath = json['archivePath'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataArchiveiOSToJson(DataArchiveiOS instance) =>
|
||||
<String, dynamic>{
|
||||
'workspacePath': instance.workspacePath,
|
||||
'scheme': instance.scheme,
|
||||
'archivePath': instance.archivePath,
|
||||
};
|
||||
|
||||
DataExportiOS _$DataExportiOSFromJson(Map<String, dynamic> json) =>
|
||||
DataExportiOS()
|
||||
..archivePath = json['archivePath'] as String
|
||||
..exportOptionPlistPath = json['exportOptionPlistPath'] as String
|
||||
..exportPath = json['exportPath'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataExportiOSToJson(DataExportiOS instance) =>
|
||||
<String, dynamic>{
|
||||
'archivePath': instance.archivePath,
|
||||
'exportOptionPlistPath': instance.exportOptionPlistPath,
|
||||
'exportPath': instance.exportPath,
|
||||
};
|
||||
|
||||
DataPublishiOS _$DataPublishiOSFromJson(Map<String, dynamic> json) =>
|
||||
DataPublishiOS()
|
||||
..bundleID = json['bundleID'] as String
|
||||
..version = json['version'] as String
|
||||
..appName = json['appName'] as String
|
||||
..ipaURL = json['ipaURL'] as String
|
||||
..menifestURL = json['menifestURL'] as String
|
||||
..displayImageURL = json['displayImageURL'] as String
|
||||
..fullSizeImageURL = json['fullSizeImageURL'] as String
|
||||
..destinationPath = json['destinationPath'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataPublishiOSToJson(DataPublishiOS instance) =>
|
||||
<String, dynamic>{
|
||||
'bundleID': instance.bundleID,
|
||||
'version': instance.version,
|
||||
'appName': instance.appName,
|
||||
'ipaURL': instance.ipaURL,
|
||||
'menifestURL': instance.menifestURL,
|
||||
'displayImageURL': instance.displayImageURL,
|
||||
'fullSizeImageURL': instance.fullSizeImageURL,
|
||||
'destinationPath': instance.destinationPath,
|
||||
};
|
||||
|
||||
DataExecuteApp _$DataExecuteAppFromJson(Map<String, dynamic> json) =>
|
||||
DataExecuteApp()
|
||||
..executable = json['executable'] as String
|
||||
..desktopServicePath = json['desktopServicePath'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataExecuteAppToJson(DataExecuteApp instance) =>
|
||||
<String, dynamic>{
|
||||
'executable': instance.executable,
|
||||
'desktopServicePath': instance.desktopServicePath,
|
||||
};
|
||||
|
||||
DataUploader _$DataUploaderFromJson(Map<String, dynamic> json) => DataUploader()
|
||||
..sftp = json['sftp'] as bool
|
||||
..port = json['port'] as int
|
||||
..host = json['host'] as String
|
||||
..user = json['user'] as String
|
||||
..password = json['password'] as String
|
||||
..uploadMap = Map<String, String>.from(json['uploadMap'] as Map);
|
||||
|
||||
Map<String, dynamic> _$DataUploaderToJson(DataUploader instance) =>
|
||||
<String, dynamic>{
|
||||
'sftp': instance.sftp,
|
||||
'port': instance.port,
|
||||
'host': instance.host,
|
||||
'user': instance.user,
|
||||
'password': instance.password,
|
||||
'uploadMap': instance.uploadMap,
|
||||
};
|
||||
|
||||
DataCopy _$DataCopyFromJson(Map<String, dynamic> json) => DataCopy()
|
||||
..ignorePattern = (json['ignorePattern'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList()
|
||||
..isMove = json['isMove'] as bool?
|
||||
..copyMap = Map<String, String>.from(json['copyMap'] as Map);
|
||||
|
||||
Map<String, dynamic> _$DataCopyToJson(DataCopy instance) => <String, dynamic>{
|
||||
'ignorePattern': instance.ignorePattern,
|
||||
'isMove': instance.isMove,
|
||||
'copyMap': instance.copyMap,
|
||||
};
|
||||
|
||||
DataDelete _$DataDeleteFromJson(Map<String, dynamic> json) => DataDelete()
|
||||
..ignorePattern = (json['ignorePattern'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList()
|
||||
..list = (json['list'] as List<dynamic>).map((e) => e as String).toList();
|
||||
|
||||
Map<String, dynamic> _$DataDeleteToJson(DataDelete instance) =>
|
||||
<String, dynamic>{
|
||||
'ignorePattern': instance.ignorePattern,
|
||||
'list': instance.list,
|
||||
};
|
||||
|
||||
DataRename _$DataRenameFromJson(Map<String, dynamic> json) => DataRename()
|
||||
..ignorePattern = (json['ignorePattern'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList()
|
||||
..renameMap = Map<String, String>.from(json['renameMap'] as Map);
|
||||
|
||||
Map<String, dynamic> _$DataRenameToJson(DataRename instance) =>
|
||||
<String, dynamic>{
|
||||
'ignorePattern': instance.ignorePattern,
|
||||
'renameMap': instance.renameMap,
|
||||
};
|
||||
|
||||
DataSlack _$DataSlackFromJson(Map<String, dynamic> json) => DataSlack();
|
||||
|
||||
Map<String, dynamic> _$DataSlackToJson(DataSlack instance) =>
|
||||
<String, dynamic>{};
|
||||
|
||||
DataSlackBuild _$DataSlackBuildFromJson(Map<String, dynamic> json) =>
|
||||
DataSlackBuild()
|
||||
..appName = json['appName'] as String
|
||||
..type = $enumDecode(_$SlackBuildTypeEnumMap, json['type'])
|
||||
..color = json['color'] as String
|
||||
..version = json['version'] as String
|
||||
..downloadURL = json['downloadURL'] as String
|
||||
..channel = json['channel'] as String?;
|
||||
|
||||
Map<String, dynamic> _$DataSlackBuildToJson(DataSlackBuild instance) =>
|
||||
<String, dynamic>{
|
||||
'appName': instance.appName,
|
||||
'type': _$SlackBuildTypeEnumMap[instance.type]!,
|
||||
'color': instance.color,
|
||||
'version': instance.version,
|
||||
'downloadURL': instance.downloadURL,
|
||||
'channel': instance.channel,
|
||||
};
|
||||
|
||||
const _$SlackBuildTypeEnumMap = {
|
||||
SlackBuildType.android: 'android',
|
||||
SlackBuildType.ios: 'ios',
|
||||
SlackBuildType.windows: 'windows',
|
||||
SlackBuildType.mac: 'mac',
|
||||
SlackBuildType.web: 'web',
|
||||
};
|
||||
|
||||
DataZip _$DataZipFromJson(Map<String, dynamic> json) => DataZip()
|
||||
..zipFile = json['zipFile'] as String
|
||||
..zipList =
|
||||
(json['zipList'] as List<dynamic>).map((e) => e as String).toList();
|
||||
|
||||
Map<String, dynamic> _$DataZipToJson(DataZip instance) => <String, dynamic>{
|
||||
'zipFile': instance.zipFile,
|
||||
'zipList': instance.zipList,
|
||||
};
|
||||
|
||||
DataShell _$DataShellFromJson(Map<String, dynamic> json) => DataShell()
|
||||
..workspace = json['workspace'] as String?
|
||||
..path = json['path'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataShellToJson(DataShell instance) => <String, dynamic>{
|
||||
'workspace': instance.workspace,
|
||||
'path': instance.path,
|
||||
};
|
||||
24
lib/oto/data/jenkins_data.dart
Normal file
24
lib/oto/data/jenkins_data.dart
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import 'package:json_annotation/json_annotation.dart';
|
||||
part 'jenkins_data.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class DataJenkins {
|
||||
late String workspace;
|
||||
late String jenkinsHome;
|
||||
late String jenkinsUrl;
|
||||
late String buildUrl;
|
||||
late String jobUrl;
|
||||
late String jobName;
|
||||
late String gitCommit;
|
||||
late int buildNumber;
|
||||
late int buildID;
|
||||
late String buildDisplayName;
|
||||
late String gitBranch;
|
||||
late String buildTag;
|
||||
|
||||
DataJenkins();
|
||||
|
||||
factory DataJenkins.fromJson(Map<String, dynamic> json) =>
|
||||
_$DataJenkinsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$DataJenkinsToJson(this);
|
||||
}
|
||||
37
lib/oto/data/jenkins_data.g.dart
Normal file
37
lib/oto/data/jenkins_data.g.dart
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'jenkins_data.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
DataJenkins _$DataJenkinsFromJson(Map<String, dynamic> json) => DataJenkins()
|
||||
..workspace = json['workspace'] as String
|
||||
..jenkinsHome = json['jenkinsHome'] as String
|
||||
..jenkinsUrl = json['jenkinsUrl'] as String
|
||||
..buildUrl = json['buildUrl'] as String
|
||||
..jobUrl = json['jobUrl'] as String
|
||||
..jobName = json['jobName'] as String
|
||||
..gitCommit = json['gitCommit'] as String
|
||||
..buildNumber = json['buildNumber'] as int
|
||||
..buildID = json['buildID'] as int
|
||||
..buildDisplayName = json['buildDisplayName'] as String
|
||||
..gitBranch = json['gitBranch'] as String
|
||||
..buildTag = json['buildTag'] as String;
|
||||
|
||||
Map<String, dynamic> _$DataJenkinsToJson(DataJenkins instance) =>
|
||||
<String, dynamic>{
|
||||
'workspace': instance.workspace,
|
||||
'jenkinsHome': instance.jenkinsHome,
|
||||
'jenkinsUrl': instance.jenkinsUrl,
|
||||
'buildUrl': instance.buildUrl,
|
||||
'jobUrl': instance.jobUrl,
|
||||
'jobName': instance.jobName,
|
||||
'gitCommit': instance.gitCommit,
|
||||
'buildNumber': instance.buildNumber,
|
||||
'buildID': instance.buildID,
|
||||
'buildDisplayName': instance.buildDisplayName,
|
||||
'gitBranch': instance.gitBranch,
|
||||
'buildTag': instance.buildTag,
|
||||
};
|
||||
81
lib/oto/file/copy.dart
Normal file
81
lib/oto/file/copy.dart
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class Copy implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
var data = DataCopy.fromJson(command.param);
|
||||
var result = true;
|
||||
var isMove = data.isMove == null ? false : data.isMove!;
|
||||
var entries = data.copyMap.entries;
|
||||
try {
|
||||
var ignoredList = <String>[];
|
||||
for (var entry in entries) {
|
||||
var start = Path.getNormal(Command.replaceTag(entry.key));
|
||||
var dest = Path.getNormal(Command.replaceTag(entry.value));
|
||||
var destDir = Directory(dest);
|
||||
var name = Path.getName(start);
|
||||
if (name == "*") {
|
||||
//Delete & recreate dest folder
|
||||
if (destDir.existsSync()) destDir.deleteSync(recursive: true);
|
||||
destDir.createSync(recursive: true);
|
||||
var startParentStr = Path.getParent(start);
|
||||
if (startParentStr != null) {
|
||||
var startParent = Directory(startParentStr);
|
||||
if (startParent.existsSync()) {
|
||||
var files = startParent.listSync();
|
||||
for (var file in files) {
|
||||
if (file is File) {
|
||||
await Path.copy(file.path, dest, false,
|
||||
ignorePattern: data.ignorePattern,
|
||||
ignoredList: ignoredList,
|
||||
isMove: isMove);
|
||||
} else if (file is Directory) {
|
||||
await Path.copy(file.path, dest, true,
|
||||
ignorePattern: data.ignorePattern,
|
||||
ignoredList: ignoredList,
|
||||
isMove: isMove);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw ArgumentError('Start - $start is not exist');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!destDir.existsSync()) destDir.createSync(recursive: true);
|
||||
|
||||
var type = Path.getType(start);
|
||||
if (FileType.none == type) {
|
||||
print('[FileNotFound] - $start is not exist');
|
||||
} else {
|
||||
await Path.copy(start, dest, FileType.directory == type,
|
||||
ignorePattern: data.ignorePattern,
|
||||
ignoredList: ignoredList,
|
||||
isMove: isMove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ignoredList.isNotEmpty) {
|
||||
print('==================== Ignored list ====================');
|
||||
for (var element in ignoredList) {
|
||||
print(element);
|
||||
}
|
||||
print('======================================================');
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
print('Copy General Exception: $e');
|
||||
result = false;
|
||||
}
|
||||
c.complete(result);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
40
lib/oto/file/delete.dart
Normal file
40
lib/oto/file/delete.dart
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class Delete implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
var data = DataDelete.fromJson(command.param);
|
||||
var result = true;
|
||||
try {
|
||||
var ignoredList = <String>[];
|
||||
for (var item in data.list) {
|
||||
var path = Path.getNormal(Command.replaceTag(item));
|
||||
var name = Path.getName(path);
|
||||
if (name == "*") {
|
||||
//Delete & recreate dest folder
|
||||
} else {}
|
||||
}
|
||||
|
||||
if (ignoredList.isNotEmpty) {
|
||||
print('==================== Ignored list ====================');
|
||||
for (var element in ignoredList) {
|
||||
print(element);
|
||||
}
|
||||
print('======================================================');
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
print('Copy General Exception: $e');
|
||||
result = false;
|
||||
}
|
||||
c.complete(result);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
41
lib/oto/file/rename.dart
Normal file
41
lib/oto/file/rename.dart
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class Rename implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
var data = DataRename.fromJson(command.param);
|
||||
var result = true;
|
||||
var entries = data.renameMap.entries;
|
||||
try {
|
||||
for (var entry in entries) {
|
||||
var start = Path.getNormal(Command.replaceTag(entry.key));
|
||||
var targetName = Command.replaceTag(entry.value);
|
||||
var type = Path.getType(start);
|
||||
var parentPath = Path.getParent(start)!;
|
||||
var newPath = path.join(parentPath, targetName);
|
||||
if (type == FileType.directory) {
|
||||
await Directory(start).rename(newPath);
|
||||
} else {
|
||||
await File(start).rename(newPath);
|
||||
}
|
||||
|
||||
print('Rename: $start --> ${path.basename(newPath)}');
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
print('Copy General Exception: $e');
|
||||
result = false;
|
||||
}
|
||||
c.complete(result);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
14
lib/oto/shell/jenkins_env_params.bat
Normal file
14
lib/oto/shell/jenkins_env_params.bat
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
@echo {
|
||||
@echo "workspace":"%WORKSPACE%",
|
||||
@echo "jenkinsHome":"%JENKINS_HOME%",
|
||||
@echo "jenkinsUrl":"%JENKINS_URL%",
|
||||
@echo "buildUrl":"%BUILD_URL%",
|
||||
@echo "jobUrl":"%JOB_URL%",
|
||||
@echo "jobName":"%JOB_NAME%",
|
||||
@echo "gitCommit":"%GIT_COMMIT%",
|
||||
@echo "buildNumber":%BUILD_NUMBER%,
|
||||
@echo "buildID":%BUILD_ID%,
|
||||
@echo "buildDisplayName":"%BUILD_DISPLAY_NAME%",
|
||||
@echo "gitBranch":"%GIT_BRANCH%",
|
||||
@echo "buildTag":"%BUILD_TAG%"
|
||||
@echo }
|
||||
17
lib/oto/shell/jenkins_env_params.sh
Normal file
17
lib/oto/shell/jenkins_env_params.sh
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# shellcheck disable=SC2016
|
||||
echo -e '
|
||||
{
|
||||
"workspace":"'${WORKSPACE}'",
|
||||
"jenkinsHome":"'${JENKINS_HOME}'",
|
||||
"jenkinsUrl":"'${JENKINS_URL}'",
|
||||
"buildUrl":"'${BUILD_URL}'",
|
||||
"jobUrl":"'${JOB_URL}'",
|
||||
"jobName":"'${JOB_NAME}'",
|
||||
"gitCommit":"'${GIT_COMMIT}'",
|
||||
"buildNumber":'${BUILD_NUMBER}',
|
||||
"buildID":'${BUILD_ID}',
|
||||
"buildDisplayName":"'${BUILD_DISPLAY_NAME}'",
|
||||
"gitBranch":"'${GIT_BRANCH}'",
|
||||
"buildTag":"'${BUILD_TAG}'"
|
||||
}'
|
||||
echo ${BuildData} > "${WORKSPACE}/build_data.conf"
|
||||
37
lib/oto/shell/shell.dart
Normal file
37
lib/oto/shell/shell.dart
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:dart_framework/platform/process.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class Shell implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData!;
|
||||
var data = DataShell.fromJson(command.param);
|
||||
print(command.param);
|
||||
//Start here
|
||||
var workspace = Command.replaceTag(data.workspace ?? jenkins.workspace);
|
||||
var path = Command.replaceTag(data.path);
|
||||
var shell = StringBuffer();
|
||||
if (Platform.isWindows) {
|
||||
shell.writeln('call $path');
|
||||
} else {
|
||||
shell.writeln('source $path');
|
||||
}
|
||||
var process = await ProcessExecutor.run(shell, workspace: workspace);
|
||||
c.complete(isSuccess(process.exitCode));
|
||||
return c.future;
|
||||
}
|
||||
|
||||
bool isSuccess(int exitCode) {
|
||||
var success = false;
|
||||
if (exitCode == 0 || exitCode == 128) {
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
535
lib/oto/test_data.dart
Normal file
535
lib/oto/test_data.dart
Normal file
|
|
@ -0,0 +1,535 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:yaml/yaml.dart' as yaml;
|
||||
|
||||
import 'package:oto_cli/oto/build/build_flutter.dart';
|
||||
|
||||
class TestData {
|
||||
static Map<String, dynamic> get buildMap {
|
||||
Map<String, dynamic> map = {
|
||||
"common": {"workspace": ""},
|
||||
"commands": []
|
||||
};
|
||||
if (Platform.isMacOS) {
|
||||
map = {
|
||||
"common": {"workspace": Directory.current.path},
|
||||
"commands": [
|
||||
// {
|
||||
// "command": "BuildDart",
|
||||
// "param": {"targetPath": "./"}
|
||||
// },
|
||||
// {
|
||||
// "command": "BuildFlutter",
|
||||
// "param": {
|
||||
// "targetPath": "../desktop_service_frontend",
|
||||
// "platform": BuildPlatform.Macos.toString()
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "BuildFlutter",
|
||||
// "param": {
|
||||
// "targetPath": "../desktop_service_frontend",
|
||||
// "platform": BuildPlatform.Web.toString()
|
||||
// }
|
||||
// },
|
||||
{
|
||||
"command": "BuildDartCompile",
|
||||
"param": {
|
||||
"targetPath": "/Users/toki/works/dart/desktop_service_cli",
|
||||
"targetDartFile": "./bin/desktop_service_cli.dart",
|
||||
"buildFileName": "desktop_service_cli"
|
||||
}
|
||||
},
|
||||
// {
|
||||
// "command": "Copy",
|
||||
// "param": {
|
||||
// "ignorePattern": [
|
||||
// ".git",
|
||||
// ".dart_tool",
|
||||
// ".gitignore",
|
||||
// ".idea",
|
||||
// "example"
|
||||
// ],
|
||||
// "isMove": false,
|
||||
// "copyMap": {
|
||||
// "<!common.workspace>/*": "/Users/toki/server/temp",
|
||||
// // "../toki_flutter_framework/*":
|
||||
// // "/Users/toki/server/toki_flutter_framework"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Zip",
|
||||
// "param": {
|
||||
// "zipFile":
|
||||
// "<!common.workspace>/test_v<!common.version>_<!common.hash>.zip",
|
||||
// "zipList": [
|
||||
// "<!common.workspace>/bin/*",
|
||||
// "<!common.workspace>/README.md"
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Upload",
|
||||
// "param": {
|
||||
// "sftp": false,
|
||||
// "host": "toki-labs.com",
|
||||
// "port": 215,
|
||||
// "user": "spritex",
|
||||
// "password": "Na2674126",
|
||||
// "uploadMap": {
|
||||
// "README.md": "/HDD1/WEB/_tmp",
|
||||
// "bin/*": "/HDD1/WEB/_tmp/bin"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Shell",
|
||||
// "param": {
|
||||
// "workspace": "<!common.workspace>",
|
||||
// "path": "<!common.workspace>/lib/shell/jenkins_env_params.sh"
|
||||
// }
|
||||
// }
|
||||
]
|
||||
};
|
||||
|
||||
var json = jsonEncode(yaml.loadYaml('''
|
||||
---
|
||||
common:
|
||||
workspace: ${Directory.current.path}
|
||||
|
||||
commands:
|
||||
- command: CreateAppData
|
||||
param:
|
||||
scm: Git
|
||||
relativeAssetPath: assets/data
|
||||
returnVersion: "<!common.version>"
|
||||
returnHash: "<!common.hash>"
|
||||
|
||||
#- command: BuildDart
|
||||
# param:
|
||||
# targetPath: "./"
|
||||
|
||||
#- command: BuildFlutter
|
||||
# param:
|
||||
# targetPath: "../tplayer"
|
||||
# executeBuildRunner: false
|
||||
# platform: ${BuildPlatform.Apk.toString()}
|
||||
# additional: "--release --target-platform=android-arm64"
|
||||
|
||||
#- command: BuildiOS
|
||||
# param:
|
||||
# workspacePath: "/Users/toki/jenkins/workspace/tplayer_ios/ios/Runner.xcworkspace"
|
||||
# scheme: Runner
|
||||
# destination: "generic/platform=iOS build"
|
||||
|
||||
#- command: PublishiOS
|
||||
# param:
|
||||
# bundleID: com.tokilabs.tokiplayer
|
||||
# version: <!common.version>
|
||||
# appName: TPlayer
|
||||
# ipaURL: https://toki-labs.com/build/tplayer/ios/tplayer.ipa
|
||||
# menifestURL: https://toki-labs.com/build/tplayer/ios/menifest.plist
|
||||
# displayImageURL: https://toki-labs.com/build/tplayer/icon.png
|
||||
# fullSizeImageURL: https://toki-labs.com/build/tplayer/icon.png
|
||||
# destinationPath: d:/build
|
||||
|
||||
#- command: ArchiveiOS
|
||||
# param:
|
||||
# workspacePath: "<!common.workspace>/ios/Runner.xcworkspace"
|
||||
# scheme: Runner
|
||||
# archivePath: "<!common.workspace>/build/ios/TPlayer"
|
||||
|
||||
#- command: ExportiOS
|
||||
# param:
|
||||
# archivePath: "<!common.workspace>/build/ios/TPlayer"
|
||||
# exportOptionPlistPath: "<!common.workspace>/ExportOptions.plist"
|
||||
# exportPath: "<!common.workspace>/build/ios"
|
||||
|
||||
#- command: BuildDartCompile
|
||||
# param:
|
||||
# targetPath: d:/work/dart/desktop_service_cli
|
||||
# buildFileName: desktop_service_cli
|
||||
|
||||
#- command: Copy
|
||||
# param:
|
||||
# ignorePattern: []
|
||||
# isMove: false
|
||||
# copyMap:
|
||||
# "<!common.workspace>/README.md": "<!common.workspace>/../temp"
|
||||
# "<!common.workspace>/bin/*": "<!common.workspace>/../temp/bin"
|
||||
|
||||
#- command: Rename
|
||||
# param:
|
||||
# renameMap:
|
||||
# "<!common.workspace>/../temp/README.md": "README_<!common.version>.md.back"
|
||||
# "<!common.workspace>/../temp/bin/main.dart": "main.dart.back"
|
||||
# "<!common.workspace>/../temp/test": "test2"
|
||||
|
||||
#- command: Copy
|
||||
# param:
|
||||
# isMove: true
|
||||
# copyMap:
|
||||
# "<!common.workspace>/../temp/README.md": "<!common.workspace>/../temp/bin"
|
||||
|
||||
#- command: Zip
|
||||
# param:
|
||||
# zipFile: "<!common.workspace>/test_v<!common.version>_<!common.hash>.zip"
|
||||
# zipList:
|
||||
# - "<!common.workspace>/bin/*"
|
||||
# - "<!common.workspace>/README.md"
|
||||
|
||||
#- command: Upload
|
||||
# param:
|
||||
# sftp: false
|
||||
# host: toki-labs.com
|
||||
# port: 215
|
||||
# user: spritex
|
||||
# password: Na2674126
|
||||
# uploadMap:
|
||||
# README.md: "/HDD1/WEB/_tmp"
|
||||
# bin/*: "/HDD1/WEB/_tmp/bin"
|
||||
|
||||
#- command: Shell
|
||||
# param:
|
||||
# workspace: "<!common.workspace>"
|
||||
# path: "<!common.workspace>/lib/shell/jenkins_env_params.bat"
|
||||
|
||||
#- command: ExecuteApp
|
||||
# param:
|
||||
# executable: D:/Program Files/TokiSystemTrading/SystemTradingAPIApp.exe
|
||||
# desktopServicePath: D:/work/dart/build_manager
|
||||
|
||||
#- command: SlackBuild
|
||||
# param:
|
||||
# appName: tplayer
|
||||
# type: android
|
||||
# color: ED1458
|
||||
# version: <!common.version>
|
||||
# downloadURL: http://toki-labs.com/build/tplayer/android/tplayer_arm64_<!common.version>.apk
|
||||
# channel: release
|
||||
|
||||
'''));
|
||||
map = jsonDecode(json);
|
||||
} else if (Platform.isWindows) {
|
||||
var json = jsonEncode(yaml.loadYaml('''
|
||||
---
|
||||
common:
|
||||
workspace: ${Directory.current.path}
|
||||
|
||||
commands:
|
||||
- command: CreateAppData
|
||||
param:
|
||||
scm: Git
|
||||
name: Build Manager
|
||||
relativeAssetPath: assets/data
|
||||
returnVersion: "<!common.version>"
|
||||
returnHash: "<!common.hash>"
|
||||
|
||||
#- command: BuildDart
|
||||
# param:
|
||||
# targetPath: "./"
|
||||
|
||||
#- command: BuildFlutter
|
||||
# param:
|
||||
# targetPath: "../tplayer"
|
||||
# executeBuildRunner: false
|
||||
# platform: ${BuildPlatform.Apk.toString()}
|
||||
# additional: "--release --target-platform=android-arm64"
|
||||
|
||||
#- command: BuildiOS
|
||||
# param:
|
||||
# workspacePath: "<!common.workspace>/ios/Runner.xcworkspace"
|
||||
# scheme: Runner
|
||||
# destination: "generic/platform=iOS build"
|
||||
|
||||
#- command: ArchiveiOS
|
||||
# param:
|
||||
# workspacePath: "<!common.workspace>/ios/Runner.xcworkspace"
|
||||
# scheme: Runner
|
||||
# archivePath: "<!common.workspace>/build/ios/TPlayer"
|
||||
|
||||
#- command: ExportiOS
|
||||
# param:
|
||||
# archivePath: "<!common.workspace>/build/ios/TPlayer"
|
||||
# exportOptionPlistPath: "<!common.workspace>/ExportOptions.plist"
|
||||
# exportPath: "<!common.workspace>/build/ios"
|
||||
|
||||
#- command: PublishiOS
|
||||
# param:
|
||||
# bundleID: com.tokilabs.tokiplayer
|
||||
# version: <!common.version>
|
||||
# appName: TPlayer
|
||||
# ipaURL: https://toki-labs.com/build/tplayer/ios/tplayer.ipa
|
||||
# menifestURL: https://toki-labs.com/build/tplayer/ios/manifest.plist
|
||||
# displayImageURL: https://toki-labs.com/build/tplayer/icon.png
|
||||
# fullSizeImageURL: https://toki-labs.com/build/tplayer/icon.png
|
||||
# destinationPath: d:/build
|
||||
|
||||
#- command: BuildDartCompile
|
||||
# param:
|
||||
# targetPath: d:/work/dart/desktop_service_cli
|
||||
# buildFileName: desktop_service_cli
|
||||
|
||||
#- command: Copy
|
||||
# param:
|
||||
# ignorePattern: []
|
||||
# isMove: false
|
||||
# copyMap:
|
||||
# "<!common.workspace>/README.md": "<!common.workspace>/../temp"
|
||||
# "<!common.workspace>/bin/*": "<!common.workspace>/../temp/bin"
|
||||
|
||||
#- command: Rename
|
||||
# param:
|
||||
# renameMap:
|
||||
# "<!common.workspace>/../temp/README.md": "README_<!common.version>.md.back"
|
||||
# "<!common.workspace>/../temp/bin/main.dart": "main.dart.back"
|
||||
# "<!common.workspace>/../temp/test": "test2"
|
||||
|
||||
#- command: Copy
|
||||
# param:
|
||||
# isMove: true
|
||||
# copyMap:
|
||||
# "<!common.workspace>/../temp/README.md": "<!common.workspace>/../temp/bin"
|
||||
|
||||
#- command: Zip
|
||||
# param:
|
||||
# zipFile: "<!common.workspace>/test_v<!common.version>_<!common.hash>.zip"
|
||||
# zipList:
|
||||
# - "<!common.workspace>/bin/*"
|
||||
# - "<!common.workspace>/README.md"
|
||||
|
||||
#- command: Upload
|
||||
# param:
|
||||
# sftp: false
|
||||
# host: toki-labs.com
|
||||
# port: 215
|
||||
# user: spritex
|
||||
# password: Na2674126
|
||||
# uploadMap:
|
||||
# README.md: "/HDD1/WEB/_tmp"
|
||||
# bin/*: "/HDD1/WEB/_tmp/bin"
|
||||
|
||||
#- command: Shell
|
||||
# param:
|
||||
# workspace: "<!common.workspace>"
|
||||
# path: "<!common.workspace>/lib/shell/jenkins_env_params.bat"
|
||||
|
||||
#- command: ExecuteApp
|
||||
# param:
|
||||
# executable: D:/Program Files/TokiSystemTrading/SystemTradingAPIApp.exe
|
||||
# desktopServicePath: D:/work/dart/build_manager
|
||||
|
||||
#- command: SlackBuild
|
||||
# param:
|
||||
# appName: tplayer
|
||||
# type: android
|
||||
# color: ED1458
|
||||
# version: <!common.version>
|
||||
# downloadURL: http://toki-labs.com/build/tplayer/android/tplayer_arm64_<!common.version>.apk
|
||||
# channel: release
|
||||
|
||||
'''));
|
||||
map = jsonDecode(json);
|
||||
|
||||
// map = {
|
||||
// "common": {"workspace": Directory.current.path},
|
||||
// "commands": [
|
||||
// {
|
||||
// "command": "CreateAppData",
|
||||
// "param": {
|
||||
// "scm": "Git",
|
||||
// "relativeAssetPath": "assets/data",
|
||||
// "returnVersion": "<!common.version>",
|
||||
// "returnHash": "<!common.hash>"
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "BuildDart",
|
||||
// "param": {"targetPath": "./"}
|
||||
// },
|
||||
// {
|
||||
// "command": "BuildFlutter",
|
||||
// "param": {
|
||||
// "targetPath": "../desktop_service_frontend",
|
||||
// "platform": BuildPlatform.Windows.toString()
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "BuildDartCompile",
|
||||
// "param": {
|
||||
// "targetPath": "d:\\work\\dart\\desktop_service_cli",
|
||||
// "buildFileName": "desktop_service_cli"
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Copy",
|
||||
// "param": {
|
||||
// "ignorePattern": [],
|
||||
// "isMove": false,
|
||||
// "copyMap": {
|
||||
// "<!common.workspace>/README.md": "<!common.workspace>/../temp",
|
||||
// "<!common.workspace>/bin/*": "<!common.workspace>/../temp/bin"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Zip",
|
||||
// "param": {
|
||||
// "zipFile":
|
||||
// "<!common.workspace>/test_v<!common.version>_<!common.hash>.zip",
|
||||
// "zipList": [
|
||||
// "<!common.workspace>/bin/*",
|
||||
// "<!common.workspace>/README.md"
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Upload",
|
||||
// "param": {
|
||||
// "sftp": false,
|
||||
// "host": "toki-labs.com",
|
||||
// "port": 215,
|
||||
// "user": "spritex",
|
||||
// "password": "Na2674126",
|
||||
// "uploadMap": {
|
||||
// "README.md": "/HDD1/WEB/_tmp",
|
||||
// "bin/*": "/HDD1/WEB/_tmp/bin"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Shell",
|
||||
// "param": {
|
||||
// "workspace": "<!common.workspace>",
|
||||
// "path": "<!common.workspace>/lib/shell/jenkins_env_params.bat"
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "ExecuteApp",
|
||||
// "param": {
|
||||
// "executable":
|
||||
// "D:/Program Files/TokiSystemTrading/SystemTradingAPIApp.exe",
|
||||
// "desktopServicePath": "D:/work/dart/toki_desktop_service"
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// };
|
||||
} else if (Platform.isLinux) {
|
||||
map = {
|
||||
"common": {"workspace": Directory.current.path},
|
||||
"commands": [
|
||||
// {
|
||||
// "command": "BuildDart",
|
||||
// "param": {"targetPath": "<!common.workspace>"}
|
||||
// },
|
||||
{
|
||||
"command": "BuildDartCompile",
|
||||
"param": {
|
||||
"targetPath": "/home/deck/work/desktop_service_cli",
|
||||
"targetDartFile": "./bin/desktop_service_cli.dart",
|
||||
"buildFileName": "desktop_service_cli"
|
||||
}
|
||||
},
|
||||
// {
|
||||
// "command": "BuildFlutter",
|
||||
// "param": {
|
||||
// "targetPath": "../desktop_service_frontend",
|
||||
// "platform": BuildPlatform.Linux.toString()
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Copy",
|
||||
// "param": {
|
||||
// "ignorePattern": [
|
||||
// ".git",
|
||||
// ".dart_tool",
|
||||
// ".gitignore",
|
||||
// ".idea",
|
||||
// "example"
|
||||
// ],
|
||||
// "isMove": false,
|
||||
// "copyMap": {
|
||||
// "<!common.workspace>/*": "/home/deck/temp",
|
||||
// // "../toki_flutter_framework/*":
|
||||
// // "/Users/toki/server/toki_flutter_framework"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Zip",
|
||||
// "param": {
|
||||
// "zipFile":
|
||||
// "<!common.workspace>/test_v<!common.version>_<!common.hash>.zip",
|
||||
// "zipList": [
|
||||
// "<!common.workspace>/bin/*",
|
||||
// "<!common.workspace>/README.md"
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Upload",
|
||||
// "param": {
|
||||
// "sftp": false,
|
||||
// "host": "toki-labs.com",
|
||||
// "port": 215,
|
||||
// "user": "spritex",
|
||||
// "password": "Na2674126",
|
||||
// "uploadMap": {
|
||||
// "README.md": "/HDD1/WEB/_tmp",
|
||||
// "bin/*": "/HDD1/WEB/_tmp/bin"
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "command": "Shell",
|
||||
// "param": {
|
||||
// "workspace": "<!common.workspace>",
|
||||
// "path": "<!common.workspace>/lib/shell/jenkins_env_params.sh"
|
||||
// }
|
||||
// }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static Map<String, dynamic>? get jenkinsMap {
|
||||
Map<String, dynamic>? map;
|
||||
if (Platform.isMacOS || Platform.isLinux) {
|
||||
map = {
|
||||
"workspace": Directory.current.path,
|
||||
"jenkinsHome": "/var/lib/jenkins",
|
||||
"jenkinsUrl": "http://toki-labs.com:8083/",
|
||||
"buildUrl": "http://toki-labs.com:8083/job/toki_os/54/",
|
||||
"jobUrl": "http://toki-labs.com:8083/job/toki_os/",
|
||||
"jobName": "toki_os",
|
||||
"gitCommit": "6087aadcf9f8dbe0d2f024ae32dbcf0f6955d45b",
|
||||
"buildNumber": 54,
|
||||
"buildID": 54,
|
||||
"buildDisplayName": "#54",
|
||||
"gitBranch": "origin/master",
|
||||
"buildTag": "jenkins-toki_os-54",
|
||||
"buildData": buildMap
|
||||
};
|
||||
} else if (Platform.isWindows) {
|
||||
map = {
|
||||
"workspace": Directory.current.path,
|
||||
"jenkinsHome": "/var/lib/jenkins",
|
||||
"jenkinsUrl": "http://toki-labs.com:8083/",
|
||||
"buildUrl": "http://toki-labs.com:8083/job/toki_system_trading/18/",
|
||||
"jobUrl": "http://toki-labs.com:8083/job/toki_system_trading/",
|
||||
"jobName": "toki_system_trading",
|
||||
"gitCommit": "abef2bc09c1d82e69ebe897ee079135aac9e797a",
|
||||
"buildNumber": 18,
|
||||
"buildID": 18,
|
||||
"buildDisplayName": "#18",
|
||||
"gitBranch": "origin/master",
|
||||
"buildTag": "jenkins-toki_system_trading-18",
|
||||
"buildData": buildMap
|
||||
};
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
438
lib/oto/uploader/ftp.dart
Normal file
438
lib/oto/uploader/ftp.dart
Normal file
|
|
@ -0,0 +1,438 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:ftpconnect/ftpconnect.dart';
|
||||
// ignore: implementation_imports
|
||||
import 'package:ftpconnect/src/ftp_entry.dart';
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
|
||||
class FTP {
|
||||
final String _host;
|
||||
final int _port;
|
||||
final int _timeout;
|
||||
final String _user;
|
||||
final String _pass;
|
||||
|
||||
bool _isProgress = false;
|
||||
String? _currentRemoteDir;
|
||||
FTPConnect? _ftp;
|
||||
|
||||
FTP(String host,
|
||||
{int port = 21,
|
||||
String user = 'anonymous',
|
||||
String password = '',
|
||||
int timeout = 30})
|
||||
: _host = host,
|
||||
_port = port,
|
||||
_user = user,
|
||||
_pass = password,
|
||||
_timeout = timeout {
|
||||
_ftp = FTPConnect(host,
|
||||
port: port, user: user, pass: password, timeout: timeout);
|
||||
}
|
||||
|
||||
Future<void> connect() async {
|
||||
int tryCount = 0;
|
||||
bool connected = false;
|
||||
while (!connected && tryCount < 10) {
|
||||
try {
|
||||
await _ftp!.connect();
|
||||
connected = true;
|
||||
} on Exception catch (e) {
|
||||
var code = e.hashCode;
|
||||
var type = e.runtimeType;
|
||||
print('========================= Connect Failed!');
|
||||
print('$code = $type');
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> disconnect() async {
|
||||
await _ftp!.disconnect();
|
||||
}
|
||||
|
||||
//Remote target must be folder
|
||||
Future<void> upload(Map<String, String> localRemoteMap) async {
|
||||
var cache = <String, Map<String, FileType>>{};
|
||||
Map<String, FileType> map = {};
|
||||
_currentRemoteDir = null;
|
||||
try {
|
||||
_isProgress = true;
|
||||
var entries = localRemoteMap.entries;
|
||||
for (var entry in entries) {
|
||||
var local = Path.getNormalizePath(entry.key);
|
||||
var remote = Path.getNormalizePath(entry.value);
|
||||
var parent = Path.getParent(remote);
|
||||
if (_currentRemoteDir != parent) {
|
||||
await _ftp!.changeDirectory(parent!);
|
||||
_currentRemoteDir = parent;
|
||||
if (cache.containsKey(_currentRemoteDir)) {
|
||||
map = cache[_currentRemoteDir]!;
|
||||
} else {
|
||||
map = await list(parent);
|
||||
cache[_currentRemoteDir!] = map;
|
||||
}
|
||||
}
|
||||
if (map.containsKey(remote) && map[remote] == FileType.directory) {
|
||||
await _upload(local, remote);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
_isProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _upload(String local, String remote) async {
|
||||
local = Command.replaceTag(local);
|
||||
remote = Command.replaceTag(remote);
|
||||
if (await Directory(local).exists()) {
|
||||
var name = Path.getName(local);
|
||||
var childRemoteFolder = '$remote/$name';
|
||||
await createFolder(childRemoteFolder);
|
||||
var list = Directory(local).listSync();
|
||||
for (var item in list) {
|
||||
if (await Directory(item.path).exists()) {
|
||||
await _upload(item.path, childRemoteFolder);
|
||||
} else {
|
||||
await _ftp!.changeDirectory(childRemoteFolder);
|
||||
await _ftp!.uploadFile(File(item.path));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await _ftp!.changeDirectory(remote);
|
||||
await _ftp!.uploadFile(File(local));
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Map<String, FileType>> _cache = <String, Map<String, FileType>>{};
|
||||
//Local target must be folder
|
||||
Future<void> download(Map<String, String> remoteLocalMap) async {
|
||||
var c = Completer();
|
||||
_cache = <String, Map<String, FileType>>{};
|
||||
try {
|
||||
_isProgress = true;
|
||||
var entries = remoteLocalMap.entries;
|
||||
for (var entry in entries) {
|
||||
await _download(entry.key, entry.value);
|
||||
}
|
||||
} finally {
|
||||
_isProgress = false;
|
||||
c.complete();
|
||||
}
|
||||
return c.future;
|
||||
}
|
||||
|
||||
Future<void> _download(String remote, String local) async {
|
||||
Map<String, FileType>? map;
|
||||
remote = Path.getNormalizePath(remote);
|
||||
local = Path.getNormalizePath(local);
|
||||
var parent = Path.getParent(remote);
|
||||
var name = Path.getName(remote);
|
||||
if (_cache.containsKey(parent)) {
|
||||
map = _cache[parent]!;
|
||||
} else {
|
||||
map ??= await list(parent!);
|
||||
}
|
||||
if (map.containsKey(remote)) {
|
||||
if (map[remote] == FileType.directory) {
|
||||
var childLocalFolder = '$local/$name';
|
||||
var dir = Directory(childLocalFolder);
|
||||
if (!await dir.exists()) dir.createSync();
|
||||
Map<String, FileType> childList;
|
||||
if (_cache.containsKey(remote)) {
|
||||
childList = _cache[remote]!;
|
||||
} else {
|
||||
childList = await list(remote);
|
||||
_cache[remote] = childList;
|
||||
}
|
||||
var entries = childList.entries;
|
||||
for (var entry in entries) {
|
||||
await _download(entry.key, childLocalFolder);
|
||||
}
|
||||
} else {
|
||||
await _ftp!.changeDirectory(parent!);
|
||||
await _ftp!.downloadFile(name, File('$local/$name'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, FileType>> list(String path) async {
|
||||
var c = Completer<Map<String, FileType>>();
|
||||
var map = <String, FileType>{};
|
||||
try {
|
||||
await _ftp!.changeDirectory(path);
|
||||
var list = await _ftp!.listDirectoryContent();
|
||||
var count = 0;
|
||||
for (var item in list) {
|
||||
FileType? type;
|
||||
switch (item.type) {
|
||||
case FTPEntryType.DIR:
|
||||
type = FileType.directory;
|
||||
break;
|
||||
case FTPEntryType.FILE:
|
||||
type = FileType.file;
|
||||
break;
|
||||
case FTPEntryType.LINK:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
case FTPEntryType.UNKNOWN:
|
||||
// TODO: Handle this case.
|
||||
break;
|
||||
}
|
||||
var name = item.name;
|
||||
if (name != '.' && name != '..') {
|
||||
count++;
|
||||
var remotePath = '$path/$name';
|
||||
map[remotePath] = type!;
|
||||
// print('$count = $type = $remotePath');
|
||||
}
|
||||
}
|
||||
} finally {}
|
||||
c.complete(map);
|
||||
return c.future;
|
||||
}
|
||||
|
||||
Future<void> delete(List<String> remoteList) async {
|
||||
var cache = <String, Map<String, FileType>>{};
|
||||
Map<String, FileType>? map;
|
||||
_currentRemoteDir = null;
|
||||
try {
|
||||
_isProgress = true;
|
||||
for (var item in remoteList) {
|
||||
var parent = Path.getParent(item);
|
||||
var name = Path.getName(item);
|
||||
if (_currentRemoteDir != parent) {
|
||||
await _ftp!.changeDirectory(parent!);
|
||||
_currentRemoteDir = parent;
|
||||
if (cache.containsKey(_currentRemoteDir)) {
|
||||
map = cache[_currentRemoteDir!]!;
|
||||
} else {
|
||||
map = await list(parent);
|
||||
cache[_currentRemoteDir!] = map;
|
||||
}
|
||||
}
|
||||
if (map!.containsKey(item)) {
|
||||
if (map[item] == FileType.directory) {
|
||||
await _ftp!.deleteDirectory(name);
|
||||
} else {
|
||||
await _ftp!.deleteFile(name);
|
||||
}
|
||||
print('Deleted: $item');
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
_isProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> createFolder(String path) async {
|
||||
var c = Completer<bool>();
|
||||
try {
|
||||
var parent = Path.getParent(path);
|
||||
var name = Path.getName(path);
|
||||
await _ftp!.changeDirectory(parent!);
|
||||
if (await _ftp!.checkFolderExistence(name)) {
|
||||
c.complete(false);
|
||||
print('Create failed: Already exist file or folder');
|
||||
} else {
|
||||
await _ftp!.makeDirectory(name);
|
||||
c.complete(true);
|
||||
print('Created Folder: $path');
|
||||
}
|
||||
} finally {}
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore: slash_for_doc_comments
|
||||
/********************************* SFTP **********************************
|
||||
Need sshpass
|
||||
|
||||
//Brew install - https://brew.sh/index_ko
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
|
||||
|
||||
//sshpass install - https://gist.github.com/arunoda/7790979
|
||||
brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Formula/sshpass.rb
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
class SFTP extends FTP {
|
||||
SFTP(String host,
|
||||
{int port = 22,
|
||||
String user = 'anonymous',
|
||||
String password = '',
|
||||
int timeout = 30})
|
||||
: super(host,
|
||||
port: port, user: user, password: password, timeout: timeout);
|
||||
|
||||
@override
|
||||
Future<void> connect() async {}
|
||||
|
||||
@override
|
||||
Future<void> disconnect() async {}
|
||||
|
||||
//Remote target must be folder
|
||||
@override
|
||||
Future<void> upload(Map<String, String> localRemoteMap) async {
|
||||
Map<String, FileType>? map;
|
||||
var entries = localRemoteMap.entries;
|
||||
for (var entry in entries) {
|
||||
var local = Path.getNormalizePath(entry.key);
|
||||
var remote = Path.getNormalizePath(entry.value);
|
||||
String type;
|
||||
var parent = Path.getParent(remote);
|
||||
if (map == null || !map.containsKey(local)) map = await list(parent!);
|
||||
if (map[remote] == FileType.directory) {
|
||||
if (await Directory(local).exists()) {
|
||||
type = '[D]';
|
||||
await Process.run('sshpass', [
|
||||
'-p',
|
||||
_pass,
|
||||
'scp',
|
||||
'-P',
|
||||
'$_port',
|
||||
'-r',
|
||||
local,
|
||||
'$_user@$_host:$remote'
|
||||
]).then((ProcessResult results) => print(results.stdout));
|
||||
} else {
|
||||
type = '[F]';
|
||||
await Process.run('sshpass', [
|
||||
'-p',
|
||||
_pass,
|
||||
'scp',
|
||||
'-P',
|
||||
'$_port',
|
||||
local,
|
||||
'$_user@$_host:$remote'
|
||||
]).then((ProcessResult results) => print(results.stdout));
|
||||
}
|
||||
print('Uploaded: $type$local --> $remote');
|
||||
} else {
|
||||
throw ArgumentError('Remote target should be "Folder"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Local target must be folder
|
||||
@override
|
||||
Future<void> download(Map<String, String> remoteLocalMap) async {
|
||||
Map<String, FileType>? map;
|
||||
var entries = remoteLocalMap.entries;
|
||||
for (var entry in entries) {
|
||||
var remote = Path.getNormalizePath(entry.key);
|
||||
var local = Path.getNormalizePath(entry.value);
|
||||
String type;
|
||||
var parent = remote.substring(0, remote.lastIndexOf('/'));
|
||||
if (map == null || !map.containsKey(remote)) map = await list(parent);
|
||||
if (map[remote] == FileType.directory) {
|
||||
type = '[D]';
|
||||
await Process.run('sshpass', [
|
||||
'-p',
|
||||
_pass,
|
||||
'scp',
|
||||
'-P',
|
||||
'$_port',
|
||||
'-r',
|
||||
'$_user@$_host:$remote',
|
||||
local
|
||||
]).then((ProcessResult result) => print(result.stdout));
|
||||
} else {
|
||||
type = '[F]';
|
||||
await Process.run('sshpass', [
|
||||
'-p',
|
||||
_pass,
|
||||
'scp',
|
||||
'-P',
|
||||
'$_port',
|
||||
'$_user@$_host:$remote',
|
||||
local
|
||||
]).then((ProcessResult result) => print(result.stdout));
|
||||
}
|
||||
print('Download: $type$remote --> $local');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, FileType>> list(String path) async {
|
||||
var c = Completer<Map<String, FileType>>();
|
||||
var map = <String, FileType>{};
|
||||
var count = 0;
|
||||
await Process.run('sshpass', [
|
||||
'-p',
|
||||
_pass,
|
||||
'ssh',
|
||||
'$_user@$_host',
|
||||
'-p$_port',
|
||||
'ls -l $path'
|
||||
]).then((ProcessResult result) async {
|
||||
var data = result.stdout;
|
||||
var list = data.split('\n');
|
||||
list.forEach((element) {
|
||||
if (count != 0 && element.length > 10) {
|
||||
var info = element.split(' ');
|
||||
var typeStr = info[0].substring(0, 1);
|
||||
FileType type;
|
||||
var fileName = info[info.length - 1];
|
||||
switch (typeStr) {
|
||||
case 'd':
|
||||
type = FileType.directory;
|
||||
break;
|
||||
case '-':
|
||||
type = FileType.file;
|
||||
break;
|
||||
default:
|
||||
type = FileType.link;
|
||||
}
|
||||
var mapKey = '$path/$fileName';
|
||||
// print('$count = $type = $mapKey');
|
||||
map[mapKey] = type;
|
||||
}
|
||||
count++;
|
||||
});
|
||||
});
|
||||
c.complete(map);
|
||||
return c.future;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> delete(List<String> remoteList) async {
|
||||
print('######################## delete ${remoteList.length}');
|
||||
//check file exist
|
||||
for (var item in remoteList) {
|
||||
await Process.run('sshpass', [
|
||||
'-p',
|
||||
_pass,
|
||||
'ssh',
|
||||
'$_user@$_host',
|
||||
'-p$_port',
|
||||
'rm -rf $item'
|
||||
]).then((ProcessResult results) => print(results.stdout));
|
||||
print('Deleted: $item');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> createFolder(String path) async {
|
||||
var c = Completer<bool>();
|
||||
var parent = path.substring(0, path.lastIndexOf('/'));
|
||||
var map = await list(parent);
|
||||
if (map.containsKey(path)) {
|
||||
c.complete(false);
|
||||
print('Create failed: Already exist file or folder');
|
||||
} else {
|
||||
await Process.run('sshpass', [
|
||||
'-p',
|
||||
_pass,
|
||||
'ssh',
|
||||
'$_user@$_host',
|
||||
'-p$_port',
|
||||
'mkdir $path'
|
||||
]).then((ProcessResult results) => print(results.stdout));
|
||||
c.complete(true);
|
||||
print('Created Folder: $path');
|
||||
}
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
74
lib/oto/uploader/uploader.dart
Normal file
74
lib/oto/uploader/uploader.dart
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import 'dart:async';
|
||||
import 'dart:core';
|
||||
import 'dart:io';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:oto_cli/oto/uploader/ftp.dart';
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
|
||||
class Uploader implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var data = DataUploader.fromJson(command.param);
|
||||
|
||||
//Check asterisk
|
||||
var uploadMap = <String, String>{};
|
||||
var map = data.uploadMap;
|
||||
int port = data.port == 0 ? (data.sftp ? 22 : 21) : data.port;
|
||||
|
||||
var ftp = data.sftp
|
||||
? SFTP(data.host, port: port, user: data.user, password: data.password)
|
||||
: FTP(data.host, port: port, user: data.user, password: data.password);
|
||||
print(
|
||||
'========================= [Try connection] =========================');
|
||||
await ftp.connect();
|
||||
print(
|
||||
'========================= [Connected! Start Upload] ================');
|
||||
var entries = map.entries;
|
||||
for (var entry in entries) {
|
||||
var local = path.join(Application.to.jenkinsData!.workspace, entry.key);
|
||||
var remote = entry.value;
|
||||
print('[Upload]: $local ====> $remote');
|
||||
|
||||
var parentRemote = Path.getParent(remote);
|
||||
var remoteMap = await ftp.list(parentRemote!);
|
||||
var parentLocal = Path.getParent(local);
|
||||
var nameLocal = Path.getName(local);
|
||||
|
||||
if (nameLocal == '*') {
|
||||
//에스테리크(*) 일경우 리모트 폴더를 삭제해서 전체 교체
|
||||
//Remove before folder
|
||||
if (remoteMap.containsKey(remote) &&
|
||||
remoteMap[remoteMap] == FileType.directory) {
|
||||
await ftp.delete([remote]);
|
||||
}
|
||||
//Create new folder
|
||||
await ftp.createFolder(remote);
|
||||
var parentLocalDir = Directory(parentLocal!);
|
||||
if (parentLocalDir.existsSync()) {
|
||||
var localFiles = parentLocalDir.listSync();
|
||||
var map = <String, String>{};
|
||||
for (var file in localFiles) {
|
||||
map[file.path] = remote;
|
||||
}
|
||||
await ftp.upload(map);
|
||||
} else {
|
||||
throw ArgumentError('Start - $parentLocal is not exist');
|
||||
}
|
||||
} else {
|
||||
uploadMap[local] = remote;
|
||||
}
|
||||
}
|
||||
|
||||
if (uploadMap.isNotEmpty) await ftp.upload(uploadMap);
|
||||
|
||||
await ftp.disconnect();
|
||||
print(
|
||||
'========================= [Upload completed!] ======================');
|
||||
c.complete(true);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
27
lib/oto/util/execute_app.dart
Normal file
27
lib/oto/util/execute_app.dart
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:dart_framework/platform/process.dart';
|
||||
|
||||
class ExecuteApp implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
var data = DataExecuteApp.fromJson(command.param);
|
||||
|
||||
var exe = Command.replaceTag(data.executable);
|
||||
var desktop = Command.replaceTag(data.desktopServicePath);
|
||||
print('Process Start: $exe');
|
||||
var content = 'start "" "$exe" & exit';
|
||||
|
||||
var buffer = StringBuffer(content);
|
||||
var processData =
|
||||
await ProcessExecutor.run(buffer, workspace: data.desktopServicePath);
|
||||
c.complete(true);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
55
lib/oto/util/publish_ios.dart
Normal file
55
lib/oto/util/publish_ios.dart
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
class PublishiOS implements Command {
|
||||
Function? get error => null;
|
||||
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var data = DataPublishiOS.fromJson(command.param);
|
||||
var workspace = Path.getNormal(Application.to.jenkinsData!.workspace);
|
||||
var menifestURL = Command.replaceTag(data.menifestURL);
|
||||
var destinationPath = Command.replaceTag(data.destinationPath);
|
||||
|
||||
var templatePath = path.normalize(
|
||||
'${path.dirname(Platform.script.toFilePath())}/../assets/template');
|
||||
var indexContent = await File('$templatePath/index.html').readAsString();
|
||||
indexContent = indexContent.replaceAll("MENIFEST_URL", menifestURL);
|
||||
|
||||
var destinationDir = Directory(destinationPath);
|
||||
if (!destinationDir.existsSync()) {
|
||||
await destinationDir.create(recursive: true);
|
||||
}
|
||||
var indexFile = File('$destinationPath/index.html');
|
||||
await indexFile.writeAsString(indexContent);
|
||||
|
||||
print('Created "index.html" --> "$destinationPath/index.html"');
|
||||
|
||||
var menifestContent =
|
||||
await File('$templatePath/manifest.plist').readAsString();
|
||||
menifestContent = menifestContent
|
||||
.replaceFirst('IPA_URL', Command.replaceTag(data.ipaURL))
|
||||
.replaceFirst('BUNDLE_ID', Command.replaceTag(data.bundleID))
|
||||
.replaceFirst('VERSION', Command.replaceTag(data.version))
|
||||
.replaceFirst('APP_NAME', Command.replaceTag(data.appName))
|
||||
.replaceFirst(
|
||||
'DISPLAY_IMAGE_URL', Command.replaceTag(data.displayImageURL))
|
||||
.replaceFirst(
|
||||
'FULL_SIZE_IMAGE_URL', Command.replaceTag(data.fullSizeImageURL));
|
||||
var menifestFile = File('$destinationPath/manifest.plist');
|
||||
await menifestFile.writeAsString(menifestContent);
|
||||
|
||||
print('Created "manifest.plist" --> "$destinationPath/manifest.plist"');
|
||||
|
||||
c.complete(true);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
45
lib/oto/util/slack.dart
Normal file
45
lib/oto/util/slack.dart
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
import 'package:color/color.dart';
|
||||
import 'package:dart_framework/utils/slack/slack_sender.dart';
|
||||
|
||||
class Slack implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
var data = DataSlack.fromJson(command.param);
|
||||
var result = true;
|
||||
|
||||
//To-do: compose parameters
|
||||
|
||||
c.complete(result);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
|
||||
class SlackBuild implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
var data = DataSlackBuild.fromJson(command.param);
|
||||
var result = true;
|
||||
|
||||
var version = Command.replaceTag(data.version);
|
||||
var download = Command.replaceTag(data.downloadURL);
|
||||
var channel = data.channel ?? 'build';
|
||||
var color = Color.hex(data.color);
|
||||
var sender = SlackSender();
|
||||
await sender.sendBuild(data.appName, data.type, color, version, download,
|
||||
channel: channel);
|
||||
|
||||
c.complete(result);
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
80
lib/oto/util/zip.dart
Normal file
80
lib/oto/util/zip.dart
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:archive/archive_io.dart';
|
||||
import 'package:dart_framework/utils/path.dart';
|
||||
import 'package:oto_cli/oto/application.dart';
|
||||
import 'package:oto_cli/oto/command.dart';
|
||||
import 'package:oto_cli/oto/data/data.dart';
|
||||
|
||||
class Zip implements Command {
|
||||
@override
|
||||
Future<bool> execute(DataCommand command) async {
|
||||
Completer<bool> c = Completer<bool>();
|
||||
var common = Application.to.property;
|
||||
var jenkins = Application.to.jenkinsData;
|
||||
var data = DataZip.fromJson(command.param);
|
||||
try {
|
||||
var zipFilePath = Path.getNormal(Command.replaceTag(data.zipFile));
|
||||
print('Start Compress...');
|
||||
var parent = Directory(Path.getParent(zipFilePath)!);
|
||||
if (!parent.existsSync()) parent.createSync(recursive: true);
|
||||
var zipFile = File(zipFilePath);
|
||||
if (zipFile.existsSync()) zipFile.deleteSync();
|
||||
var tempDir = Directory(zipFilePath);
|
||||
if (!tempDir.existsSync()) {
|
||||
var encoder = ZipFileEncoder();
|
||||
encoder.create(zipFilePath);
|
||||
var list = data.zipList;
|
||||
for (var path in list) {
|
||||
path = Path.getNormal(Command.replaceTag(path));
|
||||
var name = Path.getName(path);
|
||||
if (name == '*') {
|
||||
parent = Directory(Path.getParent(path)!);
|
||||
if (parent.existsSync()) {
|
||||
var list = parent.listSync();
|
||||
for (var item in list) {
|
||||
var dir = Directory(item.path);
|
||||
var file = File(item.path);
|
||||
if (dir.existsSync()) {
|
||||
print('- Compress Dir --> ${dir.path}');
|
||||
encoder.addDirectory(dir);
|
||||
}
|
||||
if (file.existsSync()) {
|
||||
encoder.addFile(file);
|
||||
print('- Compress File --> ${file.path}');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print('================== "$path" is not exist');
|
||||
}
|
||||
} else {
|
||||
var dir = Directory(path);
|
||||
var file = File(path);
|
||||
var added = false;
|
||||
if (dir.existsSync()) {
|
||||
print('- Compress Dir --> ${dir.path}');
|
||||
encoder.addDirectory(dir);
|
||||
added = true;
|
||||
}
|
||||
if (file.existsSync()) {
|
||||
encoder.addFile(file);
|
||||
print('- Compress File --> ${file.path}');
|
||||
added = true;
|
||||
}
|
||||
if (!added) print('================== "$path" is not exist');
|
||||
}
|
||||
}
|
||||
encoder.close();
|
||||
c.complete(true);
|
||||
print('Compress success: $zipFilePath');
|
||||
} else {
|
||||
throw Exception('"${tempDir.path}" is Directory');
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
print('Zip General Exception: $e');
|
||||
}
|
||||
|
||||
return c.future;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue