Skip to content

[native_assets_cli] Version protocol between Dart SDK and packages #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions pkgs/native_assets_cli/lib/src/model/build_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'package:cli_config/cli_config.dart';
import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';

import '../utils/map.dart';
import '../utils/yaml.dart';
Expand Down Expand Up @@ -105,6 +106,16 @@ class BuildConfig {

BuildConfig._();

/// The version of [BuildConfig].
///
/// This class is used in the protocol between the Dart and Flutter SDKs
/// and packages through `build.dart` invocations.
///
/// If we ever were to make breaking changes, it would be useful to give
/// proper error messages rather than just fail to parse the YAML
/// representation in the protocol.
static Version version = Version(1, 0, 0);

factory BuildConfig.fromConfig(Config config) {
final result = BuildConfig._();
final configExceptions = <Object>[];
Expand Down Expand Up @@ -159,11 +170,29 @@ class BuildConfig {
static const toolchainEnvScriptArgsConfigKey =
'toolchain_env_script_arguments';
static const dependencyMetadataConfigKey = 'dependency_metadata';
static const _versionKey = 'version';

List<void Function(Config)> _readFieldsFromConfig() {
var targetSet = false;
var ccSet = false;
return [
(config) {
final configVersion = Version.parse(config.string('version'));
if (configVersion.major > version.major) {
throw FormatException(
'The config version $configVersion is newer than this '
'package:native_assets_cli config version $version, '
'please update native_assets_cli.',
);
}
if (configVersion.major < version.major) {
throw FormatException(
'The config version $configVersion is newer than this '
'package:native_assets_cli config version $version, '
'please update the Dart or Flutter SDK.',
);
}
},
(config) => _config = config,
(config) => _outDir = config.path(outDirConfigKey),
(config) => _packageRoot = config.path(packageRootConfigKey),
Expand Down Expand Up @@ -255,6 +284,7 @@ class BuildConfig {
for (final entry in _dependencyMetadata!.entries)
entry.key: entry.value.toYaml(),
},
_versionKey: version.toString(),
}.sortOnKey();

String toYamlString() => yamlEncode(toYaml());
Expand Down
43 changes: 37 additions & 6 deletions pkgs/native_assets_cli/lib/src/model/build_output.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:io';

import 'package:collection/collection.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';

import '../utils/datetime.dart';
Expand Down Expand Up @@ -39,29 +40,59 @@ class BuildOutput {
static const _dependenciesKey = 'dependencies';
static const _metadataKey = 'metadata';
static const _timestampKey = 'timestamp';
static const _versionKey = 'version';

factory BuildOutput.fromYamlString(String yaml) {
final yamlObject = loadYaml(yaml) as YamlMap;
return BuildOutput.fromYaml(yamlObject);
}

factory BuildOutput.fromYaml(YamlMap yamlMap) => BuildOutput(
timestamp: DateTime.parse(yamlMap[_timestampKey] as String),
assets: Asset.listFromYamlList(yamlMap[_assetsKey] as YamlList),
dependencies:
Dependencies.fromYaml(yamlMap[_dependenciesKey] as YamlList?),
metadata: Metadata.fromYaml(yamlMap[_metadataKey] as YamlMap?),
factory BuildOutput.fromYaml(YamlMap yamlMap) {
final outputVersion = Version.parse(yamlMap['version'] as String);
if (outputVersion.major > version.major) {
throw FormatException(
'The output version $outputVersion is newer than the '
'package:native_assets_cli config version $version in Dart or Flutter, '
'please update the Dart or Flutter SDK.',
);
}
if (outputVersion.major < version.major) {
throw FormatException(
'The output version $outputVersion is newer than this '
'package:native_assets_cli config version $version in Dart or Flutter, '
'please update native_assets_cli.',
);
}

return BuildOutput(
timestamp: DateTime.parse(yamlMap[_timestampKey] as String),
assets: Asset.listFromYamlList(yamlMap[_assetsKey] as YamlList),
dependencies:
Dependencies.fromYaml(yamlMap[_dependenciesKey] as YamlList?),
metadata: Metadata.fromYaml(yamlMap[_metadataKey] as YamlMap?),
);
}

Map<String, Object> toYaml() => {
_timestampKey: timestamp.toString(),
_assetsKey: assets.toYaml(),
_dependenciesKey: dependencies.toYaml(),
_metadataKey: metadata.toYaml(),
_versionKey: version.toString(),
}..sortOnKey();

String toYamlString() => yamlEncode(toYaml());

/// The version of [BuildOutput].
///
/// This class is used in the protocol between the Dart and Flutter SDKs
/// and packages through `build.dart` invocations.
///
/// If we ever were to make breaking changes, it would be useful to give
/// proper error messages rather than just fail to parse the YAML
/// representation in the protocol.
static Version version = Version(1, 0, 0);

static const fileName = 'build_output.yaml';

/// Writes the YAML file from [outDir]/[fileName].
Expand Down
1 change: 1 addition & 0 deletions pkgs/native_assets_cli/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ environment:
dependencies:
cli_config: ^0.1.1
collection: ^1.17.1
pub_semver: ^2.1.3
yaml: ^3.1.1
yaml_edit: ^2.1.0

Expand Down
1 change: 1 addition & 0 deletions pkgs/native_assets_cli/test/example/native_add_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ void main() async {
if (toolchainEnvScriptArgs != null)
'-D${BuildConfig.toolchainEnvScriptArgsConfigKey}='
'${toolchainEnvScriptArgs!.join(' ')}',
'-Dversion=${BuildConfig.version}',
],
workingDirectory: testPackageUri.toFilePath(),
);
Expand Down
18 changes: 17 additions & 1 deletion pkgs/native_assets_cli/test/model/build_config_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ void main() async {
'package_root': tempUri.resolve('packageRoot/').toFilePath(),
'target': 'android_arm64',
'link_mode_preference': 'prefer-static',
'version': BuildOutput.version.toString(),
});

final fromConfig = BuildConfig.fromConfig(config);
Expand Down Expand Up @@ -175,7 +176,8 @@ link_mode_preference: prefer-static
out_dir: ${outDir.toFilePath()}
package_root: ${tempUri.toFilePath()}
target: ios_arm64
target_ios_sdk: iphoneos''';
target_ios_sdk: iphoneos
version: ${BuildConfig.version}''';
expect(yamlString, equals(expectedYamlString));

final buildConfig2 = BuildConfig.fromConfig(
Expand Down Expand Up @@ -298,4 +300,18 @@ target_ios_sdk: iphoneos''';
final fromConfig = BuildConfig.fromConfig(config);
expect(fromConfig, equals(buildConfig1));
});

for (final version in ['9001.0.0', '0.0.1']) {
test('BuildConfig version $version', () {
final outDir = tempUri.resolve('out1/');
final config = Config(fileParsed: {
'link_mode_preference': 'prefer-static',
'out_dir': outDir.toFilePath(),
'package_root': tempUri.toFilePath(),
'target': 'linux_x64',
'version': version,
});
expect(() => BuildConfig.fromConfig(config), throwsFormatException);
});
}
}
14 changes: 12 additions & 2 deletions pkgs/native_assets_cli/test/model/build_output_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void main() {
}),
);

const yamlEncoding = '''timestamp: 2022-11-10 13:25:01.000
final yamlEncoding = '''timestamp: 2022-11-10 13:25:01.000
assets:
- name: foo
link_mode: dynamic
Expand All @@ -59,7 +59,8 @@ assets:
dependencies:
- path/to/file.ext
metadata:
key: value''';
key: value
version: ${BuildOutput.version}''';

test('built info yaml', () {
final yaml = buildOutput.toYamlString().replaceAll('\\', '/');
Expand Down Expand Up @@ -94,4 +95,13 @@ metadata:
);
expect(buildOutput3.timestamp, DateTime.parse('2022-11-10 13:25:01.000'));
});

for (final version in ['9001.0.0', '0.0.1']) {
test('BuildOutput version $version', () {
expect(
() => BuildOutput.fromYamlString('version: $version'),
throwsFormatException,
);
});
}
}