99 lines
3 KiB
Dart
99 lines
3 KiB
Dart
import '../services/adb_service.dart';
|
|
import 'adb_device.dart';
|
|
import 'pending_install.dart';
|
|
|
|
enum InstallAttemptOutcome { success, failure }
|
|
|
|
class InstallAttemptResult {
|
|
const InstallAttemptResult({
|
|
required this.pendingInstall,
|
|
required this.device,
|
|
required this.result,
|
|
});
|
|
|
|
final PendingInstall pendingInstall;
|
|
final AdbDevice device;
|
|
final AdbInstallResult result;
|
|
|
|
InstallAttemptOutcome get outcome => result.succeeded
|
|
? InstallAttemptOutcome.success
|
|
: InstallAttemptOutcome.failure;
|
|
|
|
bool get succeeded => outcome == InstallAttemptOutcome.success;
|
|
|
|
bool get failed => outcome == InstallAttemptOutcome.failure;
|
|
|
|
String get artifactLabel =>
|
|
'#${pendingInstall.buildNumber} · ${pendingInstall.jobName} · '
|
|
'${pendingInstall.fileName}';
|
|
|
|
String get outputSummary {
|
|
final stdout = result.stdout.trim();
|
|
final stderr = result.stderr.trim();
|
|
if (succeeded) {
|
|
return [stdout, stderr].where((it) => it.isNotEmpty).join('\n');
|
|
}
|
|
|
|
if (stderr.isNotEmpty) return _firstNonEmptyLine(stderr);
|
|
if (stdout.isNotEmpty) return _firstNonEmptyLine(stdout);
|
|
return '설치 실패';
|
|
}
|
|
|
|
String get maskedOutputSummary => _maskSensitive(outputSummary);
|
|
|
|
String get maskedDeviceSerial => _maskSerial(device.serial);
|
|
|
|
String get maskedReport {
|
|
final lines = [
|
|
'AppSok 설치 리포트',
|
|
'결과: ${succeeded ? '성공' : '실패'}',
|
|
'exitCode: ${result.exitCode}',
|
|
'Build: $artifactLabel',
|
|
'Device: ${device.displayName} ($maskedDeviceSerial)',
|
|
if (maskedOutputSummary.isNotEmpty) '요약: $maskedOutputSummary',
|
|
if (result.stdout.trim().isNotEmpty)
|
|
'stdout:\n${_maskSensitive(result.stdout.trim())}',
|
|
if (result.stderr.trim().isNotEmpty)
|
|
'stderr:\n${_maskSensitive(result.stderr.trim())}',
|
|
];
|
|
return lines.join('\n');
|
|
}
|
|
|
|
String _firstNonEmptyLine(String text) {
|
|
final lines = text
|
|
.split('\n')
|
|
.map((line) => line.trim())
|
|
.where((line) => line.isNotEmpty);
|
|
return lines.isEmpty ? '' : lines.first;
|
|
}
|
|
|
|
String _maskSensitive(String value) {
|
|
final masked = value
|
|
.replaceAll(RegExp(r'https?:\/\/[^\s]+'), '[masked-url]')
|
|
.replaceAllMapped(
|
|
RegExp(
|
|
r'\b(authorization)\s*[:=]\s*bearer\s+[A-Za-z0-9._~+/=-]+',
|
|
caseSensitive: false,
|
|
),
|
|
(match) => '${match.group(1)}: [masked]',
|
|
)
|
|
.replaceAllMapped(
|
|
RegExp(
|
|
r'\b(api[_-]?token|token|password|passwd|secret)\s*[:=]\s*[^\s&]+',
|
|
caseSensitive: false,
|
|
),
|
|
(match) => '${match.group(1)}=[masked]',
|
|
);
|
|
return device.serial.isEmpty
|
|
? masked
|
|
: masked.replaceAll(device.serial, maskedDeviceSerial);
|
|
}
|
|
|
|
String _maskSerial(String serial) {
|
|
if (serial.isEmpty) return '[masked-serial]';
|
|
if (serial.length <= 4) return '*' * serial.length;
|
|
final prefix = serial.substring(0, 2);
|
|
final suffix = serial.substring(serial.length - 2);
|
|
return '$prefix${'*' * (serial.length - 4)}$suffix';
|
|
}
|
|
}
|