metaforce-beta 1.2.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 (78) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +22 -0
  7. data/README.md +193 -0
  8. data/Rakefile +10 -0
  9. data/bin/metaforce +14 -0
  10. data/examples/example.rb +52 -0
  11. data/lib/metaforce.rb +34 -0
  12. data/lib/metaforce/abstract_client.rb +86 -0
  13. data/lib/metaforce/cli.rb +130 -0
  14. data/lib/metaforce/client.rb +31 -0
  15. data/lib/metaforce/config.rb +100 -0
  16. data/lib/metaforce/job.rb +203 -0
  17. data/lib/metaforce/job/crud.rb +13 -0
  18. data/lib/metaforce/job/deploy.rb +87 -0
  19. data/lib/metaforce/job/retrieve.rb +102 -0
  20. data/lib/metaforce/login.rb +39 -0
  21. data/lib/metaforce/manifest.rb +106 -0
  22. data/lib/metaforce/metadata/client.rb +18 -0
  23. data/lib/metaforce/metadata/client/crud.rb +86 -0
  24. data/lib/metaforce/metadata/client/file.rb +113 -0
  25. data/lib/metaforce/reporters.rb +2 -0
  26. data/lib/metaforce/reporters/base_reporter.rb +56 -0
  27. data/lib/metaforce/reporters/deploy_reporter.rb +69 -0
  28. data/lib/metaforce/reporters/retrieve_reporter.rb +11 -0
  29. data/lib/metaforce/services/client.rb +84 -0
  30. data/lib/metaforce/version.rb +3 -0
  31. data/metaforce.gemspec +34 -0
  32. data/spec/fixtures/package.xml +17 -0
  33. data/spec/fixtures/payload.zip +0 -0
  34. data/spec/fixtures/requests/check_deploy_status/done.xml +33 -0
  35. data/spec/fixtures/requests/check_deploy_status/error.xml +26 -0
  36. data/spec/fixtures/requests/check_retrieve_status/success.xml +37 -0
  37. data/spec/fixtures/requests/check_status/done.xml +19 -0
  38. data/spec/fixtures/requests/check_status/not_done.xml +19 -0
  39. data/spec/fixtures/requests/create/in_progress.xml +12 -0
  40. data/spec/fixtures/requests/delete/in_progress.xml +12 -0
  41. data/spec/fixtures/requests/deploy/in_progress.xml +13 -0
  42. data/spec/fixtures/requests/describe_layout/success.xml +15 -0
  43. data/spec/fixtures/requests/describe_metadata/success.xml +230 -0
  44. data/spec/fixtures/requests/foo/invalid_session.xml +15 -0
  45. data/spec/fixtures/requests/list_metadata/no_result.xml +6 -0
  46. data/spec/fixtures/requests/list_metadata/objects.xml +33 -0
  47. data/spec/fixtures/requests/login/failure.xml +15 -0
  48. data/spec/fixtures/requests/login/success.xml +39 -0
  49. data/spec/fixtures/requests/retrieve/in_progress.xml +12 -0
  50. data/spec/fixtures/requests/send_email/success.xml +1 -0
  51. data/spec/fixtures/requests/update/in_progress.xml +12 -0
  52. data/spec/lib/cli_spec.rb +42 -0
  53. data/spec/lib/client_spec.rb +39 -0
  54. data/spec/lib/config_spec.rb +12 -0
  55. data/spec/lib/job/deploy_spec.rb +54 -0
  56. data/spec/lib/job/retrieve_spec.rb +28 -0
  57. data/spec/lib/job_spec.rb +111 -0
  58. data/spec/lib/login_spec.rb +18 -0
  59. data/spec/lib/manifest_spec.rb +35 -0
  60. data/spec/lib/metadata/client_spec.rb +135 -0
  61. data/spec/lib/metaforce_spec.rb +42 -0
  62. data/spec/lib/reporters/base_reporter_spec.rb +79 -0
  63. data/spec/lib/reporters/deploy_reporter_spec.rb +124 -0
  64. data/spec/lib/reporters/retrieve_reporter_spec.rb +14 -0
  65. data/spec/lib/services/client_spec.rb +37 -0
  66. data/spec/spec_helper.rb +37 -0
  67. data/spec/support/client.rb +39 -0
  68. data/wsdl/23.0/metadata.xml +3520 -0
  69. data/wsdl/23.0/partner.xml +3190 -0
  70. data/wsdl/26.0/metadata.xml +4750 -0
  71. data/wsdl/26.0/partner.xml +3340 -0
  72. data/wsdl/34.0/metadata.xml +7981 -0
  73. data/wsdl/34.0/partner.xml +5398 -0
  74. data/wsdl/35.0/metadata.xml +8183 -0
  75. data/wsdl/35.0/partner.xml +5755 -0
  76. data/wsdl/40.0/metadata.xml +29052 -0
  77. data/wsdl/40.0/partner.xml +7642 -0
  78. metadata +327 -0
