fastlane-plugin-react_native_release 0.3.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +120 -41
  3. data/lib/fastlane/plugin/react_native_release/actions/accept_android_sdk_licenses.rb +46 -0
  4. data/lib/fastlane/plugin/react_native_release/actions/add_app_var.rb +107 -0
  5. data/lib/fastlane/plugin/react_native_release/actions/add_fastlane_var.rb +99 -0
  6. data/lib/fastlane/plugin/react_native_release/actions/create_changelog.rb +92 -0
  7. data/lib/fastlane/plugin/react_native_release/actions/create_fastlane_session.rb +75 -0
  8. data/lib/fastlane/plugin/react_native_release/actions/decrypt_android_keystore.rb +131 -0
  9. data/lib/fastlane/plugin/react_native_release/actions/decrypt_app_vars.rb +117 -0
  10. data/lib/fastlane/plugin/react_native_release/actions/decrypt_fastlane_vars.rb +101 -0
  11. data/lib/fastlane/plugin/react_native_release/actions/decrypt_google_play_credentials.rb +62 -0
  12. data/lib/fastlane/plugin/react_native_release/actions/determine_release_from_commits.rb +61 -0
  13. data/lib/fastlane/plugin/react_native_release/actions/encrypt_app_vars.rb +121 -0
  14. data/lib/fastlane/plugin/react_native_release/actions/encrypt_fastlane_vars.rb +76 -0
  15. data/lib/fastlane/plugin/react_native_release/actions/encrypt_google_play_credentials.rb +64 -0
  16. data/lib/fastlane/plugin/react_native_release/actions/generate_android_keystore.rb +137 -0
  17. data/lib/fastlane/plugin/react_native_release/actions/{react_native_release_action.rb → react_native_release.rb} +35 -66
  18. data/lib/fastlane/plugin/react_native_release/actions/read_fastlane_session.rb +55 -0
  19. data/lib/fastlane/plugin/react_native_release/actions/tag_release.rb +65 -0
  20. data/lib/fastlane/plugin/react_native_release/helper/react_native_release_helper.rb +14 -5
  21. data/lib/fastlane/plugin/react_native_release/version.rb +1 -1
  22. metadata +20 -5
