diff --git a/plugins/fastlane-plugin-android_cd/README.md b/plugins/fastlane-plugin-android_cd/README.md index 92fba53..05cd7d2 100644 --- a/plugins/fastlane-plugin-android_cd/README.md +++ b/plugins/fastlane-plugin-android_cd/README.md @@ -4,7 +4,7 @@ ## Getting Started -This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-android_cd`, add the dependencies into your `PluginFile` : +This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-android_cd` , add the dependencies into your `PluginFile` : ```ruby gem "fastlane-plugin-android_cd", git: "https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-fastlane-plugins.git", branch: "main", glob: 'plugins/fastlane-plugin-android_cd/*.gemspec' @@ -22,7 +22,7 @@ To use these actions, you need to add some information to your Android folder so In your android folder, place a compressed folder containing: -- The application's signing key (in the .jks format). If this is a new application, you can generate this key with the following command: +* The application's signing key (in the .jks format). If this is a new application, you can generate this key with the following command: ```shel keytool -genkey -v -keystore key_store_name.keystore -alias key_alias_name -keyalg RSA -keysize 2048 -validity 10000 @@ -30,29 +30,39 @@ keytool -genkey -v -keystore key_store_name.keystore -alias key_alias_name -keya During the execution of the above command, you will be prompted to provide a password for your key. Make sure to remember this password, as you will need it later. -- The key.properties file containing sensitive data for using the signing key, such as the path of the key or the password. If this file does not exist yet, create it and fill in the following fields: +* The key.properties file containing sensitive data for using the signing key, such as the path of the key or the password. If this file does not exist yet, create it and fill in the following fields: - - `storeFile`: the relative or absolute path to the key storage file that contains the private key used to sign the Android application. - - `storePassword`: the password used to access the key storage file. - - `keyAlias`: the alias of the key used to sign the application. - - `keyPassword`: the password used to access the key. + + `storeFile`: the relative or absolute path to the key storage file that contains the private key used to sign the Android application. + + `storePassword`: the password used to access the key storage file. + + `keyAlias`: the alias of the key used to sign the application. + + `keyPassword`: the password used to access the key. -- The credentials in JSON format to allow the fastlane action to connect to the Google Play Store console and upload the new build. To retrieve them, follow these steps: +* The credentials in JSON format to allow the fastlane action to connect to the Google Play Store console and upload the new build. To retrieve them, follow these steps: - - Go to your Google Play Store console. - - In the Settings menu, select `API access`, then click `Create Service Account` - - Navigate to the provided Google Developers Console link in the dialog - - Click `Create Service Account` at the top of the Google Developers Console - - Provide the required details, then click `Create` - - Click `Select a role`, select `Service Accounts`, then click `Service Account User` - - In the Service Accounts dashboard, navigate to the Actions column, tap the menu for the service account that you created, then click `Create Key` - - Select JSON as the key type, then click `Save` - - Back on the Google Play Console, click `Done` to close the dialog - - Click on `Grant Access` for the newly added service account - - Make sure that the role of this service account has the permission to upload builds - - Click `Add User` to close the dialog + + Go to your Google Play Store console. + + In the Settings menu, select `API access`, then click `Create Service Account` + + Navigate to the provided Google Developers Console link in the dialog + + Click `Create Service Account` at the top of the Google Developers Console + + Provide the required details, then click `Create` + + Click `Select a role`, select `Service Accounts`, then click `Service Account User` + + In the Service Accounts dashboard, navigate to the Actions column, tap the menu for the service account that you created, then click `Create Key` + + Select JSON as the key type, then click `Save` + + Back on the Google Play Console, click `Done` to close the dialog + + Click on `Grant Access` for the newly added service account + + Make sure that the role of this service account has the permission to upload builds + + Click `Add User` to close the dialog -Once you have all three elements in your folder, it's time to encrypt them. Indeed, this folder contains elements that are too sensitive to be referenced on git. Compress the folder, place the compressed folder in the android folder of your Flutter project, and execute the following command: +Once you have all three elements in your folder, it's time to encrypt them. Indeed, this folder contains elements that are too sensitive to be referenced on git. + +Place them in a folder named `android_keys` and compress it using the following command: + +```shell +jar cfvM android_keys.zip android_keys +``` + +> The plugin will use `jar xvf android/android_keys.zip && mv android/android_keys/* android/` to extract the secret files. + +Then, encrypt the compressed folder using GPG. ```shell gpg --quiet --batch --yes --symmetric --passphrase="" --output android/android_keys.zip.gpg android/android_keys.zip @@ -74,7 +84,7 @@ build_and_deploy(beta_type: "internal") promote(from: "internal", destination: "beta") ``` -note that beta type can be `production`, `beta`, `alpha`, `internal`. +note that beta type can be `production` , `beta` , `alpha` , `internal` . ## Run tests for this plugin 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 9117249..72518a8 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 @@ -14,24 +14,11 @@ module Fastlane # Decrypt the keys archive and Extract the keys archive Helper::AndroidCdHelper.decrypt_android_keys('.') - UI.message("👉🏼 Credentials decrypted") - # Clean the project before building - other_action.gradle(task: "clean") - - # Set the build number based on the number of commits - build_number = other_action.number_of_commits - # Build the Android App Bundle - other_action.gradle( - task: "bundle", - build_type: "Release", - print_command: true, - project_dir: './', - properties: { - "android.injected.version.code" => build_number - } + other_action.flutter_build( + build: 'appbundle' ) UI.message("👉🏼 App built") @@ -44,15 +31,12 @@ module Fastlane skip_upload_metadata: true, skip_upload_images: true, skip_upload_screenshots: true, - release_status: "draft", - version_code: build_number + release_status: "draft" ) # Delete artifacts files artifacts = ['android_keys.zip', 'key.jks', 'key.properties', 'service_account_key.json'] - artifacts.each do |file| - File.delete(file) if File.exist?(file) - end + Helper::AndroidCdHelper.delete_artifacts(artifacts) UI.success('🍺 Successfully build & deploy appbundle to Google Play Store') end diff --git a/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/helper/android_cd_helper.rb b/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/helper/android_cd_helper.rb index 619583e..02d22f0 100644 --- a/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/helper/android_cd_helper.rb +++ b/plugins/fastlane-plugin-android_cd/lib/fastlane/plugin/android_cd/helper/android_cd_helper.rb @@ -26,6 +26,13 @@ module Fastlane str_variable = variable.strip if variable.class.to_s == "String" variable && !(str_variable.nil? || str_variable.empty?) end + + # Delete built files + def self.delete_artifacts(artifacts) + artifacts.each do |file| + File.delete(file) if File.exist?(file) + end + end end end 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 index 1a31510..972175d 100644 --- 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 @@ -21,25 +21,19 @@ module Fastlane # Decrypt the keys archive and Extract the keys archive Helper::IosCdHelper.decrypt_ios_keys('.') - UI.message("👉🏼 Credentials decrypted.") + UI.message("🍺 Credentials decrypted.") # Retrieve credentials creds = Helper::IosCdHelper.parse_ios_credentials('.') - UI.message("👉🏼 Credentials parsed.") + UI.message("🍺 Credentials parsed.") # Delete decrypted artifacts artifacts = ['ios_keys.zip', 'ios_credentials.json'] - artifacts.each do |file| - File.delete(file) if File.exist?(file) - end + Helper::IosCdHelper.delete_artifacts(artifacts) # Check credentials required_fields = ['developer_app_id', 'username', 'developer_app_identifier', 'app_identifier_extensions', 'apple_issuer_id', 'apple_key_id', 'team_id', 'team_name', 'apple_key_content', 'git_url', 'git_basic_authorization', 'provisioning_profiles', 'temp_keychain_user', 'temp_keychain_password'] - missing_fields = required_fields - creds.keys - - unless missing_fields.empty? - raise ArgumentError, "❌ missing keys in credential json file : #{missing_fields}" - end + Helper::IosCdHelper.check_required_fields(required_fields, creds.keys) # Delete keychain if existing if File.exist?(File.expand_path("~/Library/Keychains/#{name}-db")) @@ -55,7 +49,7 @@ module Fastlane unlock: false, timeout: 0 ) - UI.message("👉🏼 New keychain created") + UI.message("🍺 New keychain created") # Obtain App Store Connect API key api_key = other_action.app_store_connect_api_key( @@ -65,7 +59,7 @@ module Fastlane duration: 500, in_house: false ) - UI.message("👉🏼 API Key formated") + UI.message("🍺 API Key formated") last_testflight_build_number = other_action.latest_testflight_build_number( @@ -82,7 +76,7 @@ module Fastlane build_number: last_testflight_build_number, xcodeproj: "Runner.xcodeproj" ) - UI.message("👉🏼 Build number incremented") + UI.message("🍺 Build number incremented") # Install Cocoapods other_action.cocoapods( @@ -91,7 +85,7 @@ module Fastlane integrate: true, podfile: "./Podfile" ) - UI.message("👉🏼 Pod got") + 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. @@ -105,14 +99,13 @@ module Fastlane git_basic_authorization: Base64.strict_encode64(creds['git_basic_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") + 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. @@ -124,7 +117,7 @@ module Fastlane provisioningProfiles: creds['provisioning_profiles'] } ) - UI.message("👉🏼 App built") + UI.message("🍺 App built") # Upload build to App Store Connect using Pilot other_action.pilot( @@ -147,9 +140,7 @@ module Fastlane # Delete build artifacts artifacts = ['Runner.app.dSYM.zip', 'Runner.ipa'] - artifacts.each do |file| - File.delete(file) if File.exist?(file) - end + Helper::IosCdHelper.delete_artifacts(artifacts) end def self.description 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 index 939f5cf..e7b2ccf 100644 --- 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 @@ -42,6 +42,31 @@ module Fastlane puts("json file doesn't exist") end end + + # Check json fields + def self.check_required_fields(required_fields, json) + missing_fields = required_fields - json + + unless missing_fields.empty? + raise ArgumentError, "❌ missing keys in credential json file : #{missing_fields}" + end + end + + # Check if set of environment variables are defined + def self.check_environment_variables(variables) + variables.each do |variable| + unless ENV.key?(variable) + raise "❌ The environment variable '#{variable}' is not defined." + end + end + end + + # Delete built files + def self.delete_artifacts(artifacts) + artifacts.each do |file| + File.delete(file) if File.exist?(file) + end + end end end end