Skip to content

Commit fbb9e09

Browse files
committed
feat(package_info_plus): recognize tool-provided version defines as fallbacks
PackageInfoEnvironment now resolves the web version from, in order: PACKAGE_INFO_PLUS_VERSION (explicit), FLUTTER_BUILD_NAME (flutter/flutter#187935, injected by flutter_tools like FLUTTER_APP_FLAVOR), and dart.package.version (dart-lang/sdk#38855). Once either upstream proposal lands, apps need no configuration at all.
1 parent 13e02bd commit fbb9e09

3 files changed

Lines changed: 68 additions & 3 deletions

File tree

packages/package_info_plus/package_info_plus/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ Behaviour per platform:
162162
- **All other platforms** — delegates to `PackageInfo.fromPlatform()`, which reads the installed
163163
binary and is already reliable. The defines are not required there.
164164

165+
The accessor also recognizes tool-provided defines as fallbacks, so apps need no configuration at
166+
all once their build front-end injects the version itself: `FLUTTER_BUILD_NAME` /
167+
`FLUTTER_BUILD_NUMBER` (proposed in [flutter/flutter#187935](https://github.com/flutter/flutter/pull/187935))
168+
and `dart.package.version` ([dart-lang/sdk#38855](https://github.com/dart-lang/sdk/issues/38855)).
169+
The explicit `PACKAGE_INFO_PLUS_*` defines take precedence over both.
170+
165171
`PackageInfo.fromPlatform()` is unchanged; this accessor lives in a separate library that you import
166172
only when you opt in, so existing builds are unaffected.
167173

packages/package_info_plus/package_info_plus/lib/package_info_plus_environment.dart

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@ const _buildNumber = String.fromEnvironment('PACKAGE_INFO_PLUS_BUILD_NUMBER');
1717
const _appName = String.fromEnvironment('PACKAGE_INFO_PLUS_APP_NAME');
1818
const _packageName = String.fromEnvironment('PACKAGE_INFO_PLUS_PACKAGE_NAME');
1919

20+
/// Tool-provided fallbacks, recognized so that apps need no configuration at
21+
/// all once their build front-end injects the version itself:
22+
///
23+
/// * `FLUTTER_BUILD_NAME` / `FLUTTER_BUILD_NUMBER` — proposed in
24+
/// flutter/flutter#187935 (injected by flutter_tools from the pubspec
25+
/// `version`, like `FLUTTER_APP_FLAVOR` already is).
26+
/// * `dart.package.version` — companion proposal for the `dart` CLI
27+
/// (dart-lang/sdk#38855); carries the verbatim pubspec `version`,
28+
/// including any `+buildNumber` suffix.
29+
///
30+
/// The explicit `PACKAGE_INFO_PLUS_*` defines take precedence over both.
31+
const _flutterBuildName = String.fromEnvironment('FLUTTER_BUILD_NAME');
32+
const _flutterBuildNumber = String.fromEnvironment('FLUTTER_BUILD_NUMBER');
33+
const _dartPackageVersion = String.fromEnvironment('dart.package.version');
34+
2035
/// Holds the compile-time package info and enforces, at compile time, that a
2136
/// version was provided on web builds.
2237
///
@@ -28,7 +43,10 @@ const _packageName = String.fromEnvironment('PACKAGE_INFO_PLUS_PACKAGE_NAME');
2843
class _CompileTimePackageInfo {
2944
const _CompileTimePackageInfo()
3045
: assert(
31-
!kIsWeb || _version != '',
46+
!kIsWeb ||
47+
_version != '' ||
48+
_flutterBuildName != '' ||
49+
_dartPackageVersion != '',
3250
'PACKAGE_INFO_PLUS_VERSION must be provided via --dart-define on web '
3351
'builds. On the web there is no reliable runtime source for the '
3452
'version of the *running* bundle (version.json is fetched from the '
@@ -38,8 +56,21 @@ class _CompileTimePackageInfo {
3856
'_PACKAGE_NAME) to your web build.',
3957
);
4058

41-
String get version => _version;
42-
String get buildNumber => _buildNumber;
59+
String get version {
60+
if (_version != '') return _version;
61+
if (_flutterBuildName != '') return _flutterBuildName;
62+
return _dartPackageVersion.split('+').first;
63+
}
64+
65+
String get buildNumber {
66+
if (_buildNumber != '') return _buildNumber;
67+
if (_flutterBuildNumber != '') return _flutterBuildNumber;
68+
if (_dartPackageVersion.contains('+')) {
69+
return _dartPackageVersion.split('+').last;
70+
}
71+
return '';
72+
}
73+
4374
String get appName => _appName;
4475
String get packageName => _packageName;
4576
}

packages/package_info_plus/package_info_plus/test/package_info_environment_test.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'package:flutter/foundation.dart' show kIsWeb;
56
import 'package:flutter/services.dart';
67
import 'package:flutter_test/flutter_test.dart';
78
import 'package:package_info_plus/package_info_plus_environment.dart';
@@ -41,4 +42,31 @@ void main() {
4142
},
4243
onPlatform: {'browser': const Skip('Web path is compile-time enforced')},
4344
);
45+
46+
// Exercises the tool-provided fallback chain on the web path. Run with:
47+
//
48+
// flutter test test/package_info_environment_test.dart --platform chrome \
49+
// --dart-define=FLUTTER_BUILD_NAME=9.9.9 --dart-define=FLUTTER_BUILD_NUMBER=7
50+
//
51+
// (No PACKAGE_INFO_PLUS_VERSION: the explicit define would take precedence.)
52+
// Note: once flutter/flutter#187935 lands, FLUTTER_BUILD_NAME becomes
53+
// tool-reserved and is injected automatically instead of being passed by hand.
54+
test(
55+
'web path falls back to the tool-provided FLUTTER_BUILD_NAME defines',
56+
() async {
57+
if (!kIsWeb) return;
58+
final info = await PackageInfoEnvironment.packageInfo;
59+
expect(info.version, const String.fromEnvironment('FLUTTER_BUILD_NAME'));
60+
expect(
61+
info.buildNumber,
62+
const String.fromEnvironment('FLUTTER_BUILD_NUMBER'),
63+
);
64+
},
65+
skip:
66+
const bool.hasEnvironment('PACKAGE_INFO_PLUS_VERSION') ||
67+
!const bool.hasEnvironment('FLUTTER_BUILD_NAME')
68+
? 'Requires --dart-define=FLUTTER_BUILD_NAME and no '
69+
'PACKAGE_INFO_PLUS_VERSION (see comment above)'
70+
: false,
71+
);
4472
}

0 commit comments

Comments
 (0)