Skip to content

Commit 2a088c9

Browse files
authored
feat(cli): Support FVM for SDK config (#349)
When `.fvmrc` exists in a project directory, use the tagged FVM SDK instead of the default.
1 parent 907102c commit 2a088c9

File tree

25 files changed

+3571
-5
lines changed

25 files changed

+3571
-5
lines changed

.github/workflows/celest_cli.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ jobs:
4141
# Because many golden tests encode the precise Dart/Flutter SDKs used to generate
4242
# them, these values must be consistently used when running tests locally and in CI.
4343
flutter-version: 3.29.3
44+
# Needed for testing FVM integration and cross-compilation.
45+
- name: Install FVM
46+
run: |
47+
dart pub global activate fvm
48+
dart pub global run fvm:main install 3.32.0-0.2.pre
4449
- name: Setup Libsecret
4550
if: runner.os == 'Linux'
4651
run: tool/setup-ci.sh

apps/cli/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ build/
77

88
tool/debug
99
**/*.dill
10+
**/*.exe
1011
**/*.pkg
1112
vm_service_info.json

apps/cli/fixtures/fixtures_test.dart

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ class TestRunner {
133133

134134
static Future<void> _warmUp(String projectRoot) {
135135
return Isolate.run(() async {
136-
final sdkResult = await const DartSdkFinder().findSdk();
136+
final sdkResult = await DartSdkFinder(
137+
projectRoot: projectRoot,
138+
).findSdk();
137139
Sdk.current = sdkResult.sdk;
138140
return CelestAnalyzer.warmUp(projectRoot);
139141
});
@@ -142,7 +144,17 @@ class TestRunner {
142144
void run() {
143145
group(testName, () {
144146
setUpAll(() async {
145-
final sdkResult = await const DartSdkFinder().findSdk();
147+
if (fileSystem.file(p.join(projectRoot, '.fvmrc')).existsSync()) {
148+
final res = Process.runSync(
149+
'fvm',
150+
['use'],
151+
workingDirectory: projectRoot,
152+
);
153+
expect(res.exitCode, 0, reason: '${res.stdout}\n${res.stderr}');
154+
}
155+
final sdkResult = await DartSdkFinder(
156+
projectRoot: projectRoot,
157+
).findSdk();
146158
Sdk.current = sdkResult.sdk;
147159
await runPub(
148160
exe: Platform.resolvedExecutable,
@@ -394,6 +406,10 @@ class TestRunner {
394406
expect(project, isNotNull);
395407

396408
final frontend = CelestFrontend();
409+
final buildDir = fileSystem.directory(projectPaths.buildDir);
410+
if (buildDir.existsSync()) {
411+
buildDir.deleteSync(recursive: true);
412+
}
397413
final result = await frontend.build(
398414
migrateProject: false,
399415
currentProgress: cliLogger.progress('Building project...'),
@@ -404,7 +420,14 @@ class TestRunner {
404420
final outputDir = projectPaths.buildDir;
405421
final imageName = '$testName-${Random().nextInt(1000000)}';
406422
final dockerBuild = await processManager.run(
407-
['docker', 'build', '-t', imageName, '.'],
423+
[
424+
'docker',
425+
'build',
426+
'-t',
427+
imageName,
428+
if (testName case 'fvm' || 'flutter') '--platform=linux/amd64',
429+
'.',
430+
],
408431
workingDirectory: outputDir,
409432
);
410433
expect(
@@ -427,6 +450,7 @@ class TestRunner {
427450
'--rm',
428451
'-p',
429452
'$openPort:8080',
453+
if (testName case 'fvm' || 'flutter') '--platform=linux/amd64',
430454
for (final database in project!.databases.values)
431455
if (database.config case ast.CelestDatabaseConfig(:final hostname))
432456
'--env=${hostname.name}=file::memory:',
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"flutter": "3.32.0-0.2.pre"
3+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Dart
2+
.dart_tool/
3+
pubspec.lock
4+
5+
# Celest
6+
build/
7+
.env
8+
.env.*
9+
10+
# FVM Version Cache
11+
.fvm/
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"dart.flutterSdkPath": ".fvm/versions/3.32.0-0.2.pre"
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include: package:lints/recommended.yaml
2+
3+
analyzer:
4+
errors:
5+
depend_on_referenced_packages: ignore
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Generated by Celest. This file should not be modified manually, but
2+
// it can be checked into version control.
3+
// ignore_for_file: type=lint, unused_local_variable, unnecessary_cast, unnecessary_import, deprecated_member_use, invalid_use_of_internal_member
4+
5+
library; // ignore_for_file: no_leading_underscores_for_library_prefixes
6+
7+
import 'dart:io';
8+
9+
import 'package:celest_core/_internal.dart' as _$celest;
10+
import 'package:celest_core/celest_core.dart' as _$celest;
11+
import 'package:celest_core/src/util/globals.dart' as _$celest;
12+
import 'package:fvm_client/src/functions.dart';
13+
import 'package:fvm_client/src/serializers.dart';
14+
import 'package:http/http.dart' as _$http_http;
15+
import 'package:native_storage/native_storage.dart'
16+
as _$native_storage_native_storage;
17+
18+
export 'package:celest_backend/src/functions/greeting.dart'
19+
show BadNameException, Person;
20+
21+
final Celest celest = Celest();
22+
23+
enum CelestEnvironment {
24+
local,
25+
production;
26+
27+
Uri get baseUri => switch (this) {
28+
local => _$celest.kIsWeb || !Platform.isAndroid
29+
? Uri.parse('http://localhost:7777')
30+
: Uri.parse('http://10.0.2.2:7777'),
31+
production => Uri.parse('https://example.celest.run'),
32+
};
33+
}
34+
35+
class Celest with _$celest.CelestBase {
36+
var _initialized = false;
37+
38+
late CelestEnvironment _currentEnvironment;
39+
40+
late final _$native_storage_native_storage.NativeStorage nativeStorage =
41+
_$native_storage_native_storage.NativeStorage(scope: 'celest');
42+
43+
@override
44+
late _$http_http.Client httpClient =
45+
_$celest.CelestHttpClient(secureStorage: nativeStorage.secure);
46+
47+
late Uri _baseUri;
48+
49+
final _functions = CelestFunctions();
50+
51+
T _checkInitialized<T>(T Function() value) {
52+
if (!_initialized) {
53+
throw StateError(
54+
'Celest has not been initialized. Make sure to call `celest.init()` at the start of your `main` method.');
55+
}
56+
return value();
57+
}
58+
59+
CelestEnvironment get currentEnvironment =>
60+
_checkInitialized(() => _currentEnvironment);
61+
62+
@override
63+
Uri get baseUri => _checkInitialized(() => _baseUri);
64+
65+
CelestFunctions get functions => _checkInitialized(() => _functions);
66+
67+
void init({
68+
CelestEnvironment environment = CelestEnvironment.local,
69+
_$celest.Serializers? serializers,
70+
}) {
71+
if (_initialized) {
72+
_reset();
73+
}
74+
_currentEnvironment = environment;
75+
_baseUri = environment.baseUri;
76+
initSerializers(serializers: serializers);
77+
_initialized = true;
78+
}
79+
80+
void _reset() {
81+
_initialized = false;
82+
}
83+
}

0 commit comments

Comments
 (0)