leap_salesforce 0.1.18 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.gitlab-ci.yml +589 -2
- data/.idea/.rakeTasks +2 -2
- data/.idea/leap-salesforce.iml +6 -2
- data/.leap_salesforce.yml +2 -1
- data/ChangeLog +4 -0
- data/Rakefile +1 -1
- data/assets/server.key.enc +0 -0
- data/config/general.rb +2 -0
- data/config/project-scratch-def.json +12 -0
- data/exe/leap_salesforce +7 -4
- data/lib/leap_salesforce/auth.rb +87 -0
- data/lib/leap_salesforce/generator/exe_helpers.rb +15 -17
- data/lib/leap_salesforce/generator/generator.rb +1 -1
- data/lib/leap_salesforce/generator/templates/.gitignore.erb +6 -2
- data/lib/leap_salesforce/generator/templates/.leap_salesforce.yml.erb +1 -0
- data/lib/leap_salesforce/generator/templates/config/credentials/salesforce_oauth2.yml.erb +3 -1
- data/lib/leap_salesforce/generator/templates/config/general.rb.erb +6 -0
- data/lib/leap_salesforce/get_prod_auth.sh +2 -0
- data/lib/leap_salesforce/get_scratch_auth.sh +2 -0
- data/lib/leap_salesforce/loader.rb +26 -0
- data/lib/leap_salesforce/parameters.rb +38 -3
- data/lib/leap_salesforce/rake/sfdx.rake +28 -0
- data/lib/leap_salesforce/soql_data/soql_global_object_data.rb +24 -5
- data/lib/leap_salesforce/soql_data/soql_handler.rb +9 -3
- data/lib/leap_salesforce/soql_data/tooling.rb +15 -0
- data/lib/leap_salesforce/version.rb +1 -1
- data/lib/leap_salesforce.rb +37 -44
- metadata +10 -2
data/ChangeLog
CHANGED
data/Rakefile
CHANGED
Binary file
|
data/config/general.rb
CHANGED
data/exe/leap_salesforce
CHANGED
@@ -16,6 +16,7 @@ module LeapSalesforce
|
|
16
16
|
include LeapSalesforce::ExeHelpers
|
17
17
|
|
18
18
|
OAUTH_WIKI = 'https://gitlab.com/leap-dojo/leap_salesforce/wikis/SetUpOAuthApp'
|
19
|
+
SFDX_WIKI = 'https://gitlab.com/leap-dojo/leap_salesforce/wikis/UsingSfdxAuth'
|
19
20
|
|
20
21
|
desc 'init', 'Create new leap salesforce repository'
|
21
22
|
option :setup_done, default: false, type: :boolean, banner: 'Whether setup is done'
|
@@ -25,14 +26,16 @@ module LeapSalesforce
|
|
25
26
|
option :user_key, banner: 'Key to identify user by'
|
26
27
|
option :password, banner: 'User password'
|
27
28
|
option :environment, banner: 'Environment to set automation code up for'
|
29
|
+
option :sfdx, banner: 'Whether to use sfdx for authentication', default: false, type: :boolean
|
28
30
|
def init
|
29
|
-
|
31
|
+
LeapSalesforce.sfdx = options[:sfdx]
|
32
|
+
wiki = LeapSalesforce.sfdx ? SFDX_WIKI : OAUTH_WIKI
|
30
33
|
unless options[:setup_done]
|
31
|
-
|
34
|
+
# Ask user to create OAuth application by following doc
|
35
|
+
oauth_setup = input_for "Have you set up OAuth application by following #{wiki} (y/n)?", :red
|
32
36
|
exit if oauth_setup.downcase == 'n'
|
33
37
|
end
|
34
|
-
|
35
|
-
query_for_parameters
|
38
|
+
query_for_parameters # TODO: for sfdx
|
36
39
|
generate_files binding, ['Gemfile', 'Rakefile', '.leap_salesforce.yml', '.rspec', '.gitignore',
|
37
40
|
{ config: ['general.rb', { credentials: 'salesforce_oauth2.yml' }] },
|
38
41
|
{ spec: %w[spec_helper.rb limit_spec.rb crud_eg_spec.rb picklists_spec.rb] }]
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'error'
|
3
|
+
|
4
|
+
module LeapSalesforce
|
5
|
+
# Code related to authorising in LeapSalesforce
|
6
|
+
# Specific authorisation parameters are stored here. More general settings
|
7
|
+
# are stored at the layer above this
|
8
|
+
module Auth
|
9
|
+
@access_token = nil
|
10
|
+
@instance_url = nil
|
11
|
+
# @return [String] Setup JWT trail head
|
12
|
+
SETUP_JWT_LINK = 'https://trailhead.salesforce.com/content/learn/projects/automate-cicd-with-gitlab/https://trailhead.salesforce.com/content/learn/projects/automate-cicd-with-gitlab/integrate-with-gitlab'
|
13
|
+
class << self
|
14
|
+
# @return [String] Access token taken from sfdx
|
15
|
+
attr_writer :access_token
|
16
|
+
# Instance Url taken from sfdx
|
17
|
+
attr_writer :instance_url
|
18
|
+
# @return [String] Output from SFDX command
|
19
|
+
attr_accessor :sfdx_display_output
|
20
|
+
|
21
|
+
# @return [String] Access token taken from sfdx. Value is extracted if
|
22
|
+
# not cached. If not using sfdx this will not be stored here but
|
23
|
+
# within Soaspec which caches the OAuth result
|
24
|
+
def access_token
|
25
|
+
return @access_token if @access_token
|
26
|
+
|
27
|
+
extract_sfdx_variables
|
28
|
+
@access_token
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String] Instance URL taken from sfdx. Value is extracted if
|
32
|
+
# not cached
|
33
|
+
def instance_url
|
34
|
+
return @instance_url if @instance_url
|
35
|
+
|
36
|
+
extract_sfdx_variables
|
37
|
+
@instance_url
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Boolean] Whether Sfdx authentication variables are set
|
41
|
+
def sfdx_variables?
|
42
|
+
!(access_token && instance_url).nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [TrueClass] Whether JWT file exists Exception is raised if it
|
46
|
+
# is not
|
47
|
+
def jwt_file?
|
48
|
+
ENV['JWT_FOLDER'] ||= Dir.exist?('JWT') ? 'JWT' : 'assets'
|
49
|
+
unless File.exist?(File.join(ENV['JWT_FOLDER'], 'server.key'))
|
50
|
+
raise LeapSalesforce::SetupError 'Please create JWT file in ' \
|
51
|
+
" '#{ENV['JWT_FOLDER']}/server.key' following #{SETUP_JWT_LINK}"
|
52
|
+
end
|
53
|
+
|
54
|
+
true
|
55
|
+
end
|
56
|
+
|
57
|
+
# Extract sfdx variables and store them
|
58
|
+
# Set ENV['SCRATCH_ORG'] to true to authenticate and run against sandbox
|
59
|
+
def extract_sfdx_variables
|
60
|
+
script_name = if ENV['SCRATCH_ORG'] && !ENV['SCRATCH_ORG'].empty?
|
61
|
+
puts "Using sandbox #{ENV['SCRATCH_ORG_ALIAS']}"
|
62
|
+
'get_scratch_auth'
|
63
|
+
else
|
64
|
+
'get_prod_auth'
|
65
|
+
end
|
66
|
+
self.sfdx_display_output = `sh #{__dir__}/#{script_name}.sh`
|
67
|
+
self.access_token = from_output 'Access Token'
|
68
|
+
url_obtained = from_output 'Instance Url'
|
69
|
+
self.instance_url = url_obtained[-1] == '/' ? url_obtained[0..-2] : url_obtained
|
70
|
+
LeapSalesforce.client_id = ENV['SF_CONSUMER_KEY']
|
71
|
+
LeapSalesforce.password = :not_needed
|
72
|
+
LeapSalesforce.client_secret = :not_needed
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def from_output(variable)
|
78
|
+
var_line = sfdx_display_output.lines.find do |line|
|
79
|
+
line.start_with? variable
|
80
|
+
end
|
81
|
+
raise LeapSalesforce::SetupError, "Error retrieving from #{sfdx_display_output}" unless var_line
|
82
|
+
|
83
|
+
var_line.split[-1]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -21,28 +21,26 @@ module LeapSalesforce
|
|
21
21
|
|
22
22
|
# Retrieve environment and ensure that environment can be connected to
|
23
23
|
def verify_environment
|
24
|
-
LeapSalesforce.
|
25
|
-
|
26
|
-
'
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
message = "Unable to connect to #{LeapSalesforce.general_url}. Potentially problem with" \
|
31
|
-
' internet or proxy settings'.colorize :red
|
32
|
-
raise LeapSalesforce::SetupError, message
|
33
|
-
else
|
24
|
+
unless LeapSalesforce.sfdx
|
25
|
+
LeapSalesforce.environment = options[:environment] || input_for('Enter the environment you want to set things up for ' \
|
26
|
+
'(This will be parameterised so can be changed later). For production used "prod". Otherwise preference is to use the' \
|
27
|
+
' part of the URL that is unique for the environment')
|
28
|
+
end
|
29
|
+
LeapSalesforce.salesforce_reachable?
|
34
30
|
puts "\u2713 Connection to #{LeapSalesforce.general_url} successful".colorize :green
|
35
31
|
end
|
36
32
|
|
37
33
|
# Retrieve OAuth credentials and verify that they're correct
|
38
34
|
def verify_oauth
|
39
|
-
LeapSalesforce.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
'
|
44
|
-
|
45
|
-
|
35
|
+
unless LeapSalesforce.sfdx
|
36
|
+
LeapSalesforce.client_id = options[:client_id] || input_for('Client id (Customer Id)')
|
37
|
+
LeapSalesforce.client_secret = options[:client_secret] || STDIN.getpass('Client secret (Consumer Secret)')
|
38
|
+
LeapSalesforce.api_user = ERB.new(options[:username] || input_for('Salesforce username. It is ideal to start with a System admin' \
|
39
|
+
' so that any necessary metadata can be read. More users can be added later. You can use ERB to make name' \
|
40
|
+
' vary according to environment (e.g., test.user@<%= LeapSalesforce.environment %>.my.company.com)')).result(binding)
|
41
|
+
LeapSalesforce.password = options[:password] || STDIN.getpass('Password (Recommendation is that 1 password' \
|
42
|
+
' be shared across all test users to be easier to manage):')
|
43
|
+
end
|
46
44
|
LeapSalesforce.oauth_working?
|
47
45
|
end
|
48
46
|
|
@@ -32,7 +32,7 @@ module LeapSalesforce
|
|
32
32
|
|
33
33
|
# @example Create a spec_helper file and test file in spec folder
|
34
34
|
# generate_files [ { spec: [ 'spec_helper.rb', 'limit_spec.rb' ] } ]
|
35
|
-
# @param [Hash] list_of_files Hash of files to generate for
|
35
|
+
# @param [Hash, Array] list_of_files Hash of files to generate for
|
36
36
|
def generate_files(binding, list_of_files, folder: nil)
|
37
37
|
return create_inner_file(folder, list_of_files, binding) unless list_of_files.respond_to? :each
|
38
38
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LeapSalesforce
|
4
|
+
# For loading dependent code based on configuration
|
5
|
+
module Loader
|
6
|
+
# @return [String] Location of leap_salesforce YAML file
|
7
|
+
LEAP_CONFIG_FILE = '.leap_salesforce.yml'
|
8
|
+
class << self
|
9
|
+
def load_config_file
|
10
|
+
if File.exist? LEAP_CONFIG_FILE
|
11
|
+
leap_config = YAML.load_file LEAP_CONFIG_FILE
|
12
|
+
LeapSalesforce.soql_objects = leap_config.delete('soql_objects')
|
13
|
+
leap_config.each do |key, value|
|
14
|
+
if %w[SF_CONSUMER_KEY client_id client_secret password].include? key
|
15
|
+
LeapSalesforce.logger.warn "Secret key '#{key}' should be in non version" \
|
16
|
+
" controlled #{LeapSalesforce::CREDENTIAL_FILE} not in #{LEAP_CONFIG_FILE}"
|
17
|
+
end
|
18
|
+
LeapSalesforce.send("#{key}=", value)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
LeapSalesforce.logger.warn "No config file found at #{LEAP_CONFIG_FILE} for Leap Salesforce"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,6 +3,9 @@
|
|
3
3
|
require_relative 'users/users'
|
4
4
|
require_relative 'soql_object'
|
5
5
|
require 'logger'
|
6
|
+
require_relative 'auth'
|
7
|
+
# @return [String] Tutorial on creating an sfdx app
|
8
|
+
CREATE_APP_LINK = 'https://trailhead.salesforce.com/content/learn/projects/automate-cicd-with-gitlab/enable-dev-hub-and-create-a-connected-app'
|
6
9
|
|
7
10
|
# Adding parameters to set for authentication, environment and other common settings
|
8
11
|
module LeapSalesforce
|
@@ -16,6 +19,10 @@ module LeapSalesforce
|
|
16
19
|
@environment = nil
|
17
20
|
@logger = Logger.new STDOUT
|
18
21
|
@sfdx = false
|
22
|
+
# @access_token = nil
|
23
|
+
@instance_url = nil
|
24
|
+
# @return [String] File where Salesforce credentials are stored
|
25
|
+
CREDENTIAL_FILE = File.join('config', 'credentials', 'salesforce_oauth2.yml')
|
19
26
|
class << self
|
20
27
|
# @return [String] Environment to use for tests. This can be accessed to change the username used to login
|
21
28
|
# to test.salesforce with. This can be set on the command line with 'LEAP_ENV'
|
@@ -23,10 +30,25 @@ module LeapSalesforce
|
|
23
30
|
ENV['LEAP_ENV'] || @environment
|
24
31
|
end
|
25
32
|
|
26
|
-
#
|
33
|
+
# Verify connection to Salesforce environment
|
34
|
+
def salesforce_reachable?
|
35
|
+
RestClient.get(LeapSalesforce.general_url)
|
36
|
+
rescue SocketError
|
37
|
+
message = "Unable to connect to #{LeapSalesforce.general_url}. Potentially problem with" \
|
38
|
+
' internet or proxy settings'.colorize :red
|
39
|
+
raise LeapSalesforce::SetupError, message
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [TrueClass] If OAuth authentication is working, return true.
|
43
|
+
# Otherwise raise exception
|
27
44
|
def oauth_working?
|
28
|
-
|
29
|
-
|
45
|
+
salesforce_reachable?
|
46
|
+
if LeapSalesforce.sfdx
|
47
|
+
sfdx_auth_setup?
|
48
|
+
else
|
49
|
+
Soaspec::OAuth2.debug_oauth = true
|
50
|
+
Soaspec::OAuth2.new(LeapSalesforce.oauth_settings).access_token
|
51
|
+
end
|
30
52
|
rescue StandardError
|
31
53
|
raise LeapSalesforce::SetupError, "Cannot perform OAuth. See 'logs' folder for details of what was sent"
|
32
54
|
else
|
@@ -35,6 +57,19 @@ module LeapSalesforce
|
|
35
57
|
true
|
36
58
|
end
|
37
59
|
|
60
|
+
# Checks whether sfdx is setup according to standard approach. Errors are
|
61
|
+
# logged
|
62
|
+
# @return [Boolean] Whether sfdx is setup correctly
|
63
|
+
def sfdx_auth_setup?
|
64
|
+
Auth.jwt_file?
|
65
|
+
return true if LeapSalesforce::Auth.sfdx_variables?
|
66
|
+
|
67
|
+
raise LeapSalesforce::SetupError, 'LeapSalesforce::Auth.access_token and ' \
|
68
|
+
'instance_url were not able to be retrieved by sfdx'
|
69
|
+
end
|
70
|
+
|
71
|
+
# OAuth parameters when using a custom Connected application not
|
72
|
+
# using sfdx
|
38
73
|
# @return [Hash] OAuth2 parameters used in connecting to salesforce
|
39
74
|
def oauth_settings
|
40
75
|
settings = {
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Convenience tasks that use sfdx according to common environment variables
|
4
|
+
namespace :sfdx do
|
5
|
+
desc 'Login with credentials'
|
6
|
+
task :login do
|
7
|
+
puts `sfdx force:auth:jwt:grant --clientid $SF_CONSUMER_KEY --jwtkeyfile JWT/server.key --username $SF_USERNAME --setdefaultdevhubusername --setalias HubOrg`
|
8
|
+
end
|
9
|
+
|
10
|
+
task :display do
|
11
|
+
puts `sfdx force:org:display --targetusername samuel.garratt@brave-otter-ttxype.com`
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Create dev environment'
|
15
|
+
task :create_dev do
|
16
|
+
puts `sfdx force:org:create --targetdevhubusername HubOrg --setdefaultusername --definitionfile config/project-scratch-def.json --setalias $SCRATCH_ORG_ALIAS --wait 10 --durationdays 7`
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Open environment in browser'
|
20
|
+
task :open do
|
21
|
+
puts `sfdx force:org:open`
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Delete dev environment'
|
25
|
+
task :delete_dev do
|
26
|
+
puts `sfdx force:org:delete --targetusername $SCRATCH_ORG_ALIAS --noprompt`
|
27
|
+
end
|
28
|
+
end
|
@@ -1,12 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'tooling'
|
4
|
+
|
3
5
|
# Methods for working with instances of global to soql objects, not global overall
|
4
6
|
# See https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_sobject_describe.htm
|
5
7
|
module SoqlGlobalObjectData
|
8
|
+
include LeapSalesforce::Tooling
|
6
9
|
# @return [Hash] List of ids to delete when deleting a particular object
|
7
10
|
attr_accessor :ids_to_delete
|
8
11
|
|
9
12
|
# Override to handle removing dependent records
|
13
|
+
# @param [String] _id Id of record being deleted
|
10
14
|
def remove_dependent_records(_id); end
|
11
15
|
|
12
16
|
# Return key and value to look up for a provided hash
|
@@ -52,13 +56,14 @@ module SoqlGlobalObjectData
|
|
52
56
|
# @return [String] SOQL query to filter results
|
53
57
|
def soql_lookup_filter(lookup)
|
54
58
|
limit = lookup.delete(:limit)
|
59
|
+
@default_filter ||= 'CreatedDate'
|
55
60
|
conditional = ''
|
56
61
|
lookup.each do |key, value|
|
57
62
|
conditional_term = conditional.empty? ? 'WHERE' : 'AND'
|
58
63
|
key_used = map_key key
|
59
64
|
conditional += "#{conditional_term} #{key_used} #{condition_for(value)} "
|
60
65
|
end
|
61
|
-
query = conditional +
|
66
|
+
query = conditional + "ORDER BY #{@default_filter} DESC NULLS FIRST"
|
62
67
|
query += " LIMIT #{limit}" if limit
|
63
68
|
query
|
64
69
|
end
|
@@ -153,19 +158,19 @@ module SoqlGlobalObjectData
|
|
153
158
|
# @param [Hash] data Key value pairs with data to update
|
154
159
|
# @return [self] SoqlData object representing result of API update call
|
155
160
|
def update(id, data)
|
161
|
+
enforce_type_for id
|
156
162
|
must_pass = data.delete(:must_pass)
|
157
163
|
data = data.transform_values do |value|
|
158
164
|
value.is_a?(Time) ? value.salesforce_format : value
|
159
165
|
end
|
160
166
|
data.transform_keys! { |key| map_key(key) } # Map keys to valid field names
|
161
167
|
SoqlHandler.new("Update #{id}").use
|
162
|
-
|
163
168
|
update = new("Update #{self}, #{id} with '#{data}'", method: :patch,
|
164
169
|
suburl: "sobjects/#{soql_object_name}/#{id}", body: data)
|
165
170
|
update.call
|
166
171
|
return update unless must_pass
|
167
172
|
|
168
|
-
successful?
|
173
|
+
update.successful?
|
169
174
|
update
|
170
175
|
end
|
171
176
|
|
@@ -173,10 +178,11 @@ module SoqlGlobalObjectData
|
|
173
178
|
# @example Delete a contact with a specified id, failing if the delete fails
|
174
179
|
# Contact.delete '0032v00002rgv2pAAA', must_pass: true
|
175
180
|
#
|
176
|
-
# @param [String] id Id of element to remove
|
181
|
+
# @param [String, Symbol] id Id of element to remove
|
177
182
|
# @param [Boolean] must_pass Whether to raise exception if call is not successful
|
178
183
|
# @return [self] Exchange object making delete call
|
179
184
|
def delete(id, must_pass: false)
|
185
|
+
enforce_type_for id
|
180
186
|
SoqlData.ids_to_delete.reject! { |table, id_to_remove| table == self && id_to_remove == id } # Remove id from list to delete
|
181
187
|
remove_dependent_records(id)
|
182
188
|
|
@@ -225,8 +231,10 @@ module SoqlGlobalObjectData
|
|
225
231
|
# @param [Symbol, String] key Key to map to Table field name
|
226
232
|
# @return [String] Field name of Salesforce entity to use
|
227
233
|
def map_key(key)
|
228
|
-
if field_names.include?
|
234
|
+
if field_names.include?(key.to_s)
|
229
235
|
key.to_s
|
236
|
+
elsif field_names.include?(key.to_s.camelize)
|
237
|
+
key.to_s.camelize
|
230
238
|
else
|
231
239
|
return new.send("#{key}_element") if new.respond_to?("#{key}_element")
|
232
240
|
|
@@ -266,4 +274,15 @@ module SoqlGlobalObjectData
|
|
266
274
|
[value[0], value[1..-1]]
|
267
275
|
end
|
268
276
|
end
|
277
|
+
|
278
|
+
private
|
279
|
+
|
280
|
+
# Raise error if incorrect type passed
|
281
|
+
# @param [String, Symbol] id Id to verify
|
282
|
+
def enforce_type_for(id)
|
283
|
+
return if [String, Symbol].include? id.class
|
284
|
+
|
285
|
+
raise ArgumentError,
|
286
|
+
"Id must be String or Symbol but was #{id.class} to delete"
|
287
|
+
end
|
269
288
|
end
|
@@ -7,12 +7,18 @@ require 'soaspec'
|
|
7
7
|
# Credentials are stored either in 'config/credentials' folder or via environment variables
|
8
8
|
# To check out SOQL SCHEMA go to workbench.developerforce.com. Use Sandbox and login
|
9
9
|
class SoqlHandler < Soaspec::RestHandler
|
10
|
-
oauth2 LeapSalesforce.oauth_settings unless LeapSalesforce.sfdx
|
11
10
|
if LeapSalesforce.sfdx
|
12
|
-
# @return [String]
|
11
|
+
# @return [String] Instance Url taken from sfdx
|
13
12
|
def instance_url
|
14
|
-
|
13
|
+
LeapSalesforce::Auth.instance_url
|
15
14
|
end
|
15
|
+
|
16
|
+
# @return [String] Access token taken from sfdx
|
17
|
+
def access_token
|
18
|
+
LeapSalesforce::Auth.access_token
|
19
|
+
end
|
20
|
+
else
|
21
|
+
oauth2 LeapSalesforce.oauth_settings
|
16
22
|
end
|
17
23
|
base_url '<%= instance_url %>/services/data/v<%= api_version %>/'
|
18
24
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module LeapSalesforce
|
2
|
+
# Methods to interact with tooling API.
|
3
|
+
# See https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/intro_rest_resources.htm
|
4
|
+
module Tooling
|
5
|
+
def tooling_objects
|
6
|
+
new("Tooling sobjects",
|
7
|
+
method: :get, suburl: "tooling/sobjects")
|
8
|
+
end
|
9
|
+
|
10
|
+
def run_test_asynchronous
|
11
|
+
new('Test run async', method: :post,
|
12
|
+
suburl: 'tooling/runTestsAsynchronous/')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/leap_salesforce.rb
CHANGED
@@ -17,58 +17,51 @@ require 'rake'
|
|
17
17
|
require 'factory_bot' # For mass production of data
|
18
18
|
require 'faker' # For fake data
|
19
19
|
require 'leap_salesforce/error'
|
20
|
+
require 'leap_salesforce/loader'
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
module LeapSalesforce
|
23
|
+
leap_logger = LeapSalesforce.logger
|
24
|
+
leap_logger.level = Logger::DEBUG
|
25
|
+
leap_logger.datetime_format = '%Y-%m-%d %H:%M:%S'
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
leap_logger.datetime_format = '%Y-%m-%d %H:%M:%S'
|
27
|
+
LeapSalesforce::Loader.load_config_file
|
28
|
+
raise SetupError, 'LeapSalesforce.environment not set' if environment.nil? && !sfdx
|
27
29
|
|
28
|
-
if File.exist?
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
if %w[client_id client_secret password].include? key
|
33
|
-
leap_logger.warn "Secret key '#{key}' should be in non version" \
|
34
|
-
" controlled #{CREDENTIAL_FILE} not in #{LEAP_CONFIG_FILE}"
|
30
|
+
if File.exist? CREDENTIAL_FILE
|
31
|
+
# Set credentials from credentials file for ConnectedApp
|
32
|
+
YAML.load_file(CREDENTIAL_FILE).each do |key, value|
|
33
|
+
send("#{key}=", value)
|
35
34
|
end
|
36
|
-
LeapSalesforce.send("#{key}=", value)
|
37
35
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
# Either can be set
|
37
|
+
ENV['SF_CONSUMER_KEY'] ||= client_id
|
38
|
+
self.client_id ||= ENV['SF_CONSUMER_KEY']
|
41
39
|
|
42
|
-
|
40
|
+
config_folder_path = File.join(Dir.pwd, config_folder)
|
41
|
+
general_file = File.join(config_folder_path, 'general')
|
42
|
+
specific_environment_file = File.join(config_folder_path, 'environments',
|
43
|
+
environment)
|
44
|
+
require general_file if File.exist? "#{general_file}.rb"
|
45
|
+
require specific_environment_file if File.exist? "#{specific_environment_file}.rb"
|
43
46
|
|
44
|
-
if
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
47
|
+
if sfdx
|
48
|
+
# Assume authentication already made through 'sfdx force:auth:jwt:grant'
|
49
|
+
unless ENV['SF_USERNAME'] && ENV['SF_CONSUMER_KEY']
|
50
|
+
raise SetupError,
|
51
|
+
'Please set SF_USERNAME and SF_CONSUMER_KEY environment variables'
|
52
|
+
end
|
53
|
+
Auth.jwt_file?
|
54
|
+
else
|
55
|
+
%w[client_id client_secret password].each do |param|
|
56
|
+
raise SetupError, "LeapSalesforce.#{param} not set" if send(param).nil?
|
57
|
+
end
|
55
58
|
end
|
56
|
-
end
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
config_folder = File.join(Dir.pwd, LeapSalesforce.config_folder)
|
63
|
-
general_file = File.join(config_folder, 'general')
|
64
|
-
specific_environment_file = File.join(config_folder, 'environments', LeapSalesforce.environment)
|
65
|
-
require general_file if File.exist? "#{general_file}.rb"
|
66
|
-
require specific_environment_file if File.exist? "#{specific_environment_file}.rb"
|
60
|
+
require 'leap_salesforce/soql_data/soql_data'
|
61
|
+
require 'leap_salesforce/limits'
|
67
62
|
|
68
|
-
|
69
|
-
|
63
|
+
FileUtils.mkdir_p lib_folder unless Dir.exist? lib_folder
|
64
|
+
require_all lib_folder
|
70
65
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
LeapSalesforce.objects_to_verify = SoqlData.descendants if LeapSalesforce.objects_to_verify.empty?
|
66
|
+
self.objects_to_verify = SoqlData.descendants if objects_to_verify.empty?
|
67
|
+
end
|