Compare commits

..

185 Commits

Author SHA1 Message Date
PhilippFalchuk dd85251813 MAN-001 PR: added afisha and toolbar 2025-10-20 18:58:53 +03:00
Nikita Mikryukov 069396ecb8 Merge pull request 'Replaced Enterprise with AdHoc' (#28) from feature/adHoc_cert into master
Reviewed-on: #28
Reviewed-by: Vladimir Makarov <vladimir.makarov@noreply.localhost>
2025-04-04 16:08:39 +03:00
Nikita Mikryukov fce05b99ec added AdHoc type 2025-04-01 14:59:43 +03:00
Ivan Smolin efa00ff67b Merge pull request 'fix: You can't use 'build_number' and 'ipa' options in one run.' (#20) from fix/ipa_and_build_number_for_appstore into master
Reviewed-on: #20
2024-01-31 13:48:30 +03:00
Ivan Smolin 565279ef75 fix: You can't use 'build_number' and 'ipa' options in one run. 2024-01-31 13:47:24 +03:00
Ivan Smolin 66f4df9425 Merge pull request 'fix syntax issue in swiftlint script' (#19) from fix/syntax_issue_in_swiftlint_script into master
Reviewed-on: #19
2024-01-29 16:50:32 +03:00
Ivan Smolin 5a663334f0 fix syntax issue in swiftlint script 2024-01-29 16:40:50 +03:00
Ivan Smolin ccd4df9314 Merge pull request 'add SubmitForReview command lane' (#18) from feature/app_store_submit_for_review_command into master
Reviewed-on: #18
2024-01-29 16:28:02 +03:00
Ivan Smolin d900c5b9ad add SubmitForReview command lane 2024-01-26 14:58:40 +03:00
Ivan Smolin 1160ea6320 Merge pull request 'feature/separate_actions' (#17) from feature/separate_actions into master
Reviewed-on: #17
2024-01-22 13:19:19 +03:00
Ivan Smolin e732e16d21 separate SyncCodeSigning to multiple actions 2024-01-22 10:58:29 +03:00
Bogdan Terehov abe62fca64 Merge pull request 'fix: поправил ссылки в README.md' (#16) from fix/build_script_url into master
Reviewed-on: #16
2024-01-18 15:05:08 +03:00
Bogdan Terehov 7f7d535ca5 fix: поправил ссылки 2024-01-18 14:31:39 +03:00
Ivan Smolin e54d505272 Merge pull request 'fix errors during make init call' (#15) from feature/make_init_fixes into master
Reviewed-on: #15
2024-01-18 14:09:47 +03:00
Ivan Smolin 70c2899bf0 Merge pull request 'use xcodes for Xcode version selection' (#14) from feature/xcode_version_selection_via_xcodes into master
Reviewed-on: #14
2024-01-18 14:08:39 +03:00
Ivan Smolin 434c4f4e6a fix errors during make init call 2024-01-18 09:54:51 +03:00
Ivan Smolin e44811d1b7 remove unused actions and methods 2024-01-17 12:25:46 +03:00
Ivan Smolin eaad4027c6 use xcodes for Xcode version selection 2024-01-16 11:09:06 +03:00
Ivan Smolin 5be3987ea3 Merge pull request 'Shell scripts updates to cpd, api-generator and bootstrap' (#13) from feature/cpd_update into master
Reviewed-on: #13
2024-01-15 15:35:39 +03:00
Ivan Smolin f8865b3232 add --skip-lexical-errors for pmd cpd
report error on api generator run failure
add bootstrap scripts for code lint
2023-12-29 18:44:05 +05:00
Nikita Mikryukov 4dfed1b2a8 Merge pull request 'Updated repositories link' (#9) from fix/update_links into master
Reviewed-on: #9
2023-05-29 11:39:51 +03:00
Nikita Mikryukov c841e48516 changed https link to ssh 2023-05-29 09:55:50 +03:00
Nikita Mikryukov 3e249eae3d updated repositories link 2023-05-29 09:28:27 +03:00
Ivan Smolin 318e0ce021 Merge pull request 'exclude playground app from lint, add make gen command to Makefile' (#7) from feature/exclude_playground_app into master
Reviewed-on: #7
2023-05-24 14:37:43 +03:00
Ivan Smolin f1fe35d298 exclude playground app from lint, add make gen command to Makefile 2023-05-24 13:35:01 +03:00
Ivan Smolin 39109c6e60 Merge pull request 'Disable autocorrection by default, make script more independent of environment (SPM support)' (#6) from feature/swiftlint_script_spm_support into master
Reviewed-on: #6
2023-05-24 09:26:06 +03:00
Ivan Smolin 7d3f2794bc simplify temp file creation 2023-05-22 11:59:45 +03:00
Ivan Smolin b843196f3c Disable autocorrection by default, make script more independent of environment 2023-05-19 17:46:45 +03:00
Ivan Smolin 96f4d38bab Merge pull request 'update SwiftLint config to support latest 0.52.2 version features' (#5) from feature/update_swiftlint into master
Reviewed-on: #5
2023-05-19 16:33:34 +03:00
Ivan Smolin e3b688639f update SwiftLint config to support latest 0.52.2 version features 2023-05-17 16:15:22 +03:00
Vladimir Makarov 16b6523742 Merge pull request '`options[:appName]` for `get_google_services_plist_path` used' (#4) from fix/dsyms_uploading into master
Reviewed-on: #4
2023-05-04 22:53:24 +03:00
Vladimir Makarov bf2ee40721 `options[:appName]` for `get_google_services_plist_path` used 2023-05-04 21:42:57 +02:00
Vladimir Makarov cd8e8c60e4 Merge pull request 'Deprecated `:SyncSymbols` removed, `upload_symbols_to_crashlytics` moved to a common building step, `compileBitcode` removed' (#1) from feature/dsyms_uploading into master
Reviewed-on: #1
2023-04-19 16:19:42 +03:00
Vladimir Makarov 69928bb749 Deprecated `:SyncSymbols` removed, `upload_symbols_to_crashlytics` moved to a common building step, `compileBitcode` removed 2023-04-19 16:02:00 +03:00
Kirill Khoroshkov d6c818370f Merge branch 'codestyle/kotlin' into 'master'
Added kotlin codestyle

See merge request touchinstinct/BuildScripts!6
2023-04-13 14:40:14 +00:00
KirillKhoroshkov b50ced768e Added trailing comma 2023-04-01 19:37:48 +03:00
KirillKhoroshkov 7c5352e6c9 Edited README 2023-03-29 00:58:49 +03:00
KirillKhoroshkov 23fb4371b1 Edited README 2023-03-29 00:57:20 +03:00
KirillKhoroshkov 211020a30d Edited README 2023-03-28 15:52:48 +03:00
KirillKhoroshkov 4716bdb131 Edited README and removed the old scheme 2023-03-28 03:50:35 +03:00
KirillKhoroshkov 98bd66290e Moved info to the main README file 2023-03-27 01:20:56 +03:00
KirillKhoroshkov 4cdf0b8982 Added java and objective-c codestyles 2023-03-26 01:17:08 +03:00
KirillKhoroshkov 9fe5348a98 Added kotlin codestyle 2023-03-24 13:52:13 +03:00
Roman Pelmegov ba7f792f96 Merge branch 'feature/issue-276' into 'master'
Feature/issue-276

See merge request touchinstinct/BuildScripts!1
2023-03-23 14:56:48 +00:00
Roman Pelmegov 3321f3bdfd Update scripts/export_src.sh 2023-03-08 19:34:19 +00:00
Roman Pelmegov 082f618425 Merge branch 'master' into 'feature/issue-276'
# Conflicts:
#   scripts/export_src.sh
2023-03-08 19:25:19 +00:00
Roman Pelmegov d83a3628e4 Merge branch 'feature/issue-333' into 'master'
Feature/issue-333

See merge request touchinstinct/BuildScripts!2
2023-03-07 16:52:50 +00:00
Roman Pelmegov 0400dbe36d issue-333 break on git clone error 2023-03-07 16:26:54 +00:00
Roman Pelmegov 216c228898 last commit date 2023-03-07 11:07:27 +00:00
Roman Pelmegov 84db8a0e09 issue-333 fix 2023-03-03 15:13:10 +00:00
Roman Pelmegov a58de7d461 issue-276 refactor 2023-03-03 14:53:17 +00:00
Roman Pelmegov c5b7947526 issue-333 use git archive 2023-03-03 14:52:02 +00:00
Roman Pelmegov 4d7182fd67 issue-333 last commit date 2023-03-03 14:33:55 +00:00
rpelmegov 302530f3c2
Update export_src.sh 2023-02-27 05:52:11 +03:00
rpelmegov 4b5ee64737
Update export_src.sh 2023-02-06 14:39:04 +03:00
rpelmegov f0bbbb9929
issue-276 add bad path alarm 2023-01-30 07:14:20 +03:00
Vladimir Makarov ce23c714e5
Merge pull request #332 from TouchInstinct/fix/makefile_identation
Common `Makefile` indentations converted to tabs
2023-01-16 13:28:44 +03:00
Vladimir Makarov 34dcae1d5c Common `Makefile` indentations converted to tabs 2023-01-16 12:22:21 +03:00
rpelmegov 45fbc84578
Update export_src.sh 2023-01-13 06:37:01 +03:00
rpelmegov 55ab60b6ea
Update export_src.sh
<a href="https://github.com/TouchInstinct/BuildScripts/issues/276">issue-276</a> Перед экспортом репозитория проверить файлы на невалидные символы в именах
2022-12-14 14:09:56 +03:00
Ivan Smolin 99281d2105
Merge pull request #330 from TouchInstinct/feature/makefile_shortcuts
add makefile shortcuts for iOS development
2022-12-12 12:11:23 +03:00
Ivan Smolin c4b340ec44 fix Makefile commands 2022-12-09 18:21:07 +03:00
Ivan Smolin a54982e482 add makefile shortcuts for iOS development 2022-12-08 19:00:03 +03:00
Vladimir Makarov 18cf87ea18
Merge pull request #328 from TouchInstinct/fix/default_options
`default_options` empty initializer added for correct method running
2022-10-19 11:37:08 +05:00
Vladimir Makarov 8050647847 `default_options` empty initializer added for correct method running 2022-10-18 19:50:58 +05:00
Vladimir Makarov 1b8d06cb0d
Merge pull request #327 from TouchInstinct/feature/api_key_configuring
API key configuration with environment variable added
2022-10-18 00:13:29 +05:00
Vladimir Makarov 7c22f6e4fc app_store_connect_api_key action calling moved to a separate method, api_key_path used directly 2022-10-17 17:47:18 +05:00
Vladimir Makarov d924c2a995 API key configuration with environment variable added 2022-10-17 12:12:23 +05:00
Anastasiya97 1af248ea15
Merge pull request #322 from TouchInstinct/swagger_api_generator_plugin
Add plugin for Swagger Api Generator
2022-09-16 11:01:30 +03:00
AnastasiyaK97 3dfdb3de1e small fixes 2022-09-14 19:38:43 +03:00
Vladimir Makarov b350383ae7
Merge pull request #324 from TouchInstinct/fix/api_codegen
API Generator codegen fixed
2022-09-06 13:49:45 +05:00
Vladimir Makarov 120551da8f `is_api_spec_under_source_control` method rewritten to return a bool value 2022-09-06 13:39:11 +05:00
Vladimir Makarov 65a5af2e31 API Generator codegen fixed 2022-09-05 23:46:34 +05:00
AnastasiyaK97 f389e6d806 Add plugin for Swagger Api Generator 2022-08-24 18:34:25 +03:00
Vladimir Makarov 8e13458c7f
Merge pull request #320 from TouchInstinct/feature/xmx_update
API Generator `-Xmx` parameter updated to 12Gb
2022-08-19 21:00:43 +05:00
Vladimir Makarov 3f7c655c8e API Generator `-Xmx` parameter updated to 12Gb 2022-08-19 20:51:28 +05:00
Ivan Smolin 732df3171f
Merge pull request #319 from TouchInstinct/feature/api_gen_update
update api_generator to support JDK 16+ and git-less run check
2022-08-08 12:03:07 +03:00
Ivan Smolin e082796930 update api_generator to support JDK 16+ and git-less run check 2022-08-08 11:27:06 +03:00
Александр 44a7fd7f48
Merge pull request #316 from TouchInstinct/multiple_files
Add multiple files generation optional flag
2022-08-02 15:55:14 +03:00
Aleksandr Shushkov 47a67edfff Add emply line 2022-08-02 15:50:52 +03:00
Aleksandr Shushkov 021e4f410e Removed rendundant notice 2022-08-02 15:49:11 +03:00
Aleksandr Shushkov fa8322b142 Change single file flag using 2022-08-02 15:48:09 +03:00
Aleksandr Shushkov 8f4e64bc86 Add multiple files generation optional flag 2022-08-02 10:28:05 +03:00
Ivan Smolin 76ac52accf
Merge pull request #315 from TouchInstinct/feature/support_inheritance_in_xcconfig_options
support inheritance in xcconfig options
2022-07-18 16:29:37 +03:00
Ivan Smolin b908265a3e support inheritance in xcconfig options 2022-07-18 15:30:21 +03:00
Ivan Smolin fe8f581c48
Merge pull request #312 from TouchInstinct/feature/build_logs_in_project_folder
add buildlog_path, speed up pod resolution, update build options helper submodule
2022-06-17 09:52:42 +03:00
Ivan Smolin 2e08a7c062 add buildlog_path, speed up pod resolution, update build options helper submodule 2022-06-17 09:35:06 +03:00
Kirill Nayduik 2753812843
Merge pull request #311 from TouchInstinct/migrate_to_maven_central
Migrate to maven central
2022-05-11 13:59:48 +03:00
Kirill Nayduik c985b62bf0 Revert disabling Android Linter 2022-05-11 13:58:56 +03:00
Kirill Nayduik 5ad312828c Migrate from jCenter to MavenCentral 2022-05-11 13:40:07 +03:00
Kirill Nayduik 68fdb3a815 Disable Android linter as a temporary workaround 2022-04-27 15:27:54 +03:00
Kirill Nayduik 9babae50e5
Merge pull request #308 from TouchInstinct/setupLint_before_evaluate
Setup lint before evaluate
2022-04-26 18:05:16 +03:00
Kirill Nayduik 938d5bd332 Configure setting up linter for projects in different evaluation states 2022-04-25 16:32:34 +03:00
Ivan Smolin 454ec643b3
Merge pull request #307 from TouchInstinct/feature/config_generator_abstract_target_support
add support for custom abstract targets in path to cocoapods xcconfigfiles.
2022-04-20 09:02:11 +03:00
Ivan Smolin 13e28f1b7f add support for custom abstract targets in path to cocoapods xcconfig files. closes #236 2022-04-19 10:33:21 +03:00
Ivan Smolin cd82b034ed
Merge pull request #304 from TouchInstinct/fix/codegen_fixes
fix codegen project name parameter; manage codegen folders for convenience
2022-03-30 14:15:10 +03:00
Ivan Smolin 57dbcee506 fix api-generator default spec folder path 2022-03-29 20:27:37 +03:00
Ivan Smolin 2d98944976 fix codegen project name parameter; manage codegen folders for convenience 2022-03-28 12:04:26 +03:00
Ivan Smolin f30d6ec374
Merge pull request #302 from TouchInstinct/feature/openapi_generator
add support for OpenAPI generation
2022-03-10 18:59:15 +03:00
Ivan Smolin 3220b9a30c fix padding API_NAME parameter to OpenAPI codegen 2022-03-10 18:55:18 +03:00
Ivan Smolin 31d621444c add support for OpenAPI generation 2022-03-10 16:01:57 +03:00
Vladimir Makarov 51f0bd3ee7
Merge pull request #300 from TouchInstinct/feature/firebase_distribution_groups
firebase_app_distribution groups file check added
2022-02-17 22:54:43 +05:00
Vladimir Makarov 6282671df7 firebase_app_distribution groups file check added 2022-02-17 15:59:17 +05:00
Kirill Nayduik f639e34579 Setting up linters for project before evaluate 2022-02-13 20:52:11 +03:00
Александр 2799169e21
Merge pull request #294 from TouchInstinct/feature/export_custom_profile
Add .zprofile exporting
2021-12-20 11:34:11 +03:00
Aleksandr Shushkov 9dad6d730c Add .zprofile exporting 2021-12-19 19:59:17 +03:00
Grigorii 082fc9a719
Merge pull request #291 from TouchInstinct/delete_detekt_UseDataClass
Deleted detekt.UseDataClass rule
2021-12-08 19:02:45 +03:00
Grigorii 3fd44c3bbd Deleted detekt.UseDataClass rule 2021-12-08 17:57:07 +03:00
Александр 6bc60ac0ab
Merge pull request #290 from TouchInstinct/fix/php_not_found
Add user enviroment for localization script
2021-12-07 16:10:29 +03:00
Aleksandr Shushkov 8991f8c2b8 Fix PR issues from @petropavel13 2021-12-07 16:05:29 +03:00
Aleksandr Shushkov d96c126fe2 Fix adding all paths 2021-12-06 21:15:47 +03:00
Aleksandr Shushkov d7acbb0080 Fix variable names 2021-12-06 20:55:16 +03:00
Aleksandr Shushkov 5145245266 Fix executes only export commands 2021-12-06 20:52:59 +03:00
Aleksandr Shushkov 2ec3289b5b Fix PR issues from @petropavel13 2021-12-06 17:37:09 +03:00
Aleksandr Shushkov 22abe5a792 Add failure exit code 2021-12-06 16:19:44 +03:00
Aleksandr Shushkov 1db4cfc771 Fix identation 2021-12-06 16:18:04 +03:00
Aleksandr Shushkov 6b21a9845a Add php installation check 2021-12-06 16:13:46 +03:00
Aleksandr Shushkov 5f009524a3 Add user enviroment for localization script 2021-12-06 16:08:24 +03:00
Александр d2ce219af4
Merge pull request #289 from TouchInstinct/fix/add_custom_enviroment
Add user defined enviroment for copy-paste decetion script
2021-12-01 16:01:38 +03:00
Aleksandr Shushkov c94fb44966 Fix PR issues from @petropavel13 2021-12-01 15:59:42 +03:00
Aleksandr Shushkov 0fc2eb03c6 Add user defined enviroment for copy-paste decetion script 2021-12-01 15:45:13 +03:00
Ivan Smolin 81499749a1
Merge pull request #230 from TouchInstinct/feature/unused
Add unused resources script
2021-11-03 18:30:43 +03:00
Timur Kayumov 0df12c3b26
Merge pull request #285 from TouchInstinct/fix/Linter_paths_generation
Fix file paths when collect changes for linting
2021-11-03 13:15:16 +02:00
Timur Kayumov c2259b12b2 Revert path argument 2021-11-03 13:13:00 +02:00
Timur Kayumov e1290036ff Fix file paths when collect changes for linting 2021-11-03 12:57:37 +02:00
svshkv b9b7dfe3f7
Merge pull request #282 from TouchInstinct/feature/fastlane_xcode_version
Added setting xcode version
2021-10-27 12:47:52 +03:00
Alexander Rutsman e1e15d619e Added search for the newest version on ruby 2021-10-27 11:20:34 +03:00
Alexander Rutsman 7061bad2ec Added search for the newest version 2021-10-20 16:01:13 +03:00
Alexander Rutsman b319b97522 Added default xcode version 2021-10-12 19:09:36 +03:00
Alexander Rutsman ecc34d227a Added default xcode version 2021-10-12 18:42:00 +03:00
Alexander Rutsman e975ff0ed0 Added setting xcode version 2021-10-12 15:49:26 +03:00
Loupehope befc933117
Merge pull request #281 from TouchInstinct/feat/remove-lazy_var
feat: remove lazy_var
2021-09-23 19:36:56 +03:00
Vlad Suhomlinov b9429f8aaf feat: remove lazy_var 2021-09-23 19:31:39 +03:00
Loupehope ee5299c318
Merge pull request #279 from TouchInstinct/tech/lint_only_changed_files
feat: lint only changed files
2021-09-16 10:34:52 +03:00
Vlad Suhomlinov 1678af0116 docs: remove useless docs 2021-09-15 19:29:21 +03:00
Vlad Suhomlinov f98c1af719 refactor: correct lint_files_path creation 2021-09-14 08:51:53 +03:00
Vlad Suhomlinov a455072e14 refactor: revert xcargs 2021-09-13 19:26:01 +03:00
Vlad Suhomlinov 44d4ff9f74 refactor: correct fastfile 2021-09-13 19:19:37 +03:00
Vlad Suhomlinov 494bc4886b refactor: add FORCE_LINT to fastlane 2021-09-13 19:10:35 +03:00
Vlad Suhomlinov db99ec0009 refactor: add gitignore 2021-09-13 18:47:44 +03:00
Vlad Suhomlinov 9e8d088017 refactor: add FORCE_LINT arg 2021-09-13 18:47:37 +03:00
Vlad Suhomlinov 5a6dd866f7 refactor: typo 2021-09-13 11:32:21 +03:00
Vlad Suhomlinov 088114cb5c refactor: enable --use-alternative-excluding 2021-09-12 11:49:37 +03:00
Vlad Suhomlinov 40f6d12e15 refactor: enable --force-exclude 2021-09-11 13:21:48 +03:00
Vlad Suhomlinov e725685a9e refactor: add allow_zero_lintable_files to swiftlint 2021-09-11 13:01:10 +03:00
Vlad Suhomlinov 8094a04ab3 feat: lint only changed files 2021-09-11 12:48:55 +03:00
Ivan Smolin 1e95815cce
Merge pull request #277 from TouchInstinct/feature/export_project_documentation
GIT_BRANCH environment variable handling + add some docs
2021-08-31 12:21:18 +03:00
Ivan Smolin 54fdb267bc GIT_BRANCH environment variable handling + add some docs 2021-08-30 15:34:50 +03:00
Dmitriy 501ff89f28
Merge pull request #272 from TouchInstinct/feature/lazy_var_lint
Update .swiftlint.yml
2021-08-12 11:02:05 +03:00
Dmitriy 51e9a3b190
Update .swiftlint.yml 2021-08-09 12:11:51 +03:00
Dmitriy 9ae6e92e66
Update .swiftlint.yml
pr fix
2021-08-09 12:10:27 +03:00
Ivan Smolin f5b21784fe
Merge pull request #273 from TouchInstinct/feature/install_env_script
add install_env script for build phases
2021-08-09 12:05:38 +03:00
Ivan Smolin 1545208c46 add install_env script for build phases 2021-08-09 11:58:54 +03:00
Dmitriy 5ac9fd8232
Update .swiftlint.yml
add lazy var rule to swiftlint
2021-08-09 11:55:43 +03:00
Ivan Smolin cbf10f95f9
Merge pull request #269 from TouchInstinct/feature/localization_script_improvements
localization script refactoring
2021-08-04 11:03:51 +03:00
Ivan Smolin c2104468bd remove debug output 2021-08-04 11:00:50 +03:00
Ivan Smolin 7c4149778c add backslashes before characters that need to be escaped 2021-08-04 10:45:04 +03:00
Ivan Smolin 6cdd30a872 fix workspace path for code generation 2021-07-28 22:02:43 +03:00
Ivan Smolin 8d0449714b set xcconfig for framework targets as well 2021-07-28 15:58:18 +03:00
Ivan Smolin 6a032c324f replace existing options when generating xcconfigs 2021-07-27 15:03:21 +03:00
Ivan Smolin 63ecad8042 remove hadcoded CODE_SIGN_STYLE key; remove PROVISIONING_PROFILE_SPECIFIER auto generation 2021-07-22 09:29:22 +03:00
Ivan Smolin 0d555bea19 generate xcodeproj before increment build number 2021-07-21 21:06:58 +03:00
Ivan Smolin 82a44c2a1c disable cyrillic_strings rule for String+Localization.swift 2021-07-21 17:56:06 +03:00
Ivan Smolin cf2aa3f7ee localization script refactoring 2021-07-21 17:18:13 +03:00
Ivan Smolin 73abd1564f
Merge pull request #268 from TouchInstinct/feature/xcodegen_support
add xcodegen support
2021-07-21 14:00:43 +03:00
Ivan Smolin ad2172cd27 add xcodegen support 2021-07-21 13:41:14 +03:00
svshkv c302278751
Merge pull request #266 from TouchInstinct/feature/firebase_separation
Feature/firebase separation
2021-07-16 12:24:58 +03:00
Alexander Rutsman 3c5135ea5e Git revert HEAD 2021-07-07 15:23:29 +03:00
Alexander Rutsman efb5c8b60e Edit timeout 2021-07-06 12:56:18 +03:00
Alexander Rutsman 3f70495e4b Removed google service prefix 2021-07-05 16:29:00 +03:00
Ivan Smolin 1b86887958
Merge pull request #265 from TouchInstinct/fix/fastlane_2.187
replace timeout: false with timeout: 0
2021-07-04 17:03:55 +03:00
Ivan Smolin e0913de8a3 replace timeout: false with timeout: 0 according to https://github.com/fastlane/fastlane/pull/18894 2021-07-04 16:57:00 +03:00
Loupehope 79105bf5f9
Merge pull request #261 from TouchInstinct/feature/move_to_workspace
Feature - move to workspace
2021-05-21 12:48:00 +03:00
Vlad Suhomlinov 045b57e72d refactor: complete app name 2021-05-13 17:56:37 +03:00
Vlad Suhomlinov fa9ccef66b refactor: correct typo 2021-05-13 17:47:15 +03:00
Vlad Suhomlinov a132bcd939 refactor: update path to xcworkspace 2021-05-13 17:41:44 +03:00
Vlad Suhomlinov 908f69b1f8 feat: run code generation for workspace 2021-05-13 17:27:51 +03:00
Vlad e9dcba923c Update exe 2020-10-02 12:40:17 +03:00
Vlad bbe5e3a908 Code correction 2020-10-02 11:40:39 +03:00
Vlad ef6d0eb3cc Code correction 2020-10-02 11:28:06 +03:00
Vlad aa152a8fd4 Code correction 2020-10-02 11:21:45 +03:00
Vlad c11f3d4204 Update exe 2020-10-02 11:14:35 +03:00
Vlad 9a4abfd68b Code correction 2020-10-02 10:59:23 +03:00
Vlad d99cf7cb03 Code correction 2020-10-02 10:55:51 +03:00
Vlad ef8a3b6cf5 Add unused resources script 2020-10-02 10:30:35 +03:00
54 changed files with 1677 additions and 936 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# macOS
.DS_Store

View File

@ -1 +1,26 @@
# BuildScripts
## Настройки форматирования
Позволяют настроить одинаковое форматирования кода в Android Studio у всех, кто работает на проекте.
Настройки соответствуют
[Правилам оформления Kotlin кода](https://styleguide.docs.touchin.ru/Coding/KotlinCodestyle.html)
Есть два варианта использования: подключить к проекту или импортировать схему в Android Studio.
### Как подключить к проекту:
1. Скопировать директорию [`codeStyles`](./codeStyles) в директорию проекта `.idea`
2. Добавить в файл `.gitignore` строку `!.idea/codeStyles`
3. Перезапустить Android Studio, чтобы настройки применились
При таком варианте настройки будут применены у всех, кто работает на проекте.
И только для одного конкретного проекта.
### Как импортировать схему в Android Studio:
1. Скачать схему [`codeStyles/Project.xml`](./codeStyles/Project.xml)
2. В Android Studio перейти в `File` > `Settings` > `Editor` > `Code Style`
3. Нажать на шестеренку справа от выпадающего списка схем и выбрать `Import Scheme`
4. В открывшемся окне указать путь до сохраненной схемы и нажать `ОК`
5. В открывшемся окне ввести название новой схемы и нажать `ОК`

View File

@ -1,8 +0,0 @@
<application>
<component name="CodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value />
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="TouchInstinct" />
</component>
</application>

View File

@ -1,5 +0,0 @@
<application>
<component name="CodeStyleSchemeSettings">
<option name="CURRENT_SCHEME_NAME" value="TouchInstinct" />
</component>
</application>

249
codeStyles/Project.xml Normal file
View File

@ -0,0 +1,249 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="RIGHT_MARGIN" value="120" />
<option name="SOFT_MARGINS" value="100" />
<AndroidXmlCodeStyleSettings>
<option name="LAYOUT_SETTINGS">
<value>
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
</value>
</option>
<option name="MANIFEST_SETTINGS">
<value>
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
</value>
</option>
<option name="OTHER_SETTINGS">
<value>
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
</value>
</option>
</AndroidXmlCodeStyleSettings>
<JavaCodeStyleSettings>
<option name="GENERATE_FINAL_LOCALS" value="true" />
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
<option name="ANNOTATION_PARAMETER_WRAP" value="1" />
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="android" static="false" withSubpackages="true" />
<emptyLine />
<package name="com" static="false" withSubpackages="true" />
<emptyLine />
<package name="junit" static="false" withSubpackages="true" />
<emptyLine />
<package name="net" static="false" withSubpackages="true" />
<emptyLine />
<package name="org" static="false" withSubpackages="true" />
<emptyLine />
<package name="java" static="false" withSubpackages="true" />
<emptyLine />
<package name="javax" static="false" withSubpackages="true" />
<emptyLine />
<package name="" static="false" withSubpackages="true" />
<emptyLine />
<package name="" static="true" withSubpackages="true" />
<emptyLine />
</value>
</option>
<option name="JD_P_AT_EMPTY_LINES" value="false" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value />
</option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="true" />
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="true" />
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="true" />
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="true" />
<option name="CONTINUATION_INDENT_IN_ELVIS" value="true" />
<option name="ALLOW_TRAILING_COMMA" value="true" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair header="h" source="cpp" />
<pair header="h" source="c" />
</extensions>
</Objective-C-extensions>
<XML>
<option name="XML_KEEP_BLANK_LINES" value="1" />
</XML>
<codeStyleSettings language="JAVA">
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="RESOURCE_LIST_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<option name="WRAP_LONG_LINES" value="true" />
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
<option name="ENUM_CONSTANTS_WRAP" value="5" />
</codeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ENUM_CONSTANTS_WRAP" value="5" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@ -1,254 +0,0 @@
<code_scheme name="TouchInstinct">
<option name="GENERATE_FINAL_LOCALS" value="true" />
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="android" withSubpackages="true" static="false" />
<emptyLine />
<package name="com" withSubpackages="true" static="false" />
<emptyLine />
<package name="junit" withSubpackages="true" static="false" />
<emptyLine />
<package name="net" withSubpackages="true" static="false" />
<emptyLine />
<package name="org" withSubpackages="true" static="false" />
<emptyLine />
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="true" />
<emptyLine />
</value>
</option>
<option name="RIGHT_MARGIN" value="150" />
<option name="JD_P_AT_EMPTY_LINES" value="false" />
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" />
</AndroidXmlCodeStyleSettings>
<JavaCodeStyleSettings>
<option name="DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION" value="true" />
<option name="ANNOTATION_PARAMETER_WRAP" value="1" />
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
</JavaCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" />
<pair source="c" header="h" />
</extensions>
</Objective-C-extensions>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="150" />
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="RESOURCE_LIST_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="1" />
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
<option name="TERNARY_OPERATION_WRAP" value="1" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="1" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE" value="true" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<option name="WRAP_LONG_LINES" value="true" />
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
<option name="ENUM_CONSTANTS_WRAP" value="2" />
</codeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>

View File

@ -7,7 +7,7 @@ plugins {
// The kotlin-dsl plugin requires a repository to be declared
repositories {
jcenter()
mavenCentral()
google()
}
@ -36,6 +36,10 @@ gradlePlugin {
id = "api-generator-android"
implementationClass = "apigen.ApiGeneratorAndroidPlugin"
}
create("swagger-generator-android") {
id = "swagger-generator-android"
implementationClass = "apigen.SwaggerApiGeneratorAndroidPlugin"
}
create("api-generator-backend") {
id = "api-generator-backend"
implementationClass = "apigen.ApiGeneratorBackendPlugin"

View File

@ -0,0 +1,91 @@
package apigen
import org.gradle.api.Action
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.repositories
class SwaggerApiGeneratorAndroidPlugin : Plugin<Project> {
private companion object {
const val GENERATOR_CONFIG = "swaggerCodegen"
const val GENERATOR_VERSION = "3.0.34"
const val TI_GENERATOR_CONFIG = "TIKotlin-swagger-codegen"
const val TI_GENERATOR_VERSION = "1.0.0"
const val GENERATOR_EXT_NAME = "swaggerApiGenerator"
const val MAVEN_URL = "https://maven.dev.touchin.ru"
}
override fun apply(target: Project) {
with(target) {
repositories {
maven {
url = uri(MAVEN_URL)
metadataSources {
artifact()
}
}
}
configurations.create(GENERATOR_CONFIG)
configurations.create(TI_GENERATOR_CONFIG)
dependencies {
add(TI_GENERATOR_CONFIG, "ru.touchin:TIKotlin-swagger-codegen:$TI_GENERATOR_VERSION")
add(GENERATOR_CONFIG, "io.swagger.codegen.v3:swagger-codegen-cli:$GENERATOR_VERSION")
}
extensions.create<SwaggerApiGeneratorExtension>(GENERATOR_EXT_NAME)
val apiGenTask = createSwaggerApiGeneratorTask()
gradle.projectsEvaluated {
tasks.getByName("preBuild").dependsOn(apiGenTask)
}
}
}
protected fun Project.getExtension(): SwaggerApiGeneratorExtension = extensions.getByName(GENERATOR_EXT_NAME) as SwaggerApiGeneratorExtension
private fun Project.createSwaggerApiGeneratorTask(): Task = tasks.create(GENERATOR_CONFIG).doLast {
val extension = getExtension()
val taskWorkingDir = extension.taskWorkingDir ?: throw IllegalStateException("Configure taskWorkingDir for swagger generator plugin")
val apiSchemesFilePath = extension.apiSchemesFilePath ?: throw IllegalStateException("Configure sourceFilePath for swagger generator plugin")
val outputDir = extension.outputDir ?: throw IllegalStateException("Configure outputDir for swagger generator plugin")
val projectName = extension.projectName ?: throw IllegalStateException("Configure projectName for swagger generator plugin")
javaexec {
workingDir = file(taskWorkingDir)
classpath = files(configurations.getByName(GENERATOR_CONFIG).asPath,
configurations.getByName(TI_GENERATOR_CONFIG).asPath)
main = "io.swagger.codegen.v3.cli.SwaggerCodegen"
args = listOfNotNull(
"generate",
"-i",
apiSchemesFilePath,
"-l",
"TIKotlinCodegen",
"-o",
outputDir,
"--additional-properties",
"projectName=$projectName"
)
}
}
}
open class SwaggerApiGeneratorExtension(
var taskWorkingDir: String? = null,
var apiSchemesFilePath: String? = null,
var outputDir: String? = null,
var projectName: String? = null
)
fun Project.swaggerApiGenerator(configure: Action<SwaggerApiGeneratorExtension>): Unit =
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("swaggerApiGenerator", configure)

View File

@ -33,8 +33,8 @@ class AndroidLinter : Linter {
.flatten()
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
project.gradle.projectsEvaluated {
project.subprojects
project.beforeEvaluate {
subprojects
.mapNotNull { it.extensions.findByType<AppExtension>() }
.first()
.lintOptions.apply {
@ -45,8 +45,8 @@ class AndroidLinter : Linter {
htmlReport = false
isCheckDependencies = true
disable("MissingConstraints", "VectorRaster")
xmlOutput = project.getLintReportFile()
lintConfig = project.file("${extension.buildScriptDir}/static_analysis_configs/lint.xml")
xmlOutput = getLintReportFile()
lintConfig = file("${extension.buildScriptDir}/static_analysis_configs/lint.xml")
}
}
}

View File

@ -34,15 +34,18 @@ class CpdLinter : Linter {
}
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
project.extensions.findByType<CpdExtension>()!!.apply {
isSkipLexicalErrors = true
language = "kotlin"
minimumTokenCount = 60
}
project.tasks.withType<Cpd> {
reports.xml.destination = project.getCpdReportFile()
ignoreFailures = true
source = project.getSources(extension.excludes)
project.afterEvaluate {
extensions.findByType<CpdExtension>()!!.apply {
isSkipLexicalErrors = true
language = "kotlin"
minimumTokenCount = 60
}
tasks.withType<Cpd> {
reports.xml.required.set(true)
reports.xml.destination = getCpdReportFile()
ignoreFailures = true
source = getSources(extension.excludes)
}
}
}

View File

@ -32,27 +32,27 @@ class DetektLinter : Linter {
.flatten()
override fun setupForProject(project: Project, extension: StaticAnalysisExtension) {
project
.tasks
.withType(Detekt::class.java) {
exclude("**/test/**")
exclude("resources/")
exclude("build/")
exclude("tmp/")
jvmTarget = "1.8"
project.afterEvaluate {
tasks.withType(Detekt::class.java) {
exclude("**/test/**")
exclude("resources/")
exclude("build/")
exclude("tmp/")
jvmTarget = "1.8"
config.setFrom(project.files("${extension.buildScriptDir!!}/static_analysis_configs/detekt-config.yml"))
reports {
txt.enabled = false
html.enabled = false
xml {
enabled = true
destination = project.getDetektReportFile()
}
config.setFrom(files("${extension.buildScriptDir!!}/static_analysis_configs/detekt-config.yml"))
reports {
txt.enabled = false
html.enabled = false
xml {
enabled = true
destination = getDetektReportFile()
}
source = project.getSources(extension.excludes)
}
source = getSources(extension.excludes)
}
}
}
override fun getTaskNames(project: Project, buildType: String?): List<String> = listOf(":detekt")

View File

@ -28,15 +28,13 @@ class StaticAnalysisAndroidPlugin : StaticAnalysisPlugin() {
)
}
}
}
}
}
//TODO: return CpdLinter after finding better way to disable it
override fun createLinters(): List<Linter> = listOf(
DetektLinter(),
CpdLinter(),
AndroidLinter()
)

View File

@ -26,9 +26,7 @@ abstract class StaticAnalysisPlugin : Plugin<Project> {
val linters = createLinters()
afterEvaluate {
linters.forEach { it.setupForProject(target, extensions.getByType()) }
}
linters.forEach { it.setupForProject(target, extensions.getByType()) }
gradle.projectsEvaluated {
createStaticAnalysisTasks(target, linters)

View File

@ -1,31 +1,71 @@
#!/bin/sh
# Description:
# Creates archive with source code of multiple repositories.
#
# Parameters:
# $1 - github repository name without suffix (project name).
# $2, $3, ..., $n - repository suffixes (platforms).
#
# Optional environment variables:
# GIT_BRANCH - branch to use. Default - master.
#
# Example of usage:
# export_src.sh TestProject ios android backend
# GIT_BRANCH="develop" ./export_src.sh TestProject ios web
#
if [ -z "${GIT_BRANCH}" ]; then
GIT_BRANCH="master"
fi
LAST_COMMIT_DATE=""
PROJECT_NAME=$1
SRC_FOLDER_NAME=${PROJECT_NAME}-src-$(date +%F)
SRC_DIR=./${SRC_FOLDER_NAME}
SRC_FOLDER_NAME="${PROJECT_NAME}-src"
SRC_DIR="./${SRC_FOLDER_NAME}"
COMMAND_LINE_ARGUMENTS=$@
clone_platform() {
PROJECT_DIR=$1
PROJECT_NAME=$1
PLATFORM=$2
git clone --recurse-submodules -j8 git@github.com:TouchInstinct/${PROJECT_DIR}-${PLATFORM}.git --branch master
if git clone --recurse-submodules -j8 "ssh://git@git.ti:7999/touchinstinct/${PROJECT_NAME}-${PLATFORM}.git" --branch "${GIT_BRANCH}"; then
cd ${PROJECT_NAME}-${PLATFORM}
COMMIT_DATE=`git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d'`
if [[ $LAST_COMMIT_DATE < $COMMIT_DATE ]]; then
LAST_COMMIT_DATE="${COMMIT_DATE}"
fi
cd ..
else
exit 1
fi
}
mkdir -p ${SRC_DIR}
cd ${SRC_DIR}
mkdir -p "${SRC_DIR}"
cd "${SRC_DIR}"
for argument in ${COMMAND_LINE_ARGUMENTS}
do
if [ $argument != $PROJECT_NAME ]
then
if [ $argument != $PROJECT_NAME ]; then
platform=${argument} # all arguments after project name treated as platforms
clone_platform ${PROJECT_NAME} ${platform}
fi
done
ERR_PATHS=$(find . -name "*[<>:\\|?*]*" | xargs -I %s echo "- %s")
if [ "$ERR_PATHS" ]; then
echo "Export aborted! Invalid characters found in file or directories name(s):\n$ERR_PATHS"
exit 1
fi
if [ -z "${EXPORT_DATE}" ]; then
EXPORT_DATE="${LAST_COMMIT_DATE}"
fi
find . -name ".git*" -print0 | xargs -0 rm -rf
zip -r ${SRC_FOLDER_NAME}.zip .
zip -r -q "${SRC_FOLDER_NAME}-${EXPORT_DATE}".zip .
open .

View File

@ -387,9 +387,6 @@ style:
UnusedPrivateMember:
active: true
allowedNames: "(_|ignored|expected|serialVersionUID)"
UseDataClass:
active: true
excludeAnnotatedClasses: ""
UtilityClassWithPublicConstructor:
active: false
VarCouldBeVal:

View File

@ -15,7 +15,6 @@ opt_in_rules:
# idiomatic
- legacy_random
- legacy_multiple
- pattern_matching_keywords
- redundant_nil_coalescing
@ -32,8 +31,12 @@ opt_in_rules:
- fatal_error_message
- extension_access_modifier
- explicit_init
- prefer_zero_over_explicit_init
- fallthrough
- unavailable_function
- prefer_zero_over_explicit_init
- discouraged_assert
- discouraged_none_name
- shorthand_optional_binding
# style
@ -55,29 +58,46 @@ opt_in_rules:
- closure_spacing
- closure_end_indentation
- prefer_self_type_over_type_of_self
- closure_parameter_position
- comma_inheritance
- self_binding
- prefer_self_in_static_references
- direct_return
- period_spacing
# lint
- private_action
- private_outlet
- prohibited_super_call
- unused_import
- unused_declaration
- identical_operands
- overridden_super_call
- unowned_variable_capture
- strong_iboutlet
- lower_acl_than_parent
- comment_spacing
- ibinspectable_in_extension
- private_subject
- unhandled_throwing_task
# metrics
- enum_case_associated_values_count
analyzer_rules:
- capture_variable
- typesafe_array_init
- unused_declaration
- unused_import
excluded:
- Carthage
- Pods
- Generated
- "**/Generated"
- "**/Resources"
- ".gem"
- "**/*.app"
line_length:
warning: 128
@ -109,40 +129,30 @@ identifier_name:
- id
- ok
- URL
- qr
- x
- y
- z
warning_threshold: 1
allow_zero_lintable_files: true
custom_rules:
# General
uiwebview_disabled:
included: ".*.swift"
name: "UIWebView Usage Disabled"
regex: 'UIWebView'
message: "Do not use UIWebView. Use WKWebView Instead. https://developer.apple.com/reference/uikit/uiwebview"
severity: error
native_print:
name: "print -> DDLog"
regex: '(print|NSLog)\('
message: "Please use CocoaLumberjack instead `print` and `NSlog`"
severity: error
uiedge_insets_zero:
name: "UIEdgeInsets .zero"
regex: '\(top: 0, left: 0, bottom: 0, right: 0\)'
message: "Please use short init `.zero`."
severity: error
let_variable:
name: "Let Variable"
regex: 'var\s\w*(:|(\s=))\sVariable'
message: "Please make variable using `let`."
unsecure_logging:
name: "Unsecure logging"
regex: '\s(print|debugPrint|NSLog)\('
message: "Please use os_log or remove this debug statement"
severity: error
excluded_match_kinds:
- comment
- comment.mark
- comment.url
- doccomment
- doccomment.field
marks_style:
name: "Marks"
@ -163,19 +173,12 @@ custom_rules:
message: "Type definition not needed"
severity: error
unowned:
name: "Unowned"
unsafe_unowned:
name: "Unsafe unowned usage"
regex: 'unowned'
message: "Please use `weak` instead. "
message: "Please use `weak` instead."
severity: error
continue_keyword:
name: "Continue"
regex: 'continue'
message: "Don't use continue instruction"
severity: error
match_kinds: keyword
cyrillic_strings:
name: "Cyrillic strings"
regex: '[а-яА-Я]+'
@ -235,12 +238,6 @@ custom_rules:
message: "Use сontentView instead of self for addSubview or addSubviews methods in cell."
severity: warning
redundant_type_annotation_bool:
name: "Redundant type annotation for Bool"
regex: '\s((var|let))\s{1,}\w+ *((: *Bool *=)|((\w| |<|>|:)*= *BehaviorRelay<Bool>\( *value *:)) *((true)|(false))'
message: "Using a type annotation for Bool is redundant."
severity: warning
parameter_repetition:
name: "Parameter repetition"
regex: 'func ((\w+([A-Z]\w+))|(\w+)) *(<[^>]+>)? *\( *(?i)(\3|\4):'

View File

@ -3,8 +3,8 @@ file_link=$2
folder=$3
flag_of_delete=$4
readonly key_of_delete="--remove-cached"
readonly default_folder="./Downloads"
key_of_delete="--remove-cached"
default_folder="./Downloads"
if [[ ${folder} = ${key_of_delete} ]]; then
folder="${default_folder}"

View File

@ -1,14 +1,13 @@
<?php
$PRODUCT_NAME = $argv[1];
$LOCALIZATION_PATH = $argv[1];
$COMMON_STRINGS_PATH = $argv[2];
$BUNDLE = $argv[3];
function createFolder($path) {
if (!file_exists($path)) {
mkdir($path, 0777, true);
}
}
$localization = './'.$PRODUCT_NAME.'/Resources/Localization/';
$baseFile = file_get_contents(array_pop(glob($COMMON_STRINGS_PATH.'/default*.json')));
$baseJson = json_decode($baseFile, true);
@ -31,25 +30,26 @@
}
$ios_strings = preg_replace('/(\\\\)(u)([0-9a-fA-F]{4})/', '$1U$3', $ios_strings);
$lproj = $localization.$languageName.'.lproj/';
$lproj = $LOCALIZATION_PATH.$languageName.'.lproj/';
createFolder($lproj);
file_put_contents($lproj.'Localizable.strings', $ios_strings);
if($isBase) {
createFolder($localization.'Base.lproj/');
file_put_contents($localization.'Base.lproj/Localizable.strings', $ios_strings);
createFolder($LOCALIZATION_PATH.'Base.lproj/');
file_put_contents($LOCALIZATION_PATH.'Base.lproj/Localizable.strings', $ios_strings);
$ios_swift_strings = 'import Foundation'.PHP_EOL.PHP_EOL.
'// swiftlint:disable superfluous_disable_command'.PHP_EOL.
'// swiftlint:disable line_length'.PHP_EOL.
'// swiftlint:disable file_length'.PHP_EOL.
'// swiftlint:disable cyrillic_strings'.PHP_EOL.
'// swiftlint:disable identifier_name'.PHP_EOL.PHP_EOL.
'public extension String {'.PHP_EOL;
foreach ($json as $key=>$value) {
$value_without_linefeed = preg_replace("/\r|\n/", " ", $value);
$ios_swift_strings .= "\t/// ".$value_without_linefeed."\n\t".'static let '.preg_replace_callback('/_(.?)/', function ($m) { return strtoupper($m[1]); }, $key).' = NSLocalizedString("'.$key.'", comment: "")'."\n".PHP_EOL;
$ios_swift_strings .= "\t/// ".$value_without_linefeed."\n\t".'static let '.preg_replace_callback('/_(.?)/', function ($m) { return strtoupper($m[1]); }, $key).' = NSLocalizedString("'.$key.'", bundle: '.$BUNDLE.', comment: "'.addslashes($value_without_linefeed).'")'."\n".PHP_EOL;
}
$ios_swift_strings .= '}'.PHP_EOL;
file_put_contents($localization.'String+Localization.swift', $ios_swift_strings);
file_put_contents($LOCALIZATION_PATH.'String+Localization.swift', $ios_swift_strings);
}
}
?>

View File

@ -0,0 +1,39 @@
#!/bin/sh
# Description:
# Add user defined enviroment if programm not found
#
# Parameters:
# $1 - programm
#
# Examples of usage:
# . install_env.sh pmd
#
# When you run Git from the command line, it runs in the environment as set up by your Shell.
# GUI OS X apps, however, have no knowledge about your shell - and the PATH environment can be changed in many different places.
# Export our profile with path by ourselves
function source_home_file {
file="$HOME/$1"
if [[ -f "${file}" ]]; then
if ! source "${file}"; then
export_commands="$(cat "${file}" | grep "^export PATH=")"
while read export_command
do
eval "$export_command"
done <<< "$export_commands"
fi
fi
return 1
}
# Use specific exec due to Xcode has custom value of $PATH
if [ -z "$(which $1)" ]; then
source_home_file ".bash_profile" || source_home_file ".zshrc" || source_home_file ".zprofile" || true
echo "User defined enviroment has been set for ${1}"
fi

14
xcode/bootstrap/Brewfile Normal file
View File

@ -0,0 +1,14 @@
# Working environment
brew "rbenv" # ruby + bundler
brew "gettext"
# Code, configs and project generation
brew "php"
brew "python"
brew "xcodegen"
# code quality
brew "pmd"
# CI badge
# brew "imagemagick"

9
xcode/bootstrap/Gemfile Normal file
View File

@ -0,0 +1,9 @@
source "https://rubygems.org"
gem "cocoapods"
gem "fastlane"
gem 'mustache' # for config generator
gem 'xcode-install'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)

91
xcode/bootstrap/Makefile Normal file
View File

@ -0,0 +1,91 @@
GREEN := $(shell tput -Txterm setaf 2)
YELLOW := $(shell tput -Txterm setaf 3)
WHITE := $(shell tput -Txterm setaf 7)
RESET := $(shell tput -Txterm sgr0)
RUBY_VERSION="2.7.6"
open_project=(open *.xcworkspace)
install_dev_certs=(bundle exec fastlane InstallDevelopmentSigningIdentities)
install_pods=(bundle exec pod install || bundle exec pod install --repo-update)
init_rbenv=(if command -v rbenv &> /dev/null; then eval "$$(rbenv init -)"; fi)
TARGET_MAX_CHAR_NUM=20
## Show help
help:
@echo ''
@echo 'Использование:'
@echo ' ${YELLOW}make${RESET} ${GREEN}<target>${RESET}'
@echo ''
@echo 'Команды:'
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
helpMessage = match(lastLine, /^## (.*)/); \
if (helpMessage) { \
helpCommand = substr($$1, 0, index($$1, ":")-1); \
helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \
printf " ${YELLOW}%-$(TARGET_MAX_CHAR_NUM)s${RESET} ${GREEN}%s${RESET}\n", helpCommand, helpMessage; \
} \
} \
{ lastLine = $$0 }' $(MAKEFILE_LIST)
## Инициализирует проект и устанавливает системные утилиты
init:
brew bundle
$(call init_rbenv)
rbenv install -s ${RUBY_VERSION}
rbenv global ${RUBY_VERSION}
if ! gem spec bundler > /dev/null 2>&1; then\
echo "bundler gem is not installed!";\
-sudo gem install bundler;\
fi
bundle install
xcodegen
$(call install_pods)
bundle exec fastlane install_plugins
$(call install_dev_certs)
$(call open_project)
git config --local core.hooksPath .githooks
## Устанавливает поды
pod:
$(call install_pods)
## Запускает генерацию файла проекта
gen:
xcodegen
## Устанавливает сертификат и профили для запуска на девайсе
dev_certs:
$(call install_dev_certs)
## Открывает папку для ручного редактирования сертификатов и профайлов
update_certs:
bundle exec fastlane ManuallyUpdateCodeSigning
## Поднимает версию приложения (параметр "X.Y.Z")
bumpAppVersion:
ifeq ($(version),undefined)
@echo "Version parameter is missing (ex: x.y.z)" $(target)
else
bundle exec fastlane run increment_version_number version_number:$(version)
endif
## Позволяет быстро открыть workspace проекта
start:
$(call open_project)
## Очищает содержимое папки DerivedData
clean:
rm -rf ~/Library/Developer/Xcode/DerivedData/*

View File

@ -0,0 +1,25 @@
#!/bin/sh
# Description:
# Runs full linting and copy-paste-detection for project
#
# Required environment variables:
# SRCROOT - project directory.
# SCRIPT_DIR - directory of current script.
#
# Optional environment variables:
# See swiftlint.sh and copy_paste_detection.sh for complete list of available variables
#
# Example of usage:
# ./full_code_lint.sh
#
if [ -z "${SCRIPT_DIR}" ]; then
SCRIPT_DIR=${SRCROOT}/build-scripts/xcode/build_phases
fi
. ${SRCROOT}/build-scripts/xcode/aux_scripts/install_env.sh swiftlint
FORCE_LINT=true; . ${SCRIPT_DIR}/swiftlint.sh
. ${SRCROOT}/build-scripts/xcode/aux_scripts/install_env.sh cpd
. ${SCRIPT_DIR}/copy_paste_detection.sh Localization Generated Pods

View File

@ -0,0 +1,22 @@
#!/bin/sh
# Description:
# Runs incremental linting for project
#
# Required environment variables:
# SRCROOT - project directory.
# SCRIPT_DIR - directory of current script.
#
# Optional environment variables:
# See swiftlint.sh for complete list of available variables
#
# Example of usage:
# ./incremetal_code_lint.sh
#
if [ -z "${SCRIPT_DIR}" ]; then
SCRIPT_DIR=${SRCROOT}/build-scripts/xcode/build_phases
fi
. ${SRCROOT}/build-scripts/xcode/aux_scripts/install_env.sh swiftlint
. ${SCRIPT_DIR}/swiftlint.sh

6
xcode/bootstrap/setup.command Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_DIR="${DIR}/../../../"
make init -C ${PROJECT_DIR}

View File

@ -5,9 +5,16 @@
#
# Parameters:
# $1 - api generator version.
# $2 - path to generated code directory
#
# Required environment variables:
# SRCROOT - path to project folder.
#
# Optional environment variables:
# OUTPUT_PATH - path to Generated folder.
# API_SPEC_DIR - path to api specification folder
# VERBOSE - print debug messages
# API_NAME - project name that will be used by generator (example: OUTPUT_PATH/API_NAME/Classes )
#
# Examples of usage:
# . api_generator.sh 1.4.0-beta1
@ -17,112 +24,301 @@
readonly EXIT_SUCCESS=0
readonly EXIT_FAILURE=1
readonly TRUE=0
readonly FALSE=1
readonly TRUE=1
readonly FALSE=0
readonly LOG_TAG="API-GENERATOR"
notice()
{
echo "${LOG_TAG}:NOTICE: ${1}" >&2
}
debug()
{
if [ ! -z "${VERBOSE}" ]; then
echo "${LOG_TAG}:DEBUG: ${1}" >&2
fi
}
exit_on_failure()
{
eval ${1}
local -r EXIT_CODE=$?
if [ ${EXIT_CODE} -ne 0 ]; then
echo "Recent command: \`${1}\` failed with code ${EXIT_CODE}"
exit ${EXIT_CODE}
fi
}
is_force_run()
{
if [ -z "${FORCE_RUN}" ]; then
return ${FALSE}
echo ${FALSE}
return
fi
local -r STR_MODE=`tr "[:upper:]" "[:lower:]" <<< ${FORCE_RUN}`
if [ ${STR_MODE} == "yes" ] || [ ${STR_MODE} == "true" ] || [ ${STR_MODE} == "1" ]; then
return ${TRUE}
echo ${TRUE}
else
echo ${FALSE}
fi
return ${FALSE}
}
get_current_commit()
is_single_file()
{
if [ -z "${CURRENT_COMMIT}" ]; then
if [ -z "${REPO_PATH}" ]; then
if [ ! -z "${1}" ]; then
echo `git -C ${1} rev-parse --verify HEAD`
else
echo `git rev-parse --verify HEAD`
fi
if [ -z "${SINGLE_FILE}" ]; then
echo "true"
return
fi
local -r STR_MODE=`tr "[:upper:]" "[:lower:]" <<< ${SINGLE_FILE}`
if [ ${STR_MODE} == "no" ] || [ ${STR_MODE} == "false" ] || [ ${STR_MODE} == "0" ]; then
echo "false"
else
echo "true"
fi
}
get_api_spec_current_commit()
{
if [ -z "${API_SPEC_DIR}" ]; then
if [ ! -z "${1}" ]; then
echo `git -C ${1} rev-parse --verify HEAD`
else
echo `git -C ${REPO_PATH} rev-parse --verify HEAD`
echo `git rev-parse --verify HEAD`
fi
else
echo ${CURRENT_COMMIT}
echo `git -C ${API_SPEC_DIR} rev-parse --verify HEAD`
fi
}
get_api_spec_status()
{
if [ -z "${API_SPEC_DIR}" ]; then
if [ ! -z "${1}" ]; then
echo `git -C ${1} status -s`
else
echo `git status -s`
fi
else
echo `git -C ${API_SPEC_DIR} status -s`
fi
}
is_api_spec_under_source_control()
{
local IS_UNDER_SOURCE_CONTROL_CHECK
if [ -z "${API_SPEC_DIR}" ]; then
if [ ! -z "${1}" ]; then
IS_UNDER_SOURCE_CONTROL_CHECK=`git -C ${1} rev-parse --is-inside-work-tree 2>/dev/null`
else
IS_UNDER_SOURCE_CONTROL_CHECK=`git rev-parse --is-inside-work-tree 2>/dev/null`
fi
else
IS_UNDER_SOURCE_CONTROL_CHECK=`git -C ${API_SPEC_DIR} rev-parse --is-inside-work-tree 2>/dev/null`
fi
if [ "${IS_UNDER_SOURCE_CONTROL_CHECK}" = "true" ]; then
echo ${TRUE}
else
echo ${FALSE}
fi
}
is_api_spec_has_uncommited_changes()
{
if [ `is_api_spec_under_source_control` -eq ${TRUE} ]; then
local -r API_SPEC_STATUS=`get_api_spec_status`
if [ -z "${API_SPEC_STATUS}" ]; then
echo ${FALSE}
else
echo ${TRUE}
fi
else
echo ${FALSE}
fi
}
is_nothing_changed_since_last_check()
{
if is_force_run; then
echo "Force run detected. Skipping commits comparison."
return ${EXIT_FAILURE}
if [ `is_force_run` -eq ${TRUE} ]; then
notice "Force run detected. Skipping commits comparison."
echo ${TRUE}
fi
if [ -z "${COMMIT_FILE_PATH}" ]; then
if [ ! -z "${1}" ]; then
local -r COMMIT_FILE_PATH=${1}
else
echo "COMMIT_FILE_PATH should be defined or passed as first argument!"
return ${EXIT_FAILURE}
debug "COMMIT_FILE_PATH should be defined or passed as first argument!"
echo ${FALSE}
fi
fi
if [ -z "${2}" ]; then
local -r CURRENT_COMMIT=`get_current_commit`
else
local -r CURRENT_COMMIT=${2}
fi
if [ `is_api_spec_under_source_control` -eq ${TRUE} ]; then
local -r CURRENT_COMMIT=`get_api_spec_current_commit`
local -r LAST_CHECKED_COMMIT=`cat ${COMMIT_FILE_PATH}` || ""
local -r LAST_CHECKED_COMMIT=`cat ${COMMIT_FILE_PATH} 2> /dev/null || echo ""`
if [ ${CURRENT_COMMIT} = "${LAST_CHECKED_COMMIT}" ]; then
return ${EXIT_SUCCESS}
if [ ${CURRENT_COMMIT} = "${LAST_CHECKED_COMMIT}" ]; then
if [ `is_api_spec_has_uncommited_changes` -eq ${TRUE} ]; then
notice "API spec has uncomitted changes."
echo ${FALSE}
else
echo ${TRUE}
fi
else
echo ${FALSE}
fi
else
return ${EXIT_FAILURE}
fi
echo ${FALSE}
fi
}
record_current_commit()
{
if is_force_run; then
echo "Force run detected. Commit won't be recorder."
if [ `is_force_run` -eq ${TRUE} ]; then
notice "Force run detected. Commit won't be recorder."
exit ${EXIT_SUCCESS}
fi
if [ -z "${1}" ]; then
local -r CURRENT_COMMIT=`get_current_commit`
else
local -r CURRENT_COMMIT=${1}
fi
if [ -z "${COMMIT_FILE_PATH}" ]; then
if [ ! -v "${2}" ]; then
local -r COMMIT_FILE_PATH=${2}
if [ ! -v "${1}" ]; then
local -r COMMIT_FILE_PATH=${1}
else
echo "COMMIT_FILE_PATH should be defined or passed as second argument!"
debug "COMMIT_FILE_PATH should be defined or passed as second argument!"
return ${EXIT_FAILURE}
fi
fi
local -r CURRENT_COMMIT=`get_api_spec_current_commit`
echo ${CURRENT_COMMIT} > ${COMMIT_FILE_PATH}
}
openapi_codegen()
{
if [ -z "${OPEN_API_SPEC_PATH}" ]; then
if [ ! -v "${1}" ]; then
local -r OPEN_API_SPEC_PATH=${1}
else
debug "OPEN_API_SPEC_PATH should be defined or passed as first argument!"
return ${EXIT_FAILURE}
fi
fi
if [ -z "${OUTPUT_PATH}" ]; then
if [ ! -v "${2}" ]; then
local -r OUTPUT_PATH=${2}
else
debug "OUTPUT_PATH should be defined or passed as second argument!"
return ${EXIT_FAILURE}
fi
fi
if [ -z "${VERSION}" ]; then
if [ ! -v "${3}" ]; then
local -r VERSION=${3}
else
debug "VERSION should be defined or passed as third argument!"
return ${EXIT_FAILURE}
fi
fi
if [ -z "${API_NAME}" ]; then
local -r API_NAME="${PROJECT_NAME}API"
fi
notice "OpenAPI spec generation for ${OPEN_API_SPEC_PATH}"
local -r CODEGEN_VERSION="3.0.34"
local -r CODEGEN_FILE_NAME="swagger-codegen-cli-${CODEGEN_VERSION}.jar"
local -r CODEGEN_DOWNLOAD_URL="https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/${CODEGEN_VERSION}/${CODEGEN_FILE_NAME}"
. build-scripts/xcode/aux_scripts/download_file.sh ${CODEGEN_FILE_NAME} ${CODEGEN_DOWNLOAD_URL}
local -r TINETWORKING_CODEGEN_FILE_NAME="codegen-${VERSION}.jar"
local -r DOWNLOAD_URL="https://maven.dev.touchin.ru/ru/touchin/codegen/${VERSION}/${TINETWORKING_CODEGEN_FILE_NAME}"
. build-scripts/xcode/aux_scripts/download_file.sh ${TINETWORKING_CODEGEN_FILE_NAME} ${DOWNLOAD_URL}
rm -rf ${OUTPUT_PATH}/${API_NAME} # remove previously generated API (if exists)
local -r OPENAPI_COMMAND="java -cp "Downloads/${CODEGEN_FILE_NAME}:Downloads/${TINETWORKING_CODEGEN_FILE_NAME}" io.swagger.codegen.v3.cli.SwaggerCodegen generate -l TINetworking -i ${OPEN_API_SPEC_PATH} -o ${OUTPUT_PATH} --additional-properties projectName=${API_NAME}"
exit_on_failure "${OPENAPI_COMMAND}"
# flatten folders hierarchy
mv ${OUTPUT_PATH}/${API_NAME}/Classes/Swaggers/* ${OUTPUT_PATH}/${API_NAME}/
rm -rf ${OUTPUT_PATH}/${API_NAME}/Classes
}
api_generator_codegen()
{
if [ -z "${API_SPEC_DIR}" ]; then
if [ ! -v "${1}" ]; then
local -r API_SPEC_DIR=${1}
else
debug "API_SPEC_DIR should be defined or passed as first argument!"
return ${EXIT_FAILURE}
fi
fi
if [ -z "${OUTPUT_PATH}" ]; then
if [ ! -v "${2}" ]; then
local -r OUTPUT_PATH=${2}
else
debug "OUTPUT_PATH should be defined or passed as second argument!"
return ${EXIT_FAILURE}
fi
fi
if [ -z "${VERSION}" ]; then
if [ ! -v "${3}" ]; then
local -r VERSION=${3}
else
debug "VERSION should be defined or passed as third argument!"
return ${EXIT_FAILURE}
fi
fi
notice "api-generator spec generation for ${API_SPEC_DIR}/main.json"
local -r FILE_NAME="api-generator-${VERSION}.jar"
local -r DOWNLOAD_URL="https://maven.dev.touchin.ru/ru/touchin/api-generator/${VERSION}/${FILE_NAME}"
. build-scripts/xcode/aux_scripts/download_file.sh ${FILE_NAME} ${DOWNLOAD_URL}
local -r API_GENERATOR_COMMAND="java -Xmx12g -jar Downloads/${FILE_NAME} generate-client-code --output-language SWIFT --specification-path ${API_SPEC_DIR} --output-path ${OUTPUT_PATH} --single-file $(is_single_file)"
exit_on_failure "${API_GENERATOR_COMMAND}"
}
readonly BUILD_PHASES_DIR=${SRCROOT}/build_phases
mkdir -p ${BUILD_PHASES_DIR}
readonly COMMIT_FILE_PATH=${BUILD_PHASES_DIR}/api-generator-commit
readonly REPO_PATH="common"
if is_nothing_changed_since_last_check; then
echo "Nothing was changed models generation skipped."
if [ `is_nothing_changed_since_last_check` -eq ${TRUE} ]; then
notice "Nothing was changed. API generation skipped."
exit ${EXIT_SUCCESS}
fi
VERSION=$1
FILE_NAME="api-generator-${VERSION}.jar"
readonly VERSION=$1
if [ -z "${OUTPUT_PATH}" ]; then
if [ ! -z "${2}" ]; then
@ -132,13 +328,23 @@ if [ -z "${OUTPUT_PATH}" ]; then
fi
fi
if [ -z "${API_SPEC_DIR}" ]; then
readonly API_SPEC_DIR="common/api"
fi
mkdir -p ${OUTPUT_PATH}
# download api generator
readonly DOWNLOAD_URL="https://maven.dev.touchin.ru/ru/touchin/api-generator/${VERSION}/${FILE_NAME}"
. build-scripts/xcode/aux_scripts/download_file.sh ${FILE_NAME} ${DOWNLOAD_URL}
readonly OPEN_API_SPEC_PATH=`find ${API_SPEC_DIR} -maxdepth 1 -name '*.yaml' -o -name '*.yml' | head -n 1`
# execute api generator
java -Xmx6g -jar "Downloads/${FILE_NAME}" generate-client-code --output-language SWIFT --specification-path common/api --output-path ${OUTPUT_PATH} --single-file true
if [ -f "${OPEN_API_SPEC_PATH}" ]; then
openapi_codegen
elif [ -f "${API_SPEC_DIR}/main.json" ]; then
api_generator_codegen
else
notice "No api spec found!"
exit ${EXIT_FAILURE}
fi
record_current_commit
if [ $? -ne ${EXIT_FAILURE} ]; then
record_current_commit
fi

View File

@ -61,17 +61,13 @@ if has_input_files && \
SCRIPT_INPUT_FILE_VARIABLE_NAME="SCRIPT_INPUT_FILE_${i}"
SHELL_VARIABLE="\${${SCRIPT_INPUT_FILE_VARIABLE_NAME}}"
RESOLVED_FILE_NAME=`envsubst <<< ${SHELL_VARIABLE}`
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${FILE_NAMES_SEPARATOR}${RESOLVED_FILE_NAME}
if [ ! -z ${INPUT_FILE_NAMES} ]; then
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${FILE_NAMES_SEPARATOR}
else
INPUT_FILE_NAMES=${INPUT_FILE_NAMES}${FILE_NAMES_SEPARATOR}${RESOLVED_FILE_NAME}
fi
done
FILE_NAMES_SEPARATOR_LENGTH=`awk '{ print length; }' <<< "${FILE_NAMES_SEPARATOR}"`
if [ ${FILE_NAMES_SEPARATOR_LENGTH} -gt 0 ] && \
[ ! -z "${INPUT_FILE_NAMES}" ]; then
# remove separator prefix
INPUT_FILE_NAMES=`cut -c${FILE_NAMES_SEPARATOR_LENGTH}- <<< ${INPUT_FILE_NAMES}`
fi
elif has_input_file_lists; then
for i in `seq 0 $((${SCRIPT_INPUT_FILE_LIST_COUNT}-1))`
do

Binary file not shown.

View File

@ -7,7 +7,7 @@
# $1 $2 $3 $n - folders to exclude from code checking.
#
# Required environment variables:
# PROJECT_DIR - project directory.
# SRCROOT - project directory.
# SCRIPT_DIR - directory of current script.
#
# Optional environment variables:
@ -15,41 +15,47 @@
# SCRIPT_INPUT_FILE_{N} - file path to directory that should be checked.
#
# Modified files:
# ${PROJECT_DIR}/code-quality-reports/CPDLog.txt - check report.
# ${SRCROOT}/code-quality-reports/CPDLog.txt - check report.
#
# Example of usage:
# runner.sh copy_paste_detection.sh Generated Localization Pods
# copy_paste_detection.sh Generated Localization Pods
#
readonly EXIT_SUCCESS=0
readonly EXIT_FAILURE=1
EXIT_SUCCESS=0
EXIT_FAILURE=1
if which pmd >/dev/null; then
readonly REPORTS_DIR="${PROJECT_DIR}/code-quality-reports"
REPORTS_DIR="${SRCROOT}/code-quality-reports"
readonly SOURCES_DIRS=`. ${SCRIPT_DIR}/common/read_input_file_names.sh " " ${PROJECT_DIR}`
SOURCES_DIRS=`. ${SCRIPT_DIR}/common/read_input_file_names.sh " " ${SRCROOT}`
readonly COMMAND_LINE_ARGUMENTS=$@
COMMAND_LINE_ARGUMENTS=$@
FOLDERS_TO_EXLUDE=""
FOLDERS_TO_EXCLUDE=""
for argument in ${COMMAND_LINE_ARGUMENTS}
do
FOLDERS_TO_EXLUDE=${FOLDERS_TO_EXLUDE}"-or -name ${argument} "
FOLDERS_TO_EXCLUDE=${FOLDERS_TO_EXCLUDE}"-or -name ${argument} "
done
FOLDERS_TO_EXLUDE=`echo ${FOLDERS_TO_EXLUDE} | cut -c5-` # remove first "-or"
FOLDERS_TO_EXCLUDE=`echo ${FOLDERS_TO_EXCLUDE} | cut -c5-` # remove first "-or"
readonly FILES_TO_EXCLUDE=`find ${PROJECT_DIR} -type d ${FOLDERS_TO_EXLUDE} | paste -sd " " -`
FILES_TO_EXCLUDE=`find ${SRCROOT} -type d ${FOLDERS_TO_EXCLUDE} | paste -sd " " -`
mkdir -p ${REPORTS_DIR}
pmd cpd --files ${SOURCES_DIRS} --exclude ${FILES_TO_EXCLUDE} --minimum-tokens 50 --language swift --encoding UTF-8 --format net.sourceforge.pmd.cpd.XMLRenderer --failOnViolation true > ${REPORTS_DIR}/cpd-output.xml
DIRS_ARGUMENTS=""
for SOURCE_DIR in ${SOURCES_DIRS}; do
DIRS_ARGUMENTS=${DIRS_ARGUMENTS}" --dir "${SOURCE_DIR}
done
pmd cpd ${DIRS_ARGUMENTS} --exclude ${FILES_TO_EXCLUDE} --minimum-tokens 50 --language swift --encoding UTF-8 --format net.sourceforge.pmd.cpd.XMLRenderer --skip-lexical-errors true > ${REPORTS_DIR}/cpd-output.xml
php ${SCRIPT_DIR}/../aux_scripts/cpd_script.php ${REPORTS_DIR}/cpd-output.xml | tee ${REPORTS_DIR}/CPDLog.txt
# Make paths relative to PROJECT_DIR, so different developers won't rewrite entire file
readonly SED_REPLACEMENT_STRING=$(echo ${PROJECT_DIR} | sed "s/\//\\\\\//g")
# Make paths relative to SRCROOT, so different developers won't rewrite entire file
SED_REPLACEMENT_STRING=$(echo ${SRCROOT} | sed "s/\//\\\\\//g")
sed -i '' "s/${SED_REPLACEMENT_STRING}//g" "${REPORTS_DIR}/CPDLog.txt"
else

View File

@ -1,16 +1,47 @@
LOCALIZATION_PATH="${PRODUCT_NAME}/Resources/Localization"
#first argument set strings folder path
#!/bin/sh
# Description:
# Generates Localizeable.strings and String+Localization.swift files.
#
# Parameters:
# $1 - path to strings folder containing json files.
# $2 - path to Localization folder (output).
# $3 - Bundle for localization. Default is `.main`.
#
# Required environment variables:
# SCRIPT_DIR - directory of current script.
#
# Optional environment variables:
# PRODUCT_NAME - product name to produce path to localization folder (output).
#
# Examples of usage:
# . localization.sh
# . localization.sh common/strings Resources/Localization/ .main
#
readonly EXIT_SUCCESS=0
readonly EXIT_FAILURE=1
. ${SCRIPT_DIR}/../aux_scripts/install_env.sh php
STRINGS_FOLDER=${1:-"common/strings"}
LOCALIZATION_PATH=${2:-"${PRODUCT_NAME}/Resources/Localization/"}
BUNDLE=${3:-".main"}
if ! [ -e ${LOCALIZATION_PATH} ]; then
echo "${PROJECT_DIR}/${LOCALIZATION_PATH} path does not exist. Add these folders and try again."
exit 1
echo "${LOCALIZATION_PATH} path does not exist. Add these folders and try again."
exit ${EXIT_FAILURE}
fi
if ! [ -e "${PROJECT_DIR}/${STRINGS_FOLDER}" ]; then
echo "${PROJECT_DIR}/${STRINGS_FOLDER} path does not exist. Submodule with strings should be named common and contain strings folder."
exit 1
if ! [ -e "${STRINGS_FOLDER}" ]; then
echo "${STRINGS_FOLDER} path does not exist. Submodule with strings should be named common and contain strings folder."
exit ${EXIT_FAILURE}
fi
#second argument set strings script path
php ${2:-build-scripts/xcode/aux_scripts/import_strings.php} ${PRODUCT_NAME} ${STRINGS_FOLDER}
if which php >/dev/null; then
php ${SCRIPT_DIR}/../aux_scripts/import_strings.php ${LOCALIZATION_PATH} ${STRINGS_FOLDER} ${BUNDLE}
else
echo "warning: php not installed, install using 'brew install php'"
exit ${EXIT_FAILURE}
fi

View File

@ -2,6 +2,7 @@
# Description:
# Runs swiftlint with selected or default config file.
# By default it runs only for modified files.
#
# Parameters:
# $1 - path to swiftlint executable.
@ -10,16 +11,19 @@
# Required environment variables:
# SCRIPT_DIR - directory of current script.
# SRCROOT - project directory.
# PODS_ROOT - cocoapods installation directory (eg. ${SRCROOT}/Pods).
#
# Optional environment variables:
# SWIFTLINT_EXECUTABLE - path to swiftlint executable.
# SWIFTLINT_CONFIG_PATH - path to swiftlint config.
# PODS_ROOT - cocoapods installation directory (eg. ${SRCROOT}/Pods) if SWIFTLINT_EXECUTABLE or ${1} is missing
# SCRIPT_INPUT_FILE_COUNT - number of files listed in "Input files" of build phase.
# SCRIPT_INPUT_FILE_{N} - file path to directory that should be checked.
# FORCE_LINT - don't exclude not modified files.
# AUTOCORRECT - format and fix code before lint.
#
# Example of usage:
# swiftlint.sh
# FORCE_LINT=true; swiftlint.sh
# swiftlint.sh Pods/Swiftlint/swiftlint build-scripts/xcode/.swiftlint.yml
#
@ -28,8 +32,10 @@ readonly SOURCES_DIRS=`. ${SCRIPT_DIR}/common/read_input_file_names.sh "\n" ${SR
if [ -z "${SWIFTLINT_EXECUTABLE}" ]; then
if [ ! -z "${1}" ]; then
readonly SWIFTLINT_EXECUTABLE=${1}
else
elif [ ! -z "${PODS_ROOT}" ]; then
readonly SWIFTLINT_EXECUTABLE=${PODS_ROOT}/SwiftLint/swiftlint
else
readonly SWIFTLINT_EXECUTABLE=${SRCROOT}/Pods/SwiftLint/swiftlint
fi
fi
@ -41,7 +47,52 @@ if [ -z "${SWIFTLINT_CONFIG_PATH}" ]; then
fi
fi
for SOURCE_DIR in ${SOURCES_DIRS}; do
${SWIFTLINT_EXECUTABLE} autocorrect --path ${SOURCE_DIR} --config ${SWIFTLINT_CONFIG_PATH}
${SWIFTLINT_EXECUTABLE} --path ${SOURCE_DIR} --config ${SWIFTLINT_CONFIG_PATH}
done
if [ ! -z "${FORCE_LINT}" ]; then
# Если задана переменная FORCE_LINT, то проверяем все файлы проекта
for SOURCE_DIR in ${SOURCES_DIRS}; do
if [ ! -z "${AUTOCORRECT}" ]; then
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} --fix --format "${SRCROOT}/${SOURCE_DIR}"
fi
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} "${SRCROOT}/${SOURCE_DIR}"
done
else
# Xcode упадет, если будем использовать большое количество Script Input Files,
# так как просто переполнится стек - https://unix.stackexchange.com/questions/357843/setting-a-long-environment-variable-breaks-a-lot-of-commands
# Поэтому воспользуемся "скрытым" параметром Swiflint - https://github.com/realm/SwiftLint/pull/3313
# Создадим временный файл swiftlint_files с префиксом @ и в нем уже определим список файлов
# необходимых для линтовки :)
lint_files_path=`mktemp`
# Проходимся по папкам, которые требуют линтовки
for SOURCE_DIR in ${SOURCES_DIRS}; do
LINE_PREFIX="${SRCROOT}/"
pushd .
cd ${SRCROOT} # in case of runing script outside project folder (SPM)
# Отбираем файлы, которые были изменены или созданы
source_unstaged_files=$(git diff --diff-filter=d --name-only --line-prefix=${LINE_PREFIX} ${SOURCE_DIR} | grep "\.swift$")
source_staged_files=$(git diff --diff-filter=d --name-only --line-prefix=${LINE_PREFIX} --cached ${SOURCE_DIR} | grep "\.swift$")
popd
if [ ! -z "${source_unstaged_files}" ]; then
echo "${source_unstaged_files}" >> ${lint_files_path}
fi
if [ ! -z "${source_staged_files}" ]; then
echo "${source_staged_files}" >> ${lint_files_path}
fi
done
swiftlint_files_path="@${lint_files_path}"
if [ ! -z "${AUTOCORRECT}" ]; then
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} --fix --format --force-exclude --use-alternative-excluding ${swiftlint_files_path}
fi
${SWIFTLINT_EXECUTABLE} lint --config ${SWIFTLINT_CONFIG_PATH} --force-exclude --use-alternative-excluding ${swiftlint_files_path}
fi

View File

@ -0,0 +1,8 @@
readonly SOURCES_DIR=${1:-${PROJECT_DIR}/${PRODUCT_NAME}} # first argument set product dir
readonly UNUSED_RESOURCES_SCRIPT=${2:-${PROJECT_DIR}/build-scripts/xcode/build_phases/common/unused_resources} # second argument set script path
readonly REPORTS_DIR=${PROJECT_DIR}/code-quality-reports
readonly FILES_TO_EXCLUDE=`find ${SOURCES_DIR} -type d -name Localization -or -name Generated | paste -sd " " -`
mkdir ${REPORTS_DIR}
${UNUSED_RESOURCES_SCRIPT} --project ${SOURCES_DIR} --exclude ${FILES_TO_EXCLUDE} --action "l" > ${REPORTS_DIR}/Unused_resources_log.txt

View File

@ -1,15 +1,7 @@
$appName = File.basename(Dir['../*.xcworkspace'].first, '.*')
require_relative 'fastlane/touchlane/lib/touchlane'
require_relative 'managers/managers'
# ugly hack to add support for custom storage
Match.module_eval do
def self.storage_modes
return %w(git google_cloud s3 local)
end
end
private_lane :installDependencies do |options|
podsReposPath = File.expand_path "~/.cocoapods/repos/master/"
@ -21,7 +13,7 @@ private_lane :installDependencies do |options|
end
cocoapods(
repo_update: true
try_repo_update_on_error: true
)
end
@ -36,24 +28,38 @@ private_lane :uploadToFirebase do |options|
google_app_id = get_info_plist_value(path: gsp_plist_path, key: "GOOGLE_APP_ID")
firebase_app_distribution(
firebase_app_distibution_groups_path = File.expand_path "../firebase_app_distribution_groups"
# Select groups_file or groups parameter depending on groups file existence
if File.exists? firebase_app_distibution_groups_path
firebase_app_distribution(
app: google_app_id,
ipa_path: options[:ipa_path],
groups_file: firebase_app_distibution_groups_path,
release_notes_file: releaseNotesFile
)
else
firebase_app_distribution(
app: google_app_id,
ipa_path: options[:ipa_path],
groups: "touch-instinct",
release_notes_file: releaseNotesFile
)
upload_symbols_to_crashlytics(
gsp_path: get_google_services_plist_path(app_target_folder_name, configuration_type)
)
)
end
end
def upload_to_app_store_using_options(options)
def upload_to_app_store_using_options(options, submit_for_review = false)
upload_to_app_store(
username: options[:username] || options[:apple_id],
api_key_path: options[:api_key_path],
api_key: options[:api_key],
ipa: options[:ipa_path],
build_number: options[:ipa_path].nil? ? options[:buildNumber] : nil,
skip_binary_upload: options[:ipa_path].nil?,
skip_screenshots: true,
force: true, # skip metainfo prompt
submit_for_review: submit_for_review,
submission_information: options[:submission_information],
skip_metadata: true,
team_id: options[:itc_team_id],
dev_portal_team_id: options[:team_id],
@ -79,15 +85,26 @@ private_lane :addShield do |options|
end
private_lane :buildConfiguration do |options|
appName = options[:appName] || $appName
options[:appName] = options[:appName] || $appName
lane_name = options[:lane_name] || lane_context[SharedValues::LANE_NAME]
options[:scheme] = options[:scheme] || appName
options[:scheme] = options[:scheme] || options[:appName]
options[:lane_name] = lane_name
ipa_name = "#{options[:appName]}.ipa"
options[:output_name] = ipa_name
options[:ipa_path] = "./#{ipa_name}"
options[:dsym_path] = "./#{options[:appName]}.app.dSYM.zip"
options[:xcodeproj_path] = options[:xcodeproj_path] || "../#{options[:appName]}.xcodeproj"
options[:workspace] = options[:workspace] || File.expand_path("../#{options[:appName]}.xcworkspace")
configuration_type = Touchlane::ConfigurationType.from_lane_name(lane_name)
options = fill_up_options_using_configuration_type(options, configuration_type)
options = fill_up_options_using_configuration_type(options, configuration_type, true)
generate_xcodeproj_if_needed(options)
openKeychain(options)
@ -97,56 +114,51 @@ private_lane :buildConfiguration do |options|
)
end
ipa_name = "#{appName}.ipa"
options[:output_name] = ipa_name
options[:ipa_path] = "./#{ipa_name}"
options[:dsym_path] = "./#{appName}.app.dSYM.zip"
options[:xcodeproj_path] = "../#{appName}.xcodeproj"
options[:workspace] = "./#{appName}.xcworkspace"
installDependencies(options)
run_code_generation_phase_if_needed(options)
generate_enabled_features_extension_if_needed(options)
if !(options[:uploadToFabric] || options[:uploadToAppStore])
options[:skip_package_ipa] = true
sync_code_signing_using_options(options)
install_signing_identities(options)
buildArchive(options) # check build failures and static analysis
end
if options[:uploadToFabric]
sync_code_signing_using_options(options)
install_signing_identities(options)
addShield(options)
buildArchive(options)
uploadToFirebase(options)
end
if options[:uploadToAppStore]
options[:compileBitcode] = options[:compileBitcode].nil? ? true : options[:compileBitcode]
options[:include_symbols] = options[:include_symbols].nil? ? true : options[:include_symbols]
sync_code_signing_using_options(options)
install_signing_identities(options)
buildArchive(options)
upload_to_app_store_using_options(options)
upload_to_app_store_using_options(options, false)
end
upload_symbols_to_crashlytics(
gsp_path: get_google_services_plist_path(options[:appName], configuration_type)
)
end
private_lane :buildArchive do |options|
require 'json'
icloudEnvironment = options[:iCloudContainerEnvironment] || ""
exportOptions = icloudEnvironment.to_s.empty? ? {} : {iCloudContainerEnvironment: icloudEnvironment}
exportOptions[:compileBitcode] = options[:compileBitcode] || false
lane_name = options[:lane_name]
configuration = options[:configuration]
xcodeproj_path = options[:xcodeproj_path]
xcodes(select_for_current_build_only: true)
if configuration != "AppStore" # AppStore uses xcconfig choosen in Xcode
set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodeproj_path)
end
@ -155,75 +167,57 @@ private_lane :buildArchive do |options|
clean: true,
workspace: options[:workspace],
scheme: options[:scheme],
archive_path: "./",
output_directory: "./",
archive_path: "./#{$appName}.xcarchive",
buildlog_path: "./",
output_name: options[:output_name],
configuration: configuration,
export_method: options[:export_method],
export_options: exportOptions,
skip_package_ipa: options[:skip_package_ipa],
include_symbols: options[:include_symbols] || false,
include_bitcode: options[:compileBitcode] || false,
include_symbols: options[:include_symbols] || false
)
end
lane :CreatePushCertificate do |options|
configuration = get_configuration_for_type(options[:type] || "development")
options = configuration.to_options.merge(options)
lane :SubmitForReview do |options|
configuration_type = Touchlane::ConfigurationType.from_type("appstore")
options = fill_up_options_using_configuration_type(options, configuration_type, false)
certificates_path = File.expand_path "../Certificates"
Dir.mkdir(certificates_path) unless File.directory?(certificates_path)
app_identifier = options[:app_identifier]
get_push_certificate(
development: options[:development].nil? ? true : options[:development],
generate_p12: true,
active_days_limit: 30, # create new certificate if old one will expire in 30 days
save_private_key: false,
app_identifier: (app_identifier.is_a? Array) ? app_identifier.first : app_identifier,
username: options[:username] || options[:apple_id],
team_id: options[:team_id],
p12_password: "123", # empty password won't work with Pusher
output_path: certificates_path
)
upload_to_app_store_using_options(options, true)
end
lane :SyncCodeSigning do |options|
configuration_type = Touchlane::ConfigurationType.from_type(options[:type])
lane :InstallDevelopmentSigningIdentities do |options|
configuration_type = Touchlane::ConfigurationType.from_type("development")
options = fill_up_options_using_configuration_type(options, configuration_type)
sync_code_signing_using_options(options)
install_signing_identities(options)
end
lane :SyncSymbols do |options|
configuration = get_configuration_for_type(options[:type])
options = configuration.to_options.merge(options)
lane :RefreshProfiles do |options|
type = options[:type] || "development"
appName = options[:appName] || $appName
configuration_type = Touchlane::ConfigurationType.from_type(type)
options = fill_up_options_using_configuration_type(options, configuration_type)
xcodeproj_path = File.expand_path "../#{appName}.xcodeproj"
refresh_profiles(options)
end
version_number = options[:version] || "latest"
build_number = options[:build_number]
lane :ReplaceDevelopmentCertificate do |options|
configuration_type = Touchlane::ConfigurationType.from_type("development")
options = fill_up_options_using_configuration_type(options, configuration_type, true)
if configuration.type.is_app_store
download_dsyms(
username: options[:username],
app_identifier: options[:app_identifier].first,
team_id: options[:itc_team_id],
version: version_number,
build_number: build_number
)
end
replace_development_certificate(options)
end
app_target_folder_name = appName
lane :SyncAppStoreIdentities do |options|
configuration_type = Touchlane::ConfigurationType.from_type("appstore")
options = fill_up_options_using_configuration_type(options, configuration_type, true)
upload_symbols_to_crashlytics(
gsp_path: get_google_services_plist_path(app_target_folder_name, configuration.type)
)
options[:readonly] = false
sync_signing_identities(options)
end
clean_build_artifacts
lane :ManuallyUpdateCodeSigning do |options|
manually_update_code_signing(get_default_options.merge(options))
end
private_lane :openKeychain do |options|
@ -237,7 +231,7 @@ private_lane :openKeychain do |options|
name: options[:keychain_name],
password: options[:keychain_password],
unlock: true,
timeout: false,
timeout: 0,
add_to_search_list: !keychain_exists
)
else
@ -248,122 +242,78 @@ private_lane :openKeychain do |options|
end
end
lane :ManuallyUpdateCodeSigning do |options|
register_local_storage_for_match()
require 'match'
storage_factory = lambda do
new_storage = Match::Storage.for_mode('local', { git_url: get_signing_identities_path() })
new_storage.download
return new_storage
end
encryption_factory = lambda do |stor|
new_encryption = Match::Encryption.for_storage_mode('local', { working_directory: stor.working_directory })
new_encryption.decrypt_files
return new_encryption
end
get_all_files = lambda do |stor|
Dir[File.join(stor.working_directory, "**", "*.{cer,p12,mobileprovision}")]
end
storage = storage_factory.call
encryption = encryption_factory.call(storage)
old_files = get_all_files.call(storage)
sh("open #{storage.working_directory}")
# we are not using prompt() since it requires non-empty input which is not a case for Enter (\n)
puts "Enter any key when you're done"
STDIN.gets
encryption.encrypt_files
files_to_commit = get_all_files.call(storage)
old_directory = storage.working_directory
storage.save_changes!(files_to_commit: files_to_commit)
# need to check, because saving changes with delete is another function (update repo if needed)
files_diff = old_files - files_to_commit
# match can not work with both save/delete functionality `You can't provide both files_to_delete and files_to_commit right now`
# to avoid this we use storage twice if needed
if files_diff.length > 0
storage = storage_factory.call
encryption = encryption_factory.call(storage)
files_to_delete = files_diff.map do |file|
old_file = file
old_file.slice! old_directory
new_file = File.join(storage.working_directory, old_file)
File.delete(new_file) if File.exist?(new_file)
file = new_file
end
encryption.encrypt_files
storage.save_changes!(files_to_delete: files_to_delete)
end
end
def sync_code_signing_using_options(options)
register_local_storage_for_match()
match(
app_identifier: options[:app_identifier],
username: options[:username] || options[:apple_id],
api_key_path: options[:api_key_path],
team_id: options[:team_id],
type: options[:type],
readonly: options[:readonly].nil? ? true : options[:readonly],
storage_mode: "local",
# we can't pass signing_identities_path as parameter name since params is hardcoded in match/runner.rb
git_url: get_signing_identities_path(),
skip_docs: true,
keychain_name: options[:keychain_name],
keychain_password: options[:keychain_password]
)
end
def register_local_storage_for_match
Match::Storage.register_backend(type: 'local', storage_class: Touchlane::LocalStorage)
Match::Encryption.register_backend(type: 'local', encryption_class: Match::Encryption::OpenSSL)
def get_default_options
{
:git_url => get_signing_identities_path(),
:signing_identities_path => get_signing_identities_path(),
:storage_mode => Touchlane::LocalStorage::STORAGE_TYPE
}
end
def get_signing_identities_path
File.expand_path "../EncryptedSigningIdentities"
end
def fill_up_options_using_configuration_type(options, configuration_type)
def fill_up_options_using_configuration_type(options, configuration_type, keychain_password_required = false)
configuration = get_configuration_for_type(configuration_type.type)
if configuration_type.is_app_store || configuration_type.is_development
api_key_path = "fastlane/#{configuration_type.prefix}_api_key.json"
else
api_key_path = nil
end
api_key_path = File.expand_path "../fastlane/#{configuration_type.prefix}_api_key.json"
is_api_key_file_exists = File.exists?(api_key_path)
default_options = {:api_key_path => api_key_path}
# default_options required to be empty due to the possibility of skipping the configuration type check below
default_options = get_default_options
# Check whether configuration type is required to configure one of api key parameters or not
if configuration_type.is_app_store || configuration_type.is_development
# Check whether API key JSON file exists or not
if is_api_key_file_exists
# If exists then fill in all required information through api_key_path parameter
# and set a value to an options` parameter respectively
default_options[:api_key_path] = api_key_path
else
# If doesn't exist then build api_key parameter through app_store_connect_api_key action
# and set a value to an options` parameter respectively also
default_options[:api_key] = get_app_store_connect_api_key()
end
end
default_options
.merge(configuration.to_options)
.merge(get_keychain_options(options))
.merge(get_keychain_options(options, keychain_password_required))
.merge(options)
end
def get_keychain_options(options)
def get_app_store_connect_api_key()
require 'json'
api_key_parameters = JSON.parse(ENV['API_KEY_JSON'])
return app_store_connect_api_key(
key_id: api_key_parameters['key_id'],
issuer_id: api_key_parameters['issuer_id'],
key_content: api_key_parameters['key'],
duration: api_key_parameters['duration'],
in_house: api_key_parameters['in_house']
)
end
def get_keychain_options(options, keychain_password_required = false)
keychain_name = options[:keychain_name]
keychain_password = options[:keychain_password]
if is_ci?
keychain_name = keychain_name || "ci.keychain"
keychain_password = keychain_password || ""
else
keychain_password = keychain_password || prompt(
elsif keychain_password_required && keychain_password.nil?
keychain_password = prompt(
text: "Please enter your keychain password (account password): ",
secure_text: true
)
@ -379,35 +329,7 @@ def get_configuration_for_type(type)
end
def get_google_services_plist_path(app_target_folder_name, configuration_type)
File.expand_path "../#{app_target_folder_name}/Resources/#{configuration_type.prefix}-GoogleService-Info.plist"
end
def generate_enabled_features_extension_if_needed(options)
app_target_folder_name = options[:appName] || $appName
project_enabled_features_file_path = File.expand_path "../#{app_target_folder_name}/Resources/Features/Enabled.swift"
build_settings_file_path = File.expand_path "../common/build_settings.yaml"
unless is_feature_extension_needed?(options, project_enabled_features_file_path)
return
end
if options[:features].nil?
builder_features_list = [] # If Enabled.swift exists and features option is nil we need to create empty extension to avoid unexpected features
else
builder_features_list = options[:features]
.split(",").map { |feature_name| feature_name.strip } # [ "Feature1", "Feature2", "Feature3" ]
end
build_settings_features_list = Managers::FileManager.load_from_file_YAML(build_settings_file_path)["features"]
enabled_features_extension = Touchlane::Features.generate_enabled_features_extension(builder_features_list, build_settings_features_list)
Managers::FileManager.save_data_to_file(project_enabled_features_file_path, enabled_features_extension)
end
def is_feature_extension_needed?(options, project_enabled_features_file_path)
!options[:features].nil? || File.exists?(project_enabled_features_file_path)
File.expand_path "../#{app_target_folder_name}/Resources/GoogleService-Info.plist"
end
def set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodeproj_path)
@ -418,7 +340,8 @@ def set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodepro
target_to_modify_selector = lambda do |t|
supported_product_types = [
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:application],
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:app_extension]
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:app_extension],
Xcodeproj::Constants::PRODUCT_TYPE_UTI[:framework]
]
return !t.test_target_type? && supported_product_types.include?(t.product_type)
end
@ -426,23 +349,35 @@ def set_xcconfig_for_configuration_of_project(lane_name, configuration, xcodepro
application_targets = project.native_targets.select(&target_to_modify_selector)
application_targets.each do |target|
build_configuration = target.build_configuration_list[configuration]
config_name = target.name + lane_name
build_configuration_reference = project.files.select { |f| f.path.start_with?(config_name) }.first
build_configuration.base_configuration_reference = build_configuration_reference
if !build_configuration_reference.nil? # target has custom xcconfig
build_configuration = target.build_configuration_list[configuration]
build_configuration.base_configuration_reference = build_configuration_reference
end
end
project.save()
end
def generate_xcodeproj_if_needed(options)
project_yml_path = File.expand_path "../project.yml"
if !File.exists?(options[:xcodeproj_path]) && File.exists?(project_yml_path)
xcodegen(
spec: project_yml_path
)
end
end
# Build phases
def run_code_generation_phase_if_needed(options)
code_generation_script_path = File.expand_path "../.githooks/scripts/CodeGen.sh"
xcodeproj_path = File.expand_path options[:xcodeproj_path]
if File.exists? code_generation_script_path
sh(code_generation_script_path, xcodeproj_path)
sh(code_generation_script_path, options[:workspace])
end
end
end

@ -1 +1 @@
Subproject commit 3f81529c1425a74f43fe84fe8befffd81a442cc7
Subproject commit a8f072f216684bd7f5563c0211f71d6637a5f92d

View File

@ -0,0 +1,132 @@
require 'json'
require 'mustache'
require 'yaml'
require_relative '../fastlane/touchlane/lib/touchlane/configuration_type'
class String
def in_current_dir
"#{__dir__}/#{self}"
end
end
class ConfigRenderer
class XCConfigKeys
DEVELOPMENT_TEAM = "DEVELOPMENT_TEAM"
PRODUCT_BUNDLE_IDENTIFIER = "PRODUCT_BUNDLE_IDENTIFIER"
CODE_SIGN_STYLE = "CODE_SIGN_STYLE"
end
INHERITED_PREFIX = "$(inherited)"
private_constant :INHERITED_PREFIX
def initialize(configurations_file_path, build_parameters_path, configs_folder_name)
@configurations_file_path = configurations_file_path
@build_parameters_path = build_parameters_path
@configs_folder_name = configs_folder_name
end
def render_xconfigs
temp_configs_data_file_path = "configs_data.json".in_current_dir
generator_path = "build_options_helper/helper.py".in_current_dir
template_path = "target_xcconfig.mustache".in_current_dir
# Create config directory if needed
Dir.mkdir(@configs_folder_name) unless Dir.exist?(@configs_folder_name)
# Call python script and generate configs to config file
system("python #{generator_path} -bp #{@build_parameters_path} -o #{__dir__} -r ios_build_settings -p ios")
# Open settings, configurations and template files
target_xcconfig_tempate = File.read(template_path)
$configurations = YAML.load(File.open(@configurations_file_path))
$config_types = $configurations["types"]
targets = $configurations["targets"]
# Run through all target in project
targets.each do |target_name, target|
# Need open everytime, because script make some changes only for this target
configs = JSON.load(File.open(temp_configs_data_file_path))
# Run through all configs
configs.each do |config|
# Take default values
distribution_type = Touchlane::ConfigurationType.from_account_type(config["account_type"]).type
properties = target[distribution_type]
# Add properties from settings file
properties.each do |key, value|
if config["xcconfig_options"].any? { |option| key == option["key"] }
config["xcconfig_options"].map! { |option| key == option["key"] ? merge_config_data(key, option["value"], value) : option }
else
config["xcconfig_options"].append(config_option(key, value))
end
end
# Add missing properties if needed
config["xcconfig_options"].concat(generate_missing_properties(target_name, properties, distribution_type))
# Create settings pack
config_data = {
"target_name": target_name,
"abstract_targets_prefix": target["abstract_targets_prefix"],
"configuration": config
}
# Create file for every setting in loop
File.open(@configs_folder_name + "/" + target_name + config["name"] + ".xcconfig", 'w') { |file|
file.puts(Mustache.render(target_xcconfig_tempate, config_data))
}
end
end
# Remove config file, it's trash
File.delete(temp_configs_data_file_path) if File.exist?(temp_configs_data_file_path)
end
# Make tuple of key and value become mustache template element
def config_option(key, value)
return { "key" => key, "value" => value }
end
def merge_config_data(key, config_value, settings_value)
if settings_value.start_with?(INHERITED_PREFIX)
new_value = settings_value.split(INHERITED_PREFIX).last
return config_option(key, config_value + new_value)
else
return config_option(key, settings_value)
end
end
# Fetch development team from build configuration
def fetch_development_team(development_team_key, distribution_type)
current_config = $config_types[distribution_type]
team_value = current_config["team_id"]
return config_option(development_team_key, team_value)
end
# Generate missing properties if needed
def generate_missing_properties(target_name, properties, distribution_type)
result = []
# Bundle_id_key should be among the properties (required by fastlane)
unless properties.key?(XCConfigKeys::PRODUCT_BUNDLE_IDENTIFIER)
raise "#{target_name}: Could not find #{XCConfigKeys::PRODUCT_BUNDLE_IDENTIFIER} for #{distribution_type}"
end
unless properties.key?(XCConfigKeys::DEVELOPMENT_TEAM)
result.append(fetch_development_team(XCConfigKeys::DEVELOPMENT_TEAM, distribution_type))
end
unless properties.key?(XCConfigKeys::CODE_SIGN_STYLE)
result.append(config_option(XCConfigKeys::CODE_SIGN_STYLE, "Manual"))
end
return result
end
end

View File

@ -1,13 +1,16 @@
targets:
TestProject:
abstract_targets_prefix: "-TestProjectKit"
development:
PRODUCT_BUNDLE_IDENTIFIER: "ru.touchin.testproject"
PROVISIONING_PROFILE_SPECIFIER: "TestProjectDev"
CODE_SIGN_ENTITLEMENTS: "TestProject/Standard.entitlements"
SWIFT_ACTIVE_COMPILATION_CONDITIONS: "$(inherited) DEBUG_MENU"
enterprise:
PRODUCT_BUNDLE_IDENTIFIER: "com.touchin.testproject"
PROVISIONING_PROFILE_SPECIFIER: "TestProjectEnterprise"
CODE_SIGN_ENTITLEMENTS: "TestProject/Enterprise.entitlements"
SWIFT_ACTIVE_COMPILATION_CONDITIONS: "$(inherited) DEBUG_MENU"
appstore:
PRODUCT_BUNDLE_IDENTIFIER: "ru.customer.domain"
PROVISIONING_PROFILE_SPECIFIER: "TestProjectAppStore"
@ -15,13 +18,13 @@ targets:
types:
development:
apple_id: "apple@touchin.ru"
apple_id: "iosdev@touchin.ru"
team_id: "**********"
itc_team_id: "**********"
enterprise:
apple_id: "enterpriseapple@touchin.ru"
team_id: "**********"
appstore:
apple_id: "apple@touchin.ru"
apple_id: "iosdev@touchin.ru"
team_id: "**********"
itc_team_id: "**********"

View File

@ -1,7 +1,4 @@
require 'json'
require 'mustache'
require 'yaml'
require_relative "config_renderer"
#
# Usage: render_xcconfigs.rb <configurations.yaml> <build_parameters.yaml> [<ouptut folder>]
#
@ -10,128 +7,9 @@ require 'yaml'
# It is recommended to remove old .xcconfig files before running this script.
#
class String
def in_current_dir
"#{__dir__}/#{self}"
end
end
# Input files paths
configurations_file_path = ARGV[0]
temp_configs_data_file_path = "configs_data.json".in_current_dir
generator_path = "build_options_helper/helper.py".in_current_dir
template_path = "target_xcconfig.mustache".in_current_dir
build_parameters_path = ARGV[1]
configs_folder_name = ARGV[2] || "TargetConfigurations"
# Create config directory if needed
Dir.mkdir(configs_folder_name) unless Dir.exist?(configs_folder_name)
# Call python script and generate configs to config file
system("python #{generator_path} -bp #{build_parameters_path} -o #{__dir__} -r ios_build_settings -p ios")
# Open settings, configurations and template files
target_xcconfig_tempate = File.read(template_path)
$configurations = YAML.load(File.open(configurations_file_path))
$config_types = $configurations["types"]
# Set global property
targets = $configurations["targets"]
# Make tuple of key and value become mustache template element
def config_option(key, value)
return { "key" => key, "value" => value }
end
# Maps lane prefix to distribution type
def distribution_type_of(account_type)
case account_type
when "Standard"
"development"
when "Enterprise"
"enterprise"
when "AppStore"
"appstore"
else
raise "Error: Unsupported distribution type #{account_type}"
end
end
# Fetch development team from build configuration
def fetch_development_team(development_team_key, distribution_type)
current_config = $config_types[distribution_type]
team_value = current_config["team_id"]
return config_option(development_team_key, team_value)
end
# Return empty array or generated provisioning profile hash
def generate_provisioning_profile(provisioning_key, bundle_id, distribution_type)
case distribution_type
when "appstore"
app_store_profile = "match AppStore " + bundle_id
config_option(provisioning_key, app_store_profile)
else
config_option(provisioning_key, bundle_id)
end
end
# Generate missing properties if needed
def generate_missing_properties(target_name, properties, distribution_type)
result = []
development_team_key = "DEVELOPMENT_TEAM"
provisioning_key = "PROVISIONING_PROFILE_SPECIFIER"
bundle_id_key = "PRODUCT_BUNDLE_IDENTIFIER"
# Bundle_id_key should be among the properties (required by fastlane)
unless properties.key?(bundle_id_key)
raise "#{target_name}: Could not find #{bundle_id_key} for #{distribution_type}"
end
unless properties.key?(development_team_key)
result.append(fetch_development_team(development_team_key, distribution_type))
end
unless properties.key?(provisioning_key)
result.append(generate_provisioning_profile(provisioning_key, properties[bundle_id_key], distribution_type))
end
return result
end
# Run through all target in project
targets.each do |target_name, target|
# Need open everytime, because script make some changes only for this target
configs = JSON.load(File.open(temp_configs_data_file_path))
# Run through all configs
configs.each do |config|
# Take default values
distribution_type = distribution_type_of(config["account_type"])
properties = target[distribution_type]
# Add properties from settings file
properties.each do |key, value|
config["xcconfig_options"].append(config_option(key, value))
end
# Add missing properties if needed
config["xcconfig_options"].concat(generate_missing_properties(target_name, properties, distribution_type))
# Create settings pack
config_data = {
"target_name": target_name,
"configuration": config
}
# Create file for every setting in loop
File.open(configs_folder_name + "/" + target_name + config["name"] + ".xcconfig", 'w') { |file|
file.puts(Mustache.render(target_xcconfig_tempate, config_data))
}
end
end
# Remove config file, it's trash
File.delete(temp_configs_data_file_path) if File.exist?(temp_configs_data_file_path)
ConfigRenderer.new(configurations_file_path, build_parameters_path, configs_folder_name).render_xconfigs()

View File

@ -1,7 +1,5 @@
#include "Pods/Target Support Files/Pods-{{target_name}}/Pods-{{target_name}}.{{configuration.build_type}}.xcconfig"
#include "Pods/Target Support Files/Pods{{abstract_targets_prefix}}-{{target_name}}/Pods{{abstract_targets_prefix}}-{{target_name}}.{{configuration.build_type}}.xcconfig"
{{#configuration.xcconfig_options}}
{{key}} = {{value}}
{{/configuration.xcconfig_options}}
CODE_SIGN_STYLE = Manual
{{/configuration.xcconfig_options}}

View File

@ -6,6 +6,8 @@ module Touchlane
class LocalStorage < Match::Storage::Interface
attr_accessor :signing_identities_path
STORAGE_TYPE = "local"
def self.configure(params)
return self.new(
# we can't pass signing_identities_path since params is hardcoded in match/runner.rb

View File

@ -0,0 +1,16 @@
require 'match'
# ugly hack to add support for custom storage
Match.module_eval do
def self.storage_modes
return ['git', 'google_cloud' 's3', Touchlane::LocalStorage::STORAGE_TYPE]
end
end
def register_local_storage_for_match
storage_type = Touchlane::LocalStorage::STORAGE_TYPE
Match::Storage.register_backend(type: storage_type, storage_class: Touchlane::LocalStorage)
Match::Encryption.register_backend(type: storage_type, encryption_class: Match::Encryption::OpenSSL)
end

View File

@ -1,6 +1,9 @@
module Touchlane
require_relative "touchlane/configuration_type"
require_relative "touchlane/configuration"
require_relative "touchlane/features"
require_relative "match/storage/local_storage"
require_relative "match/storage/local_storage_register"
require_relative "touchlane/actions/sync_signing_identities"
require_relative "touchlane/actions/refresh_profiles"
require_relative "touchlane/actions/replace_development_certificate"
require_relative "touchlane/actions/manually_update_code_signing"
end

View File

@ -0,0 +1,62 @@
require 'match'
require_relative '../../match/storage/local_storage'
def manually_update_code_signing(options)
register_local_storage_for_match()
storage_factory = lambda do
new_storage = Match::Storage.from_params(options)
new_storage.download
return new_storage
end
encryption_factory = lambda do |stor|
new_encryption = Match::Encryption.for_storage_mode(options[:storage_mode], { working_directory: stor.working_directory })
new_encryption.decrypt_files
return new_encryption
end
get_all_files = lambda do |stor|
Dir[File.join(stor.working_directory, "**", "*.{cer,p12,mobileprovision}")]
end
storage = storage_factory.call
encryption = encryption_factory.call(storage)
old_files = get_all_files.call(storage)
sh("open #{storage.working_directory}")
# we are not using prompt() since it requires non-empty input which is not a case for Enter (\n)
puts "Enter any key when you're done"
STDIN.gets
encryption.encrypt_files
files_to_commit = get_all_files.call(storage)
old_directory = storage.working_directory
storage.save_changes!(files_to_commit: files_to_commit)
# need to check, because saving changes with delete is another function (update repo if needed)
files_diff = old_files - files_to_commit
# match can not work with both save/delete functionality `You can't provide both files_to_delete and files_to_commit right now`
# to avoid this we use storage twice if needed
if files_diff.length > 0
storage = storage_factory.call
encryption = encryption_factory.call(storage)
files_to_delete = files_diff.map do |file|
old_file = file
old_file.slice! old_directory
new_file = File.join(storage.working_directory, old_file)
File.delete(new_file) if File.exist?(new_file)
file = new_file
end
encryption.encrypt_files
storage.save_changes!(files_to_delete: files_to_delete)
end
end

View File

@ -0,0 +1,96 @@
require 'match'
require 'fastlane_core'
require 'Spaceship'
def refresh_profiles(options)
register_local_storage_for_match()
profiles_tmp_dir = Dir.mktmpdir
unless options[:cert_id]
cert_type = Match.cert_type_sym(options[:type])
storage = Match::Storage.from_params(options)
storage.download
output_dir_certs = File.join(storage.prefixed_working_directory, "certs", cert_type.to_s)
matched_certs = Dir.glob("*.cer", base: output_dir_certs)
if matched_certs.empty?
FastlaneCore::UI.error("Unable to locate certificate to upate profiles")
raise "No certificates found at #{output_dir_certs}"
end
if matched_certs.length > 1
options[:cert_id] = File.basename(FastlaneCore::UI.select("Please select the certificate", matched_certs), ".cer")
else
options[:cert_id] = File.basename(matched_certs.first, ".cer")
end
if options[:cert_path].nil? && options[:p12_path].nil?
encryption = Match::Encryption.for_storage_mode(options[:storage_mode], { working_directory: storage.working_directory })
encryption.decrypt_files
tmp_certs_dir = Dir.mktmpdir
cer_file_name = "#{options[:cert_id]}.cer"
cert_path = File.join(output_dir_certs, cer_file_name)
options[:cert_path] = File.join(tmp_certs_dir, cer_file_name)
p12_file_name = "#{options[:cert_id]}.p12"
p12_path = File.join(output_dir_certs, p12_file_name)
options[:p12_path] = File.join(tmp_certs_dir, p12_file_name)
IO.copy_stream(cert_path, options[:cert_path])
IO.copy_stream(p12_path, options[:p12_path])
end
end
app_identifier = options[:app_identifier]
Spaceship::ConnectAPI.token = Spaceship::ConnectAPI::Token.from_json_file(options[:api_key_path])
if app_identifier.is_a? Array
app_identifier.each { |app_id| refresh_profile_for_app(options, app_id, profiles_tmp_dir) }
else
refresh_profile_for_app(options, app_identifier, profiles_tmp_dir)
end
end
def refresh_profile_for_app(options, app_id, profiles_tmp_dir)
provisioning_name = Fastlane::Actions.lane_context[Touchlane::SharedValues::TOUCH_BUNDLE_ID_PROFILE_NAME_MAPPING][app_id]
profiles = Spaceship::ConnectAPI::Profile.all(filter: { name: provisioning_name })
if profiles.empty?
sigh_for_app(options, app_id, provisioning_name, profiles_tmp_dir)
else
FastlaneCore::UI.important("Did find existing profile #{provisioning_name}. Removing it from dev portal.")
profiles.each { |profile| profile.delete! if profile.name == provisioning_name }
sigh_for_app(options, app_id, provisioning_name, profiles_tmp_dir)
end
Match::Importer.new.import_cert(
options,
cert_path: options[:cert_path],
p12_path: options[:p12_path],
profile_path: lane_context[Fastlane::Actions::SharedValues::SIGH_PROFILE_PATH]
)
end
def sigh_for_app(options, app_id, provisioning_name, profiles_tmp_dir)
sigh(
app_identifier: app_id,
development: options[:development],
username: options[:username] || options[:apple_id],
api_key_path: options[:api_key_path],
api_key: options[:api_key],
team_id: options[:team_id],
provisioning_name: provisioning_name,
output_path: profiles_tmp_dir,
cert_id: options[:cert_id],
force: true # will also add all available devices to this profile
)
end

View File

@ -0,0 +1,24 @@
def replace_development_certificate(options)
register_local_storage_for_match()
certs_path_tmp_dir = Dir.mktmpdir
cert(
development: true,
username: options[:username] || options[:apple_id],
api_key_path: options[:api_key_path],
api_key: options[:api_key],
team_id: options[:team_id],
output_path: certs_path_tmp_dir,
keychain_password: options[:keychain_password]
)
options[:cert_id] = lane_context[Fastlane::Actions::SharedValues::CERT_CERTIFICATE_ID]
options[:cert_path] = lane_context[Fastlane::Actions::SharedValues::CERT_FILE_PATH]
options[:p12_path] = File.join(File.dirname(options[:cert_path]), "#{options[:cert_id]}.p12")
options[:readonly] = false
refresh_profiles(options)
sh("open #{certs_path_tmp_dir}")
end

View File

@ -0,0 +1,26 @@
def install_signing_identities(options)
readonly_options = options
readonly_options[:readonly] = true
sync_signing_identities(readonly_options)
end
def sync_signing_identities(options)
register_local_storage_for_match()
match(
app_identifier: options[:app_identifier],
username: options[:username] || options[:apple_id],
api_key_path: options[:api_key_path],
api_key: options[:api_key],
team_id: options[:team_id],
type: options[:type],
readonly: options[:readonly].nil? ? true : options[:readonly],
storage_mode: options[:storage_mode],
# we can't pass signing_identities_path as parameter name since params is hardcoded in match/runner.rb
git_url: options[:signing_identities_path] || options[:git_url],
skip_docs: true,
keychain_name: options[:keychain_name],
keychain_password: options[:keychain_password]
)
end

View File

@ -1,6 +1,10 @@
require "yaml"
module Touchlane
module SharedValues
TOUCH_BUNDLE_ID_PROFILE_NAME_MAPPING = :TOUCH_BUNDLE_ID_PROFILE_NAME_MAPPING
end
class Configuration
def initialize(type, app_identifier, apple_id, team_id, itc_team_id)
@type = type
@ -13,6 +17,8 @@ module Touchlane
attr_reader :type, :app_identifier, :apple_id, :team_id, :itc_team_id
def self.from_file(path, type)
Fastlane::Actions.lane_context[SharedValues::TOUCH_BUNDLE_ID_PROFILE_NAME_MAPPING] = {}
configuration_hash = load_configuration_from_file(path)
attrs_hash = configuration_hash["types"][type]
identifiers = get_app_identifiers_from_configuration_hash(configuration_hash, type)
@ -35,8 +41,15 @@ module Touchlane
def self.get_app_identifiers_from_configuration_hash(configuration_hash, type)
identifier_key = "PRODUCT_BUNDLE_IDENTIFIER"
profile_name_key = "PROVISIONING_PROFILE_SPECIFIER"
configuration_hash["targets"].collect do |target, types|
types[type][identifier_key] or raise "#{target}: There is no #{identifier_key} field in #{type}"
bundle_id = types[type][identifier_key]
profile_name = types[type][profile_name_key]
Fastlane::Actions.lane_context[SharedValues::TOUCH_BUNDLE_ID_PROFILE_NAME_MAPPING][bundle_id] = profile_name
bundle_id or raise "#{target}: There is no #{identifier_key} field in #{type}"
end
end

View File

@ -3,13 +3,15 @@ module Touchlane
DEVELOPMENT = "development"
ENTERPRISE = "enterprise"
APP_STORE = "appstore"
ADHOC = "adhoc"
DEVELOPMENT_PREFIX = "Standard"
ENTERPRISE_PREFIX = "Enterprise"
APP_STORE_PREFIX = "AppStore"
ADHOC_PREFIX = "AdHoc"
private_constant :DEVELOPMENT, :ENTERPRISE, :APP_STORE
private_constant :DEVELOPMENT_PREFIX, :ENTERPRISE_PREFIX, :APP_STORE_PREFIX
private_constant :DEVELOPMENT, :ENTERPRISE, :APP_STORE, :ADHOC_PREFIX
private_constant :DEVELOPMENT_PREFIX, :ENTERPRISE_PREFIX, :APP_STORE_PREFIX, :ADHOC_PREFIX
def initialize(type)
@type = type
@ -30,6 +32,10 @@ module Touchlane
@export_method = "app-store"
@configuration = "AppStore"
@prefix = APP_STORE_PREFIX
when ADHOC
@export_method = type
@export_method = "ad-hoc"
@prefix = ADHOC_PREFIX
else
raise "Unknown type passed #{type}"
end
@ -47,9 +53,11 @@ module Touchlane
from_type(APP_STORE)
when lane_name.start_with?(DEVELOPMENT_PREFIX)
from_type(DEVELOPMENT)
when lane_name.start_with?(ADHOC_PREFIX)
from_type(ADHOC)
else
raise "Unable to map #{lane_name} to #{ConfigurationType.class}."
+ "Available prefixes: #{DEVELOPMENT_PREFIX}, #{ENTERPRISE_PREFIX}, #{APP_STORE_PREFIX}"
+ "Available prefixes: #{DEVELOPMENT_PREFIX}, #{ENTERPRISE_PREFIX}, #{APP_STORE_PREFIX}, #{ADHOC_PREFIX}"
end
end
@ -57,9 +65,26 @@ module Touchlane
new(type)
end
def self.from_account_type(account_type)
case account_type
when DEVELOPMENT_PREFIX
from_type(DEVELOPMENT)
when ENTERPRISE_PREFIX
from_type(ENTERPRISE)
when APP_STORE_PREFIX
from_type(APP_STORE)
when ADHOC_PREFIX
from_type(ADHOC)
else
raise "Unable to map #{account_type} to #{ConfigurationType.class}."
+ "Available account types: #{DEVELOPMENT_PREFIX}, #{ENTERPRISE_PREFIX}, #{APP_STORE_PREFIX}, #{ADHOC_PREFIX}"
end
end
def to_options
{
:type => @type,
:development => @is_development,
:export_method => @export_method,
:configuration => @configuration
}

View File

@ -1,26 +0,0 @@
require_relative '../../../../managers/managers'
require_relative '../../../../templates/templates'
module Touchlane
class Features
def self.generate_enabled_features_extension(builder_features_list, build_settings_features_list)
# Check is entered features contains in configuration file
features_diff = builder_features_list - build_settings_features_list
unless features_diff.empty?
raise "Unexpected features: " + features_diff.join(', ')
end
# Generate enabled features extension from feature names
enabled_features_extension_template = Templates::FeatureTemplates.enabled_features_extension
utils = Managers::TemplateManager.new(builder_features_list)
utils.render(enabled_features_extension_template).strip
end
private_class_method :new
end
end

View File

@ -1,33 +0,0 @@
require 'yaml'
require 'json'
module Managers
class FileManager
def self.save_data_to_file(path, data)
unless File.exists? path
raise "Unable to save data to file at #{path}"
else
File.open(path, "w") do |f|
f.write(data)
end
end
end
def self.load_from_file_YAML(path)
unless File.exists? path
raise "Unable to load data from file at #{path}"
else
YAML.load_file(path)
end
end
def self.save_data_to_file_in_json(path, data)
json_data = JSON.pretty_generate(data)
save_data_to_file(path, json_data)
end
private_class_method :new
end
end

View File

@ -1,19 +0,0 @@
require 'erb'
module Managers
class TemplateManager
include ERB::Util
attr_accessor :items
def initialize(items)
@items = items
end
def render(template)
ERB.new(template).result(binding)
end
end
end

View File

@ -1,4 +0,0 @@
module Managers
require_relative "lib/file_manager"
require_relative "lib/template_manager"
end

View File

@ -1,3 +0,0 @@
module Templates
require_relative "templates/features_templates"
end

View File

@ -1,34 +0,0 @@
module Templates
module FeatureTemplates
def self.features_enum
"
// MARK: - Generated feature toggles
public enum Feature: String, Codable, RawRepresentable, CaseIterable {
<% for @item in @items %>
case <%= @item %>
<% end %>
}
"
end
def self.enabled_features_extension
"
// MARK: - Generated enabled features
public extension Feature {
static var enabled: [Feature] {
[
<% for @item in @items %>
\.<%= @item %>,
<% end %>
]
}
}
"
end
end
end