forcer 0.4.14 → 0.4.15
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/.idea/.rakeTasks +1 -1
- data/.idea/codeStyleSettings.xml +13 -0
- data/.idea/dictionaries/gaziz.xml +3 -0
- data/.idea/forcer.iml +26 -22
- data/README.md +82 -47
- data/lib/forcer/version.rb +1 -1
- data/lib/forcer_main.rb +2 -0
- data/lib/metadata_services/metadata_service.rb +1 -0
- data/lib/metadata_services/sfdc_directory_service.rb +36 -7
- data/lib/utilities/action_options_service.rb +51 -30
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6101468b6bfe4249a1f178acc2ad0ac8a41a86b
|
|
4
|
+
data.tar.gz: d16e4e974373d621a39bc3ebdf4e072b2676f046
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5e1a2c5b9464d586d06715cc496347dd76da334bd74a72242713c7f11b88e943786b39935de483e23988d734a913ed9e268441e3f3d4ba7382e8a79c3aa03f14
|
|
7
|
+
data.tar.gz: b39ba5f19cc9c3c0b1adbf463dae0d80b06a8f19973f60c5fe732b29ac871a90db7ac76c4a39cb11eecb712134225a59a92be0813e32fb057473f9bf46ff7058
|
data/.idea/.rakeTasks
CHANGED
|
@@ -4,4 +4,4 @@ You are allowed to:
|
|
|
4
4
|
1. Remove rake task
|
|
5
5
|
2. Add existing rake tasks
|
|
6
6
|
To add existing rake tasks automatically delete this file and reload the project.
|
|
7
|
-
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build forcer-0.4.
|
|
7
|
+
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build forcer-0.4.15.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Build and install forcer-0.4.15.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install forcer-0.4.15.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.4.15 and build and push forcer-0.4.15.gem to Rubygems" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<project version="4">
|
|
3
|
+
<component name="ProjectCodeStyleSettingsManager">
|
|
4
|
+
<option name="PER_PROJECT_SETTINGS">
|
|
5
|
+
<value>
|
|
6
|
+
<XML>
|
|
7
|
+
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
|
8
|
+
</XML>
|
|
9
|
+
</value>
|
|
10
|
+
</option>
|
|
11
|
+
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
|
|
12
|
+
</component>
|
|
13
|
+
</project>
|
data/.idea/forcer.iml
CHANGED
|
@@ -11,28 +11,32 @@
|
|
|
11
11
|
</component>
|
|
12
12
|
<component name="NewModuleRootManager">
|
|
13
13
|
<content url="file://$MODULE_DIR$" />
|
|
14
|
-
<orderEntry type="jdk" jdkName="RVM: ruby-2.2
|
|
14
|
+
<orderEntry type="jdk" jdkName="RVM: ruby-2.2-head" jdkType="RUBY_SDK" />
|
|
15
15
|
<orderEntry type="sourceFolder" forTests="false" />
|
|
16
|
-
<orderEntry type="library" scope="PROVIDED" name="akami (v1.3.
|
|
17
|
-
<orderEntry type="library" scope="PROVIDED" name="builder (v3.2.2, RVM: ruby-2.2
|
|
18
|
-
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.
|
|
19
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
20
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
21
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
22
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
23
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
24
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
25
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
26
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
27
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
28
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
29
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
30
|
-
<orderEntry type="library" scope="PROVIDED" name="rspec
|
|
31
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
32
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
33
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
34
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
35
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
36
|
-
<orderEntry type="library" scope="PROVIDED" name="
|
|
16
|
+
<orderEntry type="library" scope="PROVIDED" name="akami (v1.3.1, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
17
|
+
<orderEntry type="library" scope="PROVIDED" name="builder (v3.2.2, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
18
|
+
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.10.6, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
19
|
+
<orderEntry type="library" scope="PROVIDED" name="codeclimate-test-reporter (v0.4.7, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
20
|
+
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
21
|
+
<orderEntry type="library" scope="PROVIDED" name="docile (v1.1.5, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
22
|
+
<orderEntry type="library" scope="PROVIDED" name="gyoku (v1.3.1, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
23
|
+
<orderEntry type="library" scope="PROVIDED" name="httpi (v2.4.1, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
24
|
+
<orderEntry type="library" scope="PROVIDED" name="json (v1.8.2, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
25
|
+
<orderEntry type="library" scope="PROVIDED" name="mini_portile (v0.6.2, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
26
|
+
<orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.6.6.2, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
27
|
+
<orderEntry type="library" scope="PROVIDED" name="nori (v2.6.0, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
28
|
+
<orderEntry type="library" scope="PROVIDED" name="rack (v1.6.4, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
29
|
+
<orderEntry type="library" scope="PROVIDED" name="rake (v10.4.2, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
30
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec (v3.2.0, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
31
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.2.3, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
32
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.2.1, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
33
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.2.1, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
34
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.2.2, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
35
|
+
<orderEntry type="library" scope="PROVIDED" name="rubyzip (v1.1.7, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
36
|
+
<orderEntry type="library" scope="PROVIDED" name="savon (v2.11.1, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
37
|
+
<orderEntry type="library" scope="PROVIDED" name="simplecov (v0.10.0, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
38
|
+
<orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.10.0, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
39
|
+
<orderEntry type="library" scope="PROVIDED" name="thor (v0.19.1, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
40
|
+
<orderEntry type="library" scope="PROVIDED" name="wasabi (v3.5.0, RVM: ruby-2.2-head) [gem]" level="application" />
|
|
37
41
|
</component>
|
|
38
42
|
</module>
|
data/README.md
CHANGED
|
@@ -4,24 +4,29 @@
|
|
|
4
4
|
[](https://codeclimate.com/github/gazazello/forcer)
|
|
5
5
|
[](https://codeclimate.com/github/gazazello/forcer/coverage)
|
|
6
6
|
|
|
7
|
-
Forcer is a ruby command line
|
|
7
|
+
Forcer is a ruby command line app and gem for interaction with Salesforce Metadata (Metadata API).
|
|
8
|
+
Calling deploy and other available metadata commands should be quicker than using traditional ANT tool
|
|
9
|
+
provided by Salesforce. So in some sense Forcer is an open source replacement for ANT migration tool.
|
|
10
|
+
Forcer is designed to help Force.com developers who use "proper" development process that includes:
|
|
8
11
|
|
|
9
|
-
1. every
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
1. Git (Every deployment and every change to any _tracked_ project component is committed to a git repo)
|
|
13
|
+
1. A separate dev_org\dev_sandbox for every developer
|
|
14
|
+
2. Parallel development of multiple features by a single developer (can use single Dev Org)
|
|
15
|
+
3. Code reviews
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
|
|
18
|
+
Advantages over traditional ANT tool scripts:
|
|
14
19
|
|
|
15
20
|
1. Configurability
|
|
16
21
|
2. Commands for specific tasks (i.e. delete components or rename components)
|
|
17
|
-
3. Easily
|
|
22
|
+
3. Easily adding REST Api functionality (i.e. load initial data after new org created)
|
|
18
23
|
|
|
19
24
|
|
|
20
|
-
This project is inspired by
|
|
21
|
-
is written and attempting to contribute into it. So after days of reading
|
|
22
|
-
SOAP api calls are done to
|
|
23
|
-
The idea is to make structure of Forcer simpler than
|
|
24
|
-
of files. I admit that my code is not perfect and far from professional ruby styles, so
|
|
25
|
+
This project is written in Ruby and inspired by Metaforce. It turned out to be easier to start my own project after trying to understand how Metaforce
|
|
26
|
+
is written and attempting to contribute into it. So after days of reading Metaforce's code and trying to understand, how
|
|
27
|
+
SOAP api calls are done to Salesforce and how 'thor' is used to create command line app, I was ready to write my own tool.
|
|
28
|
+
The idea is to make structure of Forcer simpler than Metaforce and let contributors understand code by reading smaller amount
|
|
29
|
+
of files. I admit that my code is not perfect and far from professional ruby styles, so help is appreciated.
|
|
25
30
|
But please lets keep this tool simple with only necessary commands and functionality.
|
|
26
31
|
|
|
27
32
|
## System Requirements
|
|
@@ -31,7 +36,7 @@ Ruby version: 2.1.2 or later
|
|
|
31
36
|
|
|
32
37
|
## Installation
|
|
33
38
|
|
|
34
|
-
Add this line to
|
|
39
|
+
Add this line to application's Gemfile:
|
|
35
40
|
|
|
36
41
|
```ruby
|
|
37
42
|
gem 'forcer'
|
|
@@ -41,13 +46,13 @@ And then execute:
|
|
|
41
46
|
|
|
42
47
|
$ bundle
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
Alternatively install it as:
|
|
45
50
|
|
|
46
51
|
$ gem install forcer
|
|
47
52
|
|
|
48
|
-
##
|
|
53
|
+
## How to use?
|
|
49
54
|
Currently the app is tested and being used only on Mac OS and Linux (I used Ubuntu). I have NOT tested on Windows yet, but
|
|
50
|
-
if
|
|
55
|
+
if help in testing and reporting results for Windows is appreciated by the rest.
|
|
51
56
|
|
|
52
57
|
Call help to list all available operations for Forcer:
|
|
53
58
|
|
|
@@ -63,7 +68,7 @@ To list options and flags available for each command call help for each operatio
|
|
|
63
68
|
--checkOnly ...
|
|
64
69
|
...
|
|
65
70
|
|
|
66
|
-
To deploy
|
|
71
|
+
To deploy project (stored in local filesystem) to destination org first from terminal users need to change directory
|
|
67
72
|
to project folder that somewhere inside contains folder "src" with all metadata to deploy:
|
|
68
73
|
|
|
69
74
|
$(master): cd ~/my_workspace/TestProject/
|
|
@@ -77,7 +82,8 @@ Here is a very simple deploy command:
|
|
|
77
82
|
$(master): forcer deploy
|
|
78
83
|
|
|
79
84
|
This command will start deployment recursively searching for sfdc project source folder "src" and using the first found for deployment.
|
|
80
|
-
|
|
85
|
+
|
|
86
|
+
*NOTE: "src" folder must contain a valid package.xml file intended to be used for deployment.*
|
|
81
87
|
|
|
82
88
|
|
|
83
89
|
## Configuration
|
|
@@ -107,29 +113,42 @@ a template content:
|
|
|
107
113
|
security_token: sample_token2
|
|
108
114
|
|
|
109
115
|
#### Where should I place "configuration.yml"?
|
|
110
|
-
It should be in the same directory where
|
|
116
|
+
It should be in the same directory where users call Forcer or inside "forcer_config" folder. First "forcer_config" folder
|
|
111
117
|
is scanned for configuration.yml file, then current directory (if not found in "forcer_config" folder). More about folder
|
|
112
118
|
"forcer_config" at the end of Configuration section.
|
|
113
119
|
|
|
114
|
-
$(master): ls
|
|
120
|
+
$(master): ls -R
|
|
121
|
+
forcer_config
|
|
122
|
+
forcer_config/configuration.yml
|
|
123
|
+
project
|
|
124
|
+
project/src
|
|
125
|
+
...
|
|
126
|
+
|
|
127
|
+
Alternatively users can rely on default (same for all projects) exclude_... configuration files. And
|
|
128
|
+
use only "configuration.yml" for a project without folder "forcer_config":
|
|
129
|
+
|
|
130
|
+
$(master): ls -R
|
|
115
131
|
./configuration.yml
|
|
132
|
+
project
|
|
133
|
+
project/src
|
|
116
134
|
...
|
|
117
135
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
visit wiki pages of this project.
|
|
136
|
+
Each of two methods above allows having separate "configuration.yml" file for each project.
|
|
137
|
+
|
|
138
|
+
*NOTE: If users run Forcer from git repo directory with project files and keep the "configuration.yml"
|
|
139
|
+
outside of "forcer_config", then users should add "configuration.yml" to gitignore. This will help to avoid committing
|
|
140
|
+
sensitive data. For more information on setup and usage of configuration.yml please visit wiki pages of this project.*
|
|
124
141
|
|
|
125
|
-
|
|
142
|
+
## Excluding certain metadata from deployment
|
|
126
143
|
Forcer is a flexible tool that allows developers:
|
|
127
144
|
|
|
128
|
-
|
|
145
|
+
### Exclude components (metadata files) and even whole folders from deployment. For example object Idea.object (excluded by default) usually fails deployments.
|
|
146
|
+
|
|
147
|
+
#### How to exclude components and whole directories from deployment?
|
|
148
|
+
It is possible to make Forcer exclude components and directories by adding name of a "to-be-excluded"
|
|
149
|
+
component/directory into "exclude_components.yml" configuration file. _This will make Forcer skip the entire
|
|
150
|
+
component/directory from deployment._
|
|
129
151
|
|
|
130
|
-
#### How to exclude components and and whole directories from deployment?
|
|
131
|
-
Name of the file is "exclude_components.yml".
|
|
132
|
-
|
|
133
152
|
#### "exclude_components.yml" contains:
|
|
134
153
|
|
|
135
154
|
- objects/Idea.object
|
|
@@ -147,11 +166,20 @@ Forcer is a flexible tool that allows developers:
|
|
|
147
166
|
[your_ruby_version_location (like ".../rvm/gems/ruby-[version]")]/gems/forcer-[version]/lib/metadata_services/exclude_components.yml
|
|
148
167
|
|
|
149
168
|
|
|
150
|
-
|
|
169
|
+
### Exclude XML elements from deployment. For example all references to "Social..." layouts (excluded by default) in profiles fail deployments.
|
|
170
|
+
|
|
171
|
+
#### IMPORTANT NOTE! By default XML exclusion works only when deploy to sandboxes. You can force XML exclusion
|
|
172
|
+
when deploying to production using *--forceExclude* flag. Run _forcer help deploy_ to see all options.
|
|
173
|
+
*Excluding XML snippets for production deployment can cause loss of data*. Also be aware if you exclude
|
|
174
|
+
the whole node like field or weblink (assuming that node exists in target org), that node will be preserved
|
|
175
|
+
intact in the target org. But if you skip a sub-node of that parent node (like removing lookupFilter)
|
|
176
|
+
then it considered as modifying existing node and that node will be overwritten in target org. So
|
|
177
|
+
if you cannot deploy part of node it might be a good idea to skip deployment of whole node or file.
|
|
151
178
|
|
|
152
179
|
#### How to exclude XML elements (snippets) from deployment?
|
|
153
|
-
|
|
154
|
-
|
|
180
|
+
It is possible to make Forcer exclude XML elements/snippets from deployment by adding nokogiri
|
|
181
|
+
search pattern of a "to-be-excluded" XML element/snippet into "exclude_xml_nodes.yml" configuration file.
|
|
182
|
+
_This will make Forcer deploy components but filter our certain undesired XML elements_.
|
|
155
183
|
|
|
156
184
|
#### Sample "exclude_xml_nodes.yml":
|
|
157
185
|
|
|
@@ -210,16 +238,24 @@ apparent what "forcer_config" belongs to what project:
|
|
|
210
238
|
project/src
|
|
211
239
|
...
|
|
212
240
|
|
|
213
|
-
Forcer is designed to be used with
|
|
214
|
-
to gitignore.
|
|
215
|
-
|
|
241
|
+
Forcer is designed to be used with Git. So considering a project directory is in git repo, folder "forcer_config" should be added
|
|
242
|
+
to gitignore. Alternatively if users want to share exclude_... configuration files with other team members,
|
|
243
|
+
then at least every team member should add "/forcer_config/configuration.yml" to gitignore in order to prevent committing sensitive
|
|
244
|
+
authorization information. But in any scenario "forcer_config" can be reused for any branch or Salesforce project on current computer.
|
|
245
|
+
*The idea is to switch to any branch and be able to deploy it using "forcer_config" in current project git directory.*
|
|
246
|
+
|
|
247
|
+
$(master): forcer deploy --dest my_dev_org1
|
|
248
|
+
...
|
|
249
|
+
$(master): git checkout feature_branch1
|
|
250
|
+
$(feature_branch1): forcer deploy --dest my_dev_org2
|
|
251
|
+
...
|
|
216
252
|
|
|
217
253
|
### Command line examples
|
|
218
|
-
If
|
|
254
|
+
If users already filled configuration.yml correctly then deployments are much faster. Here is a sample command to start deployment of a project in current folder:
|
|
219
255
|
|
|
220
256
|
$(master): forcer deploy --dest dest_alias_in_configuration_yml
|
|
221
257
|
|
|
222
|
-
|
|
258
|
+
In case users want to call validation-only request then, since it is part of "deploy" soap call, they need to simply dd flag --checkOnly :
|
|
223
259
|
|
|
224
260
|
$(master): forcer deploy --dest dest_alias_in_configuration_yml --checkOnly
|
|
225
261
|
|
|
@@ -242,11 +278,11 @@ Please note that messages and language can and will change because the app devel
|
|
|
242
278
|
|
|
243
279
|
## Possible problems
|
|
244
280
|
|
|
245
|
-
1. When
|
|
246
|
-
"em-http-request". If
|
|
247
|
-
solution is
|
|
281
|
+
1. When test run Forcer on ruby version 2.1.5 on Ubuntu, the app threw exception about missing library
|
|
282
|
+
"em-http-request". If installed ruby version is 2.1.5 and dependencies cannot be resolved, probably the simplest
|
|
283
|
+
solution is to switch ruby version to 2.1.2 or 2.2.0 or later.
|
|
248
284
|
2. openssl library version 1.0.2 on Mac OS (maybe other platforms too) has problems with ruby 2.2.0 when deploy larger
|
|
249
|
-
zip-files.
|
|
285
|
+
zip-files. These are steps to fix the issue on Mac OS:
|
|
250
286
|
|
|
251
287
|
$(master): brew update
|
|
252
288
|
$(master): brew uninstall openssl
|
|
@@ -255,8 +291,9 @@ zip-files. In order to fix please follow steps:
|
|
|
255
291
|
$(master): rvm remove 2.2.0
|
|
256
292
|
$(master): rvm install 2.2.0 --with-openssl-dir=`brew --prefix openssl`
|
|
257
293
|
|
|
258
|
-
3. Most probably users will make multiple attempts before the very first deployment succeeds.
|
|
259
|
-
numerous specific features in metadata deployment. And users of Forcer
|
|
294
|
+
3. Most probably users will have to make multiple attempts before the very first deployment succeeds.
|
|
295
|
+
The reason is Salesforce has numerous specific features in metadata deployment. And users of Forcer
|
|
296
|
+
gem will have to:
|
|
260
297
|
|
|
261
298
|
* skip/remove certain components from deployment (manually or using exclude_components.xml)
|
|
262
299
|
* filter out certain XML elements from deployment (manually or using exclude_xml_nodes.xml)
|
|
@@ -265,16 +302,14 @@ numerous specific features in metadata deployment. And users of Forcer gem will
|
|
|
265
302
|
find . -type f -name '*.profile' -exec sed -i '' s/username_org1/username_org2/ {} +
|
|
266
303
|
|
|
267
304
|
* API version differences between orgs can create issues
|
|
268
|
-
* Salesforce updates can make
|
|
305
|
+
* Salesforce updates can make current project folder undeployable sometimes
|
|
269
306
|
* other problems requiring modification of XML files
|
|
270
307
|
|
|
271
308
|
4. Contributors may encounter problems with bundler and code-climate if run rspec. The easiest solution is to comment out
|
|
272
309
|
these lines in file spec_helper.rb :
|
|
273
310
|
|
|
274
|
-
if Gem.available?("codeclimate-test-reporter")
|
|
275
311
|
require "codeclimate-test-reporter"
|
|
276
312
|
CodeClimate::TestReporter.start
|
|
277
|
-
end
|
|
278
313
|
|
|
279
314
|
|
|
280
315
|
## Contributing
|
data/lib/forcer/version.rb
CHANGED
data/lib/forcer_main.rb
CHANGED
|
@@ -15,6 +15,8 @@ module Forcer
|
|
|
15
15
|
"current project directory. Please read project documentation on github for more information."
|
|
16
16
|
|
|
17
17
|
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 :source."
|
|
18
|
+
option :forceExclude, :type => :boolean, :desc => "To turn ON all xml exclusion for Production, set --forcerExclude to TRUE"
|
|
19
|
+
option :skipExclude, :type => :boolean, :desc => "To turn OFF absolutely all exclusions (package.mxl too), set --skipExclude to TRUE"
|
|
18
20
|
option :checkOnly, :type => :boolean, :aliases => :c, :desc => "Only validates without actual deployment. Default is FALSE."
|
|
19
21
|
option :rollbackOnError, :type => :boolean, :aliases => :b, :desc => "Rolls back whole deployment if error occurs. Default is TRUE."
|
|
20
22
|
option :runAllTests, :type => :boolean, :aliases => :t, :desc => "Make all unit tests run. Default if FALSE. For production deployment it is always true."
|
|
@@ -85,6 +85,7 @@ module Metadata
|
|
|
85
85
|
|
|
86
86
|
deploy_request_xml = File.read(File.dirname(__FILE__) + "/deploy_request.xml");
|
|
87
87
|
xml_param = deploy_request_xml % [debug_options_snippet, @current_session_id, blob_zip, deploy_options_snippet]
|
|
88
|
+
p "Uploading project zip file. This may take a while."
|
|
88
89
|
response = @metadata_client.call(:deploy, :xml => xml_param)
|
|
89
90
|
# todo catch exceptions
|
|
90
91
|
|
|
@@ -13,11 +13,7 @@ module Metadata
|
|
|
13
13
|
def initialize(args = {})
|
|
14
14
|
@args = args
|
|
15
15
|
@output_file_name = tempfile_name("zip")
|
|
16
|
-
@files_to_exclude = Set.new()
|
|
17
|
-
@snippets_to_exclude = {}
|
|
18
16
|
find_source_dir
|
|
19
|
-
prepare_files_to_exclude
|
|
20
|
-
prepare_xml_nodes_to_exclude
|
|
21
17
|
end
|
|
22
18
|
|
|
23
19
|
# copy files from original directory to be xml_filtered when creating zip
|
|
@@ -35,7 +31,6 @@ module Metadata
|
|
|
35
31
|
|
|
36
32
|
entries = dir_content(@input_dir_name)
|
|
37
33
|
p "excluding specified components from deployment"
|
|
38
|
-
p "filtering deployment files removing specified XML elements"
|
|
39
34
|
write_entries(entries, "")
|
|
40
35
|
ensure
|
|
41
36
|
@zip_io.close # close before deleting tmpdir, or NOT_FOUND exception
|
|
@@ -94,6 +89,7 @@ module Metadata
|
|
|
94
89
|
|
|
95
90
|
# Opens file. Removes all bad xml snippets. Rewrites results back into original file
|
|
96
91
|
def filter_xml(filename)
|
|
92
|
+
prepare_xml_nodes_to_exclude if @snippets_to_exclude.nil?
|
|
97
93
|
doc = Nokogiri::XML(File.read(filename))
|
|
98
94
|
file_modified = false
|
|
99
95
|
@snippets_to_exclude.each do |suffix, expressions|
|
|
@@ -119,7 +115,7 @@ module Metadata
|
|
|
119
115
|
entries.each do |entry|
|
|
120
116
|
# need relative local file path to use in new zip file too
|
|
121
117
|
zip_file_path = (path == "" ? entry : File.join(path, entry)) # maybe without if/else
|
|
122
|
-
next if
|
|
118
|
+
next if exclude_file?(zip_file_path.downcase)
|
|
123
119
|
|
|
124
120
|
# need full file path to use in copy/paste
|
|
125
121
|
disk_file_path = File.join(@input_dir_name, zip_file_path)
|
|
@@ -129,12 +125,22 @@ module Metadata
|
|
|
129
125
|
sub_dir = dir_content(disk_file_path)
|
|
130
126
|
write_entries(sub_dir, zip_file_path)
|
|
131
127
|
else
|
|
132
|
-
filter_xml(disk_file_path)
|
|
128
|
+
filter_xml(disk_file_path) unless xml_exclusion_skipped_for?(disk_file_path)
|
|
133
129
|
@zip_io.add(zip_file_path, disk_file_path)
|
|
134
130
|
end
|
|
135
131
|
end
|
|
136
132
|
end
|
|
137
133
|
|
|
134
|
+
def exclude_file?(filename)
|
|
135
|
+
raise Exception if (filename.nil? or filename.empty?)
|
|
136
|
+
if (@files_to_exclude.nil? or @files_to_exclude.empty?)
|
|
137
|
+
@files_to_exclude = Set.new()
|
|
138
|
+
prepare_files_to_exclude
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
return @files_to_exclude.include?(filename)
|
|
142
|
+
end
|
|
143
|
+
|
|
138
144
|
# Returns array of files for the specified directory (full_path) without current_dir "." and
|
|
139
145
|
# prev directory ".."
|
|
140
146
|
def dir_content(full_path)
|
|
@@ -173,5 +179,28 @@ module Metadata
|
|
|
173
179
|
return false
|
|
174
180
|
end
|
|
175
181
|
end
|
|
182
|
+
|
|
183
|
+
# check if destination server is Production
|
|
184
|
+
def is_production
|
|
185
|
+
return (@args[:host].start_with?("https://login") or @args[:host].start_with?("login"))
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# By default for Production it only processes package.xml and other files
|
|
189
|
+
# (objects, profiles, ...) are ignored (xml exclusions are OFF except package.xml). By default
|
|
190
|
+
# for Sandbox all xml exclusion are turned ON. Package.xml exclusions are OK because they allow
|
|
191
|
+
# skip deployment of certain objects/files.
|
|
192
|
+
# To turn ON all xml exclusion for Production, set --forcerExclude to TRUE
|
|
193
|
+
# To turn OFF absolutely all exclusions (package.mxl too), set --skipExclude to TRUE
|
|
194
|
+
def xml_exclusion_skipped_for?(full_filename)
|
|
195
|
+
raise Exception if (full_filename.nil? or full_filename.empty?)
|
|
196
|
+
return true if @args[:skipExclude]
|
|
197
|
+
|
|
198
|
+
if full_filename.end_with?("package.xml")
|
|
199
|
+
return false
|
|
200
|
+
else
|
|
201
|
+
return (is_production unless @args[:forceExclude])
|
|
202
|
+
end
|
|
203
|
+
end
|
|
176
204
|
end # class SfdcDirectoryService
|
|
205
|
+
|
|
177
206
|
end # module Metadata
|
|
@@ -7,19 +7,9 @@ module Forcer
|
|
|
7
7
|
# directory can include 'configuration.yml', 'exclude_components.yml', 'exclude_xml_nodes.yml'
|
|
8
8
|
# if directory not found tries to load only configuration.yml from local directory
|
|
9
9
|
def self.load_config(old_options = {})
|
|
10
|
-
options =
|
|
11
|
-
old_options.each do |k, v|
|
|
12
|
-
options.store(k.to_sym, v)
|
|
13
|
-
end
|
|
10
|
+
options = clone_options(old_options)
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
p "config folder not specified or not found"
|
|
17
|
-
options[:configs] = Dir.pwd + "/forcer_config"
|
|
18
|
-
p "config folder in CURRENT DIRECTORY ? => #{Dir.exists?(options[:configs])}"
|
|
19
|
-
else
|
|
20
|
-
p "specified config folder FOUND"
|
|
21
|
-
options[:configs] = File.expand_path(options[:configs], __FILE__)
|
|
22
|
-
end
|
|
12
|
+
verify_config_folder(options)
|
|
23
13
|
|
|
24
14
|
load_login_info(options)
|
|
25
15
|
|
|
@@ -32,43 +22,74 @@ module Forcer
|
|
|
32
22
|
|
|
33
23
|
class << self
|
|
34
24
|
|
|
25
|
+
# Thor restricts options modification. Therefore have to clone hash "options"
|
|
26
|
+
def clone_options(old_options = {})
|
|
27
|
+
options = {}
|
|
28
|
+
old_options.each do |k, v|
|
|
29
|
+
options.store(k.to_sym, v)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
return options
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def verify_config_folder(options = {})
|
|
36
|
+
if options[:configs].nil? || !(Dir.exists?(File.expand_path(options[:configs], __FILE__)))
|
|
37
|
+
p "config folder not specified or not found"
|
|
38
|
+
options[:configs] = Dir.pwd + "/forcer_config"
|
|
39
|
+
p "config folder in CURRENT DIRECTORY ? => #{Dir.exists?(options[:configs])}"
|
|
40
|
+
else
|
|
41
|
+
p "specified config folder FOUND"
|
|
42
|
+
options[:configs] = File.expand_path(options[:configs], __FILE__)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
35
46
|
# attempts to read salesforce org information from forcer_config/configuration.yml
|
|
36
47
|
# if forcer_config/configuration.yml not found, then try configuration.yml in current directory
|
|
37
48
|
def load_login_info(options = {})
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
p "CONFIGURATION.YML with org details FOUND in CONFIG FOLDER"
|
|
41
|
-
config_file_path = File.join(options[:configs], "/configuration.yml")
|
|
42
|
-
options[:login_info_path] = config_file_path
|
|
43
|
-
else
|
|
44
|
-
p "loading CONFIGURATION.YML from CURRENT DIRECTORY"
|
|
45
|
-
config_file_path = File.join(Dir.pwd, "/configuration.yml")
|
|
46
|
-
end
|
|
50
|
+
config_file_path = get_config_file_path(options)
|
|
47
51
|
|
|
52
|
+
# don't raise exception and let user enter all necessary information
|
|
48
53
|
return options unless File.exists?(config_file_path)
|
|
49
54
|
|
|
50
|
-
|
|
55
|
+
destination_org = options[:dest]
|
|
51
56
|
configuration = YAML.load_file(config_file_path).to_hash
|
|
52
57
|
|
|
53
|
-
return options if configuration[
|
|
58
|
+
return options if configuration[destination_org].nil?
|
|
54
59
|
|
|
55
|
-
configuration[
|
|
60
|
+
configuration[destination_org].each do |key, value|
|
|
56
61
|
options.store(key.to_sym, value.to_s) unless value.to_s.empty?
|
|
57
62
|
end
|
|
63
|
+
|
|
58
64
|
options[:host] = "https://#{options[:host]}" unless options[:host].include?("http")
|
|
59
|
-
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# defines which configuration.yml to use for authentication. Preference is to save configuration.yml
|
|
68
|
+
# in folder 'forcer_config' which itself should be placed in project git repo directory
|
|
69
|
+
def get_config_file_path(options = {})
|
|
70
|
+
config_file_path = File.join(options[:configs], "/configuration.yml")
|
|
71
|
+
|
|
72
|
+
if File.exists?(config_file_path)
|
|
73
|
+
p "CONFIGURATION.YML with org details FOUND in CONFIG FOLDER"
|
|
74
|
+
options[:login_info_path] = config_file_path
|
|
75
|
+
else
|
|
76
|
+
p "loading CONFIGURATION.YML from CURRENT DIRECTORY"
|
|
77
|
+
config_file_path = File.join(Dir.pwd, "/configuration.yml")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return config_file_path
|
|
81
|
+
end
|
|
60
82
|
|
|
61
83
|
|
|
62
84
|
# add absolute paths to exclude_... files from focer_config directory
|
|
63
85
|
def add_exclude_paths(options = {})
|
|
86
|
+
return if (options[:configs].nil?)
|
|
64
87
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
end
|
|
88
|
+
exclude_components_path = File.join(options[:configs], "/exclude_components.yml")
|
|
89
|
+
options[:exclude_components] = exclude_components_path if File.exists?(exclude_components_path)
|
|
68
90
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
end
|
|
91
|
+
exclude_xml_path = File.join(options[:configs], "/exclude_xml_nodes.yml")
|
|
92
|
+
options[:exclude_xml] = exclude_xml_path if File.exists?(exclude_xml_path)
|
|
72
93
|
end
|
|
73
94
|
|
|
74
95
|
end # class << self
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: forcer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- gaziz tazhenov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-08-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: savon
|
|
@@ -134,6 +134,8 @@ files:
|
|
|
134
134
|
- ".gitignore"
|
|
135
135
|
- ".idea/.name"
|
|
136
136
|
- ".idea/.rakeTasks"
|
|
137
|
+
- ".idea/codeStyleSettings.xml"
|
|
138
|
+
- ".idea/dictionaries/gaziz.xml"
|
|
137
139
|
- ".idea/encodings.xml"
|
|
138
140
|
- ".idea/forcer.iml"
|
|
139
141
|
- ".idea/misc.xml"
|
|
@@ -181,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
181
183
|
version: '0'
|
|
182
184
|
requirements: []
|
|
183
185
|
rubyforge_project:
|
|
184
|
-
rubygems_version: 2.4.
|
|
186
|
+
rubygems_version: 2.4.6
|
|
185
187
|
signing_key:
|
|
186
188
|
specification_version: 4
|
|
187
189
|
summary: '"facilitates change management for dev teams who use force.com and git"'
|