forcer 0.4.1 → 0.4.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/forcer.svg)](http://badge.fury.io/rb/forcer)
|
3
|
+
[![Build Status](https://travis-ci.org/gazazello/forcer.svg?branch=master)](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
|