fastlane-plugin-react_native_release 0.3.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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