diff --git a/CHANGELOG.md b/CHANGELOG.md index 6412c1e..2aeb29d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Support reading config from sentry.properties file ([#191](https://github.com/getsentry/sentry-dart-plugin/pull/191)) + ### Dependencies - Bump CLI from v2.21.2 to v2.22.3 ([#180](https://github.com/getsentry/sentry-dart-plugin/pull/180)) diff --git a/lib/src/configuration.dart b/lib/src/configuration.dart index f453004..d3aa78f 100644 --- a/lib/src/configuration.dart +++ b/lib/src/configuration.dart @@ -3,10 +3,10 @@ import 'dart:io'; import 'package:file/file.dart'; import 'package:process/process.dart'; import 'package:system_info2/system_info2.dart'; -import 'package:yaml/yaml.dart'; import 'cli/host_platform.dart'; import 'cli/setup.dart'; +import 'utils/config-reader/config_reader.dart'; import 'utils/extensions.dart'; import 'utils/injector.dart'; import 'utils/log.dart'; @@ -80,57 +80,51 @@ class Configuration { /// https://docs.sentry.io/product/cli/releases/#dealing-with-missing-commits late bool ignoreMissing; - dynamic _getPubspec() { - final file = injector.get().file("pubspec.yaml"); - if (!file.existsSync()) { - Log.error("Pubspec not found: ${file.absolute.path}"); - return {}; - } - final pubspecString = file.readAsStringSync(); - final pubspec = loadYaml(pubspecString); - return pubspec; - } - /// Loads the configuration values Future getConfigValues(List arguments) async { - final environments = Platform.environment; const taskName = 'reading config values'; Log.startingTask(taskName); - await _findAndSetCliPath(); - final pubspec = _getPubspec(); - final config = pubspec['sentry'] as YamlMap?; - release = config?['release']?.toString() ?? environments['SENTRY_RELEASE']; - dist = config?['dist']?.toString() ?? environments['SENTRY_DIST']; + final reader = ConfigReader(); + loadConfig(reader); + + Log.taskCompleted(taskName); + } + + void loadConfig(ConfigReader reader) { + final environments = Platform.environment; + final pubspec = ConfigReader.getPubspec(); + + release = reader.getString('release') ?? environments['SENTRY_RELEASE']; + dist = reader.getString('dist') ?? environments['SENTRY_DIST']; version = pubspec['version'].toString(); name = pubspec['name'].toString(); - uploadDebugSymbols = - config?.get('upload_debug_symbols', 'upload_native_symbols') ?? true; - uploadSourceMaps = config?['upload_source_maps'] ?? false; - uploadSources = - config?.get('upload_sources', 'include_native_sources') ?? false; - commits = (config?['commits'] ?? 'auto').toString(); - ignoreMissing = config?['ignore_missing'] ?? false; + uploadDebugSymbols = reader.getBool('upload_debug_symbols', + deprecatedKey: 'upload_native_symbols') ?? + true; + uploadSourceMaps = reader.getBool('upload_source_maps') ?? false; + uploadSources = reader.getBool('upload_sources', + deprecatedKey: 'include_native_sources') ?? + false; + commits = (reader.getString('commits') ?? 'auto').toString(); + ignoreMissing = reader.getBool('ignore_missing') ?? false; // uploading JS and Map files need to have the correct folder structure // otherwise symbolication fails, the default path for the web build folder is build/web // but can be customized so making it flexible. final webBuildPath = - config?['web_build_path']?.toString() ?? _fs.path.join('build', 'web'); + reader.getString('web_build_path') ?? _fs.path.join('build', 'web'); webBuildFilesFolder = _fs.path.join(buildFilesFolder, webBuildPath); - project = config?['project']?.toString(); // or env. var. SENTRY_PROJECT - org = config?['org']?.toString(); // or env. var. SENTRY_ORG - waitForProcessing = config?['wait_for_processing'] ?? false; + project = reader.getString('project'); // or env. var. SENTRY_PROJECT + org = reader.getString('org'); // or env. var. SENTRY_ORG + waitForProcessing = reader.getBool('wait_for_processing') ?? false; authToken = - config?['auth_token']?.toString(); // or env. var. SENTRY_AUTH_TOKEN - url = config?['url']?.toString(); // or env. var. SENTRY_URL - logLevel = - config?['log_level']?.toString(); // or env. var. SENTRY_LOG_LEVEL - - Log.taskCompleted(taskName); + reader.getString('auth_token'); // or env. var. SENTRY_AUTH_TOKEN + url = reader.getString('url'); // or env. var. SENTRY_URL + logLevel = reader.getString('log_level'); // or env. var. SENTRY_LOG_LEVEL } /// Validates the configuration values and log an error if required fields @@ -227,19 +221,3 @@ class Configuration { 'Trying to fallback to preinstalled Sentry CLI, if available on PATH: $cliPath'); } } - -extension _Config on YamlMap { - T? get(String name, String? deprecatedName) { - if (deprecatedName != null && containsKey(deprecatedName)) { - Log.warn( - 'Your pubspec.yaml contains `$deprecatedName` which is deprecated. Consider switching to `$name`.'); - } - if (containsKey(name)) { - return this[name]; - } else if (deprecatedName != null && containsKey(deprecatedName)) { - return this[deprecatedName]; - } else { - return null; - } - } -} diff --git a/lib/src/utils/config-reader/config_reader.dart b/lib/src/utils/config-reader/config_reader.dart new file mode 100644 index 0000000..18611a3 --- /dev/null +++ b/lib/src/utils/config-reader/config_reader.dart @@ -0,0 +1,70 @@ +import 'package:properties/properties.dart'; +import 'package:yaml/yaml.dart'; +import 'package:file/file.dart'; + +import '../injector.dart'; +import '../log.dart'; +import 'no_op_config_reader.dart'; +import 'properties_config_reader.dart'; +import 'yaml_config_reader.dart'; + +abstract class ConfigReader { + String? getString(String key, {String? deprecatedKey}); + bool? getBool(String key, {String? deprecatedKey}); + bool contains(String key); + + /// By default this ConfigReader factory will try to load pubspec.yaml first. + /// If the sentry config doesn't exist on pubspec.yaml it will use sentry.properties as fallback. + factory ConfigReader() { + // Attempt to retrieve the config from pubspec.yaml first + final pubspec = getPubspec(); + final sentryConfig = pubspec['sentry'] as YamlMap?; + if (sentryConfig != null) { + Log.info('retrieving config from pubspec.yaml'); + return YamlConfigReader(sentryConfig); + } else { + Log.info('sentry config not found in pubspec.yaml'); + } + + // If sentry config is not found in pubspec.yaml, try loading from sentry.properties + final propertiesFile = injector.get().file("sentry.properties"); + if (propertiesFile.existsSync()) { + Log.info('retrieving config from sentry.properties'); + // Loads properties class via string as there are issues loading the file + // from path if run in the test suite + final properties = + Properties.fromString(propertiesFile.readAsStringSync()); + return PropertiesConfigReader(properties); + } + Log.error('no config found, please use sentry.properties or pubspec.yaml.'); + return NoOpConfigReader(); + } + + static dynamic getPubspec() { + final file = injector.get().file("pubspec.yaml"); + if (!file.existsSync()) { + Log.error("Pubspec not found: ${file.absolute.path}"); + return {}; + } + final pubspecString = file.readAsStringSync(); + final pubspec = loadYaml(pubspecString); + return pubspec; + } +} + +extension Config on ConfigReader { + T? get( + String name, String? deprecatedName, T? Function(String key) resolve) { + if (deprecatedName != null && contains(deprecatedName)) { + Log.warn( + 'Your config contains `$deprecatedName` which is deprecated. Consider switching to `$name`.'); + } + if (contains(name)) { + return resolve(name); + } else if (deprecatedName != null && contains(deprecatedName)) { + return resolve(deprecatedName); + } else { + return null; + } + } +} diff --git a/lib/src/utils/config-reader/no_op_config_reader.dart b/lib/src/utils/config-reader/no_op_config_reader.dart new file mode 100644 index 0000000..e792e28 --- /dev/null +++ b/lib/src/utils/config-reader/no_op_config_reader.dart @@ -0,0 +1,20 @@ +import 'config_reader.dart'; + +class NoOpConfigReader implements ConfigReader { + NoOpConfigReader(); + + @override + bool? getBool(String key, {String? deprecatedKey}) { + return null; + } + + @override + String? getString(String key, {String? deprecatedKey}) { + return null; + } + + @override + bool contains(String key) { + return false; + } +} diff --git a/lib/src/utils/config-reader/properties_config_reader.dart b/lib/src/utils/config-reader/properties_config_reader.dart new file mode 100644 index 0000000..22d25b1 --- /dev/null +++ b/lib/src/utils/config-reader/properties_config_reader.dart @@ -0,0 +1,24 @@ +import 'package:properties/properties.dart'; + +import 'config_reader.dart'; + +class PropertiesConfigReader implements ConfigReader { + final Properties _properties; + + PropertiesConfigReader(Properties properties) : _properties = properties; + + @override + bool? getBool(String key, {String? deprecatedKey}) { + return get(key, deprecatedKey, (key) => _properties.getBool((key))); + } + + @override + String? getString(String key, {String? deprecatedKey}) { + return get(key, deprecatedKey, (key) => _properties.get((key))); + } + + @override + bool contains(String key) { + return _properties.contains(key); + } +} diff --git a/lib/src/utils/config-reader/yaml_config_reader.dart b/lib/src/utils/config-reader/yaml_config_reader.dart new file mode 100644 index 0000000..5ae2431 --- /dev/null +++ b/lib/src/utils/config-reader/yaml_config_reader.dart @@ -0,0 +1,24 @@ +import 'package:yaml/yaml.dart'; + +import 'config_reader.dart'; + +class YamlConfigReader implements ConfigReader { + final YamlMap? _yamlMap; + + YamlConfigReader(YamlMap? yamlMap) : _yamlMap = yamlMap; + + @override + bool? getBool(String key, {String? deprecatedKey}) { + return get(key, deprecatedKey, (key) => _yamlMap?[key] as bool?); + } + + @override + String? getString(String key, {String? deprecatedKey}) { + return get(key, deprecatedKey, (key) => (_yamlMap?[key]).toString()); + } + + @override + bool contains(String key) { + return _yamlMap?.containsKey(key) ?? false; + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 458d6e0..d51c962 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,6 +18,7 @@ dependencies: crypto: ^3.0.2 convert: ^3.0.2 process: ^4.2.4 + properties: ^2.1.0 dev_dependencies: lints: ^3.0.0 diff --git a/test/plugin_test.dart b/test/plugin_test.dart index 59c5534..fe4632e 100644 --- a/test/plugin_test.dart +++ b/test/plugin_test.dart @@ -11,8 +11,13 @@ import 'package:test/test.dart'; import 'package:sentry_dart_plugin/sentry_dart_plugin.dart'; import 'package:sentry_dart_plugin/src/utils/injector.dart'; +import 'utils/config_file_type.dart'; +import 'utils/config_formatter.dart'; +import 'utils/config_writer.dart'; + void main() { final plugin = SentryDartPlugin(); + late ConfigWriter configWriter; late MockProcessManager pm; late FileSystem fs; @@ -23,6 +28,12 @@ void main() { const release = '$project@$version'; const buildDir = '/subdir'; + /// File types from which we can read configs. + const fileTypes = [ + ConfigFileType.pubspecYaml, + ConfigFileType.sentryProperties, + ]; + setUp(() { // override dependencies for testing pm = MockProcessManager(); @@ -31,175 +42,164 @@ void main() { fs.currentDirectory = fs.directory(buildDir)..createSync(); injector.registerSingleton(() => fs, override: true); injector.registerSingleton(() => MockCLI(), override: true); + configWriter = ConfigWriter(fs, project, version); }); for (final url in const ['http://127.0.0.1', null]) { - group('url: $url', () { - final commonArgs = - '${url == null ? '' : '--url http://127.0.0.1 '}--auth-token t'; - final commonCommands = [ - if (!Platform.isWindows) 'chmod +x $cli', - '$cli help' - ]; - - Future> runWith(String config) async { - // properly indent the configuration for the `sentry` section in the yaml - if (url != null) { - config = 'url: $url\n$config'; + for (var fileType in fileTypes) { + group('url: $url', () { + final commonArgs = + '${url == null ? '' : '--url http://127.0.0.1 '}--auth-token t'; + final commonCommands = [ + if (!Platform.isWindows) 'chmod +x $cli', + '$cli help' + ]; + + Future> runWith(String config) async { + final formattedConfig = + ConfigFormatter.formatConfig(config, fileType, url); + configWriter.write(fileType, formattedConfig); + + final exitCode = await plugin.run([]); + expect(exitCode, 0); + expect(pm.commandLog.take(commonCommands.length), commonCommands); + return pm.commandLog.skip(commonCommands.length); } - final configIndented = - config.trim().split('\n').map((l) => ' ${l.trim()}').join('\n'); - - fs.file('pubspec.yaml').writeAsStringSync(''' -name: $project -version: $version - -sentry: - auth_token: t # TODO: support not specifying this, let sentry-cli use the value it can find in its configs - project: p - org: o -$configIndented -'''); - - final exitCode = await plugin.run([]); - expect(exitCode, 0); - expect(pm.commandLog.take(commonCommands.length), commonCommands); - return pm.commandLog.skip(commonCommands.length); - } - - test('fails without args and pubspec', () async { - final exitCode = await plugin.run([]); - expect(exitCode, 1); - expect(pm.commandLog, commonCommands); - }); - test('works with pubspec', () async { - final commandLog = await runWith(''' + test('works with all configuration files', () async { + final commandLog = await runWith(''' upload_debug_symbols: true upload_sources: true upload_source_maps: true log_level: debug ignore_missing: true '''); - final args = '$commonArgs --log-level debug'; - expect(commandLog, [ - '$cli $args debug-files upload $orgAndProject --include-sources $buildDir', - '$cli $args releases $orgAndProject new $release', - '$cli $args releases $orgAndProject files $release upload-sourcemaps $buildDir/build/web --ext map --ext js', - '$cli $args releases $orgAndProject files $release upload-sourcemaps $buildDir --ext dart', - '$cli $args releases $orgAndProject set-commits $release --auto --ignore-missing', - '$cli $args releases $orgAndProject finalize $release' - ]); - }); + final args = '$commonArgs --log-level debug'; + expect(commandLog, [ + '$cli $args debug-files upload $orgAndProject --include-sources $buildDir', + '$cli $args releases $orgAndProject new $release', + '$cli $args releases $orgAndProject files $release upload-sourcemaps $buildDir/build/web --ext map --ext js', + '$cli $args releases $orgAndProject files $release upload-sourcemaps $buildDir --ext dart', + '$cli $args releases $orgAndProject set-commits $release --auto --ignore-missing', + '$cli $args releases $orgAndProject finalize $release' + ]); + }); - test('defaults', () async { - final commandLog = await runWith(''); - expect(commandLog, [ - '$cli $commonArgs debug-files upload $orgAndProject $buildDir', - '$cli $commonArgs releases $orgAndProject new $release', - '$cli $commonArgs releases $orgAndProject set-commits $release --auto', - '$cli $commonArgs releases $orgAndProject finalize $release' - ]); - }); + test('fails without args and pubspec', () async { + final exitCode = await plugin.run([]); + expect(exitCode, 1); + expect(pm.commandLog, commonCommands); + }); - group('commits', () { - // https://docs.sentry.io/product/cli/releases/#sentry-cli-commit-integration - for (final value in const [ - null, // test the implicit default - 'true', - 'auto', - 'repo_name@293ea41d67225d27a8c212f901637e771d73c0f7', - 'repo_name@293ea41d67225d27a8c212f901637e771d73c0f7..1e248e5e6c24b79a5c46a2e8be12cef0e41bd58d', - ]) { - test(value, () async { - final commandLog = - await runWith(value == null ? '' : 'commits: $value'); - final expectedArgs = - (value == null || value == 'auto' || value == 'true') - ? '--auto' - : '--commit $value'; + test('defaults', () async { + final commandLog = await runWith(''); + expect(commandLog, [ + '$cli $commonArgs debug-files upload $orgAndProject $buildDir', + '$cli $commonArgs releases $orgAndProject new $release', + '$cli $commonArgs releases $orgAndProject set-commits $release --auto', + '$cli $commonArgs releases $orgAndProject finalize $release' + ]); + }); + + group('commits', () { + // https://docs.sentry.io/product/cli/releases/#sentry-cli-commit-integration + for (final value in const [ + null, // test the implicit default + 'true', + 'auto', + 'repo_name@293ea41d67225d27a8c212f901637e771d73c0f7', + 'repo_name@293ea41d67225d27a8c212f901637e771d73c0f7..1e248e5e6c24b79a5c46a2e8be12cef0e41bd58d', + ]) { + test(value, () async { + final commandLog = + await runWith(value == null ? '' : 'commits: $value'); + final expectedArgs = + (value == null || value == 'auto' || value == 'true') + ? '--auto' + : '--commit $value'; + expect(commandLog, [ + '$cli $commonArgs debug-files upload $orgAndProject $buildDir', + '$cli $commonArgs releases $orgAndProject new $release', + '$cli $commonArgs releases $orgAndProject set-commits $release $expectedArgs', + '$cli $commonArgs releases $orgAndProject finalize $release' + ]); + }); + } + + // if explicitly disabled + test('false', () async { + final commandLog = await runWith('commits: false'); expect(commandLog, [ '$cli $commonArgs debug-files upload $orgAndProject $buildDir', '$cli $commonArgs releases $orgAndProject new $release', - '$cli $commonArgs releases $orgAndProject set-commits $release $expectedArgs', '$cli $commonArgs releases $orgAndProject finalize $release' ]); }); - } - - // if explicitly disabled - test('false', () async { - final commandLog = await runWith('commits: false'); - expect(commandLog, [ - '$cli $commonArgs debug-files upload $orgAndProject $buildDir', - '$cli $commonArgs releases $orgAndProject new $release', - '$cli $commonArgs releases $orgAndProject finalize $release' - ]); }); - }); - group('custom releases and dists', () { - test('custom release with a dist in it', () async { - final dist = 'myDist'; - final customRelease = 'myRelease@myVersion+$dist'; + group('custom releases and dists', () { + test('custom release with a dist in it', () async { + final dist = 'myDist'; + final customRelease = 'myRelease@myVersion+$dist'; - final commandLog = await runWith(''' + final commandLog = await runWith(''' upload_debug_symbols: false upload_source_maps: true release: $customRelease dist: anotherDist '''); - final args = commonArgs; - expect(commandLog, [ - '$cli $args releases $orgAndProject new $customRelease', - '$cli $args releases $orgAndProject files $customRelease upload-sourcemaps $buildDir/build/web --ext map --ext js --dist $dist', - '$cli $args releases $orgAndProject files $customRelease upload-sourcemaps $buildDir --ext dart --dist $dist', - '$cli $args releases $orgAndProject set-commits $customRelease --auto', - '$cli $args releases $orgAndProject finalize $customRelease' - ]); - }); + final args = commonArgs; + expect(commandLog, [ + '$cli $args releases $orgAndProject new $customRelease', + '$cli $args releases $orgAndProject files $customRelease upload-sourcemaps $buildDir/build/web --ext map --ext js --dist $dist', + '$cli $args releases $orgAndProject files $customRelease upload-sourcemaps $buildDir --ext dart --dist $dist', + '$cli $args releases $orgAndProject set-commits $customRelease --auto', + '$cli $args releases $orgAndProject finalize $customRelease' + ]); + }); - test('custom release with a custom dist', () async { - final dist = 'myDist'; - final customRelease = 'myRelease@myVersion'; - final fullRelease = '$customRelease+$dist'; + test('custom release with a custom dist', () async { + final dist = 'myDist'; + final customRelease = 'myRelease@myVersion'; + final fullRelease = '$customRelease+$dist'; - final commandLog = await runWith(''' + final commandLog = await runWith(''' upload_debug_symbols: false upload_source_maps: true release: $customRelease dist: $dist '''); - final args = commonArgs; - expect(commandLog, [ - '$cli $args releases $orgAndProject new $fullRelease', - '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir/build/web --ext map --ext js --dist $dist', - '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir --ext dart --dist $dist', - '$cli $args releases $orgAndProject set-commits $fullRelease --auto', - '$cli $args releases $orgAndProject finalize $fullRelease' - ]); - }); + final args = commonArgs; + expect(commandLog, [ + '$cli $args releases $orgAndProject new $fullRelease', + '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir/build/web --ext map --ext js --dist $dist', + '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir --ext dart --dist $dist', + '$cli $args releases $orgAndProject set-commits $fullRelease --auto', + '$cli $args releases $orgAndProject finalize $fullRelease' + ]); + }); - test('custom dist', () async { - final dist = 'myDist'; - final fullRelease = '$release+$dist'; + test('custom dist', () async { + final dist = 'myDist'; + final fullRelease = '$release+$dist'; - final commandLog = await runWith(''' + final commandLog = await runWith(''' upload_debug_symbols: false upload_source_maps: true dist: $dist '''); - final args = commonArgs; - expect(commandLog, [ - '$cli $args releases $orgAndProject new $fullRelease', - '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir/build/web --ext map --ext js --dist $dist', - '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir --ext dart --dist $dist', - '$cli $args releases $orgAndProject set-commits $fullRelease --auto', - '$cli $args releases $orgAndProject finalize $fullRelease' - ]); + final args = commonArgs; + expect(commandLog, [ + '$cli $args releases $orgAndProject new $fullRelease', + '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir/build/web --ext map --ext js --dist $dist', + '$cli $args releases $orgAndProject files $fullRelease upload-sourcemaps $buildDir --ext dart --dist $dist', + '$cli $args releases $orgAndProject set-commits $fullRelease --auto', + '$cli $args releases $orgAndProject finalize $fullRelease' + ]); + }); }); }); - }); + } } } diff --git a/test/utils/config_file_type.dart b/test/utils/config_file_type.dart new file mode 100644 index 0000000..8623dc4 --- /dev/null +++ b/test/utils/config_file_type.dart @@ -0,0 +1 @@ +enum ConfigFileType { pubspecYaml, sentryProperties } diff --git a/test/utils/config_formatter.dart b/test/utils/config_formatter.dart new file mode 100644 index 0000000..9e777e7 --- /dev/null +++ b/test/utils/config_formatter.dart @@ -0,0 +1,40 @@ +import 'config_file_type.dart'; + +class ConfigFormatter { + static String formatConfig( + String config, ConfigFileType fileType, String? url) { + // Add URL if provided + if (url != null) { + config = _addUrlPrefix(config, fileType, url); + } + + // Format config based on file type + switch (fileType) { + case ConfigFileType.sentryProperties: + return _formatSentryPropertiesConfig(config); + case ConfigFileType.pubspecYaml: + return _formatPubspecYamlConfig(config); + default: + throw Exception('Unknown config file type: $fileType'); + } + } + + static String _addUrlPrefix( + String config, ConfigFileType fileType, String url) { + final urlLine = + fileType == ConfigFileType.sentryProperties ? 'url=$url' : 'url: $url'; + return '$urlLine\n$config'; + } + + static String _formatSentryPropertiesConfig(String config) { + return config + .replaceAll(': ', '=') + .split('\n') + .map((line) => line.trim()) + .join('\n'); + } + + static String _formatPubspecYamlConfig(String config) { + return config.split('\n').map((line) => ' ${line.trim()}').join('\n'); + } +} diff --git a/test/utils/config_writer.dart b/test/utils/config_writer.dart new file mode 100644 index 0000000..1405f44 --- /dev/null +++ b/test/utils/config_writer.dart @@ -0,0 +1,41 @@ +import 'package:file/file.dart'; + +import 'config_file_type.dart'; + +class ConfigWriter { + final FileSystem fs; + final String project; + final String version; + + ConfigWriter(this.fs, this.project, this.version); + + void write(ConfigFileType configFile, String config) { + // Write the basic options to pubspec.yaml which is needed for all configs + fs.file('pubspec.yaml').writeAsStringSync(''' +name: $project +version: $version +'''); + + if (configFile == ConfigFileType.pubspecYaml) { + fs.file('pubspec.yaml').writeAsStringSync( + ''' +sentry: + auth_token: t + project: p + org: o +''', + mode: FileMode.append, + ); + fs.file('pubspec.yaml').writeAsStringSync(config, mode: FileMode.append); + } else if (configFile == ConfigFileType.sentryProperties) { + fs.file('sentry.properties').writeAsStringSync(''' +auth_token=t +project=p +org=o +'''); + fs + .file('sentry.properties') + .writeAsStringSync(config, mode: FileMode.append); + } + } +}