diff --git a/plugins/.DS_Store b/plugins/.DS_Store new file mode 100644 index 0000000..a9ae6c7 Binary files /dev/null and b/plugins/.DS_Store differ diff --git a/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/build_and_deploy_action.rb b/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/build_and_deploy_action.rb index 316ab0e..92552ef 100644 --- a/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/build_and_deploy_action.rb +++ b/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/build_and_deploy_action.rb @@ -7,7 +7,7 @@ module Fastlane def self.run(params) # Check parameters unless Helper::AndroidCdHelper.is_set(params[:beta_type]) - UI.error("Parameters beta_type cannot be null") + UI.error("❌ Parameters beta_type cannot be null") puts("Error on beta type parameter") end @@ -23,17 +23,17 @@ module Fastlane build_number = Fastlane::Actions.number_of_commits # Build the Android App Bundle - Fastlane::Actions.gradle( - task: "bundle", - build_type: "Release", - print_command: true, - properties: { - "android.injected.version.code" => build_number - } - ) + Actions(GradleAction.run( + task: "bundle", + build_type: "Release", + print_command: true, + properties: { + "android.injected.version.code" => build_number + } + )) # Upload the Android App Bundle to the Play Store - Fastlane::Actions.upload_to_play_store( + Actions::UploadToPlayStoreAction.run( track: params[:beta_type], json_key: './service_account_key.json', aab: '../build/app/outputs/bundle/release/app-release.aab', diff --git a/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/promote_action.rb b/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/promote_action.rb index 9bab7e6..e3c9ef4 100644 --- a/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/promote_action.rb +++ b/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/actions/promote_action.rb @@ -24,7 +24,7 @@ module Fastlane # Upload the Android App Bundle to the Play Store Fastlane::Actions.upload_to_play_store( - track: params[:beta_type], + track: params[:from], json_key: './service_account_key.json', skip_upload_apk: true, skip_upload_aab: true, diff --git a/plugins/fastlane-plugin-ios_cd/.github/workflows/test.yml b/plugins/fastlane-plugin-ios_cd/.github/workflows/test.yml new file mode 100644 index 0000000..56cf580 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/.github/workflows/test.yml @@ -0,0 +1,29 @@ +name: Test + +on: + push: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/cache@v1 + with: + path: vendor/bundle + key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile') }} + restore-keys: | + ${{ runner.os }}-gem- + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.5 + - name: Install dependencies + run: bundle check || bundle install --jobs=4 --retry=3 --path vendor/bundle + - name: Run tests + run: bundle exec rake + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: test-results + path: test-results diff --git a/plugins/fastlane-plugin-ios_cd/.gitignore b/plugins/fastlane-plugin-ios_cd/.gitignore new file mode 100644 index 0000000..b7e3986 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/.gitignore @@ -0,0 +1,12 @@ +*.gem +Gemfile.lock + +## Documentation cache and generated files: +/.yardoc/ +/_yardoc/ +/doc/ +/rdoc/ +fastlane/README.md +fastlane/report.xml +coverage +test-results diff --git a/plugins/fastlane-plugin-ios_cd/.rspec b/plugins/fastlane-plugin-ios_cd/.rspec new file mode 100644 index 0000000..e1f89b5 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/.rspec @@ -0,0 +1,5 @@ +--require spec_helper +--color +--format d +--format RspecJunitFormatter +--out test-results/rspec/rspec.xml diff --git a/plugins/fastlane-plugin-ios_cd/.rubocop.yml b/plugins/fastlane-plugin-ios_cd/.rubocop.yml new file mode 100644 index 0000000..fc36fbb --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/.rubocop.yml @@ -0,0 +1,188 @@ +--- +require: +- rubocop/require_tools +- rubocop-performance +AllCops: + TargetRubyVersion: 2.6 + NewCops: enable + Include: + - "**/*.rb" + - "**/*file" + - "**/*.gemspec" + - "*/lib/assets/*Template" + - "*/lib/assets/*TemplateAndroid" + Exclude: + - "**/lib/assets/custom_action_template.rb" + - "./vendor/**/*" + - "**/lib/assets/DefaultFastfileTemplate" + - "**/lib/assets/MatchfileTemplate" + - "**/spec/fixtures/broken_files/broken_file.rb" + - "**/*.provisionprofile" +Lint/ErbNewArguments: + Enabled: false +Style/SlicingWithRange: + Enabled: false +Style/MultipleComparison: + Enabled: false +Style/PercentLiteralDelimiters: + Enabled: false +Style/ClassCheck: + EnforcedStyle: kind_of? +Style/FrozenStringLiteralComment: + Enabled: false +Style/SafeNavigation: + Enabled: false +Performance/RegexpMatch: + Enabled: false +Performance/StringReplacement: + Enabled: false +Style/NumericPredicate: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Naming/VariableNumber: + Enabled: false +Style/MissingRespondToMissing: + Enabled: false +Style/MultilineBlockChain: + Enabled: false +Style/NumericLiteralPrefix: + Enabled: false +Style/TernaryParentheses: + Enabled: false +Style/EmptyMethod: + Enabled: false +Lint/UselessAssignment: + Exclude: + - "**/spec/**/*" +Require/MissingRequireStatement: + Exclude: + - "**/spec/**/*.rb" + - "**/spec_helper.rb" + - spaceship/lib/spaceship/babosa_fix.rb + - fastlane_core/lib/fastlane_core/ui/disable_colors.rb + - "**/Fastfile" + - "**/*.gemspec" + - rakelib/**/* + - "**/*.rake" + - "**/Rakefile" + - fastlane/**/* + - supply/**/* +Layout/FirstHashElementIndentation: + Enabled: false +Layout/HashAlignment: + Enabled: false +Layout/DotPosition: + Enabled: false +Style/DoubleNegation: + Enabled: false +Style/SymbolArray: + Enabled: false +Layout/HeredocIndentation: + Enabled: false +Style/MixinGrouping: + Exclude: + - "**/spec/**/*" +Lint/SuppressedException: + Enabled: false +Lint/UnusedBlockArgument: + Enabled: false +Lint/AmbiguousBlockAssociation: + Enabled: false +Style/GlobalVars: + Enabled: false +Style/ClassAndModuleChildren: + Enabled: false +Style/SpecialGlobalVars: + Enabled: false +Metrics/AbcSize: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Style/WordArray: + MinSize: 19 +Style/SignalException: + Enabled: false +Style/RedundantReturn: + Enabled: false +Style/IfUnlessModifier: + Enabled: false +Style/AndOr: + Enabled: true + EnforcedStyle: conditionals +Metrics/ClassLength: + Max: 320 +Layout/LineLength: + Max: 370 +Metrics/ParameterLists: + Max: 17 +Style/GuardClause: + Enabled: false +Style/StringLiterals: + Enabled: false +Style/ConditionalAssignment: + Enabled: false +Style/RedundantSelf: + Enabled: false +Lint/UnusedMethodArgument: + Enabled: false +Lint/ParenthesesAsGroupedExpression: + Exclude: + - "**/spec/**/*" +Naming/PredicateName: + Enabled: false +Style/PerlBackrefs: + Enabled: false +Layout/SpaceAroundOperators: + Exclude: + - "**/spec/actions_specs/xcodebuild_spec.rb" +Naming/FileName: + Exclude: + - "**/Dangerfile" + - "**/Brewfile" + - "**/Gemfile" + - "**/Podfile" + - "**/Rakefile" + - "**/Fastfile" + - "**/Deliverfile" + - "**/Snapfile" + - "**/Pluginfile" + - "**/*.gemspec" +Style/Documentation: + Enabled: false +Style/MutableConstant: + Enabled: false +Style/ZeroLengthPredicate: + Enabled: false +Style/IfInsideElse: + Enabled: false +Style/CollectionMethods: + Enabled: false +Style/MethodCallWithArgsParentheses: + Enabled: true + IgnoredMethods: + - require + - require_relative + - fastlane_require + - gem + - program + - command + - raise + - attr_accessor + - attr_reader + - desc + - lane + - private_lane + - platform + - to + - not_to + - describe + - it + - be + - context + - before + - after diff --git a/plugins/fastlane-plugin-ios_cd/.travis.yml b/plugins/fastlane-plugin-ios_cd/.travis.yml new file mode 100644 index 0000000..3b35e45 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/.travis.yml @@ -0,0 +1,4 @@ +# os: osx # enable this if you need macOS support +language: ruby +rvm: + - 2.2.4 diff --git a/plugins/fastlane-plugin-ios_cd/Gemfile b/plugins/fastlane-plugin-ios_cd/Gemfile new file mode 100644 index 0000000..0a7944e --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/Gemfile @@ -0,0 +1,9 @@ +source('https://rubygems.org') + +gemspec + +gem 'json' +gem "cocoapods" + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/plugins/fastlane-plugin-ios_cd/LICENSE b/plugins/fastlane-plugin-ios_cd/LICENSE new file mode 100644 index 0000000..c1a9462 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Malo Léon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/fastlane-plugin-ios_cd/README.md b/plugins/fastlane-plugin-ios_cd/README.md new file mode 100644 index 0000000..bf19973 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/README.md @@ -0,0 +1,52 @@ +# ios_cd plugin + +[![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-ios_cd) + +## Getting Started + +This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-ios_cd`, add it to your project by running: + +```bash +fastlane add_plugin ios_cd +``` + +## About ios_cd + +Testflight and AppStore deployment plugin for Fastlane, simplifying the build and deployment porcess to internal, external, and production channels, and promoting builds for testing. + +**Note to author:** Add a more detailed description about this plugin here. If your plugin contains multiple actions, make sure to mention them here. + +## Example + +Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`. + +**Note to author:** Please set up a sample project to make it easy for users to explore what your plugin does. Provide everything that is necessary to try out the plugin in this project (including a sample Xcode/Android project if necessary) + +## Run tests for this plugin + +To run both the tests, and code style validation, run + +``` +rake +``` + +To automatically fix many of the styling issues, use +``` +rubocop -a +``` + +## Issues and Feedback + +For any other issues and feedback about this plugin, please submit it to this repository. + +## Troubleshooting + +If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide. + +## Using _fastlane_ Plugins + +For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/). + +## About _fastlane_ + +_fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools). diff --git a/plugins/fastlane-plugin-ios_cd/Rakefile b/plugins/fastlane-plugin-ios_cd/Rakefile new file mode 100644 index 0000000..094ebe2 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/Rakefile @@ -0,0 +1,9 @@ +require 'bundler/gem_tasks' + +require 'rspec/core/rake_task' +RSpec::Core::RakeTask.new + +require 'rubocop/rake_task' +RuboCop::RakeTask.new(:rubocop) + +task(default: [:spec, :rubocop]) diff --git a/plugins/fastlane-plugin-ios_cd/fastlane-plugin-ios_cd.gemspec b/plugins/fastlane-plugin-ios_cd/fastlane-plugin-ios_cd.gemspec new file mode 100644 index 0000000..62cdadd --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/fastlane-plugin-ios_cd.gemspec @@ -0,0 +1,36 @@ +lib = File.expand_path("lib", __dir__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'fastlane/plugin/ios_cd/version' + +Gem::Specification.new do |spec| + spec.name = 'fastlane-plugin-ios_cd' + spec.version = Fastlane::IosCd::VERSION + spec.author = 'Malo Léon' + spec.email = 'malo.leon@wyatt-studio.fr' + + spec.summary = 'Testflight and AppStore deployment plugin for Fastlane, simplifying the build and deployment porcess to internal, external, and production channels, and promoting builds for testing.' + # spec.homepage = "https://github.com//fastlane-plugin-ios_cd" + spec.license = "MIT" + + spec.files = Dir["lib/**/*"] + %w(README.md LICENSE) + spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) + spec.require_paths = ['lib'] + + spec.required_ruby_version = '>= 2.6' + + # Don't add a dependency to fastlane or fastlane_re + # since this would cause a circular dependency + + # spec.add_dependency 'your-dependency', '~> 1.0.0' + + spec.add_development_dependency('bundler') + spec.add_development_dependency('fastlane', '>= 2.212.2') + spec.add_development_dependency('pry') + spec.add_development_dependency('rake') + spec.add_development_dependency('rspec') + spec.add_development_dependency('rspec_junit_formatter') + spec.add_development_dependency('rubocop', '1.12.1') + spec.add_development_dependency('rubocop-performance') + spec.add_development_dependency('rubocop-require_tools') + spec.add_development_dependency('simplecov') +end diff --git a/plugins/fastlane-plugin-ios_cd/fastlane/Fastfile b/plugins/fastlane-plugin-ios_cd/fastlane/Fastfile new file mode 100644 index 0000000..79918ea --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/fastlane/Fastfile @@ -0,0 +1,3 @@ +lane :test do + build_and_deploy(beta_type: "internal") +end diff --git a/plugins/fastlane-plugin-ios_cd/fastlane/Pluginfile b/plugins/fastlane-plugin-ios_cd/fastlane/Pluginfile new file mode 100644 index 0000000..e0576b0 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/fastlane/Pluginfile @@ -0,0 +1 @@ +# Autogenerated by fastlane diff --git a/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd.rb b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd.rb new file mode 100644 index 0000000..f355051 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd.rb @@ -0,0 +1,16 @@ +require 'fastlane/plugin/ios_cd/version' + +module Fastlane + module IosCd + # Return all .rb files inside the "actions" and "helper" directory + def self.all_classes + Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))] + end + end +end + +# By default we want to import all available actions and helpers +# A plugin can contain any number of actions and plugins +Fastlane::IosCd.all_classes.each do |current| + require current +end diff --git a/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/actions/build_and_deploy_action.rb b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/actions/build_and_deploy_action.rb new file mode 100644 index 0000000..5e62d3a --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/actions/build_and_deploy_action.rb @@ -0,0 +1,158 @@ +require 'fastlane/action' +require_relative '../helper/ios_cd_helper' + +module Fastlane + module Actions + class BuildAndDeployAction < Action + def self.run(params) + # Check parameters + unless Helper::IosCdHelper.is_set(params[:beta_type]) + UI.error("❌ Parameters beta_type cannot be null") + puts("Error on beta type parameter") + end + + UI.message("⌛️ Building and deploying to Store in #{params[:beta_type]}..") + + # Decrypt the keys archive and Extract the keys archive + Helper::IosCdHelper.decrypt_ios_keys('.') + UI.message("👉🏼 Credentials decrypted.") + + # Retrieve credentials + creds = Helper::IosCdHelper.parseIosCredentials('.') + UI.message("👉🏼 Credentials parsed.") + + # Delete keychain if existing + if File.exist?(File.expand_path("~/Library/Keychains/#{name}-db")) + other_action.delete_keychain( + name: creds['temp_keychain_user'].to_s + ) + end + + # Create keychain to store certifs + other_action.create_keychain( + name: creds['temp_keychain_user'].to_s, + password: creds['temp_keychain_password'].to_s, + unlock: false, + timeout: 0 + ) + UI.message("👉🏼 New keychain created") + + # Obtain App Store Connect API key + api_key = other_action.app_store_connect_api_key( + key_id: creds['apple_key_id'].to_s, + issuer_id: creds['apple_issuer_id'].to_s, + key_content: creds['apple_key_content'].to_s, + duration: 1200, + in_house: false + ) + UI.message("👉🏼 API Key formated") + + last_testflight_build_number = + other_action.latest_testflight_build_number( + api_key: api_key, + team_id: creds['team_id'].to_s, + team_name: creds['team_name'].to_s, + platform: 'ios', + app_identifier: creds['developer_app_identifier'].to_s, + username: creds['username'].to_s + ) + 1 + + # Increment build number for latest TestFlight build + other_action.increment_build_number( + build_number: last_testflight_build_number + 1, + xcodeproj: "Runner.xcodeproj" + ) + UI.message("👉🏼 Build number incremented") + + # Install Cocoapods + other_action.cocoapods( + clean_install: true, + clean: true, + integrate: true, + podfile: "./Podfile" + ) + UI.message("👉🏼 Pod got") + + # Set up code signing using match + # Configures and runs `match` which manages code signing certificates and provisioning profiles for the project. + # The function takes the app's bundle identifier, an authorization token for the project's Git repository, and the name and password for a temporary keychain used to store the signing certificate. + # It uses the App Store Connect API key to access the App Store and increment the build number. + # It then runs `gym` to build and sign the app using the selected provisioning profile, and finally, uses `pilot` to upload the app to TestFlight for beta testing. + other_action.match( + api_key: api_key, + type: 'appstore', + app_identifier: creds['app_identifier_extensions'], + git_basic_authorization: Base64.strict_encode64(ENV["GIT_AUTHORIZATION"]), + keychain_name: creds['temp_keychain_user'].to_s, + keychain_password: creds['temp_keychain_password'].to_s, + git_url: creds['git_url'].to_s, + username: creds['username'].to_s, + team_id: creds['team_id'].to_s, + team_name: creds['team_name'].to_s, + git_url: creds['git_url'].to_s, + storage_mode: "git" + ) + UI.message("👉🏼 App signed") + + # Build and export app using Gym + # Builds and packages an iOS app or framework for distribution to the App Store, TestFlight, or Enterprise distribution. + other_action.gym( + configuration: "Release", + workspace: "Runner.xcworkspace", + export_method: "app-store", + export_options: { + provisioningProfiles: creds['provisioning_profiles'] + } + ) + UI.message("👉🏼 App built") + + # Upload build to App Store Connect using Pilot + other_action.pilot( + api_key: api_key, + apple_id: creds['developer_app_id'].to_s, + app_identifier: creds['developer_app_identifier'].to_s, + skip_waiting_for_build_processing: true, + skip_submission: true, + distribute_external: false, + notify_external_testers: false, + ipa: "./Runner.ipa" + ) + + # Delete keychain if existing + if File.exist?(File.expand_path("~/Library/Keychains/#{name}-db")) + other_action.delete_keychain( + name: creds['temp_keychain_user'] + ) + end + end + + def self.description + "Testflight and AppStore deployment plugin for Fastlane, simplifying the build and deployment porcess to internal, external, and production channels, and promoting builds for testing." + end + + def self.authors + ["SAS Wyatt Studio"] + end + + def self.return_value + end + + def self.details + "The Fastlane Testflight / Appstore deloyment action streamlines the build and deployment to internal, external and production channels. Allow you to promote builds on testflight beta tests." + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new(key: :beta_type, + env_name: "IOS_CD_TEST_TYPE", + optional: false, + description: "Type of test (internal, external, production)") + ] + end + + def self.is_supported?(platform) + [:ios].include?(platform) + end + end + end +end diff --git a/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/actions/promote_action.rb b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/actions/promote_action.rb new file mode 100644 index 0000000..de15c0b --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/actions/promote_action.rb @@ -0,0 +1,71 @@ +require 'fastlane/action' +require_relative '../helper/ios_cd_helper' + +module Fastlane + module Actions + class PromoteAction < Action + def self.run(params) + + UI.message("⌛️ Promoting to Store in external test..") + + # Decrypt the keys archive and Extract the keys archive + Helper::IosCdHelper.decrypt_ios_keys('.') + UI.message("👉🏼 Credentials decrypted.") + + # Retrieve credentials + creds = Helper::IosCdHelper.parseIosCredentials('.') + UI.message("👉🏼 Credentials parsed.") + + # Obtain App Store Connect API key + api_key = other_action.app_store_connect_api_key( + key_id: creds['apple_key_id'].to_s, + issuer_id: creds['apple_issuer_id'].to_s, + key_content: creds['apple_key_content'].to_s, + duration: 1200, + in_house: false + ) + UI.message("👉🏼 API Key formated") + + # Upload build to App Store Connect using Pilot + other_action.pilot( + api_key: api_key, + apple_id: creds['developer_app_id'].to_s, + app_identifier: creds['developer_app_identifier'].to_s, + skip_waiting_for_build_processing: false, + distribute_only: true, + skip_submission: true, + distribute_external: true, + notify_external_testers: true, + groups: [ + "Bêta externe", + ], + app_platform:'ios', + ) + + end + + def self.description + "Testflight and AppStore deployment plugin for Fastlane, simplifying the build and deployment porcess to internal, external, and production channels, and promoting builds for testing." + end + + def self.authors + ["SAS Wyatt Studio"] + end + + def self.return_value + end + + def self.details + "The Fastlane Testflight / Appstore deloyment action streamlines the build and deployment to internal, external and production channels. Allow you to promote builds on testflight beta tests." + end + + def self.available_options + [] + end + + def self.is_supported?(platform) + [:ios].include?(platform) + end + end + end +end diff --git a/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/helper/ios_cd_helper.rb b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/helper/ios_cd_helper.rb new file mode 100644 index 0000000..db2d2b9 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/helper/ios_cd_helper.rb @@ -0,0 +1,47 @@ +require 'fastlane/action' +require 'json' +require 'fastlane_core/ui/ui' + +module Fastlane + module Helper + class IosCdHelper + # Check if a parameter is set or not + def self.is_set(variable) + str_variable = variable + str_variable = variable.strip if variable.class.to_s == "String" + variable && !(str_variable.nil? || str_variable.empty?) + end + + # Decrypts ios credentials + def self.decrypt_ios_keys(ios_directory) + # Define the GPG command with options + gpg_command = "gpg --quiet --batch --yes --decrypt --passphrase=#{ENV['IOS_KEYS_SECRET_PASSPHRASE']} \ + --output #{ios_directory}/ios_keys.zip #{ios_directory}/ios_keys.zip.gpg" + + # Execute the GPG command using system + system(gpg_command) + + # Check if the command executed successfully + if $?.success? + # Move the extracted files to the current directory + `jar xvf #{ios_directory}/ios_keys.zip && mv #{ios_directory}/ios_keys/* #{ios_directory}` + else + puts("Erreur lors de la décompression du fichier GPG") + end + end + + # Parse credential file + def self.parseIosCredentials(ios_directory) + if File.exist?("#{ios_directory}/ios_crendentials.json") + # Read file and decrypt it + file = File.read("#{ios_directory}/ios_crendentials.json") + JSON.parse(file) + + else + UI.error("❌ Ios credentials doesn't exist") + puts("json file doesn't exist") + end + end + end + end +end diff --git a/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/version.rb b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/version.rb new file mode 100644 index 0000000..3415157 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/lib/fastlane/plugin/ios_cd/version.rb @@ -0,0 +1,5 @@ +module Fastlane + module IosCd + VERSION = "0.1.0" + end +end diff --git a/plugins/fastlane-plugin-ios_cd/spec/ios_cd_action_spec.rb b/plugins/fastlane-plugin-ios_cd/spec/ios_cd_action_spec.rb new file mode 100644 index 0000000..1cd4e6f --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/spec/ios_cd_action_spec.rb @@ -0,0 +1,9 @@ +describe Fastlane::Actions::BuildAndDeployAction do + describe '#run' do + it 'prints a message' do + expect(Fastlane::UI).to receive(:message).with("The ios_cd plugin is working!") + + Fastlane::Actions::BuildAndDeployAction.run(nil) + end + end +end diff --git a/plugins/fastlane-plugin-ios_cd/spec/spec_helper.rb b/plugins/fastlane-plugin-ios_cd/spec/spec_helper.rb new file mode 100644 index 0000000..7440b08 --- /dev/null +++ b/plugins/fastlane-plugin-ios_cd/spec/spec_helper.rb @@ -0,0 +1,15 @@ +$LOAD_PATH.unshift(File.expand_path('../lib', __dir__)) + +require 'simplecov' + +# SimpleCov.minimum_coverage 95 +SimpleCov.start + +# This module is only used to check the environment is currently a testing env +module SpecHelper +end + +require 'fastlane' # to import the Action super class +require 'fastlane/plugin/ios_cd' # import the actual plugin + +Fastlane.load_actions # load other actions (in case your plugin calls other actions or shared values)