fix: only build patch artifacts once if release version is specified and flutter version is not current (#1785)
This commit is contained in:
@@ -112,19 +112,11 @@ If this option is not provided, the version number will be determined from the p
|
||||
final shorebirdYaml = shorebirdEnv.getShorebirdYaml()!;
|
||||
final appId = shorebirdYaml.getAppId(flavor: flavor);
|
||||
final app = await codePushClientWrapper.getApp(appId: appId);
|
||||
|
||||
final originalFlutterRevision = shorebirdEnv.flutterRevision;
|
||||
final buildProgress = logger.progress('Building patch');
|
||||
try {
|
||||
await buildAppBundle(flavor: flavor, target: target);
|
||||
buildProgress.complete();
|
||||
} on ProcessException catch (error) {
|
||||
buildProgress.fail('Failed to build: ${error.message}');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
var hasBuiltWithLatestFlutter = false;
|
||||
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
|
||||
final bundleDirPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
@@ -143,6 +135,17 @@ If this option is not provided, the version number will be determined from the p
|
||||
releaseVersion = argReleaseVersion;
|
||||
} else {
|
||||
logger.detail('No release version provided. Determining from bundle.');
|
||||
final buildProgress = logger.progress('Building patch');
|
||||
try {
|
||||
await buildAppBundle(flavor: flavor, target: target);
|
||||
buildProgress.complete();
|
||||
} on ProcessException catch (error) {
|
||||
buildProgress.fail('Failed to build: ${error.message}');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
hasBuiltWithLatestFlutter = true;
|
||||
|
||||
final detectReleaseVersionProgress = logger.progress(
|
||||
'Detecting release version',
|
||||
);
|
||||
@@ -200,6 +203,20 @@ Current Flutter Revision: $originalFlutterRevision
|
||||
await shorebirdFlutter.useRevision(revision: originalFlutterRevision);
|
||||
flutterVersionProgress.complete();
|
||||
}
|
||||
} else if (!hasBuiltWithLatestFlutter) {
|
||||
// If we haven't already built the patch with the latest version of
|
||||
// Flutter (i.e., if the release version was provided as an argument and
|
||||
// we didn't need to build the patch to determine the release version),
|
||||
// build it now.
|
||||
final buildProgress = logger.progress('Building patch');
|
||||
try {
|
||||
await buildAppBundle(flavor: flavor, target: target);
|
||||
buildProgress.complete();
|
||||
} on ProcessException catch (error) {
|
||||
buildProgress.fail('Failed to build: ${error.message}');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
hasBuiltWithLatestFlutter = true;
|
||||
}
|
||||
|
||||
final releaseArtifacts = await codePushClientWrapper.getReleaseArtifacts(
|
||||
|
||||
@@ -121,30 +121,11 @@ If this option is not provided, the version number will be determined from the p
|
||||
const releasePlatform = ReleasePlatform.ios;
|
||||
final flavor = results.findOption('flavor', argParser: argParser);
|
||||
final target = results.findOption('target', argParser: argParser);
|
||||
|
||||
final shorebirdYaml = shorebirdEnv.getShorebirdYaml()!;
|
||||
final appId = shorebirdYaml.getAppId(flavor: flavor);
|
||||
final app = await codePushClientWrapper.getApp(appId: appId);
|
||||
var hasBuiltWithLatestFlutter = false;
|
||||
|
||||
try {
|
||||
await _buildPatch(flavor: flavor, target: target);
|
||||
} catch (_) {
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final archivePath = getXcarchiveDirectory()?.path;
|
||||
if (archivePath == null) {
|
||||
logger.err('Unable to find .xcarchive directory');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final plistFile = File(p.join(archivePath, 'Info.plist'));
|
||||
if (!plistFile.existsSync()) {
|
||||
logger.err('No Info.plist file found at ${plistFile.path}.');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final plist = Plist(file: plistFile);
|
||||
final String releaseVersion;
|
||||
final argReleaseVersion = results['release-version'] as String?;
|
||||
if (argReleaseVersion != null) {
|
||||
@@ -153,15 +134,19 @@ If this option is not provided, the version number will be determined from the p
|
||||
} else {
|
||||
logger.detail('No release version provided. Determining from archive.');
|
||||
try {
|
||||
releaseVersion = plist.versionNumber;
|
||||
} catch (error) {
|
||||
logger.err(
|
||||
'Failed to determine release version from ${plistFile.path}: $error',
|
||||
);
|
||||
await _buildPatch(flavor: flavor, target: target);
|
||||
} catch (_) {
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
hasBuiltWithLatestFlutter = true;
|
||||
|
||||
logger.info('Detected release version $releaseVersion');
|
||||
try {
|
||||
releaseVersion = _readVersionFromPlist();
|
||||
logger.info('Detected release version $releaseVersion');
|
||||
} on _ReadVersionException catch (error) {
|
||||
logger.err(error.message);
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
}
|
||||
|
||||
final release = await codePushClientWrapper.getRelease(
|
||||
@@ -207,6 +192,23 @@ Current Flutter Revision: $currentFlutterRevision
|
||||
await shorebirdFlutter.useRevision(revision: currentFlutterRevision);
|
||||
flutterVersionProgress.complete();
|
||||
}
|
||||
} else if (!hasBuiltWithLatestFlutter) {
|
||||
// If we haven't already built the patch with the latest version of
|
||||
// Flutter (i.e., if the release version was provided as an argument and
|
||||
// we didn't need to build the patch to determine the release version),
|
||||
// build it now.
|
||||
try {
|
||||
await _buildPatch(flavor: flavor, target: target);
|
||||
} catch (_) {
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
hasBuiltWithLatestFlutter = true;
|
||||
}
|
||||
|
||||
final archivePath = getXcarchiveDirectory()?.path;
|
||||
if (archivePath == null) {
|
||||
logger.err('Unable to find .xcarchive directory');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final releaseArtifact = await codePushClientWrapper.getReleaseArtifact(
|
||||
@@ -404,6 +406,29 @@ ${summary.join('\n')}
|
||||
'out.vmcode',
|
||||
);
|
||||
|
||||
String _readVersionFromPlist() {
|
||||
final archivePath = getXcarchiveDirectory()?.path;
|
||||
if (archivePath == null) {
|
||||
throw _ReadVersionException('Unable to find .xcarchive directory');
|
||||
}
|
||||
|
||||
final plistFile = File(p.join(archivePath, 'Info.plist'));
|
||||
if (!plistFile.existsSync()) {
|
||||
throw _ReadVersionException(
|
||||
'No Info.plist file found at ${plistFile.path}.',
|
||||
);
|
||||
}
|
||||
|
||||
final plist = Plist(file: plistFile);
|
||||
try {
|
||||
return plist.versionNumber;
|
||||
} catch (error) {
|
||||
throw _ReadVersionException(
|
||||
'Failed to determine release version from ${plistFile.path}: $error',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _buildPatch({
|
||||
required String? flavor,
|
||||
required String? target,
|
||||
@@ -474,3 +499,13 @@ ${summary.join('\n')}
|
||||
return ExitCode.success.code;
|
||||
}
|
||||
}
|
||||
|
||||
/// {@template _ReadVersionException}
|
||||
/// Exception thrown when the release version cannot be determined.
|
||||
/// {@endtemplate}
|
||||
class _ReadVersionException implements Exception {
|
||||
/// {@macro _ReadVersionException}
|
||||
_ReadVersionException(this.message);
|
||||
|
||||
final String message;
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(otherRevision);
|
||||
when(
|
||||
() => shorebirdFlutter.useRevision(revision: any(named: 'revision')),
|
||||
).thenAnswer((invocation) async {
|
||||
).thenAnswer((_) async {
|
||||
// Cause builds to fail after switching flutter versions.
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
@@ -539,6 +539,45 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
verifyNever(() => bundletool.getVersionCode(any()));
|
||||
verifyNever(() => logger.progress('Detecting release version'));
|
||||
});
|
||||
|
||||
test('exits with code 70 if build fails', () async {
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('only builds once if release uses different flutter revision',
|
||||
() async {
|
||||
const otherRevision = 'other-revision';
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(otherRevision);
|
||||
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
|
||||
verify(
|
||||
() => shorebirdFlutter.useRevision(revision: release.flutterRevision),
|
||||
).called(1);
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
'flutter',
|
||||
[
|
||||
'build',
|
||||
'appbundle',
|
||||
'--release',
|
||||
],
|
||||
runInShell: any(named: 'runInShell'),
|
||||
),
|
||||
).called(1);
|
||||
verify(
|
||||
() => shorebirdFlutter.useRevision(revision: otherRevision),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('when release-version option is not provided', () {
|
||||
|
||||
@@ -805,6 +805,65 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('exits with code 70 if xcarchive is not found', () async {
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
Directory(
|
||||
p.join(projectRoot.path, 'build'),
|
||||
).deleteSync(recursive: true);
|
||||
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => logger.err(
|
||||
any(that: contains('Unable to find .xcarchive directory')),
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('exits with code 70 if build fails', () async {
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('only builds once if release uses different flutter revision',
|
||||
() async {
|
||||
const otherRevision = 'other-revision';
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(otherRevision);
|
||||
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
|
||||
verify(
|
||||
() => shorebirdFlutter.useRevision(
|
||||
revision: preLinkerRelease.flutterRevision),
|
||||
).called(1);
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
'flutter',
|
||||
any(
|
||||
that: containsAll([
|
||||
'build',
|
||||
'ipa',
|
||||
'--release',
|
||||
]),
|
||||
),
|
||||
runInShell: any(named: 'runInShell'),
|
||||
),
|
||||
).called(1);
|
||||
verify(
|
||||
() => shorebirdFlutter.useRevision(revision: otherRevision),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('when release-version option is not provided', () {
|
||||
|
||||
Reference in New Issue
Block a user