forcer 0.4.1 → 0.4.11
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.
- checksums.yaml +4 -4
- data/README.md +82 -6
- data/lib/forcer/version.rb +1 -1
- data/lib/forcer_main.rb +1 -2
- data/lib/metadata_services/metadata_service.rb +0 -16
- data/lib/metadata_services/sfdc_directory_service.rb +2 -25
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62557f4f1a234342ffdf0c2200f109b11b9cb202
|
4
|
+
data.tar.gz: 6ed0f6dc2a5bad4c368dbd31ddcfbfe31eafaf74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 772236104b4fd9ef9eca8d27306ece9088be064dc3d50991eb80b382d582ca0864b661e59712b17982ce78e0ebe86ce9758c2a998ac06cacd477b909d0148126
|
7
|
+
data.tar.gz: eb11cdf7d170dc3ae344a2db30bc52fc7e71c305d95b0dc5f9807a19cada50e063cb56d3feebce26339ea4e3d4118f2c1cfa2469f515f5940ab4902d660e7e54
|
data/README.md
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
# Forcer
|
2
|
+
[](http://badge.fury.io/rb/forcer)
|
3
|
+
[](https://travis-ci.org/gazazello/forcer)
|
4
|
+
|
2
5
|
forcer is a ruby command line application and gem designed to help force.com developers who utilize git and proper development process that includes:
|
3
6
|
|
4
7
|
1. every developer should have a separate dev_org\dev_sandbox
|
5
8
|
2. code reviews
|
6
9
|
3. parallel development of multiple features by a single developer
|
7
10
|
|
11
|
+
advantages over traditional ant scripts:
|
12
|
+
|
13
|
+
1. Configurability
|
14
|
+
2. Easy integration with CI (i.e. Jenkins)
|
15
|
+
3. Commands for specific tasks (i.e. delete components or rename components)
|
16
|
+
4. Easily add REST Api functionality (i.e. load initial data after new org created)
|
17
|
+
|
8
18
|
|
9
19
|
This project is inspired by metaforce. It turned out to be easier to start my own project after trying to understand how metaforce
|
10
20
|
is written and attempting to contribute into it. So after days of reading metaforces code and trying to understand, how
|
@@ -66,7 +76,7 @@ Please note that "src" folder must contain a valid package.xml file that you int
|
|
66
76
|
|
67
77
|
### Configuration
|
68
78
|
forcer can store information about deployment organization to avoid typing details for each deployment. Information like username,
|
69
|
-
password (it is strongly recommended to avoid storing password) can be saved in configuration.yml file. And here is a template content:
|
79
|
+
password (it is strongly recommended to avoid storing password) can be saved in "configuration.yml" file. And here is a template content:
|
70
80
|
|
71
81
|
anything_as_your_org_alias:
|
72
82
|
host: login.salesforce.com
|
@@ -74,17 +84,83 @@ password (it is strongly recommended to avoid storing password) can be saved in
|
|
74
84
|
password:
|
75
85
|
security_token: sample_token
|
76
86
|
|
87
|
+
#### Where to put "configuration.yml"?
|
88
|
+
It should be in the same directory where you call forcer. Then the app can pick it up and login properly.
|
89
|
+
|
90
|
+
$: ls
|
91
|
+
./configuration.yml
|
92
|
+
...
|
93
|
+
|
94
|
+
$: forcer deploy ...
|
95
|
+
|
96
|
+
This allows having separate "configuration.yml" file for each project. If you are calling forcer from git repo directory
|
97
|
+
with project files, please add "configuration.yml" to gitignore. This should help you avoiding committing sensitive data.
|
77
98
|
For more information on setup and usage of configuration.yml please visit wiki pages of this project.
|
78
99
|
|
79
100
|
### Excluding certain metadata from deployment
|
80
|
-
forcer is a flexible tool that allows developers
|
101
|
+
forcer is a flexible tool that allows developers:
|
102
|
+
|
103
|
+
- Exclude certain ncomponents (metadata files) and even whole folders from deployment. For example object Idea.object (excluded by default) usually fails deployments.
|
81
104
|
|
82
|
-
|
83
|
-
|
105
|
+
#### How to exclude components and folders from deployment?
|
106
|
+
Name of the file is "exclude_components.yml".
|
107
|
+
|
108
|
+
#### "exclude_components.yml" contains:
|
109
|
+
|
110
|
+
- objects/Idea.object
|
111
|
+
- layouts/SocialPersona-Social Persona Layout.layout
|
112
|
+
- layouts/SocialPost-Social Post Layout.layout
|
113
|
+
- profiles # excludes whole profiles directory
|
114
|
+
|
115
|
+
#### Where should I place "exclude_components.yml"?
|
116
|
+
|
117
|
+
[your_ruby_version_location (like ".../rvm/gems/ruby-2.2.0")]/gems/forcer-0.4.1/lib/metadata_services/exclude_components.yml
|
118
|
+
forcer is released with default "exclude_components.yml". Users (developers) can modify or replace values to exclude
|
119
|
+
certain components or folders.
|
120
|
+
|
121
|
+
|
122
|
+
- Exclude certain XML elements from deployment. For example all references to "Social..." layouts (excluded by default) in profiles fail deployments.
|
84
123
|
|
85
|
-
|
86
|
-
of
|
124
|
+
#### How to exclude XML elements (snippets) from deployment?
|
125
|
+
Name of the file is "exclude_xml_nodes.yml".
|
126
|
+
|
127
|
+
#### Sample "exclude_xml_nodes.yml":
|
128
|
+
|
129
|
+
:".profile":
|
130
|
+
- [ "*//layoutAssignments/layout[starts-with('Social')]" , true ]
|
131
|
+
- [ "*//tabVisibilities/tab[starts-with('standard-Social')]" , true ]
|
132
|
+
|
133
|
+
This means "for all files with filenames ending with '.profiles' do
|
134
|
+
|
135
|
+
find snippets like:
|
136
|
+
|
137
|
+
<layoutAsignments>
|
138
|
+
<layout>Social blah blah blah</layout>
|
139
|
+
</layoutAsignments>
|
140
|
+
|
141
|
+
Then take the first parameter which is nokogiri expression. forcer automatically removes all found nodes from document
|
142
|
+
|
143
|
+
<layout>Social blah blah blah</layout>
|
144
|
+
|
145
|
+
Then if second parameter is TRUE, remove parent node too. In this example remove
|
146
|
+
|
147
|
+
<layoutAsignments>
|
148
|
+
</layoutAsignments>
|
149
|
+
|
150
|
+
Alternatively if second parameter is FALSE then parent node will remain in the document
|
151
|
+
|
152
|
+
The same logic applies for the second sample value:
|
153
|
+
|
154
|
+
- [ "*//tabVisibilities/tab[starts-with('standard-Social')]" , true ]
|
155
|
+
|
156
|
+
#### Where should I place "exclude_xml_nodes.yml"?
|
157
|
+
|
158
|
+
[your_ruby_version_location (like ".../rvm/gems/ruby-2.2.0")]/gems/forcer-[version]/lib/metadata_services/exclude_xml_nodes.yml
|
159
|
+
forcer is released with "exclude_xml_nodes.yml". Users (developers) can modify or replace values to exclude xml elements.
|
87
160
|
|
161
|
+
Currently forcer does not allow multiple "exclude_components.xml" and "exclude_xml_nodes.xml" files.I understand that
|
162
|
+
working on multiple projects simultaneously can require you to exclude different files/components for each project.
|
163
|
+
Support of multiple config files can be added as a new feature per request.
|
88
164
|
|
89
165
|
### Command line examples
|
90
166
|
If you already filled configuration.yml correctly then deployments are much faster. Here is a sample command to start deployment of a project in current folder:
|
data/lib/forcer/version.rb
CHANGED
data/lib/forcer_main.rb
CHANGED
@@ -5,8 +5,7 @@ require_relative "./metadata_services/metadata_service"
|
|
5
5
|
|
6
6
|
module Forcer
|
7
7
|
class ForcerMain < Thor
|
8
|
-
class_option :dest, :aliases => :d
|
9
|
-
class_option :config
|
8
|
+
class_option :dest, :aliases => :d, :desc => "Alias of destination sfdc org in your configuration.yml file. If you do not have configuration.yml in current directory, just skip the option."
|
10
9
|
|
11
10
|
option :source, :aliases => :s, :desc => "Path to folder that contains 'src' directory somewhere. No restriction on exact 'src' location, except it should be somewhere in :sourse."
|
12
11
|
option :checkOnly, :type => :boolean, :aliases => :c, :desc => "Only validates without actual deployment. Default is FALSE."
|
@@ -153,19 +153,3 @@ module Metadata
|
|
153
153
|
|
154
154
|
end # class MetadataService
|
155
155
|
end # module Metadata
|
156
|
-
|
157
|
-
# test area
|
158
|
-
|
159
|
-
# args = {
|
160
|
-
# host: "https://test.salesforce.com",
|
161
|
-
# username: "gaziz@eventbrite.com.comitydev",
|
162
|
-
# password: "?kMMTR[d}X7`Fd}>@T.",
|
163
|
-
# security_token: "fpX1t6k2We39Qtq42NKbnLWSQ"
|
164
|
-
# }
|
165
|
-
# metadata_service = Metadata::MetadataService.new(
|
166
|
-
# File.expand_path("../../../tmp/TestProject", __FILE__),
|
167
|
-
# args
|
168
|
-
# )
|
169
|
-
#
|
170
|
-
# p metadata_service.list.body
|
171
|
-
# p metadata_service.deploy.body[:deploy_response][:result][:state]
|
@@ -43,7 +43,6 @@ module Metadata
|
|
43
43
|
FileUtils.remove_entry(tmpdir)
|
44
44
|
end
|
45
45
|
|
46
|
-
# FileUtils.cp_r(@output_file_name, "/Users/gt/Desktop/temp.zip")
|
47
46
|
return @output_file_name
|
48
47
|
end
|
49
48
|
|
@@ -81,37 +80,22 @@ module Metadata
|
|
81
80
|
end
|
82
81
|
|
83
82
|
@snippets_to_exclude = YAML.load_file(exclude_filename)
|
84
|
-
# YAML.load_file(exclude_filename).each do |suffix, expressions|
|
85
|
-
# @snippets_to_exclude[key] << value
|
86
|
-
# pp "=== #{key} => #{value}"
|
87
|
-
# expressions.each do |exp, flag|
|
88
|
-
# pp "=== exp => #{exp}"
|
89
|
-
# pp "=== exp => #{flag}"
|
90
|
-
# end
|
91
|
-
# end
|
92
|
-
# pp "====== snippets => #{@snippets_to_exclude} ==== #{@snippets_to_exclude.class}"
|
93
83
|
end
|
94
84
|
|
95
85
|
# Opens file. Removes all bad xml snippets. Rewrites results back into original file
|
96
86
|
def filter_xml(filename)
|
97
87
|
doc = Nokogiri::XML(File.read(filename))
|
98
|
-
# if (filename.end_with?("package.xml"))
|
99
|
-
# p "======= errors of package.xml => #{doc.errors}"
|
100
|
-
# end
|
101
88
|
file_modified = false
|
102
89
|
@snippets_to_exclude.each do |suffix, expressions|
|
103
90
|
next unless filename.end_with?(suffix.to_s)
|
104
|
-
# p "==== processing suffix = #{suffix} vs #{filename}"
|
105
|
-
# p "==== processing snippets = #{snippets}"
|
106
91
|
expressions.each do |search_string, should_remove_parent|
|
107
|
-
# pp "==== processing snippet = #{search_string}"
|
108
92
|
nodes = doc.search(search_string.to_s)
|
109
93
|
unless nodes.empty?
|
110
94
|
file_modified = true
|
111
95
|
nodes.each do |n|
|
112
96
|
parent = n.parent
|
113
|
-
n.remove unless should_remove_parent
|
114
|
-
parent.remove if should_remove_parent #
|
97
|
+
n.remove unless should_remove_parent # remove only node if parent to stay
|
98
|
+
parent.remove if should_remove_parent # remove the whole parent node with all children including current node
|
115
99
|
end
|
116
100
|
end
|
117
101
|
end
|
@@ -119,9 +103,6 @@ module Metadata
|
|
119
103
|
File.open(filename, "w") do |file|
|
120
104
|
file.print(doc.to_xml)
|
121
105
|
end if file_modified
|
122
|
-
# if (filename.end_with?("Admin.profile"))
|
123
|
-
# FileUtils.cp(filename, "/Users/gt/Desktop/testAdmin.profile")
|
124
|
-
# end
|
125
106
|
end
|
126
107
|
|
127
108
|
def write_entries(entries, path)
|
@@ -184,7 +165,3 @@ module Metadata
|
|
184
165
|
end
|
185
166
|
end # class SfdcDirectoryService
|
186
167
|
end # module Metadata
|
187
|
-
|
188
|
-
# simple test
|
189
|
-
# test_generator = Metadata::SfdcDirectoryService.new("/Users/gt/Desktop/TestProject")
|
190
|
-
# test_generator.write
|