From 481ab045b2e77a20fa3f9a2febbca679e5d6f952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Takahashi?= Date: Mon, 27 Jan 2025 11:59:15 +0000 Subject: [PATCH] refactor(analyze): Rename Flow Files to Debug files along with non-primitive usage of debug files --- .../main/java/maestro/cli/api/ApiClient.kt | 30 +-------- .../java/maestro/cli/cloud/CloudInteractor.kt | 7 +- .../cli/insights/TestAnalysisManager.kt | 64 +++++++++++-------- 3 files changed, 43 insertions(+), 58 deletions(-) diff --git a/maestro-cli/src/main/java/maestro/cli/api/ApiClient.kt b/maestro-cli/src/main/java/maestro/cli/api/ApiClient.kt index 6a76bc4e38..ee4e79ec82 100644 --- a/maestro-cli/src/main/java/maestro/cli/api/ApiClient.kt +++ b/maestro-cli/src/main/java/maestro/cli/api/ApiClient.kt @@ -1,8 +1,6 @@ package maestro.cli.api import com.fasterxml.jackson.annotation.JsonIgnoreProperties -import com.fasterxml.jackson.annotation.JsonSubTypes -import com.fasterxml.jackson.annotation.JsonTypeInfo import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.github.michaelbull.result.Err @@ -11,7 +9,7 @@ import com.github.michaelbull.result.Result import maestro.cli.CliError import maestro.cli.analytics.Analytics import maestro.cli.analytics.AnalyticsReport -import maestro.cli.insights.FlowFiles +import maestro.cli.insights.AnalysisDebugFiles import maestro.cli.model.FlowStatus import maestro.cli.runner.resultview.AnsiResultView import maestro.cli.util.CiUtils @@ -460,32 +458,10 @@ class ApiClient( fun analyze( authToken: String, - flowFiles: List, + debugFiles: AnalysisDebugFiles, ): AnalyzeResponse { - if (flowFiles.isEmpty()) throw CliError("Missing flow files to analyze") - - val screenshots = mutableListOf>() - val logs = mutableListOf>() - - flowFiles.forEach { flowFile -> - flowFile.imageFiles.forEach { (imageData, path) -> - val imageName = path.fileName.toString() - screenshots.add(Pair(imageName, imageData)) - } - - flowFile.textFiles.forEach { (textData, path) -> - val textName = path.fileName.toString() - logs.add(Pair(textName, textData)) - } - } - - val requestBody = mapOf( - "screenshots" to screenshots, - "logs" to logs - ) - val mediaType = "application/json; charset=utf-8".toMediaType() - val body = JSON.writeValueAsString(requestBody).toRequestBody(mediaType) + val body = JSON.writeValueAsString(debugFiles).toRequestBody(mediaType) val url = "$baseUrl/v2/analyze" diff --git a/maestro-cli/src/main/java/maestro/cli/cloud/CloudInteractor.kt b/maestro-cli/src/main/java/maestro/cli/cloud/CloudInteractor.kt index b64255f4c0..5bd16019f3 100644 --- a/maestro-cli/src/main/java/maestro/cli/cloud/CloudInteractor.kt +++ b/maestro-cli/src/main/java/maestro/cli/cloud/CloudInteractor.kt @@ -9,7 +9,7 @@ import maestro.cli.api.RobinUploadResponse import maestro.cli.api.UploadStatus import maestro.cli.auth.Auth import maestro.cli.device.Platform -import maestro.cli.insights.FlowFiles +import maestro.cli.insights.AnalysisDebugFiles import maestro.cli.model.FlowStatus import maestro.cli.model.RunningFlow import maestro.cli.model.RunningFlows @@ -498,7 +498,7 @@ class CloudInteractor( fun analyze( apiKey: String?, - flowFiles: List, + debugFiles: AnalysisDebugFiles, debugOutputPath: Path, ): Int { val authToken = getAuthToken(apiKey) @@ -506,7 +506,7 @@ class CloudInteractor( PrintUtils.info("\n\uD83D\uDD0E Analyzing Flow(s)...") try { - val response = client.analyze(authToken, flowFiles) + val response = client.analyze(authToken, debugFiles) if (response.htmlReport.isNullOrEmpty()) { PrintUtils.info(response.output) @@ -528,5 +528,4 @@ class CloudInteractor( return 1 } } - } diff --git a/maestro-cli/src/main/java/maestro/cli/insights/TestAnalysisManager.kt b/maestro-cli/src/main/java/maestro/cli/insights/TestAnalysisManager.kt index 2bd1d05f37..d14e53819b 100644 --- a/maestro-cli/src/main/java/maestro/cli/insights/TestAnalysisManager.kt +++ b/maestro-cli/src/main/java/maestro/cli/insights/TestAnalysisManager.kt @@ -18,9 +18,20 @@ import kotlin.io.path.exists import kotlin.io.path.readText import kotlin.io.path.writeText -data class FlowFiles( - val imageFiles: List>, - val textFiles: List> +data class AnalysisScreenshot ( + val data: ByteArray, + val path: Path, +) + +data class AnalysisLog ( + val data: ByteArray, + val path: Path, +) + +data class AnalysisDebugFiles( + val screenshots: List, + val logs: List, + val commands: List, ) class TestAnalysisManager(private val apiUrl: String, private val apiKey: String?) { @@ -29,61 +40,60 @@ class TestAnalysisManager(private val apiUrl: String, private val apiKey: String } fun runAnalysis(debugOutputPath: Path): Int { - val flowFiles = processFilesByFlowName(debugOutputPath) - if (flowFiles.isEmpty()) { + val debugFiles = processDebugFiles(debugOutputPath) + if (debugFiles == null) { PrintUtils.warn("No screenshots or debug artifacts found for analysis.") return 0; } return CloudInteractor(apiclient).analyze( apiKey = apiKey, - flowFiles = flowFiles, + debugFiles = debugFiles, debugOutputPath = debugOutputPath ) } - private fun processFilesByFlowName(outputPath: Path): List { + private fun processDebugFiles(outputPath: Path): AnalysisDebugFiles? { val files = Files.walk(outputPath) .filter(Files::isRegularFile) .collect(Collectors.toList()) - return if (files.isNotEmpty()) { - val (imageFiles, textFiles) = getDebugFiles(files) - listOf( - FlowFiles( - imageFiles = imageFiles, - textFiles = textFiles - ) - ) - } else { - emptyList() + if (files.isEmpty()) { + return null } + + return getDebugFiles(files) } - private fun getDebugFiles(files: List): Pair>, List>> { - val imageFiles = mutableListOf>() - val textFiles = mutableListOf>() + private fun getDebugFiles(files: List): AnalysisDebugFiles { + val logs = mutableListOf() + val commands = mutableListOf() + val screenshots = mutableListOf() - files.forEach { filePath -> - val content = Files.readAllBytes(filePath) - val fileName = filePath.fileName.toString().lowercase() + files.forEach { path -> + val data = Files.readAllBytes(path) + val fileName = path.fileName.toString().lowercase() when { fileName.endsWith(".png") || fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") -> { - imageFiles.add(content to filePath) + screenshots.add(AnalysisScreenshot(data = data, path = path)) } fileName.startsWith("commands") -> { - textFiles.add(content to filePath) + commands.add(AnalysisLog(data = data, path = path)) } fileName == "maestro.log" -> { - textFiles.add(content to filePath) + logs.add(AnalysisLog(data = data, path = path)) } } } - return Pair(imageFiles, textFiles) + return AnalysisDebugFiles( + logs = logs, + commands = commands, + screenshots = screenshots, + ) } /**