feat(shorebird_cli): add flutter build failure recommendations (#3022)
This commit is contained in:
@@ -67,6 +67,33 @@ extension on String {
|
||||
/// Builds aabs, ipas, and other artifacts produced by `flutter build`.
|
||||
/// @{endtemplate}
|
||||
class ArtifactBuilder {
|
||||
/// A general recommendation when building artifacts fails.
|
||||
static String runVanillaFlutterBuildRecommendation(String buildCommand) => '''
|
||||
|
||||
${styleBold.wrap('💡 Fix Recommendations')}
|
||||
|
||||
• Check that running `flutter build` with the same command-line arguments
|
||||
completes successfully by running the following command:
|
||||
|
||||
${lightCyan.wrap(buildCommand)}
|
||||
|
||||
If the above command fails, then this is *NOT* a Shorebird issue and the
|
||||
the underlying `flutter build` failure must be resolved for Shorebird to
|
||||
build a release.
|
||||
|
||||
• If `flutter build` completes successfully, please ensure that you are
|
||||
providing the desired flutter version to the release command via
|
||||
the `--flutter-version` option. If you do not specify a `--flutter-version`
|
||||
Shorebird will default to the latest stable version of Flutter.
|
||||
We strongly encourage always specifying an explicit Flutter version:
|
||||
|
||||
${lightCyan.wrap('shorebird release <platform> --flutter-version=3.29.0')}
|
||||
|
||||
• If `flutter build` completes successfully and `shorebird release`
|
||||
fails when using the same flutter version, please file an issue:
|
||||
${link(uri: Uri.parse('https://github.com/shorebirdtech/shorebird/issues/new'))}
|
||||
''';
|
||||
|
||||
/// Builds an aab using `flutter build appbundle`. Runs `flutter pub get` with
|
||||
/// the system installation of Flutter to reset
|
||||
/// `.dart_tool/package_config.json` after the build completes or fails.
|
||||
@@ -100,10 +127,15 @@ class ArtifactBuilder {
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build AAB.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -165,10 +197,15 @@ Reason: Exited with code $exitCode.''');
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build APK.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
@@ -222,10 +259,15 @@ Reason: Exited with code $exitCode.''');
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build AAR.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -257,10 +299,15 @@ Reason: Exited with code $exitCode.''');
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build linux app.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -305,10 +352,15 @@ Reason: Exited with code $exitCode.''');
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build macOS app.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
appDillPath = _findAppDill(projectRoot: projectRoot, after: buildStart);
|
||||
@@ -366,10 +418,15 @@ Reason: Exited with code $exitCode.''');
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build IPA.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
appDillPath = _findAppDill(projectRoot: projectRoot, after: buildStart);
|
||||
@@ -420,11 +477,15 @@ Reason: Exited with code $exitCode.''');
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build iOS framework.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.
|
||||
''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
appDillPath = _findAppDill(projectRoot: projectRoot, after: buildStart);
|
||||
@@ -535,10 +596,15 @@ Either run `flutter pub get` manually, or follow the steps in ${cannotRunInVSCod
|
||||
);
|
||||
|
||||
if (exitCode != ExitCode.success.code) {
|
||||
throw ArtifactBuildException('''
|
||||
throw ArtifactBuildException(
|
||||
'''
|
||||
Failed to build windows app.
|
||||
Command: $executable ${arguments.join(' ')}
|
||||
Reason: Exited with code $exitCode.''');
|
||||
Reason: Exited with code $exitCode.''',
|
||||
fixRecommendation: runVanillaFlutterBuildRecommendation(
|
||||
[executable, ...arguments].join(' '),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -342,7 +342,17 @@ Either run `flutter pub get` manually, or follow the steps in ${cannotRunInVSCod
|
||||
verifyCorrectFlutterPubGet(
|
||||
() => expectLater(
|
||||
() => runWithOverrides(() => builder.buildAppBundle()),
|
||||
throwsA(isA<ArtifactBuildException>()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -534,7 +544,17 @@ Either run `flutter pub get` manually, or follow the steps in ${cannotRunInVSCod
|
||||
verifyCorrectFlutterPubGet(
|
||||
() => expectLater(
|
||||
() => runWithOverrides(() => builder.buildApk()),
|
||||
throwsA(isA<ArtifactBuildException>()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -651,7 +671,17 @@ Either run `flutter pub get` manually, or follow the steps in ${cannotRunInVSCod
|
||||
() async => runWithOverrides(
|
||||
() => builder.buildAar(buildNumber: buildNumber),
|
||||
),
|
||||
throwsA(isA<ArtifactBuildException>()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -700,14 +730,24 @@ Either run `flutter pub get` manually, or follow the steps in ${cannotRunInVSCod
|
||||
expect(
|
||||
() => runWithOverrides(() => builder.buildLinuxApp()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.message,
|
||||
'message',
|
||||
equals('''
|
||||
isA<ArtifactBuildException>()
|
||||
.having(
|
||||
(e) => e.message,
|
||||
'message',
|
||||
equals('''
|
||||
Failed to build linux app.
|
||||
Command: flutter build linux --release
|
||||
Reason: Exited with code 70.'''),
|
||||
),
|
||||
)
|
||||
.having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -890,7 +930,17 @@ Reason: Exited with code 70.'''),
|
||||
test('throws ArtifactBuildException', () {
|
||||
expect(
|
||||
() => runWithOverrides(() => builder.buildMacos(codesign: false)),
|
||||
throwsA(isA<ArtifactBuildException>()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1067,7 +1117,17 @@ Reason: Exited with code 70.'''),
|
||||
test('throws ArtifactBuildException', () {
|
||||
expect(
|
||||
() => runWithOverrides(() => builder.buildIpa(codesign: false)),
|
||||
throwsA(isA<ArtifactBuildException>()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1126,7 +1186,17 @@ Reason: Exited with code 70.'''),
|
||||
() async => expectLater(
|
||||
() async =>
|
||||
runWithOverrides(() => builder.buildIpa(codesign: false)),
|
||||
throwsA(isA<ArtifactBuildException>()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -1271,7 +1341,17 @@ Reason: Exited with code 70.'''),
|
||||
verifyCorrectFlutterPubGet(
|
||||
() => expectLater(
|
||||
() => runWithOverrides(builder.buildIosFramework),
|
||||
throwsA(isA<ArtifactBuildException>()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -1391,14 +1471,24 @@ Reason: Exited with code 70.'''),
|
||||
expect(
|
||||
() => runWithOverrides(() => builder.buildWindowsApp()),
|
||||
throwsA(
|
||||
isA<ArtifactBuildException>().having(
|
||||
(e) => e.message,
|
||||
'message',
|
||||
equals('''
|
||||
isA<ArtifactBuildException>()
|
||||
.having(
|
||||
(e) => e.message,
|
||||
'message',
|
||||
equals('''
|
||||
Failed to build windows app.
|
||||
Command: flutter build windows --release
|
||||
Reason: Exited with code 70.'''),
|
||||
),
|
||||
)
|
||||
.having(
|
||||
(e) => e.fixRecommendation,
|
||||
'recommendation',
|
||||
startsWith(
|
||||
ArtifactBuilder.runVanillaFlutterBuildRecommendation(
|
||||
'',
|
||||
).substring(0, 80),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user