From 199b6e204517d19fe072f0341f328284fd475bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Novotn=C3=BD?= <62177414+yardexx@users.noreply.github.com> Date: Sun, 18 Dec 2022 18:06:48 +0100 Subject: [PATCH] release/v0.0.1 dev.5 (#9) --- CHANGELOG.md | 13 ++- README.md | 1 + brick.yaml | 4 +- hooks/errors/freerasp_brick_exception.dart | 19 ++- hooks/post_gen.dart | 25 +++- hooks/pre_gen.dart | 10 +- hooks/pubspec.yaml | 2 +- .../invalid/missing_build_action_entries.dart | 73 ++++++++++++ .../valid/contains_pre_actions.dart | 98 ++++++++++++++++ .../valid/missing_pre_actions.dart | 89 +++++++++++++++ .../xcscheme_files/xcscheme_files.dart | 3 + hooks/test/utils/gradle_updater_test.dart | 2 +- hooks/test/utils/scheme_updater_test.dart | 89 +++++++++++++++ hooks/utils/gradle_updater.dart | 3 - hooks/utils/scheme_updater.dart | 108 ++++++++++++++++++ hooks/utils/utils.dart | 1 + 16 files changed, 524 insertions(+), 16 deletions(-) create mode 100644 hooks/test/test_inputs/xcscheme_files/invalid/missing_build_action_entries.dart create mode 100644 hooks/test/test_inputs/xcscheme_files/valid/contains_pre_actions.dart create mode 100644 hooks/test/test_inputs/xcscheme_files/valid/missing_pre_actions.dart create mode 100644 hooks/test/test_inputs/xcscheme_files/xcscheme_files.dart create mode 100644 hooks/test/utils/scheme_updater_test.dart create mode 100644 hooks/utils/scheme_updater.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2a02c..bd8c2d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,4 +31,15 @@ ## 🎯 Improvements - Updated README -- Updated CHANGELOG (uhm... sorry about that 😅) \ No newline at end of file +- Updated CHANGELOG (uhm... sorry about that 😅) + +# 0.0.1-dev.5 +## ✨ New Features +- Optional automatic iOS script insertion in Runner.xcscheme - experimental (iOS) + +## 🎯 Improvements +- Updated README + +## 🛠 Fixed issues +- Fixed incorrect `mason` version in `brick.yaml` +- Specified explicit `mason` version to `>=0.1.0-dev.39` in `pubspec.yaml` diff --git a/README.md b/README.md index 0ab062b..4fba945 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ way to create configuration. - 🎯 Dependency check using `pub get` - 🔧 Fix apply using `dart fix` - 🤖 Android SDK level check and automatic update +- 🍎 iOS script insertion in Runner.xcscheme (Experimental) ## How to add ➕ This brick is currently **NOT** available on [brickhub.dev](https://brickhub.dev/). diff --git a/brick.yaml b/brick.yaml index 49088cb..7bf4d7f 100644 --- a/brick.yaml +++ b/brick.yaml @@ -1,10 +1,10 @@ name: freerasp_brick description: A brick for configuration generation and automatic setup for freeRASP. -version: 0.0.1-dev.4 +version: 0.0.1-dev.5 environment: - mason: ">=0.1.0-dev.40 <0.1.0" + mason: ">=0.1.0-dev.39 <0.1.0" vars: watcher_mail: diff --git a/hooks/errors/freerasp_brick_exception.dart b/hooks/errors/freerasp_brick_exception.dart index 0ef2f12..945e460 100644 --- a/hooks/errors/freerasp_brick_exception.dart +++ b/hooks/errors/freerasp_brick_exception.dart @@ -15,10 +15,25 @@ class FreeRaspBrickException implements Exception { ); } - factory FreeRaspBrickException.gradleUpdateFailure({StackTrace? stackTrace}) { + factory FreeRaspBrickException.gradleUpdateFailure({ + String? message, + StackTrace? stackTrace, + }) { return FreeRaspBrickException( code: 'gradle-failure', - message: 'Issue occurred during update of gradle file.', + message: message ?? 'Issue occurred during update of gradle file.', + stackTrace: stackTrace, + ); + } + + factory FreeRaspBrickException.schemeUpdateFailure({ + String? message, + StackTrace? stackTrace, + }) { + return FreeRaspBrickException( + code: 'xcscheme-failure', + message: + message ?? 'Issue occurred during update of Runner.xcscheme file.', stackTrace: stackTrace, ); } diff --git a/hooks/post_gen.dart b/hooks/post_gen.dart index f91b3b7..d020dd1 100644 --- a/hooks/post_gen.dart +++ b/hooks/post_gen.dart @@ -3,18 +3,18 @@ import 'dart:io'; import 'package:mason/mason.dart'; -import 'utils/gradle_updater.dart'; +import 'utils/utils.dart'; const String androidBuild = 'build.gradle'; const String flutterBuild = 'lib'; Future run(HookContext context) async { final logger = context.logger; - await _runPubAdd(logger); await _runPubGet(logger); await _runDartFix(logger); await _runGradleCheck(context); + await _runSchemeCheck(context); } Future _runPubAdd(Logger logger) async { @@ -53,13 +53,13 @@ Future _runDartFix(Logger logger) async { Future _runGradleCheck(HookContext context) async { final progress = context.logger.progress('Checking build.gradle file'); - if (!(context.vars['check_gradle'] as bool)) { + if (!(context.vars['update_gradle'] as bool)) { progress.complete('Gradle check not required. Skipping...'); return; } try { - final hasUpdated = gradleUpdate('android/app/build.gradle'); + final hasUpdated = GradleUpdater.update('android/app/build.gradle'); progress.complete( hasUpdated ? 'build.gradle successfully updated' @@ -69,3 +69,20 @@ Future _runGradleCheck(HookContext context) async { progress.fail("Couldn't update build.gradle"); } } + +Future _runSchemeCheck(HookContext context) async { + final progress = context.logger.progress('Checking xcscheme file'); + + if (!(context.vars['update_scheme'] as bool)) { + progress.complete('Xcscheme check not required. Skipping...'); + return; + } + + try { + SchemeUpdater.update( + 'ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme', + ); + } catch (e) { + progress.fail("Couldn't update xcscheme"); + } +} diff --git a/hooks/pre_gen.dart b/hooks/pre_gen.dart index 9e67fdb..bb672a0 100644 --- a/hooks/pre_gen.dart +++ b/hooks/pre_gen.dart @@ -27,9 +27,15 @@ void parseCupertinoData(HookContext context) { defaultValue: defaultAppPackage, ); + final updateScheme = logger.masonConfirm( + 'Do you want to update Runner.xcscheme?', + defaultValue: true, + ); + context.vars.addAll({ 'bundle_id': bundleId, 'team_id': teamId, + 'update_scheme': updateScheme, }); } @@ -43,7 +49,7 @@ void parseAndroidData(HookContext context) { final signingHash = logger.masonPrompt("What's app singing hash?"); - final checkGradle = logger.masonConfirm( + final updateGradle = logger.masonConfirm( 'Do you want to check and update API level (minSdkVersion)?', defaultValue: true, ); @@ -51,6 +57,6 @@ void parseAndroidData(HookContext context) { context.vars.addAll({ 'package_name': packageName, 'signing_hash': signingHash, - 'check_gradle': checkGradle, + 'update_gradle': updateGradle, }); } diff --git a/hooks/pubspec.yaml b/hooks/pubspec.yaml index 63178a7..17db23c 100644 --- a/hooks/pubspec.yaml +++ b/hooks/pubspec.yaml @@ -5,7 +5,7 @@ environment: dependencies: file: ^6.1.4 - mason: ^0.1.0-dev + mason: ^0.1.0-dev.39 dev_dependencies: test: ^1.22.0 diff --git a/hooks/test/test_inputs/xcscheme_files/invalid/missing_build_action_entries.dart b/hooks/test/test_inputs/xcscheme_files/invalid/missing_build_action_entries.dart new file mode 100644 index 0000000..307ecb5 --- /dev/null +++ b/hooks/test/test_inputs/xcscheme_files/invalid/missing_build_action_entries.dart @@ -0,0 +1,73 @@ +const missingBuildActionEntries = ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +'''; diff --git a/hooks/test/test_inputs/xcscheme_files/valid/contains_pre_actions.dart b/hooks/test/test_inputs/xcscheme_files/valid/contains_pre_actions.dart new file mode 100644 index 0000000..9b5ac4d --- /dev/null +++ b/hooks/test/test_inputs/xcscheme_files/valid/contains_pre_actions.dart @@ -0,0 +1,98 @@ +const containsPreActions = ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +'''; diff --git a/hooks/test/test_inputs/xcscheme_files/valid/missing_pre_actions.dart b/hooks/test/test_inputs/xcscheme_files/valid/missing_pre_actions.dart new file mode 100644 index 0000000..e19783a --- /dev/null +++ b/hooks/test/test_inputs/xcscheme_files/valid/missing_pre_actions.dart @@ -0,0 +1,89 @@ +const missingPreActions = ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +'''; diff --git a/hooks/test/test_inputs/xcscheme_files/xcscheme_files.dart b/hooks/test/test_inputs/xcscheme_files/xcscheme_files.dart new file mode 100644 index 0000000..94be938 --- /dev/null +++ b/hooks/test/test_inputs/xcscheme_files/xcscheme_files.dart @@ -0,0 +1,3 @@ +export 'invalid/missing_build_action_entries.dart'; +export 'valid/contains_pre_actions.dart'; +export 'valid/missing_pre_actions.dart'; diff --git a/hooks/test/utils/gradle_updater_test.dart b/hooks/test/utils/gradle_updater_test.dart index 163232d..3c1aefb 100644 --- a/hooks/test/utils/gradle_updater_test.dart +++ b/hooks/test/utils/gradle_updater_test.dart @@ -32,7 +32,7 @@ void main() { '(API 16)', () { expect( GradleUpdater.update('variable_build.gradle', mockFileSystem), - true, + isTrue, ); final updatedLevel = mockFileSystem diff --git a/hooks/test/utils/scheme_updater_test.dart b/hooks/test/utils/scheme_updater_test.dart new file mode 100644 index 0000000..c117638 --- /dev/null +++ b/hooks/test/utils/scheme_updater_test.dart @@ -0,0 +1,89 @@ +import 'package:file/file.dart'; +import 'package:file/memory.dart'; +import 'package:test/test.dart'; + +import '../../utils/utils.dart'; +import '../test_inputs/xcscheme_files/xcscheme_files.dart'; + +void main() { + const scriptText = + r'''scriptText = "cd "${SRCROOT}/.symlinks/plugins/talsec/ios" if [ "${CONFIGURATION}" = "Release" ]; then rm -rf ./TalsecRuntime.xcframework ln -s ./Release/TalsecRuntime.xcframework/ TalsecRuntime.xcframework else rm -rf ./TalsecRuntime.xcframework ln -s ./Debug/TalsecRuntime.xcframework/ TalsecRuntime.xcframework fi ">'''; + + group('SchemeUpdater.update', () { + late FileSystem mockFileSystem; + + group('Valid inputs', () { + setUpAll(() { + mockFileSystem = MemoryFileSystem(); + + mockFileSystem + .file('preactions.xcscheme') + .writeAsStringSync(containsPreActions); + + mockFileSystem + .file('missing_preactions.xcscheme') + .writeAsStringSync(missingPreActions); + }); + + test('Should insert build script when scheme contains no preactions', () { + expect( + SchemeUpdater.update('missing_preactions.xcscheme', mockFileSystem), + isTrue, + ); + + final lines = mockFileSystem + .file('missing_preactions.xcscheme') + .readAsLinesSync(); + + var found = false; + for (final line in lines) { + if (line.contains(scriptText)) { + found = true; + break; + } + } + + expect(found, isTrue); + }); + + test('Should insert build script when scheme contains some preactions', + () { + expect( + SchemeUpdater.update('preactions.xcscheme', mockFileSystem), + isTrue, + ); + + final lines = + mockFileSystem.file('preactions.xcscheme').readAsLinesSync(); + + var found = false; + for (final line in lines) { + if (line.contains(scriptText)) { + found = true; + break; + } + } + + expect(found, isTrue); + }); + }); + + group('Invalid inputs', () { + setUpAll(() { + mockFileSystem = MemoryFileSystem(); + + mockFileSystem + .file('missing_build.xcscheme') + .writeAsStringSync(missingBuildActionEntries); + }); + + test('Should return false when scheme contains no build action entries', + () { + expect( + SchemeUpdater.update('missing_build.xcscheme', mockFileSystem), + isFalse, + ); + }); + }); + }); +} diff --git a/hooks/utils/gradle_updater.dart b/hooks/utils/gradle_updater.dart index 695c855..192f303 100644 --- a/hooks/utils/gradle_updater.dart +++ b/hooks/utils/gradle_updater.dart @@ -86,6 +86,3 @@ class GradleUpdater { } } } - -/// Functional type of call for [GradleUpdater.update]. -bool gradleUpdate(String path) => GradleUpdater.update(path); diff --git a/hooks/utils/scheme_updater.dart b/hooks/utils/scheme_updater.dart new file mode 100644 index 0000000..8f5422d --- /dev/null +++ b/hooks/utils/scheme_updater.dart @@ -0,0 +1,108 @@ +import 'package:file/file.dart'; +import 'package:file/local.dart'; + +import '../errors/errors.dart'; + +/// A class which adds Talsec pre-build script phase to Xcode project. +/// +/// [SchemeUpdater] takes [String] path to Runner.xcscheme file which is then +/// parsed and checked, then checks for "PreActions" and/or "BuildActionEntries" +/// keys and inserts Talsec pre-build script phase. +/// +/// If any issues occurs, [FreeRaspBrickException] is thrown. +class SchemeUpdater { + const SchemeUpdater._(); + + static const _shellScript = r''' + + + + + + + + '''; + + static const _preActionsTag = ''' + + '''; + + /// Updated xcscheme file at given [path]. + /// + /// Be aware that this method doesn't check if pre-build script phase is + /// already present. + /// + /// Returns true if Talsec pre-build script phase was added, false otherwise. + static bool update(String path, [FileSystem fs = const LocalFileSystem()]) { + try { + _updateFile(fs.file(path)); + } catch (e) { + return false; + } + return true; + } + + static void _updateFile(File schemeFile) { + return _addScript(schemeFile); + } + + /// Adds Talsec pre-build script phase to given [schemeFile]. + /// + /// If [schemeFile] doesn't contain "PreActions" tag, it is added. If adding + /// "PreActions" tag fails, [FreeRaspBrickException] is thrown. + /// + /// Throws [FreeRaspBrickException] if any issues occurs. + static void _addScript(File schemeFile) { + _checkForPreActions(schemeFile); + + final lines = schemeFile.readAsLinesSync(); + + var index = -1; + for (final value in lines) { + if (value.contains('')) { + index = lines.indexOf(value); + } + } + + lines.insert(index + 1, _shellScript); + schemeFile.writeAsStringSync(lines.join('\n')); + } + + /// Checks if [schemeFile] contains "PreActions" tag. + /// + /// If not, it is added. + /// + /// Throws [FreeRaspBrickException] if any issues occurs. + static void _checkForPreActions(File schemeFile) { + final lines = schemeFile.readAsLinesSync(); + + var index = -1; + for (final value in lines) { + if (value.contains('')) { + return; + } + + if (value.contains('')) { + index = lines.indexOf(value); + break; + } + } + + if (index == -1) { + throw FreeRaspBrickException.schemeUpdateFailure( + message: 'Unable to find tag.', + ); + } + + lines.insert(index, _preActionsTag); + schemeFile.writeAsStringSync(lines.join('\n')); + } +} diff --git a/hooks/utils/utils.dart b/hooks/utils/utils.dart index 67da207..39e2502 100644 --- a/hooks/utils/utils.dart +++ b/hooks/utils/utils.dart @@ -1 +1,2 @@ export 'gradle_updater.dart'; +export 'scheme_updater.dart';