Skip to content

Commit

Permalink
Merge branch 'main' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
russellwheatley committed Apr 18, 2024
2 parents c3d3a98 + 66a1d89 commit f04e23e
Show file tree
Hide file tree
Showing 17 changed files with 295 additions and 148 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## 2024-04-10

### Changes

---

Packages with breaking changes:

- There are no breaking changes in this release.

Packages with other changes:

- [`flutterfire_cli` - `v1.0.0`](#flutterfire_cli---v100)

---

#### `flutterfire_cli` - `v1.0.0`

- Moved flutterfire_cli package from dev release to general release.


## 2024-03-26

### Changes
Expand Down
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,17 @@ flutterfire --help

## Install

The general release is available for installation by running the following command:
To install, run the following command:

```bash
dart pub global activate flutterfire_cli
```

We recommend installing the dev version which has been in use for some time, has become fairly stable and will soon be part of the general release:

```bash
dart pub global activate flutterfire_cli 0.3.0-dev.21 --overwrite
```

- FlutterFire CLI requires the Firebase CLI (`firebase-tools`) to be installed on your local machine, [follow these instructions](https://firebase.google.com/docs/cli) for installation.
- If you're running on a windows machine, we highly recommend you install via npm (i.e. `npm install -g firebase-tools`). The standalone
`firebase-tools` version can cause problems which you can read about [here](https://github.com/invertase/flutterfire_cli/issues/55#issuecomment-1316201478).

## Documentation for `v0.3.0-dev.21`
## Documentation for `v1.0.0`

### Default setup

Expand Down
4 changes: 4 additions & 0 deletions packages/flutterfire_cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.0

- Moved flutterfire_cli package from dev release to general release.

## 0.3.0-dev.21

- **FIX**(android): ensure app/build.gradle only writes google services dependency once ([#269](https://github.com/invertase/flutterfire_cli/issues/269)). ([f195b16f](https://github.com/invertase/flutterfire_cli/commit/f195b16f0a3131288d4fccf3e1140093a2d68708))
Expand Down
81 changes: 30 additions & 51 deletions packages/flutterfire_cli/lib/src/commands/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,8 @@ class ConfigCommand extends FlutterFireCommand {
final value = argResults!['android-package-name'] as String?;
final deprecatedValue = argResults!['android-app-id'] as String?;

// TODO validate packagename is valid if provided.

if (value != null) {
validateAndroidPackageName(value);
return value;
}
if (deprecatedValue != null) {
Expand All @@ -290,26 +289,17 @@ class ConfigCommand extends FlutterFireCommand {
return deprecatedValue;
}

if (isCI) {
throw FirebaseCommandException(
'configure',
'Please provide value for android-package-name.',
);
}
return null;
}

String? get iosBundleId {
final value = argResults!['ios-bundle-id'] as String?;
// TODO validate bundleId is valid if provided
if (value != null) return value;

if (isCI) {
throw FirebaseCommandException(
'configure',
'Please provide value for ios-bundle-id.',
);
if (value != null) {
validateAppBundleId(value, kIos);
return value;
}

return null;
}

Expand All @@ -318,12 +308,6 @@ class ConfigCommand extends FlutterFireCommand {

if (value != null) return value;

if (isCI) {
throw FirebaseCommandException(
'configure',
'Please provide value for web-app-id.',
);
}
return null;
}

Expand All @@ -332,26 +316,17 @@ class ConfigCommand extends FlutterFireCommand {

if (value != null) return value;

if (isCI) {
throw FirebaseCommandException(
'configure',
'Please provide value for $kWindowsAppIdFlag.',
);
}
return null;
}

String? get macosBundleId {
final value = argResults!['macos-bundle-id'] as String?;
// TODO validate bundleId is valid if provided
if (value != null) return value;

if (isCI) {
throw FirebaseCommandException(
'configure',
'Please provide value for macos-bundle-id.',
);
if (value != null) {
validateAppBundleId(value, kMacos);
return value;
}

return null;
}

Expand All @@ -369,8 +344,11 @@ class ConfigCommand extends FlutterFireCommand {
return argResults!['out'] as String;
}

bool? get overwriteFirebaseOptions {
return argResults!['overwrite-firebase-options'] as bool?;
bool get overwriteFirebaseOptions {
if (argResults!['overwrite-firebase-options'] == null) {
return false;
}
return argResults!['overwrite-firebase-options'] as bool;
}

// Still needed for local CI testing
Expand Down Expand Up @@ -597,9 +575,17 @@ class ConfigCommand extends FlutterFireCommand {
return;
}

// 1. Validate and prompt first
// 1. Select Firebase project and platforms
final selectedFirebaseProject = await _selectFirebaseProject();
final selectedPlatforms = _selectPlatforms();

if (!selectedPlatforms.containsValue(true)) {
throw NoFlutterPlatformsSelectedException();
}

// 2. Validate and prompt for platform specific inputs
if (Platform.isMacOS) {
if (flutterApp!.ios) {
if (flutterApp!.ios && selectedPlatforms[kIos]!) {
iosInputs = await appleValidation(
platform: kIos,
flutterAppPath: flutterApp!.package.path,
Expand All @@ -608,7 +594,7 @@ class ConfigCommand extends FlutterFireCommand {
buildConfiguration: iosBuildConfiguration,
);
}
if (flutterApp!.macos) {
if (flutterApp!.macos && selectedPlatforms[kMacos]!) {
macosInputs = await appleValidation(
platform: kMacos,
flutterAppPath: flutterApp!.package.path,
Expand All @@ -619,7 +605,7 @@ class ConfigCommand extends FlutterFireCommand {
}
}

if (flutterApp!.android) {
if (flutterApp!.android && selectedPlatforms[kAndroid]!) {
androidInputs = androidValidation(
flutterAppPath: flutterApp!.package.path,
serviceFilePath: androidServiceFilePath,
Expand All @@ -629,17 +615,10 @@ class ConfigCommand extends FlutterFireCommand {
final firebaseConfigurationFileInputs = dartConfigurationFileValidation(
configurationFilePath: outputFilePath,
flutterAppPath: flutterApp!.package.path,
overwrite: yes,
overwrite: yes || overwriteFirebaseOptions == true,
);

final selectedFirebaseProject = await _selectFirebaseProject();
final selectedPlatforms = _selectPlatforms();

if (!selectedPlatforms.containsValue(true)) {
throw NoFlutterPlatformsSelectedException();
}

// 2. Get values for all selected platforms
// 3. Get values for all selected platforms
final fetchedFirebaseOptions = await fetchAllFirebaseOptions(
flutterApp: flutterApp!,
firebaseProjectId: selectedFirebaseProject.projectId,
Expand All @@ -659,7 +638,7 @@ class ConfigCommand extends FlutterFireCommand {
linux: selectedPlatforms[kLinux] != null && selectedPlatforms[kLinux]!,
);

// 3. Writes for all selected platforms
// 4. Writes for all selected platforms
final firebaseJsonWrites = <FirebaseJsonWrites>[];

if (fetchedFirebaseOptions.androidOptions != null &&
Expand Down Expand Up @@ -728,7 +707,7 @@ class ConfigCommand extends FlutterFireCommand {
firebaseJsonWrites.add(firebaseJsonWrite);
}

// 4. Writes for "firebase.json" file in root of project
// 5. Writes for "firebase.json" file in root of project
if (firebaseJsonWrites.isNotEmpty) {
await writeToFirebaseJson(
listOfWrites: firebaseJsonWrites,
Expand Down
1 change: 0 additions & 1 deletion packages/flutterfire_cli/lib/src/common/exception.dart

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ String getAndroidServiceFile({
);
}
} else {
if (isCI) {
throw ValidationException(
kAndroid,
'The path: $serviceFilePath is not a valid path for the Android `google-services.json` file. Please re-run the command with a valid path.',
);
}
// Prompt for service file path
final serviceFilePath = promptInput(
final promptedServiceFilePath = promptInput(
'Enter a path for your android "$androidServiceFileName" file ("$kAndroidOutFlag" flag.) relative to the root of your Flutter project. Example input: android/app/staging/$androidServiceFileName',
validator: (String x) {
final segments = removeForwardBackwardSlash(x).split('/');
Expand All @@ -54,15 +60,15 @@ String getAndroidServiceFile({
},
);

if (path.basename(serviceFilePath) == androidServiceFileName) {
if (path.basename(promptedServiceFilePath) == androidServiceFileName) {
return path.join(
flutterAppPath,
removeForwardBackwardSlash(serviceFilePath),
removeForwardBackwardSlash(promptedServiceFilePath),
);
} else {
return path.join(
flutterAppPath,
removeForwardBackwardSlash(serviceFilePath),
removeForwardBackwardSlash(promptedServiceFilePath),
androidServiceFileName,
);
}
Expand Down
12 changes: 12 additions & 0 deletions packages/flutterfire_cli/lib/src/common/prompts/apple_prompts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ Future<String> promptCheckBuildConfiguration(
);

if (!buildConfigurations.contains(buildConfiguration)) {
if (isCI) {
throw ValidationException(
platform,
'The build configuration: $buildConfiguration does not exist. Please re-run the command with a valid build configuration.',
);
}
final response = promptSelect(
'You have chosen a buildConfiguration that does not exist: $buildConfiguration. Please choose one of the following build configurations',
buildConfigurations,
Expand Down Expand Up @@ -91,6 +97,12 @@ Future<String> promptCheckTarget(String target, String platform) async {
await findTargetsAvailable(platform, getXcodeProjectPath(platform));

if (!targets.contains(target)) {
if (isCI) {
throw ValidationException(
platform,
'The target $target does not exist. Please re-run the command with a valid target.',
);
}
final response = promptSelect(
'You have chosen a target that does not exist: $target. Please choose one of the following targets',
targets,
Expand Down
12 changes: 12 additions & 0 deletions packages/flutterfire_cli/lib/src/common/strings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,15 @@ class ServiceFileException implements FlutterFireException {
return 'ServiceFileRequirementException: $platform - $message';
}
}

class ValidationException implements FlutterFireException {
ValidationException(this.platform, this.message) : super();

final String platform;
final String message;

@override
String toString() {
return 'ValidationException: $platform - $message';
}
}
30 changes: 30 additions & 0 deletions packages/flutterfire_cli/lib/src/common/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import 'package:path/path.dart'

import '../flutter_app.dart';
import 'platform.dart';
import 'strings.dart';

/// Key for windows platform.
const String kWindows = 'windows';
Expand Down Expand Up @@ -504,3 +505,32 @@ String getXcodeProjectPath(String platform) {
'Runner.xcodeproj',
);
}

void validateAppBundleId(
String bundleId,
String platform,
) {
final bundleIdRegex = RegExp(
r'^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)+$',
);

if (!bundleIdRegex.hasMatch(bundleId)) {
throw ValidationException(
platform,
'Invalid Apple App Bundle ID',
);
}
}

void validateAndroidPackageName(String appId) {
final appIdRegex = RegExp(
r'^[a-zA-Z]+(\.[a-zA-Z_][a-zA-Z0-9_]*)+$',
);

if (!appIdRegex.hasMatch(appId)) {
throw ValidationException(
kAndroid,
'Invalid Android Package Name',
);
}
}
18 changes: 18 additions & 0 deletions packages/flutterfire_cli/lib/src/common/validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ Future<AppleInputs> appleValidation({
}

if (buildConfiguration != null && target != null) {
if (isCI) {
throw ValidationException(
platform,
'Cannot set both target and build configuration in CI.',
);
}
// If user has set both, we need to find out which one they want to use
final response = promptSelect(
'You have both a build configuration (most likely choice) and a target set up. Which would you like to use?',
Expand All @@ -50,6 +56,12 @@ Future<AppleInputs> appleValidation({
}

if (serviceFilePath != null && target == null && buildConfiguration == null) {
if (isCI) {
throw ValidationException(
platform,
'Cannot set service file path without a target or build configuration in CI.',
);
}
// If user has set serviceFilePath, but not a config type, we need to find out which one they want to use
final response = promptSelect(
'You have to choose a configuration type. Either build configuration (most likely choice) or a target set up.',
Expand Down Expand Up @@ -131,6 +143,12 @@ DartConfigurationFileInputs dartConfigurationFileValidation({
configurationFilePath: configurationFilePath,
flutterAppPath: flutterAppPath,
);
if (isCI && !overwrite) {
throw ValidationException(
kDart,
'Required to overwrite Dart Firebase options configuration file in CI. Use `--overwrite-firebase-options` or `--yes` flag.',
);
}
final writeConfigurationFile = overwrite ||
promptWriteConfigurationFile(
configurationFilePath: validatedConfigurationFilePath,
Expand Down
Loading

0 comments on commit f04e23e

Please sign in to comment.