@@ -0,0 +1,113 @@
1
+ module Metaforce
2
+ module Metadata
3
+ class Client
4
+ module File
5
+
6
+ # Public: Specify an array of component types to list.
7
+ #
8
+ # Examples
9
+ #
10
+ # # Get a list of apex classes on the server and output the names of each
11
+ # client.list_metadata('ApexClass').collect { |t| t.full_name }
12
+ # #=> ["al__SObjectPaginatorListenerForTesting", "al__IndexOutOfBoundsException", ... ]
13
+ #
14
+ # # Get a list of apex components and apex classes
15
+ # client.list_metadata('CustomObject', 'ApexComponent')
16
+ # #=> ["ContractContactRole", "Solution", "Invoice_Statements__c", ... ]
17
+ def list_metadata(*args)
18
+ queries = args.map(&:to_s).map(&:camelize).map { |t| {:type => t} }
19
+ request :list_metadata do |soap|
20
+ soap.body = { :queries => queries }
21
+ end
22
+ end
23
+
24
+ # Public: Describe the organization's metadata.
25
+ #
26
+ # version - API version (default: latest).
27
+ #
28
+ # Examples
29
+ #
30
+ # # List the names of all metadata types
31
+ # client.describe.metadata_objects.collect { |t| t.xml_name }
32
+ # #=> ["CustomLabels", "StaticResource", "Scontrol", "ApexComponent", ... ]
33
+ def describe(version=nil)
34
+ request :describe_metadata do |soap|
35
+ soap.body = { :api_version => version } unless version.nil?
36
+ end
37
+ end
38
+
39
+ # Public: Checks the status of an async result.
40
+ #
41
+ # ids - A list of ids to check.
42
+ # type - either :deploy or :retrieve
43
+ #
44
+ # Examples
45
+ #
46
+ # client.status('04sU0000000Wx6KIAS')
47
+ # #=> {:done=>true, :id=>"04sU0000000Wx6KIAS", :state=>"Completed", ...}
48
+ def status(ids, type=nil)
49
+ method = :check_status
50
+ method = :"check_#{type}_status" if type
51
+ ids = [ids] unless ids.respond_to?(:each)
52
+ request method do |soap|
53
+ soap.body = { :ids => ids }
54
+ end
55
+ end
56
+
57
+ # Public: Deploy code to Salesforce.
58
+ #
59
+ # zip_file - The base64 encoded contents of the zip file.
60
+ # options - Hash of DeployOptions.
61
+ #
62
+ # Returns the AsyncResult
63
+ def _deploy(zip_file, options={})
64
+ request :deploy do |soap|
65
+ soap.body = { :zip_file => zip_file, :deploy_options => options }
66
+ end
67
+ end
68
+
69
+ # Public: Retrieve code from Salesforce.
70
+ #
71
+ # Returns the AsyncResult
72
+ def _retrieve(options={})
73
+ request :retrieve do |soap|
74
+ soap.body = { :retrieve_request => options }
75
+ end
76
+ end
77
+
78
+ # Public: Deploy code to Salesforce.
79
+ #
80
+ # path - A path to a zip file, or a directory to deploy.
81
+ # options - Deploy options.
82
+ #
83
+ # Examples
84
+ #
85
+ # client.deploy(File.expand_path('./src'))
86
+ def deploy(path, options={})
87
+ Job::Deploy.new(self, path, options)
88
+ end
89
+
90
+ def retrieve(options={})
91
+ Job::Retrieve.new(self, options)
92
+ end
93
+
94
+ # Public: Retrieves files specified in the manifest file (A package.xml
95
+ # file).
96
+ def retrieve_unpackaged(manifest, options={})
97
+ package = if manifest.is_a?(Metaforce::Manifest)
98
+ manifest
99
+ elsif manifest.is_a?(String)
100
+ Metaforce::Manifest.new(::File.open(manifest).read)
101
+ end
102
+ options = {
103
+ :api_version => Metaforce.configuration.api_version,
104
+ :single_package => true,
105
+ :unpackaged => { :types => package.to_package }
106
+ }.merge(options)
107
+ retrieve(options)
108
+ end
109
+
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,2 @@
1
+ require 'metaforce/reporters/deploy_reporter'
2
+ require 'metaforce/reporters/retrieve_reporter'
@@ -0,0 +1,56 @@
1
+ require 'thor/shell/color'
2
+
3
+ module Metaforce
4
+ module Reporters
5
+ class BaseReporter < Thor::Shell::Color
6
+ def initialize(results)
7
+ super()
8
+ @results = results
9
+ end
10
+
11
+ def report
12
+ end
13
+
14
+ def report_problems
15
+ return unless problems?
16
+ say
17
+ say "Problems:", :red
18
+ say
19
+ problems.each { |message| problem(message) }
20
+ end
21
+
22
+ def problem(message)
23
+ say "#{short_padding}#{message.file_name}:#{message.line_number}", :red
24
+ say "#{long_padding}#{message.problem}"
25
+ say
26
+ end
27
+
28
+ def short_padding
29
+ ' '
30
+ end
31
+
32
+ def long_padding
33
+ ' '
34
+ end
35
+
36
+ def problems?
37
+ problems.any?
38
+ end
39
+
40
+ def issues?
41
+ problems?
42
+ end
43
+
44
+ private
45
+
46
+ def messages
47
+ @messages ||= Array[@results.messages].compact.flatten
48
+ end
49
+
50
+ def problems
51
+ messages.select { |message| message.problem }
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,69 @@
1
+ require 'metaforce/reporters/base_reporter'
2
+
3
+ module Metaforce
4
+ module Reporters
5
+ class DeployReporter < BaseReporter
6
+
7
+ def report
8
+ report_problems
9
+ report_failed_tests
10
+ report_test_results if report_test_results?
11
+ end
12
+
13
+ def report_failed_tests
14
+ return unless failures?
15
+ say
16
+ say "Failures:", :red
17
+ say
18
+ failures.each { |failure| failed(failure) }
19
+ end
20
+
21
+ def report_test_results
22
+ say
23
+ say "Finished in #{total_time} seconds"
24
+ say "#{num_tests} tests, #{num_failures} failures", failures? ? :red : :green
25
+ end
26
+
27
+ def failed(failure)
28
+ say "#{short_padding}#{failure.stack_trace}:", :red
29
+ say "#{long_padding}#{failure.message}"
30
+ say
31
+ end
32
+
33
+ def failures?
34
+ num_failures > 0
35
+ end
36
+
37
+ def issues?
38
+ problems? || failures?
39
+ end
40
+
41
+ private
42
+
43
+ def report_test_results?
44
+ @results.success && problems.empty?
45
+ end
46
+
47
+ def test_results
48
+ @results.run_test_result
49
+ end
50
+
51
+ def failures
52
+ @failures ||= Array[test_results.failures].compact.flatten
53
+ end
54
+
55
+ def total_time
56
+ test_results.total_time
57
+ end
58
+
59
+ def num_tests
60
+ test_results.num_tests_run.to_i
61
+ end
62
+
63
+ def num_failures
64
+ test_results.num_failures.to_i
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ require 'metaforce/reporters/base_reporter'
2
+
3
+ module Metaforce
4
+ module Reporters
5
+ class RetrieveReporter < BaseReporter
6
+ def report
7
+ report_problems
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,84 @@
1
+ module Metaforce
2
+ module Services
3
+ class Client < Metaforce::AbstractClient
4
+ endpoint :server_url
5
+ wsdl Metaforce.configuration.partner_wsdl
6
+
7
+ # Public: Sends an email using Salesforce.
8
+ #
9
+ # options - Hash of email options (http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_sendemail.htm)
10
+ #
11
+ # Examples
12
+ #
13
+ # client.send_email(
14
+ # to_addresses: ['foo@bar.com'],
15
+ # subject: 'Hello World',
16
+ # plain_text_body: 'Hello World'
17
+ # )
18
+ #
19
+ # Returns the result.
20
+ def send_email(options={})
21
+ request :send_email do |soap|
22
+ soap.body = {
23
+ :messages => options,
24
+ :attributes! => { 'ins0:messages' => { 'xsi:type' => 'ins0:SingleEmailMessage' } }
25
+ }
26
+ end
27
+ end
28
+
29
+ # Public: Retrieves layout information for the specified sobject.
30
+ #
31
+ # sobject - String name of the sobject.
32
+ # record_type_id - String id of a record type to filter on.
33
+ #
34
+ # Examples
35
+ #
36
+ # client.describe_layout('Account', '012000000000000AAA')
37
+ #
38
+ # Returns the layout metadata for the sobject.
39
+ def describe_layout(sobject, record_type_id=nil)
40
+ request :describe_layout do |soap|
41
+ soap.body = { 'sObjectType' => sobject }
42
+ soap.body.merge!('recordTypeID' => record_type_id) if record_type_id
43
+ end
44
+ end
45
+
46
+ # Public: Get active picklists for a record type.
47
+ #
48
+ # sobject - String name of the sobject.
49
+ # record_type_id - String id of a record type to filter on.
50
+ # field - String name of the field to get picklist values for.
51
+ #
52
+ # Examples
53
+ #
54
+ # client.picklist_values('Account', '012000000000000AAA', 'Some_Field__c')
55
+ # # => [['Label', 'Value']]
56
+ #
57
+ # Returns the picklist_values
58
+ def picklist_values(sobject, record_type_id, field)
59
+ describe_layout(sobject, record_type_id).record_type_mappings.picklists_for_record_type
60
+ .select { |p| p.picklist_name == field }.first.picklist_values
61
+ .select { |p| p.active }.collect { |p| [ p.label, p.value ] }
62
+ end
63
+
64
+ def inspect
65
+ "#<#{self.class} @options=#{@options.inspect}>"
66
+ end
67
+
68
+ # Public: Retrieves the current system timestamp
69
+ # (Coordinated Universal Time (UTC) time zone) from the API.
70
+ #
71
+ # Example: client.services.send(:get_server_timestamp)
72
+ def get_server_timestamp
73
+ request :get_server_timestamp
74
+ end
75
+
76
+ # Public: Retrieves personal information for the user associated
77
+ # with the current session.
78
+ # Example: client.services.send(:get_user_info)
79
+ def get_user_info
80
+ request :get_user_info
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+ module Metaforce
2
+ VERSION = '1.2.0'
3
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'metaforce/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'metaforce-beta'
7
+ s.version = Metaforce::VERSION
8
+ s.authors = ['Tomoaki Abe', 'Masato Igarashi']
9
+ s.email = ['abe@enzou.tokyo', 'm@igrs.jp']
10
+ s.homepage = 'https://github.com/openlogi/metaforce'
11
+ s.summary = %q{A Ruby gem for interacting with the Salesforce Metadata API}
12
+ s.description = %q{A Ruby gem for interacting with the Salesforce Metadata API}
13
+
14
+ s.rubyforge_project = 'metaforce-beta'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ['lib']
20
+
21
+ s.add_dependency 'savon', '~> 1.2.0'
22
+ s.add_dependency 'rubyzip', '~> 1.3.0'
23
+ s.add_dependency 'activesupport', '~> 5.2.4'
24
+ s.add_dependency 'hashie', '~> 4.0.0'
25
+ s.add_dependency 'thor', '~> 1.0.1'
26
+ s.add_dependency 'nokogiri', '1.10.7'
27
+ s.add_dependency 'listen', '~> 3.2.1'
28
+
29
+ s.add_development_dependency 'rake', '~> 13.0.1'
30
+ s.add_development_dependency 'rspec', '~> 3.9.0'
31
+ s.add_development_dependency 'rspec-its', '~> 1.3.0'
32
+ s.add_development_dependency 'webmock', '~> 3.7.6'
33
+ s.add_development_dependency 'savon_spec', '~> 1.3.0'
34
+ end
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0"?>
2
+ <Package xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <types>
4
+ <members>TestClass</members>
5
+ <members>AnotherClass</members>
6
+ <name>ApexClass</name>
7
+ </types>
8
+ <types>
9
+ <members>Component</members>
10
+ <name>ApexComponent</name>
11
+ </types>
12
+ <types>
13
+ <members>Assets</members>
14
+ <name>StaticResource</name>
15
+ </types>
16
+ <version>26.0</version>
17
+ </Package>
Binary file
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <soapenv:Body>
4
+ <checkDeployStatusResponse>
5
+ <result>
6
+ <id>04sU0000000WRCXIA4</id>
7
+ <messages>
8
+ <changed>true</changed>
9
+ <created>true</created>
10
+ <deleted>false</deleted>
11
+ <fileName>src/classes/TestClass.cls</fileName>
12
+ <fullName>TestClass</fullName>
13
+ <id>01pU0000000pDrtIAE</id>
14
+ <success>true</success>
15
+ </messages>
16
+ <messages>
17
+ <changed>true</changed>
18
+ <created>false</created>
19
+ <deleted>false</deleted>
20
+ <fileName>src/package.xml</fileName>
21
+ <fullName>package.xml</fullName>
22
+ <success>true</success>
23
+ </messages>
24
+ <runTestResult>
25
+ <numFailures>0</numFailures>
26
+ <numTestsRun>0</numTestsRun>
27
+ <totalTime>-1.0</totalTime>
28
+ </runTestResult>
29
+ <success>true</success>
30
+ </result>
31
+ </checkDeployStatusResponse>
32
+ </soapenv:Body>
33
+ </soapenv:Envelope>
@@ -0,0 +1,26 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <soapenv:Body>
4
+ <checkDeployStatusResponse>
5
+ <result>
6
+ <id>04sU0000000WRBLIA4</id>
7
+ <messages>
8
+ <changed>false</changed>
9
+ <created>false</created>
10
+ <deleted>false</deleted>
11
+ <fileName>classes/package.xml</fileName>
12
+ <fullName>package.xml</fullName>
13
+ <problem>No package.xml found</problem>
14
+ <problemType>Error</problemType>
15
+ <success>false</success>
16
+ </messages>
17
+ <runTestResult>
18
+ <numFailures>0</numFailures>
19
+ <numTestsRun>0</numTestsRun>
20
+ <totalTime>0.0</totalTime>
21
+ </runTestResult>
22
+ <success>false</success>
23
+ </result>
24
+ </checkDeployStatusResponse>
25
+ </soapenv:Body>
26
+ </soapenv:Envelope>