metaforce 0.5.3 → 1.0.0a

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 (72) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +1 -11
  4. data/LICENSE +22 -0
  5. data/README.md +91 -96
  6. data/Rakefile +6 -14
  7. data/examples/example.rb +51 -0
  8. data/lib/metaforce/abstract_client.rb +76 -0
  9. data/lib/metaforce/client.rb +27 -0
  10. data/lib/metaforce/config.rb +41 -19
  11. data/lib/metaforce/job/crud.rb +13 -0
  12. data/lib/metaforce/job/deploy.rb +87 -0
  13. data/lib/metaforce/job/retrieve.rb +92 -0
  14. data/lib/metaforce/job.rb +183 -0
  15. data/lib/metaforce/login.rb +39 -0
  16. data/lib/metaforce/manifest.rb +18 -93
  17. data/lib/metaforce/metadata/client/crud.rb +86 -0
  18. data/lib/metaforce/metadata/client/file.rb +113 -0
  19. data/lib/metaforce/metadata/client.rb +7 -225
  20. data/lib/metaforce/services/client.rb +45 -86
  21. data/lib/metaforce/version.rb +1 -1
  22. data/lib/metaforce.rb +27 -7
  23. data/metaforce.gemspec +19 -16
  24. data/spec/fixtures/package.xml +1 -1
  25. data/spec/fixtures/payload.zip +0 -0
  26. data/spec/fixtures/requests/{describe_layout → foo}/invalid_session.xml +0 -0
  27. data/spec/fixtures/requests/send_email/success.xml +1 -0
  28. data/spec/lib/client_spec.rb +34 -0
  29. data/spec/lib/config_spec.rb +8 -50
  30. data/spec/lib/job/deploy_spec.rb +53 -0
  31. data/spec/lib/job/retrieve_spec.rb +28 -0
  32. data/spec/lib/job_spec.rb +95 -0
  33. data/spec/lib/login_spec.rb +18 -0
  34. data/spec/lib/manifest_spec.rb +22 -168
  35. data/spec/lib/metadata/client_spec.rb +84 -179
  36. data/spec/lib/metaforce_spec.rb +20 -0
  37. data/spec/lib/services/client_spec.rb +22 -35
  38. data/spec/spec_helper.rb +24 -3
  39. data/spec/support/client.rb +38 -0
  40. data/wsdl/26.0/metadata.xml +4750 -0
  41. data/wsdl/26.0/partner.xml +3340 -0
  42. metadata +114 -77
  43. data/Guardfile +0 -9
  44. data/bin/metaforce +0 -6
  45. data/lib/metaforce/core_extensions/string.rb +0 -31
  46. data/lib/metaforce/core_extensions.rb +0 -1
  47. data/lib/metaforce/custom_actions.rb +0 -29
  48. data/lib/metaforce/error.rb +0 -3
  49. data/lib/metaforce/login_details.rb +0 -28
  50. data/lib/metaforce/metadata/crud.rb +0 -103
  51. data/lib/metaforce/metadata/file.rb +0 -74
  52. data/lib/metaforce/metadata/transaction.rb +0 -100
  53. data/lib/metaforce/metadata.rb +0 -4
  54. data/lib/metaforce/rake/deploy.rb +0 -35
  55. data/lib/metaforce/rake/retrieve.rb +0 -39
  56. data/lib/metaforce/rake/tests.rb +0 -62
  57. data/lib/metaforce/rake.rb +0 -43
  58. data/lib/metaforce/services.rb +0 -1
  59. data/lib/metaforce/tasks/README.md +0 -62
  60. data/lib/metaforce/tasks/metaforce.rake +0 -5
  61. data/lib/metaforce/thor/metaforce.rb +0 -117
  62. data/lib/metaforce/types.rb +0 -249
  63. data/spec/.gitignore +0 -1
  64. data/spec/fixtures/sample/Rakefile +0 -2
  65. data/spec/fixtures/sample/metaforce.yml +0 -13
  66. data/spec/fixtures/sample/src/classes/TestClass.cls +0 -2
  67. data/spec/fixtures/sample/src/classes/TestClass.cls-meta.xml +0 -5
  68. data/spec/fixtures/sample/src/package.xml +0 -8
  69. data/spec/lib/core_extensions/string_spec.rb +0 -23
  70. data/spec/lib/metadata/crud_spec.rb +0 -66
  71. data/spec/lib/metadata/file_spec.rb +0 -17
  72. data/spec/lib/metadata/transaction_spec.rb +0 -68
