feat(shorebird_cli): shorebird release uploads artifacts for all arches (#265)
This commit is contained in:
@@ -202,32 +202,30 @@ shorebird release
|
||||
**Sample**
|
||||
|
||||
```
|
||||
shorebird release
|
||||
✓ Building release (17.9s)
|
||||
✓ Fetching apps (0.1s)
|
||||
$ shorebird release
|
||||
✓ Building release (5.1s)
|
||||
✓ Fetching apps (0.2s)
|
||||
|
||||
What is the version of this release? (0.1.0) 0.1.0
|
||||
What is the version of this release? (1.0.0) 1.0.0
|
||||
|
||||
🚀 Ready to create a new release!
|
||||
|
||||
📱 App: My App (61fc9c16-3c4a-4825-a155-9765993614aa)
|
||||
📦 Release Version: 0.1.0
|
||||
⚙️ Architecture: aarch64
|
||||
🕹️ Platform: android
|
||||
#️⃣ Hash: cfe26dddf8aff17131042f9dfad409c83eb130c5a9f2fd6f77325b2388062265
|
||||
|
||||
Your next step is to upload the release artifact to the Play Store.
|
||||
./build/app/outputs/bundle/release/app-release.aab
|
||||
|
||||
See the following link for more information:
|
||||
https://support.google.com/googleplay/android-developer/answer/9859152?hl=en
|
||||
📱 App: My App (30370f27-dbf1-4673-8b20-fb096e38dffa)
|
||||
📦 Release Version: 1.0.0
|
||||
🕹️ Platform: android (arm64, arm32, x86)
|
||||
|
||||
Would you like to continue? (y/N) Yes
|
||||
✓ Fetching releases (55ms)
|
||||
✓ Creating release (45ms)
|
||||
✓ Creating artifact (1.8s)
|
||||
✓ Creating artifacts (4.6s)
|
||||
|
||||
✅ Published Release!
|
||||
|
||||
Your next step is to upload the app bundle to the Play Store.
|
||||
./build/app/outputs/bundle/release/app-release.aab
|
||||
|
||||
See the following link for more information:
|
||||
https://support.google.com/googleplay/android-developer/answer/9859152?hl=en
|
||||
```
|
||||
|
||||
### Patch
|
||||
|
||||
@@ -41,13 +41,6 @@ class ReleaseCommand extends ShorebirdCommand
|
||||
allowed: ['android'],
|
||||
allowedHelp: {'android': 'The Android platform.'},
|
||||
defaultsTo: 'android',
|
||||
)
|
||||
..addOption(
|
||||
'arch',
|
||||
help: 'The architecture of the release (e.g. "aarch64").',
|
||||
allowed: ['aarch64'],
|
||||
allowedHelp: {'aarch64': 'The 64-bit ARM architecture.'},
|
||||
defaultsTo: 'aarch64',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -88,27 +81,6 @@ make smaller updates to your app.
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final artifactPath = p.join(
|
||||
Directory.current.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
|
||||
final artifact = File(artifactPath);
|
||||
|
||||
if (!artifact.existsSync()) {
|
||||
logger.err('Artifact not found: "${artifact.path}"');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final hash = _hashFn(await artifact.readAsBytes());
|
||||
final pubspecYaml = getPubspecYaml()!;
|
||||
final shorebirdYaml = getShorebirdYaml()!;
|
||||
final codePushClient = buildCodePushClient(
|
||||
@@ -152,8 +124,11 @@ Did you forget to run "shorebird init"?''',
|
||||
'What is the version of this release?',
|
||||
defaultValue: pubspecVersionString,
|
||||
);
|
||||
final arch = results['arch'] as String;
|
||||
|
||||
final platform = results['platform'] as String;
|
||||
final archNames = ShorebirdBuildMixin.architectures.keys.map(
|
||||
(arch) => arch.name,
|
||||
);
|
||||
|
||||
logger.info('''
|
||||
|
||||
@@ -161,9 +136,7 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to create a new release!'))}
|
||||
|
||||
📱 App: ${lightCyan.wrap(app.displayName)} ${lightCyan.wrap('(${app.id})')}
|
||||
📦 Release Version: ${lightCyan.wrap(releaseVersion)}
|
||||
⚙️ Architecture: ${lightCyan.wrap(arch)}
|
||||
🕹️ Platform: ${lightCyan.wrap(platform)}
|
||||
#️⃣ Hash: ${lightCyan.wrap(hash)}
|
||||
🕹️ Platform: ${lightCyan.wrap(platform)} ${lightCyan.wrap('(${archNames.join(', ')})')}
|
||||
''');
|
||||
|
||||
final confirm = logger.confirm('Would you like to continue?');
|
||||
@@ -198,26 +171,44 @@ ${styleBold.wrap(lightGreen.wrap('🚀 Ready to create a new release!'))}
|
||||
}
|
||||
}
|
||||
|
||||
final createArtifactProgress = logger.progress('Creating artifact');
|
||||
try {
|
||||
await codePushClient.createReleaseArtifact(
|
||||
releaseId: release.id,
|
||||
artifactPath: artifact.path,
|
||||
arch: arch,
|
||||
platform: platform,
|
||||
hash: hash,
|
||||
final createArtifactProgress = logger.progress('Creating artifacts');
|
||||
for (final archMetadata in ShorebirdBuildMixin.architectures.values) {
|
||||
final artifactPath = p.join(
|
||||
Directory.current.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
archMetadata.path,
|
||||
'libapp.so',
|
||||
);
|
||||
createArtifactProgress.complete();
|
||||
} catch (error) {
|
||||
createArtifactProgress.fail('$error');
|
||||
return ExitCode.software.code;
|
||||
final artifact = File(artifactPath);
|
||||
final hash = _hashFn(await artifact.readAsBytes());
|
||||
|
||||
try {
|
||||
await codePushClient.createReleaseArtifact(
|
||||
releaseId: release.id,
|
||||
artifactPath: artifact.path,
|
||||
arch: archMetadata.arch,
|
||||
platform: platform,
|
||||
hash: hash,
|
||||
);
|
||||
} catch (error) {
|
||||
createArtifactProgress.fail('$error');
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
}
|
||||
|
||||
createArtifactProgress.complete();
|
||||
|
||||
logger
|
||||
..success('\n✅ Published Release!')
|
||||
..info('''
|
||||
|
||||
Your next step is to upload the release artifact to the Play Store.
|
||||
Your next step is to upload the app bundle to the Play Store.
|
||||
${lightCyan.wrap("./build/app/outputs/bundle/release/app-release.aab")}
|
||||
|
||||
See the following link for more information:
|
||||
|
||||
@@ -3,7 +3,36 @@ import 'dart:io';
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
|
||||
enum Arch {
|
||||
arm64,
|
||||
arm32,
|
||||
x86,
|
||||
}
|
||||
|
||||
class ArchMetadata {
|
||||
const ArchMetadata({required this.path, required this.arch});
|
||||
|
||||
final String path;
|
||||
final String arch;
|
||||
}
|
||||
|
||||
mixin ShorebirdBuildMixin on ShorebirdCommand {
|
||||
// TODO(felangel): extend to other platforms.
|
||||
static const architectures = <Arch, ArchMetadata>{
|
||||
Arch.arm64: ArchMetadata(
|
||||
path: 'arm64-v8a',
|
||||
arch: 'aarch64',
|
||||
),
|
||||
Arch.arm32: ArchMetadata(
|
||||
path: 'armeabi-v7a',
|
||||
arch: 'arm',
|
||||
),
|
||||
Arch.x86: ArchMetadata(
|
||||
path: 'x86_64',
|
||||
arch: 'x86_64',
|
||||
),
|
||||
};
|
||||
|
||||
Future<void> buildRelease() async {
|
||||
const executable = 'flutter';
|
||||
final arguments = [
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:path/path.dart' as p;
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/commands/commands.dart';
|
||||
import 'package:shorebird_cli/src/config/config.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:test/test.dart';
|
||||
@@ -86,6 +87,24 @@ flutter:
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
void setUpTempArtifacts(Directory dir) {
|
||||
for (final archMetadata in ShorebirdBuildMixin.architectures.values) {
|
||||
final artifactPath = p.join(
|
||||
dir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
archMetadata.path,
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
argResults = _MockArgResults();
|
||||
applicationConfigHome = Directory.systemTemp.createTempSync();
|
||||
@@ -192,36 +211,12 @@ flutter:
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
});
|
||||
|
||||
test('throws software error when artifact is not found (default).',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
verify(
|
||||
() => logger.err(any(that: contains('Artifact not found:'))),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('throws error when fetching apps fails.', () async {
|
||||
const error = 'something went wrong';
|
||||
when(() => codePushClient.getApps()).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
@@ -236,19 +231,7 @@ flutter:
|
||||
).thenReturn(appDisplayName);
|
||||
when(() => codePushClient.getApps()).thenAnswer((_) async => []);
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
@@ -269,19 +252,7 @@ Did you forget to run "shorebird init"?''',
|
||||
() => logger.prompt(any(), defaultValue: any(named: 'defaultValue')),
|
||||
).thenReturn(appDisplayName);
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
@@ -296,19 +267,7 @@ Did you forget to run "shorebird init"?''',
|
||||
() => codePushClient.getReleases(appId: any(named: 'appId')),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
@@ -330,19 +289,7 @@ Did you forget to run "shorebird init"?''',
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
@@ -366,19 +313,7 @@ Did you forget to run "shorebird init"?''',
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
@@ -389,19 +324,7 @@ Did you forget to run "shorebird init"?''',
|
||||
|
||||
test('succeeds when release is successful', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
@@ -425,19 +348,7 @@ Did you forget to run "shorebird init"?''',
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
'stripped_native_libs',
|
||||
'release',
|
||||
'out',
|
||||
'lib',
|
||||
'arm64-v8a',
|
||||
'libapp.so',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
|
||||
Reference in New Issue
Block a user