From c928a1da49a093f9282cd89111134d17fe454b7d Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Wed, 5 Feb 2025 13:10:10 -0600 Subject: [PATCH] feat(shorebird_cli): export `patch-debug.zip` in codemagic (#2853) --- cspell.config.yaml | 1 + .../shorebird_cli/lib/src/platform/apple.dart | 21 ++++++ .../test/src/platform/apple_test.dart | 65 ++++++++++++++++++- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/cspell.config.yaml b/cspell.config.yaml index ad4be560..2df84d45 100644 --- a/cspell.config.yaml +++ b/cspell.config.yaml @@ -24,6 +24,7 @@ words: - canvaskit - carryforward - cipd + - codemagic - codesign - codesigned - codesigning diff --git a/packages/shorebird_cli/lib/src/platform/apple.dart b/packages/shorebird_cli/lib/src/platform/apple.dart index d71b0584..04e43032 100644 --- a/packages/shorebird_cli/lib/src/platform/apple.dart +++ b/packages/shorebird_cli/lib/src/platform/apple.dart @@ -9,6 +9,7 @@ import 'package:shorebird_cli/src/archive/directory_archive.dart'; import 'package:shorebird_cli/src/commands/patch/patcher.dart'; import 'package:shorebird_cli/src/executables/aot_tools.dart'; import 'package:shorebird_cli/src/logging/shorebird_logger.dart'; +import 'package:shorebird_cli/src/platform.dart'; import 'package:shorebird_cli/src/shorebird_artifacts.dart'; import 'package:shorebird_cli/src/shorebird_env.dart'; import 'package:xml/xml.dart'; @@ -226,6 +227,26 @@ class Apple { final debugInfoZip = await dumpDebugInfoDir.zipToTempFile(); debugInfoZip.copySync(p.join('build', Patcher.debugInfoFile.path)); logger.detail('Link debug info saved to ${Patcher.debugInfoFile.path}'); + + // If we're running on codemagic, export the patch-debug.zip artifact. + // https://docs.codemagic.io/knowledge-others/upload-custom-artifacts + final codemagicExportDir = platform.environment['CM_EXPORT_DIR']; + if (codemagicExportDir != null) { + logger.detail( + '''Codemagic environment detected. Exporting ${Patcher.debugInfoFile.path} to $codemagicExportDir''', + ); + try { + debugInfoZip.copySync( + p.join(codemagicExportDir, p.basename(Patcher.debugInfoFile.path)), + ); + } on Exception catch (error) { + logger.detail( + ''' +Failed to export ${Patcher.debugInfoFile.path} to $codemagicExportDir. +$error''', + ); + } + } } try { diff --git a/packages/shorebird_cli/test/src/platform/apple_test.dart b/packages/shorebird_cli/test/src/platform/apple_test.dart index 8c798fe0..76cfefa2 100644 --- a/packages/shorebird_cli/test/src/platform/apple_test.dart +++ b/packages/shorebird_cli/test/src/platform/apple_test.dart @@ -1,12 +1,13 @@ -import 'dart:io'; +import 'dart:io' hide Platform; -import 'package:io/io.dart'; import 'package:mason_logger/mason_logger.dart'; import 'package:mocktail/mocktail.dart'; import 'package:path/path.dart' as p; +import 'package:platform/platform.dart'; import 'package:scoped_deps/scoped_deps.dart'; import 'package:shorebird_cli/src/executables/executables.dart'; import 'package:shorebird_cli/src/logging/logging.dart'; +import 'package:shorebird_cli/src/platform.dart'; import 'package:shorebird_cli/src/platform/platform.dart'; import 'package:shorebird_cli/src/shorebird_artifacts.dart'; import 'package:shorebird_cli/src/shorebird_env.dart'; @@ -26,6 +27,7 @@ void main() { late AotTools aotTools; late Apple apple; late Progress progress; + late Platform platform; late ShorebirdArtifacts shorebirdArtifacts; late ShorebirdLogger logger; late ShorebirdEnv shorebirdEnv; @@ -36,6 +38,7 @@ void main() { values: { aotToolsRef.overrideWith(() => aotTools), loggerRef.overrideWith(() => logger), + platformRef.overrideWith(() => platform), shorebirdArtifactsRef.overrideWith(() => shorebirdArtifacts), shorebirdEnvRef.overrideWith(() => shorebirdEnv), }, @@ -45,12 +48,14 @@ void main() { setUp(() { aotTools = MockAotTools(); apple = Apple(); + platform = MockPlatform(); progress = MockProgress(); logger = MockShorebirdLogger(); shorebirdArtifacts = MockShorebirdArtifacts(); shorebirdEnv = MockShorebirdEnv(); when(() => logger.progress(any())).thenReturn(progress); + when(() => platform.environment).thenReturn({}); }); group(MissingXcodeProjectException, () { @@ -479,6 +484,62 @@ To add macOS, run "flutter create . --platforms macos"''', ), ).called(1); }); + + group('when running in codemagic', () { + late Directory codemagicExportDir; + + setUp(() { + codemagicExportDir = Directory.systemTemp.createTempSync(); + when(() => platform.environment).thenReturn( + {'CM_EXPORT_DIR': codemagicExportDir.path}, + ); + }); + + test('copies debug info to codemagic exports', () async { + final copiedPatchDebugInfo = File( + p.join(codemagicExportDir.path, 'patch-debug.zip'), + ); + expect(copiedPatchDebugInfo.existsSync(), isFalse); + await runWithOverrides( + () => apple.runLinker( + aotOutputFile: aotOutputFile, + kernelFile: File('missing'), + releaseArtifact: File('missing'), + vmCodeFile: File('missing'), + splitDebugInfoArgs: [], + ), + ); + expect(copiedPatchDebugInfo.existsSync(), isTrue); + verify( + () => logger.detail( + any(that: startsWith('Codemagic environment detected.')), + ), + ).called(1); + }); + + test('gracefully handles errors', () async { + when(() => platform.environment).thenReturn( + {'CM_EXPORT_DIR': 'invalid path'}, + ); + await runWithOverrides( + () => apple.runLinker( + aotOutputFile: aotOutputFile, + kernelFile: File('missing'), + releaseArtifact: File('missing'), + vmCodeFile: File('missing'), + splitDebugInfoArgs: [], + ), + ); + + verify( + () => logger.detail( + any( + that: contains('PathNotFoundException: Cannot copy file to'), + ), + ), + ).called(1); + }); + }); }); group('when call to aotTools.link fails', () {