@@ -1,100 +0,0 @@
1
- require 'base64'
2
-
3
- module Metaforce
4
-
5
- # Convenience class for deployment/retrieval results
6
- class Transaction
7
- # The Salesforce ID for this task
8
- attr_reader :id
9
- # The type of transaction (e.g. _:deploy_, _:retrieve_)
10
- attr_reader :type
11
-
12
- def initialize(client, id, type=nil)
13
- @client = client
14
- @id = id
15
- @type = type
16
- wait_until_done if Metaforce.configuration.wait_until_done
17
- end
18
-
19
- # Creates a new transaction and sets type to +:deploy+.
20
- def self.deployment(client, id)
21
- self.new client, id, :deploy
22
- end
23
-
24
- # Creates a new transaction and sets type to +:retrieve+.
25
- def self.retrieval(client, id)
26
- self.new client, id, :retrieve
27
- end
28
-
29
- # Wrapper for <tt>Client.status</tt>.
30
- def status
31
- @status = @client.status(@id)
32
- end
33
-
34
- # Wrapper for <tt>Client.done?</tt>.
35
- def done?
36
- @done = @client.done?(@id) unless @done
37
- @done
38
- end
39
- alias :complete? :done?
40
- alias :completed? :done?
41
-
42
- # Returns the decoded content of the returned zip file.
43
- def zip_file
44
- raise 'Request was not a retrieve.' unless @type == :retrieve
45
- Base64.decode64(result[:zip_file])
46
- end
47
-
48
- # Unzips the returned zip file to +destination+.
49
- def to(destination)
50
- zip = zip_file
51
- file = Tempfile.new('retrieve')
52
- file.write(zip)
53
- path = file.path
54
- file.close
55
-
56
- Zip::ZipFile.open(path) do |zip|
57
- zip.each do |f|
58
- path = File.join(destination, f.name)
59
- FileUtils.mkdir_p(File.dirname(path))
60
- zip.extract(f, path) { true }
61
- end
62
- end
63
- self
64
- end
65
-
66
- # Returns the deploy or retrieve result
67
- def result(options={})
68
- @result = @client.status(@id, @type) if @result.nil?
69
- raise SalesforceError, @result[:message] if @result[:state] == "Error"
70
- @result
71
- end
72
-
73
- # Enters a loop until .done? returns true
74
- def wait_until_done
75
- max_wait = 30
76
- wait_time = 1
77
- until self.done?
78
- sleep(wait_time)
79
- if wait_time < 30
80
- wait_time *= 2
81
- else
82
- wait_time = max_wait
83
- end
84
- end
85
- end
86
-
87
- BLACK_LIST = [:@client]
88
-
89
- def to_s
90
- public_vars = self.instance_variables.reject { |var|
91
- BLACK_LIST.include? var
92
- }.map { |var|
93
- "#{var}=\"#{instance_variable_get(var)}\""
94
- }.join(" ")
95
-
96
- "<##{self.class}:#{self.object_id.to_s(8)} #{public_vars}>"
97
- end
98
-
99
- end
100
- end
@@ -1,4 +0,0 @@
1
- require 'metaforce/metadata/transaction'
2
- require 'metaforce/metadata/client'
3
- require 'metaforce/metadata/crud'
4
- require 'metaforce/metadata/file'
@@ -1,35 +0,0 @@
1
- require 'metaforce'
2
- require 'term/ansicolor'
3
- require 'rake'
4
- require 'rake/tasklib'
5
- include Term::ANSIColor
6
-
7
- module Metaforce
8
- module Rake
9
-
10
- class DeployTask < ::Rake::TaskLib
11
- attr_accessor :name
12
-
13
- # The directory to deploy
14
- attr_accessor :directory
15
-
16
- def initialize(name = 'metaforce:deploy')
17
- @name = name
18
- @directory = File.expand_path('src')
19
- yield self if block_given?
20
- define
21
- end
22
-
23
- def define
24
- desc "Deploy metadata"
25
- task @name do
26
- client = Metaforce::Rake.client
27
- d = client.deploy(@directory)
28
- puts green "Deployed #{@directory} successfully" if d.result[:success]
29
- end
30
- end
31
-
32
- end
33
-
34
- end
35
- end
@@ -1,39 +0,0 @@
1
- require 'metaforce'
2
- require 'term/ansicolor'
3
- require 'rake'
4
- require 'rake/tasklib'
5
- include Term::ANSIColor
6
-
7
- module Metaforce
8
- module Rake
9
-
10
- class RetrieveTask < ::Rake::TaskLib
11
- attr_accessor :name
12
-
13
- # Path to the manifest file
14
- attr_accessor :manifest
15
-
16
- # The directory to unzip the retrieved files to
17
- attr_accessor :directory
18
-
19
- def initialize(name = 'metaforce:retrieve')
20
- @name = name
21
- @manifest = File.expand_path('src/package.xml')
22
- @directory = File.expand_path('retrieved')
23
- yield self if block_given?
24
- define
25
- end
26
-
27
- def define
28
- desc "Retrieve metadata"
29
- task @name do
30
- client = Metaforce::Rake.client
31
- r = client.retrieve_unpackaged(@manifest).to(@directory)
32
- puts green "Files retrieved sucessfully to #{@directory}"
33
- end
34
- end
35
-
36
- end
37
-
38
- end
39
- end
@@ -1,62 +0,0 @@
1
- require 'metaforce'
2
- require 'term/ansicolor'
3
- require 'rake'
4
- require 'rake/tasklib'
5
- include Term::ANSIColor
6
-
7
- module Metaforce
8
- module Rake
9
-
10
- class TestsTask < ::Rake::TaskLib
11
- attr_accessor :name
12
-
13
- # The directory to deploy
14
- attr_accessor :directory
15
-
16
- def initialize(name = 'metaforce:tests:ci')
17
- @name = name
18
- @directory = File.expand_path('src')
19
- yield self if block_given?
20
- define
21
- end
22
-
23
- def define
24
- desc "Deploy metadata, run all tests, then undeploy"
25
- task @name do
26
- ENV['env'] = ENV['env'] || 'ci'
27
- client = Metaforce::Rake.client
28
- Metaforce.log = false
29
- result = client.deploy(@directory, :options => { :run_all_tests => true }).result
30
- failures = result[:run_test_result][:failures]
31
-
32
- if failures
33
- failures = [failures] unless failures.is_a?(Array)
34
- puts "Failures:"
35
- failures.each_with_index do |failure, index|
36
- index = index + 1
37
- puts
38
- puts "\t#{index}) #{failure[:method_name]}"
39
- puts red "\t #{failure[:message]}"
40
- puts
41
- puts magenta "\t ##{failure[:stack_trace]}"
42
- puts
43
- end
44
- end
45
-
46
- color = failures ? :red : :green
47
- puts "Finished in #{Float(result[:run_test_result][:total_time]) / 100} seconds"
48
- puts send(color, "#{result[:run_test_result][:num_tests_run]} tests, #{result[:run_test_result][:num_failures]} failures")
49
-
50
- if failures
51
- puts "\nFailed tests:\n"
52
- failures.each do |failure|
53
- puts "#{red failure[:stack_trace]} #{magenta "# #{failure[:method_name]}"}"
54
- end
55
- end
56
-
57
- abort if failures
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,43 +0,0 @@
1
- require 'yaml'
2
- require 'metaforce/rake/deploy'
3
- require 'metaforce/rake/retrieve'
4
- require 'metaforce/rake/tests'
5
-
6
- module Metaforce
7
- module Rake
8
-
9
- class << self
10
- CONFIG_FILE = 'metaforce.yml'
11
-
12
- # Loads the config and creates a client
13
- def client
14
- load_config
15
- Metaforce::Metadata::Client.new :username => @username,
16
- :password => @password,
17
- :security_token => @security_token
18
- end
19
-
20
- # Loads configuration settings from metaforce.yml
21
- def load_config
22
- if File.exists?(CONFIG_FILE)
23
- config = YAML.load_file(CONFIG_FILE)
24
- env = ENV['env'] || 'default'
25
- config = config.has_key?(env) ? config[env] : config
26
- @username = config["username"]
27
- @password = config["password"]
28
- @security_token = config["security_token"] || ''
29
- @test = config["test"] || false
30
- @log = config["log"] || true
31
- Metaforce.log = @log
32
- Metaforce.configuration.test = @test
33
- else
34
- print "username: "; @username = STDIN.gets.chomp
35
- print "password: "; @password = STDIN.gets.chomp
36
- print "security token: "; @security_token = STDIN.gets.chomp
37
- Metaforce.log = true
38
- end
39
- end
40
-
41
- end
42
- end
43
- end
@@ -1 +0,0 @@
1
- require 'metaforce/services/client'
@@ -1,62 +0,0 @@
1
- # Metaforce Rake Tasks
2
- These are a set of default rake tasks that can be used for deploying/retrieving
3
- metadata using Rake and Metaforce. The following rake tasks are provided:
4
-
5
- * metaforce:deploy
6
- * metaforce:retrieve
7
- * metaforce:tests:ci
8
-
9
- You can include the rake tasks by adding the following to your Rakefile:
10
-
11
- ```ruby
12
- begin
13
- require 'metaforce'
14
- load 'metaforce/tasks/metaforce.rake'
15
- rescue LoadError
16
- task :metaforce do
17
- puts "Couldn't load metaforce tasks"
18
- end
19
- end
20
- ```
21
-
22
- ## metaforce.yml
23
- Include a metaforce.yml file in the root if you'd rather not type in your
24
- username, password and security token everytime you deploy or retrieve.
25
-
26
- With one environment:
27
-
28
- ```yaml
29
- ---
30
- username: user
31
- password: password
32
- security_token: securitytoken
33
- test: true # defaults to false
34
- ```
35
-
36
- With multiple environments:
37
-
38
- ```yaml
39
- ---
40
- production:
41
- username: user
42
- password: password
43
- security_token: securitytoken
44
- sandbox:
45
- username: user
46
- password: password
47
- security_token: securitytoken
48
- test: true
49
- ```
50
-
51
- This would deploy using the `sandbox` environment:
52
-
53
- `rake metaforce:deploy env="sandbox"`
54
-
55
- ## Continuous Integration
56
- The `metaforce:tests:ci` task is provided to make continuous integration with
57
- something like [Jenkins](http://jenkins-ci.org) easier.
58
-
59
- By default, the `metaforce:tests:ci` task will use the `ci` environment in
60
- metaforce.yml, so you should set that up before you use this task.
61
-
62
- The task will deploy the metadata and run all tests.
@@ -1,5 +0,0 @@
1
- require 'metaforce/rake'
2
-
3
- Metaforce::Rake::DeployTask.new
4
- Metaforce::Rake::RetrieveTask.new
5
- Metaforce::Rake::TestsTask.new
@@ -1,117 +0,0 @@
1
- require 'thor' #should probably be in say, lib/metaforce.rb, but I don't want to make that decision alone.
2
-
3
- class MetaForce < Thor
4
- include Thor::Actions
5
- require './lib/metaforce/custom_actions'
6
- require './lib/metaforce/login_details'
7
- require './lib/metaforce'
8
- include Thor::Actions::CustomActions
9
-
10
- ######## Tasks ############################################################
11
- desc "login", "accepts login parameters and completes a soap call to salesforce via the partner api."
12
- method_option :reset, :type => :boolean, :aliases => "-r", :required => false, :banner => " Reset stored login information"
13
- def login
14
- if ((File.exists? LoginDetails::STORAGE_LOCATION) && (options[:reset].nil?))
15
- say "Using stored login information"
16
- @login_details = LoginDetails.load
17
- else
18
- login_email = ask "Login Email address: "
19
- sandbox = yes? "Is this a sandbox org login: "
20
- login_pass = masked_ask "Login Password: "
21
- login_security_token = masked_ask "Security Token: "
22
- say "If you'd like I can save this login information to this directories .git/config/force.com.config"
23
- say "----- PLEASE NOTE, HOWEVER, THAT SAVING THIS INFORMATION IS INSECURE AND IS IN NO WAY ENCRYPTED"
24
- save = yes? "Should I save this Login information? (y/n) "
25
-
26
- if save
27
- @login_details = LoginDetails.new(login_email, login_pass, login_security_token, sandbox)
28
- @login_details.save!
29
- else
30
- @login_details = LoginDetails.new(login_email, login_pass, login_security_token, sandbox)
31
- end
32
- end
33
-
34
- raise "Failed to find viable login information!" if @login_details.nil?
35
- Metaforce.log = @login_details.log
36
- Metaforce.configuration.test = @login_details.sandbox
37
- @client = Metaforce::Metadata::Client.new :username => @login_details.username,
38
- :password => @login_details.password,
39
- :security_token => @login_details.security_token
40
- end
41
-
42
- ######## Deploy ###########################################################
43
- desc "deploy", "deploys the current working directory's src folder to salesforce"
44
- method_option :dir, :type => :string, :aliases => "-d", :required => true, :default => "src", :banner => "Specify the directory to deploy"
45
- method_option :reset, :type => :boolean, :aliases => "-r", :required => false, :banner => " Reset stored login information"
46
- def deploy
47
- login unless @client
48
- login unless options[:reset].nil?
49
- raise "failed to create connection!" unless @client
50
- deploy_results = @client.deploy(options[:dir]).result
51
- say "Deploy Successful!", color = Thor::Shell::Color::GREEN if deploy_results[:success]
52
- end
53
-
54
- ######## RunTests #########################################################
55
- desc "test", "runs _all_ salesforce unit tests!"
56
- method_option :dir, :type => :string, :aliases => "-d", :required => true, :default => "src", :banner => "Specify the directory to execute tests"
57
- method_option :reset, :type => :boolean, :aliases => "-r", :required => false, :banner => " Reset stored login information"
58
- def test
59
- login unless @client
60
- login unless options[:reset].nil?
61
- raise "failed to create connection!" unless @client
62
- result = spinner {
63
- result = @client.deploy(options[:dir], :options => { :run_all_tests => true }).result
64
- }
65
- failures = result[:run_test_result][:failures]
66
- if failures
67
- failures = [failures] unless failures.responds_to? :each
68
- say "--- FAILURES: ", color = Thor::Shell::Color::RED
69
- failures.each_with_index do |f,i|
70
- say "#{"-" * 80}", color = Thor::Shell::Color::YELLOW
71
- say ""
72
- say "\t(#{index +1}) #{failure[:method_name]}"
73
- say "\t\t#{failure[:message]}", color = Thor::Shell::Color::RED
74
- say ""
75
- say "\t\t#{failure[:stack_trace]}", color => Thor::Shell::Color::MAGENTA
76
- say ""
77
- end
78
- end
79
-
80
- color = (failures) ? Thor::Shell::Color::RED : Thor::Shell::Color::GREEN
81
- say "Finished in #{Float(result[:run_test_result][:total_time]) / 100} seconds"
82
- say "#{result[:run_test_result][:num_tests_run]} tests, #{result[:run_test_result][:num_failures]} failures", color = color
83
- end
84
-
85
- ######## Pull #############################################################
86
- desc "pull", "Pull all MetaData objects specified in the package.xml file"
87
- method_option :reset, :type => :boolean, :aliases => "-r", :required => false, :banner => " Reset stored login information"
88
- method_option :manifest, :type => :string, :aliases => "-m", :required => true, :banner => " Path to Manifest.xml", :default => "src/package.xml"
89
- method_option :dir, :type => :string, :aliases => "-d", :required => false, :banner => " Download to directory", :default => "retrieved"
90
- def pull
91
- login unless @client
92
- login unless options[:reset].nil?
93
- raise "failed to create connection!" unless @client
94
- result = spinner {
95
- @client.retrieve_unpackaged(options[:manifest]).to(options[:dir])
96
- }
97
- say "Files retrieved sucessfully to #{@directory}", color = Thor::Shell::Color::GREEN
98
- end
99
-
100
- ######## Clone ############################################################
101
- desc "clone", "Pull all MetaData objects from the current org"
102
- method_option :reset, :type => :boolean, :aliases => "-r", :required => false, :banner => " Reset stored login information"
103
- method_option :dir, :type => :string, :aliases => "-d", :required => true, :banner => " Download to directory", :default => "retrieved"
104
- def clone
105
- login unless @client
106
- login unless options[:reset].nil?
107
- raise "failed to create connection!" unless @client
108
- result = spinner {
109
- metadata_objects = Hash.new
110
- @client.metadata_objects.collect { |t| metadata_objects[t[:xml_name].underscore.to_sym] = ["*"] }
111
- md = Metaforce::Manifest.new(metadata_objects)
112
- @client.retrieve_unpackaged(md).to(options[:dir])
113
- }
114
- say "Files retrieved sucessfully to #{options[:dir]}", color = Thor::Shell::Color::GREEN
115
- end
116
-
117
- end