@@ -0,0 +1,92 @@
1
+ require 'fastlane/action'
2
+
3
+ module Fastlane
4
+ module Actions
5
+ class CreateChangelogAction < Action
6
+ def self.run(params)
7
+ title = params[:title]
8
+ commit_message = params[:commit_message]
9
+ # Determine our local branch name, set the upstream, and pull.
10
+ # We need to pull since another build may have already finished and created a changelog
11
+ local_branch ||= other_action.git_branch.gsub(/origin/, '')
12
+ sh("git branch --set-upstream-to=origin/#{local_branch} #{local_branch}")
13
+ other_action.git_pull
14
+
15
+ # Get release notes since last version
16
+ # This exports a slack and a regular markdown format
17
+ notes = other_action.conventional_changelog(title: title, format: 'slack')
18
+ notesMD = other_action.conventional_changelog(title: title, format: 'markdown')
19
+
20
+ # Prepend new Changelog to existing one
21
+ UI.message("pre-pending to CHANGELOG")
22
+ UI.message(notes)
23
+ new_file = '../CHANGELOG.md.new'
24
+ original_file = '../CHANGELOG.md'
25
+
26
+ open(new_file, 'w') do |nf|
27
+ notesMD.split("\n").each { |line| nf.puts line }
28
+ nf.puts "\n"
29
+
30
+ File.foreach(original_file) do |li|
31
+ nf.puts li
32
+ end
33
+ end
34
+
35
+ File.delete original_file
36
+ File.rename new_file, original_file
37
+
38
+ # Commit it
39
+ other_action.git_commit(
40
+ path: [File.join(Dir.pwd, original_file)],
41
+ message: commit_message,
42
+ skip_git_hooks: true
43
+ )
44
+
45
+ { plain: notes, markdown: notesMD }
46
+ end
47
+
48
+ #####################################################
49
+ # @!group documentation
50
+ #####################################################
51
+
52
+ def self.description
53
+ "Determines if a release should happen based on conventional commits."
54
+ end
55
+
56
+ def self.details
57
+ "If using conventional commits, only continues to release if there are features / fixes."
58
+ end
59
+
60
+ def self.available_options
61
+ [
62
+ FastlaneCore::ConfigItem.new(key: :title,
63
+ env_name: "FL_CREATE_CHANGELOG_TITLE",
64
+ description: "What title should we use for the CHANGELOG?",
65
+ type: String),
66
+ FastlaneCore::ConfigItem.new(key: :commit_message,
67
+ env_name: "FL_CREATE_CHANGELOG_COMMIT_MESSAGE",
68
+ description: "What should the commit message be?",
69
+ type: String,
70
+ default_value: "chore(changelog): Update CHANGELOG [skip ci]")
71
+ ]
72
+ end
73
+
74
+ def self.return_value
75
+ # If your method provides a return value, you can describe here what it does
76
+ end
77
+
78
+ def self.details
79
+ # "Saves the current vars in android/fastlane/.env and ios/fastlane/.env"
80
+ end
81
+
82
+ def self.authors
83
+ # So no one will ever forget your contribution to fastlane :) You are awesome btw!
84
+ ["cball"]
85
+ end
86
+
87
+ def self.is_supported?(platform)
88
+ [:ios, :android].include?(platform)
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,75 @@
1
+ require 'fastlane/action'
2
+ require 'fastlane/plugin/cryptex'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class CreateFastlaneSessionAction < Action
7
+ def self.run(params)
8
+ username = params[:username]
9
+ key = Helper::ReactNativeReleaseHelper::FASTLANE_SESSION_CRYPTEX_KEY
10
+ fastlane_key = Helper::ReactNativeReleaseHelper::FASTLANE_CRYPTEX_KEY
11
+ fastlane_session_cookie_path = "#{File.expand_path('~')}/.fastlane/spaceship/#{username}/cookie"
12
+
13
+ UI.message "Generating a new fastlane session."
14
+ UI.message "Please enter the 6 digit 2FA code if one is sent to your device otherwise the script will continue automatically."
15
+
16
+ sh("fastlane spaceauth -u #{username.shellescape}")
17
+
18
+ # store the session
19
+ other_action.cryptex(
20
+ type: "import",
21
+ in: fastlane_session_cookie_path,
22
+ key: key
23
+ )
24
+
25
+ # store the username that created the session in fastlane_vars
26
+ existing_fastlane_vars = other_action.cryptex(
27
+ type: 'export_env',
28
+ key: fastlane_key,
29
+ )
30
+
31
+ other_action.cryptex(
32
+ type: "import_env",
33
+ key: fastlane_key,
34
+ # PILOT_USERNAME needs to be set to the same username as the session above
35
+ hash: existing_fastlane_vars.merge({ 'PILOT_USERNAME' => username })
36
+ )
37
+
38
+ UI.success "Uploaded session for #{username} to #{key}."
39
+ end
40
+
41
+ def self.description
42
+ "Simplify 2FA authentication for App Store Connect"
43
+ end
44
+
45
+ def self.authors
46
+ ["cball", "isaiahgrey93"]
47
+ end
48
+
49
+ def self.return_value
50
+ # If your method provides a return value, you can describe here what it does
51
+ end
52
+
53
+ def self.details
54
+ "Creates a cookie for authenticating with App Store connecting. Handles generating, encrypting, and storing the cookie."
55
+ end
56
+
57
+ def self.available_options
58
+ [
59
+ FastlaneCore::ConfigItem.new(key: :username,
60
+ env_name: "FL_CREATE_FASTLANE_SESSION_USERNAME",
61
+ description: "Enter the Apple username to generate a App Store Connect session",
62
+ type: String)
63
+ ]
64
+ end
65
+
66
+ def self.is_supported?(platform)
67
+ # Adjust this if your plugin only works for a particular platform (iOS vs. Android, for example)
68
+ # See: https://docs.fastlane.tools/advanced/#control-configuration-by-lane-and-by-platform
69
+ #
70
+ [:ios, :android].include?(platform)
71
+ end
72
+
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,131 @@
1
+ require 'fastlane/action'
2
+ require 'fastlane/plugin/cryptex'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class DecryptAndroidKeystoreAction < Action
7
+ def self.run(params)
8
+ key = Helper::ReactNativeReleaseHelper::ANDROID_KEYSTORE_CRYPTEX_KEY
9
+ file = Helper::ReactNativeReleaseHelper::ANDROID_KEYSTORE_PATH
10
+
11
+ begin
12
+ env_file_exists = File.exists?(file)
13
+
14
+ if (env_file_exists && UI.confirm("This will overwrite your existing .env file. Proceed?"))
15
+ self.export_and_decrypt_keystore(file,key)
16
+
17
+ elsif(env_file_exists)
18
+ UI.abort_with_message!("Stepping away...")
19
+ else
20
+ self.export_and_decrypt_keystore(file,key)
21
+ end
22
+ # If we don't have a keystore, cryptex will throw an exception.
23
+ rescue => ex
24
+ UI.abort_with_message!('Error decrypting keystore. Does it exist in the repo?')
25
+ end
26
+
27
+ UI.success("Decrypted #{key} to keystore.")
28
+ end
29
+
30
+ def self.export_and_decrypt_keystore(file,key)
31
+ other_action.cryptex(
32
+ type: "export",
33
+ out: file,
34
+ key: key,
35
+ verbose: true
36
+ )
37
+ # There is currently a bug where the keystore needs to be in multiple paths
38
+ # Optimized for the CI process to be running from the lane in android directory
39
+ sh("cp ./app/android.keystore ./")
40
+ end
41
+
42
+ # Creates a new android keystore based on the provided params. Wraps Cryptex.
43
+ def self.create_keystore_with_params(params)
44
+ begin
45
+ other_action.cryptex_generate_keystore(
46
+ destination: params[:destination],
47
+ password: params[:password],
48
+ fullname: params[:fullname],
49
+ city: params[:city],
50
+ alias: params[:alias]
51
+ )
52
+ rescue => ex
53
+ UI.abort_with_message!("Could not create keystore. Do you already have one with this alias?")
54
+ end
55
+
56
+ params[:destination]
57
+ end
58
+
59
+ # Saves a keystore to the repo. Note this will overwrite it!
60
+ def self.encrypt_keystore(keystore_path)
61
+ key = Helper::ReactNativeReleaseHelper::ANDROID_KEYSTORE_CRYPTEX_KEY
62
+
63
+ other_action.cryptex(
64
+ type: "import",
65
+ in: keystore_path,
66
+ key: key
67
+ )
68
+ end
69
+
70
+ #####################################################
71
+ # @!group Documentation
72
+ #####################################################
73
+
74
+ def self.description
75
+ "Decrypts app env vars and sets the values in the root .env file"
76
+ end
77
+
78
+ def self.details
79
+ # Optional:
80
+ # this is your chance to provide a more detailed description of this action
81
+ end
82
+
83
+ def self.available_options
84
+ [
85
+ FastlaneCore::ConfigItem.new(key: :encrypt_in_repo,
86
+ env_name: "FL_GENERATE_ANDROID_KEYSTORE_ENCRYPT_IN_REPO",
87
+ description: "If the new keystore should be encrypted and saved",
88
+ type: Boolean,
89
+ default_value: false),
90
+ FastlaneCore::ConfigItem.new(key: :password,
91
+ env_name: "FL_GENERATE_ANDROID_KEYSTORE_PASSWORD",
92
+ description: "Password for the Keystore",
93
+ type: String),
94
+ FastlaneCore::ConfigItem.new(key: :alias,
95
+ env_name: "FL_GENERATE_ANDROID_KEYSTORE_ALIAS",
96
+ description: "ALIAS for the Keystore",
97
+ type: String),
98
+ FastlaneCore::ConfigItem.new(key: :destination,
99
+ env_name: "FL_GENERATE_ANDROID_KEYSTORE_DESTINATION",
100
+ description: "Where to put decrypted keystore",
101
+ default_value: "../android/app/android.keystore"),
102
+ FastlaneCore::ConfigItem.new(key: :fullname,
103
+ env_name: "FL_GENERATE_ANDROID_KEYSTORE_FULLNAME",
104
+ description: "Fullname of keystore owner",
105
+ type: String),
106
+ FastlaneCore::ConfigItem.new(key: :city,
107
+ env_name: "FL_GENERATE_ANDROID_KEYSTORE_CITY",
108
+ description: "City of keystore owner",
109
+ type: String),
110
+ ]
111
+ end
112
+
113
+ def self.return_value
114
+ # If your method provides a return value, you can describe here what it does
115
+ end
116
+
117
+ def self.details
118
+ # "Saves the current vars in android/fastlane/.env and ios/fastlane/.env"
119
+ end
120
+
121
+ def self.authors
122
+ # So no one will ever forget your contribution to fastlane :) You are awesome btw!
123
+ ["cball", "isaiahgrey93", "cmejet"]
124
+ end
125
+
126
+ def self.is_supported?(platform)
127
+ [:ios, :android].include?(platform)
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,117 @@
1
+ require 'fastlane/action'
2
+ require 'fastlane/plugin/cryptex'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class DecryptAppVarsAction < Action
7
+ def self.run(params)
8
+ is_ci = ENV['CI'] === 'true'
9
+ namespace = params[:namespace]
10
+ write_env = params[:write_env]
11
+ skip_confirmation= params[:skip_confirmation]
12
+ default_cryptex_app_key = Helper::ReactNativeReleaseHelper::APP_CRYPTEX_KEY
13
+ cryptex_app_key = Helper::ReactNativeReleaseHelper.app_key_for(namespace)
14
+ is_same_key = default_cryptex_app_key == cryptex_app_key
15
+ message = ''
16
+
17
+ if(!skip_confirmation)
18
+ if is_same_key
19
+ message = "This will decrypt values from #{cryptex_app_key}. Proceed?"
20
+ else
21
+ message = "This will decrypt and merge values from #{cryptex_app_key} into #{default_cryptex_app_key}. Proceed?"
22
+ end
23
+
24
+
25
+ if !is_ci && !UI.confirm(message)
26
+ UI.abort_with_message!("Stepping away...")
27
+ end
28
+ end
29
+
30
+ app_vars = other_action.cryptex(
31
+ type: "export_env",
32
+ key: default_cryptex_app_key
33
+ )
34
+
35
+ namespaced_vars = other_action.cryptex(
36
+ type: "export_env",
37
+ key: cryptex_app_key
38
+ )
39
+
40
+ merged_vars = app_vars.merge(namespaced_vars)
41
+ has_env_file = File.exists?(Helper::ReactNativeReleaseHelper::APP_ENV_PATH)
42
+ should_write_env = write_env && (is_ci || skip_confirmation || !has_env_file || UI.confirm("It looks like you already have an .env file. Overwrite it?"))
43
+
44
+ # write an env file with the merged values
45
+ if (should_write_env)
46
+ # TODO: handle running action from root and from ios/android folders. This will not work properly in the root as is.
47
+ open('../.env', 'w') do |f|
48
+ merged_vars.each {|key, value| f.puts "#{key}=#{value}" }
49
+ end
50
+
51
+ UI.success('.env written')
52
+ else
53
+ UI.success('not writing .env')
54
+ end
55
+
56
+ merged_vars
57
+ end
58
+
59
+ #####################################################
60
+ # @!group Documentation
61
+ #####################################################
62
+
63
+ def self.description
64
+ "Decrypts app env vars and sets the values in the root .env file"
65
+ end
66
+
67
+ def self.details
68
+ # Optional:
69
+ # this is your chance to provide a more detailed description of this action
70
+ end
71
+
72
+ def self.available_options
73
+ [
74
+ FastlaneCore::ConfigItem.new(key: :namespace,
75
+ env_name: "FL_DECRYPT_APP_VARS_NAMESPACE", # The name of the environment variable
76
+ description: "What namespace should we use? (alpha, beta, release, ENTER = root)", # a short description of this parameter
77
+ type: String,
78
+ verify_block: lambda do |value|
79
+ unless Helper::ReactNativeReleaseHelper::VALID_NAMESPACES.include?(value)
80
+ UI.user_error!("Invalid namespace #{value}. Valid targets are #{Helper::ReactNativeReleaseHelper::VALID_NAMESPACES.join(', ')}")
81
+ next
82
+ end
83
+ end),
84
+ FastlaneCore::ConfigItem.new(key: :write_env,
85
+ env_name: "FL_DECRYPT_APP_VARS_WRITE_ENV", # The name of the environment variable
86
+ description: "If we should write an .env file", # a short description of this parameter
87
+ type: Boolean,
88
+ default_value: true),
89
+ FastlaneCore::ConfigItem.new(key: :skip_confirmation,
90
+ env_name: "FL_ENCRYPT_APP_VARS_SKIP_CONFIRMATION", # The name of the environment variable
91
+ description: "Allows commands to be run from within CLI and skip the UI.message confirmation dialog", # a short description of this parameter
92
+ type: Boolean,
93
+ short_option:'s',
94
+ default_value: false,
95
+ optional: true)
96
+ ]
97
+ end
98
+
99
+ def self.return_value
100
+ # If your method provides a return value, you can describe here what it does
101
+ end
102
+
103
+ def self.details
104
+ # "Saves the current vars in android/fastlane/.env and ios/fastlane/.env"
105
+ end
106
+
107
+ def self.authors
108
+ # So no one will ever forget your contribution to fastlane :) You are awesome btw!
109
+ ["cball", "isaiahgrey93", "cmejet"]
110
+ end
111
+
112
+ def self.is_supported?(platform)
113
+ [:ios, :android].include?(platform)
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,101 @@
1
+ require 'fastlane/action'
2
+ require 'fastlane/plugin/cryptex'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class DecryptFastlaneVarsAction < Action
7
+ def self.run(params)
8
+
9
+ is_ci = ENV['CI'] === 'true'
10
+ write_env = params[:write_env]
11
+
12
+ env = other_action.cryptex(
13
+ type: "export_env",
14
+ key: Helper::ReactNativeReleaseHelper::FASTLANE_CRYPTEX_KEY,
15
+ set_env: params[:set_env]
16
+ )
17
+
18
+ should_write_env = write_env && !is_ci
19
+
20
+
21
+ UI.success('Successfully decrypted fastlane vars.')
22
+
23
+ # write fastlane env files
24
+ if (should_write_env)
25
+
26
+ UI.success('Writing fastlane vars to <root>/fastlane/.env.')
27
+
28
+ open('./fastlane/.env', 'w') do |f|
29
+ env.each {|key, value| f.puts "#{key}=#{value}" }
30
+ end
31
+
32
+ UI.success('Writing fastlane vars to <root>/ios/fastlane/.env.')
33
+
34
+ open('./ios/fastlane/.env', 'w') do |f|
35
+ env.each {|key, value| f.puts "#{key}=#{value}" }
36
+ end
37
+
38
+ UI.success('Writing fastlane vars to <root>/android/fastlane/.env.')
39
+
40
+ open('./android/fastlane/.env', 'w') do |f|
41
+ env.each {|key, value| f.puts "#{key}=#{value}" }
42
+ end
43
+
44
+ UI.success('Fastlane .env files were successfully written.')
45
+ else
46
+ UI.success('Fastlane .env not generated.')
47
+ end
48
+
49
+ env
50
+ end
51
+
52
+ #####################################################
53
+ # @!group Documentation
54
+ #####################################################
55
+
56
+ def self.description
57
+ "Decrypts fastlane ENV vars from the encrypted repo. Optionally sets them in ENV."
58
+ end
59
+
60
+ def self.details
61
+ # Optional:
62
+ # this is your chance to provide a more detailed description of this action
63
+ end
64
+
65
+ def self.available_options
66
+ # Define all options your action supports.
67
+
68
+ # Below a few examples
69
+ [
70
+ FastlaneCore::ConfigItem.new(key: :set_env,
71
+ env_name: "FL_DECRYPT_FASTLANE_VARS_SET_ENV", # The name of the environment variable
72
+ description: "Sets the decrypted values in env", # a short description of this parameter
73
+ type: Boolean,
74
+ default_value: true),
75
+ FastlaneCore::ConfigItem.new(key: :write_env,
76
+ env_name: "FL_DECRYPT_FASTLANE_VARS_WRITE_ENV", # The name of the environment variable
77
+ description: "If we should write fastlane .env files", # a short description of this parameter
78
+ type: Boolean,
79
+ default_value: true)
80
+ ]
81
+ end
82
+
83
+ def self.return_value
84
+ # If your method provides a return value, you can describe here what it does
85
+ end
86
+
87
+ def self.details
88
+ # "Saves the current vars in android/fastlane/.env and ios/fastlane/.env"
89
+ end
90
+
91
+ def self.authors
92
+ # So no one will ever forget your contribution to fastlane :) You are awesome btw!
93
+ ["cball", "isaiahgrey93"]
94
+ end
95
+
96
+ def self.is_supported?(platform)
97
+ [:ios, :android].include?(platform)
98
+ end
99
+ end
100
+ end
101
+ end