fulmar 2.1.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 48f13381dfd883f6eb5f0c44a15aae30a4625914
4
- data.tar.gz: 52c89009ba658dc348df94c69e47940afd99f76b
3
+ metadata.gz: 6a8c600aba68edc3253bda3a138e56d76b38a283
4
+ data.tar.gz: 82c43b52167c6b2b478bf75b25a28697d72316d5
5
5
  SHA512:
6
- metadata.gz: 34b44d1c3f492b53a15b8481d11d9bb33fde77a17e51ae2a72fb25f5560ee856f985ff84e96123c4306e976b6d18cdec949c11e259fe12cb8b8b836c37d80a0d
7
- data.tar.gz: 1717d95355ec5ed3800809f2712477872f72380525f7d8b1132ab9a4fab522af94581613d12e3bf1192287ce72787b7f2ff5fa27baf469d7c0f0d4e8695c04ec
6
+ metadata.gz: 2738a4ead46f2ea844230efb8466d78c97150396eac1f1f7d74f7064c60f2e2532b69cf724b6212e247094fc839652397cf5575605af24acb893dc1ca387b1ef
7
+ data.tar.gz: 8295d787803f53c9e6d470ae1d4259f576f5bd20abdefc2e327cd3ca76c7faa4813d531301ef1f34e11b3b6151b2254d1d92cadffb2c697b5805252a3a313e84
data/README.md CHANGED
@@ -292,6 +292,34 @@ before calling file_sync.publish to create the symlink (current => releases/2015
292
292
  As you probably figured out, your webserver uses the "current" symlink to get the base directory of your web
293
293
  application. Here, you would point it to /tmp/current/public or something like that.
294
294
 
295
+ ### Custom versioning
296
+
297
+ When deploying via Gitlab CI, the current branch or tag is available in the environment variable `CI_COMMIT_REF_NAME`. You very likely want to use tags here and set something like
298
+
299
+ ```yaml
300
+ only:
301
+ - /^live_\d+\.\d+.\d+/
302
+ ```
303
+
304
+ in your .gitlab-ci.yaml. This way, whenever you tag something with e.g. "live_1.2.0" and push it, a deployment will trigger. Fulmar can be configured to read the content of an environment variable and use that as
305
+ the version name. So you can add `version_name` to your config and set it to the gitlab env variable:
306
+
307
+ ```yaml
308
+ environments:
309
+ all:
310
+ local_path: .
311
+ my_server:
312
+ files:
313
+ hostname: my-ssh-server
314
+ remote_path: /tmp
315
+ type: rsync_with_versions
316
+ shared:
317
+ - data
318
+ version_name: CI_COMMIT_REF_NAME
319
+ ```
320
+
321
+ This way, fulmar will call the release "live_1.2.0" instead of the current timestamp.
322
+
295
323
  ### Configuration templates
296
324
 
297
325
  Sometimes you need different versions of files on your different environments. An exmaple might be the .htaccess file.
@@ -8,7 +8,7 @@ module Fulmar
8
8
  class Application < Rake::Application
9
9
  def initialize
10
10
  super
11
- @rakefiles = %w(fulmarfile Fulmarfile fulmarfile.rb Fulmarfile.rb)
11
+ @rakefiles = %w[fulmarfile Fulmarfile fulmarfile.rb Fulmarfile.rb]
12
12
  end
13
13
 
14
14
  def name
@@ -71,13 +71,13 @@ module Fulmar
71
71
  end
72
72
  ]
73
73
  options << [
74
- '--debug',
75
- nil,
76
- 'Run in debug mode.',
77
- lambda do |_value|
78
- configuration = Fulmar::Domain::Service::ConfigurationService.instance
79
- configuration.debug = true
80
- end
74
+ '--debug',
75
+ nil,
76
+ 'Run in debug mode.',
77
+ lambda do |_value|
78
+ configuration = Fulmar::Domain::Service::ConfigurationService.instance
79
+ configuration.debug = true
80
+ end
81
81
  ]
82
82
  options
83
83
  end
@@ -29,8 +29,8 @@ module Fulmar
29
29
  if ready?
30
30
  @data[:environments][@environment][@target][id] = value
31
31
  else
32
- fail 'Environment or target not set. Please set both variables via configuration.environment = \'xxx\' / '\
33
- 'configuration.target = \'yyy\''
32
+ raise 'Environment or target not set. Please set both variables via configuration.environment = \'xxx\' / '\
33
+ 'configuration.target = \'yyy\''
34
34
  end
35
35
  end
36
36
 
@@ -50,8 +50,8 @@ module Fulmar
50
50
  # Checks if environment and target are set
51
51
  def ready?
52
52
  return false if @environment.nil? || @target.nil?
53
- fail 'Environment is invalid' if @data[:environments][@environment].nil?
54
- fail 'Target is invalid' if @data[:environments][@environment][@target].nil?
53
+ raise 'Environment is invalid' if @data[:environments][@environment].nil?
54
+ raise 'Target is invalid' if @data[:environments][@environment][@target].nil?
55
55
  true
56
56
  end
57
57
 
@@ -14,11 +14,11 @@ module Fulmar
14
14
  end
15
15
 
16
16
  def target_test(name, &block)
17
- @tests[name] = Proc.new do
17
+ @tests[name] = proc do
18
18
  results = []
19
19
  @config.each do |env, target, _data|
20
20
  @config.set env, target
21
- result = block.call(@config)
21
+ result = yield(@config)
22
22
  if result
23
23
  result[:message] = "in [#{env}:#{target}]: #{result[:message]}"
24
24
  results << result
@@ -2,7 +2,7 @@ target_test 'hostname is set' do |config|
2
2
  if config[:hostname].blank? && !config[:host].blank?
3
3
  next {
4
4
  severity: :warning,
5
- message: "config has a host (#{[:host]}) but is missing a hostname"
5
+ message: "config has a host (#{config[:host]}) but is missing a hostname"
6
6
  }
7
7
  end
8
8
  end
@@ -16,8 +16,8 @@ target_test 'hostnames in ssh config' do |config|
16
16
  end
17
17
 
18
18
  target_test 'required hostnames' do |config|
19
- types = %i(rsync rsync_with_version maria)
19
+ types = %i[rsync rsync_with_version maria]
20
20
  if types.include?(config[:type]) && config[:hostname].blank?
21
- next {severity: :error, message: "config requires a hostname (#{config[:hostname]})"}
21
+ next { severity: :error, message: "config requires a hostname (#{config[:hostname]})" }
22
22
  end
23
23
  end
@@ -1,5 +1,4 @@
1
- relevant_options = [:rsync, :local_path, :remote_path, :host, :hostname, :shared, :templates,
2
- :ssh_config, :type]
1
+ relevant_options = %i[rsync local_path remote_path host hostname shared templates ssh_config type]
3
2
  relevant_options.each do |option|
4
3
  target_test "empty configuration settings #{option}" do |config|
5
4
  if config.key?(option) && config[option].nil?
@@ -8,8 +8,8 @@ target_test 'local path exists' do |config|
8
8
  end
9
9
 
10
10
  target_test 'remote_path is set' do |config|
11
- types = %w(rsync rsync_with_version)
11
+ types = %w[rsync rsync_with_version]
12
12
  if types.include?(config[:type]) && config[:remote_path].blank?
13
- next {severity: :error, message: 'config is missing a remote path for rsync'}
13
+ next { severity: :error, message: 'config is missing a remote path for rsync' }
14
14
  end
15
15
  end
@@ -1,5 +1,8 @@
1
1
  global_test 'project name is set' do |config|
2
- next {severity: :warning,
3
- message: 'Project name is not set (must be short, no spaces)'
4
- } if config.project.name.blank?
2
+ if config.project.name.blank?
3
+ next {
4
+ severity: :warning,
5
+ message: 'Project name is not set (must be short, no spaces)'
6
+ }
7
+ end
5
8
  end
@@ -17,7 +17,7 @@ module Fulmar
17
17
  else
18
18
  help = config[:type] == '' ? 'Add a "type: " field to your deployment yaml file. ' : ''
19
19
  transfer_model = nil
20
- fail "Transfer type '#{config[:type]}' is not valid. #{help}Valid values are: rsync, rsync_with_versions."
20
+ raise "Transfer type '#{config[:type]}' is not valid. #{help}Valid values are: rsync, rsync_with_versions."
21
21
  end
22
22
 
23
23
  transfer_model
@@ -58,7 +58,7 @@ module Fulmar
58
58
  end
59
59
 
60
60
  def storage
61
- fail 'You need to set an environment and a target first' unless config.ready?
61
+ raise 'You need to set an environment and a target first' unless config.ready?
62
62
  @storage ||= {}
63
63
  @storage[config.environment] ||= {}
64
64
  @storage[config.environment][config.target] ||= {}
@@ -17,8 +17,8 @@ module Fulmar
17
17
  config = ConfigurationService.instance.configuration
18
18
 
19
19
  if config.plugins.class == Array
20
- fail 'Plugin list must not be an array. Have a look at https://github.com/CORE4/fulmar#plugins for ' +
21
- 'more information'
20
+ raise 'Plugin list must not be an array. Have a look at https://github.com/CORE4/fulmar#plugins for ' +
21
+ 'more information'
22
22
  end
23
23
 
24
24
  config.plugins.each_pair do |name, plugin_config|
@@ -22,8 +22,8 @@ module Fulmar
22
22
 
23
23
  def template_path(template_file)
24
24
  template = "#{@config[:local_path]}/#{template_file}"
25
- fail "Template filenames must end in .erb - '#{template}' does not" unless template[-4, 4] == '.erb'
26
- fail "Cannot render missing config file '#{template}'" unless File.exist? template
25
+ raise "Template filenames must end in .erb - '#{template}' does not" unless template[-4, 4] == '.erb'
26
+ raise "Cannot render missing config file '#{template}'" unless File.exist? template
27
27
  template
28
28
  end
29
29
  end
@@ -13,7 +13,7 @@ module Fulmar
13
13
  remote_path: nil,
14
14
  local_path: '.',
15
15
  type: :rsync_with_versions
16
- }
16
+ }.freeze
17
17
 
18
18
  attr_accessor :config
19
19
 
@@ -31,9 +31,9 @@ module Fulmar
31
31
 
32
32
  # Test the supplied config for required parameters
33
33
  def test_config
34
- required = [:host, :remote_path, :local_path]
35
- required.each { |key| fail "Configuration is missing required setting '#{key}'." if @config.blank? }
36
- fail ':remote_path must be absolute' if @config[:remote_path][0, 1] != '/'
34
+ required = %i[host remote_path local_path]
35
+ required.each { |key| raise "Configuration is missing required setting '#{key}'." if @config.blank? }
36
+ raise ':remote_path must be absolute' if @config[:remote_path][0, 1] != '/'
37
37
  end
38
38
 
39
39
  def prepare
@@ -27,7 +27,7 @@ module Fulmar
27
27
  @config[:rsync][:exclude_file] = @config[:local_path] + '/.rsyncignore'
28
28
  end
29
29
 
30
- fail 'Hostname not set. Cannot initialize sync.' if @config[:hostname].nil? || @config[:hostname].empty?
30
+ raise 'Hostname not set. Cannot initialize sync.' if @config[:hostname].nil? || @config[:hostname].empty?
31
31
 
32
32
  super(@config)
33
33
  end
@@ -12,8 +12,8 @@ module Fulmar
12
12
  # Every deployment results in a new directory in the releases directory with the deployment time as
13
13
  # the folder name. A symlink 'current' points to this new directory after publish() is called.
14
14
  class RsyncWithVersions < Base
15
- TIME_FOLDER = '%Y-%m-%d_%H%M%S'
16
- TIME_READABLE = '%Y-%m-%d %H:%M:%S'
15
+ TIME_FOLDER = '%Y-%m-%d_%H%M%S'.freeze
16
+ TIME_READABLE = '%Y-%m-%d %H:%M:%S'.freeze
17
17
 
18
18
  DEFAULT_CONFIG = {
19
19
  temp_dir: 'temp',
@@ -28,8 +28,9 @@ module Fulmar
28
28
  },
29
29
  symlinks: {},
30
30
  limit_releases: 5,
31
+ version_name: Time.now.strftime('%Y-%m-%d_%H%M%S'),
31
32
  shared: []
32
- }
33
+ }.freeze
33
34
 
34
35
  # @param [Fulmar::Domain::Service::ConfigurationService] config
35
36
  def initialize(config)
@@ -40,8 +41,6 @@ module Fulmar
40
41
  if @config[:rsync][:exclude_file].blank? && File.exist?(@config[:local_path] + '/.rsyncignore')
41
42
  @config[:rsync][:exclude_file] = @config[:local_path] + '/.rsyncignore'
42
43
  end
43
-
44
- @release_time = Time.now
45
44
  end
46
45
 
47
46
  # Ensures all needed services are set up
@@ -49,6 +48,10 @@ module Fulmar
49
48
  super
50
49
  @remote_shell = Fulmar::Shell.new @config[:remote_path], @config.ssh_user_and_host
51
50
  @remote_shell.debug = @config[:debug]
51
+
52
+ if /^[A-Z][A-Z0-9\-_]+$/ =~ @config[:version_name]
53
+ @config[:version_name] = ENV[@config[:version_name]].split('/').last
54
+ end
52
55
  end
53
56
 
54
57
  # Copy the files via rsync to the release_path on the remote machine
@@ -56,10 +59,10 @@ module Fulmar
56
59
  def transfer
57
60
  prepare unless @prepared
58
61
 
59
- fail 'Deployment failed when trying to prepare remote directories for sync.' unless create_paths
60
- fail 'Deployment failed. Cannot sync files.' unless @local_shell.run(rsync_command)
61
- fail 'Deployment failed when trying to move file from temporary upload dir.' unless copy_temp_to_release
62
- fail 'Deployment failed when creating symlinks for shared folders' unless add_shared
62
+ raise 'Deployment failed when trying to prepare remote directories for sync.' unless create_paths
63
+ raise 'Deployment failed. Cannot sync files.' unless @local_shell.run(rsync_command)
64
+ raise 'Deployment failed when trying to move file from temporary upload dir.' unless copy_temp_to_release
65
+ raise 'Deployment failed when creating symlinks for shared folders' unless add_shared
63
66
  end
64
67
 
65
68
  # Publishes the current release (i.e. sets the 'current' symlink)
@@ -78,7 +81,7 @@ module Fulmar
78
81
  # Gets the currently generated release directory
79
82
  # @return [String] the release directory
80
83
  def release_dir
81
- @config[:releases_dir] + '/' + @release_time.strftime('%Y-%m-%d_%H%M%S')
84
+ @config[:releases_dir] + '/' + @config[:version_name]
82
85
  end
83
86
 
84
87
  # Lists the existing releases on the remote machine
@@ -86,13 +89,17 @@ module Fulmar
86
89
  # @return [Array] list of dirs or dates/times
87
90
  def list_releases(plain = true)
88
91
  prepare unless @prepared
89
- @remote_shell.run "ls -1 '#{@config[:releases_dir]}'"
90
- list = @remote_shell.last_output.select { |dir| dir.match(/^\d{4}-\d{2}-\d{2}_\d{6}/) }
92
+ @remote_shell.run "ls -1tr '#{@config[:releases_dir]}'"
93
+ list = @remote_shell.last_output
91
94
  return list if plain
92
95
 
93
96
  current = current_release
94
97
  list.collect do |item|
95
- Time.strptime(item, TIME_FOLDER).strftime(TIME_READABLE) + (item == current ? ' *' : '')
98
+ if item =~ /^\d{4}-\d{2}-\d{2}_\d{6}/
99
+ Time.strptime(item, TIME_FOLDER).strftime(TIME_READABLE) + (item == current ? ' *' : '')
100
+ else
101
+ item + (item == current ? ' *' : '')
102
+ end
96
103
  end
97
104
  end
98
105
 
@@ -101,7 +108,7 @@ module Fulmar
101
108
  def cleanup
102
109
  limit = @config[:limit_releases].to_i
103
110
  return true unless limit > 0
104
- releases = list_releases.sort
111
+ releases = list_releases
105
112
  return true if releases.length <= limit
106
113
  obsolete_dirs = releases[0, releases.length - limit].collect { |dir| "\"#{@config[:releases_dir]}/#{dir}\"" }
107
114
  @remote_shell.run "rm -fr #{obsolete_dirs.join(' ')}"
@@ -124,7 +131,7 @@ module Fulmar
124
131
  return false if release.nil?
125
132
 
126
133
  # Convenience: Allow more readable version string from output
127
- if release.match(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)
134
+ if release =~ /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/
128
135
  release = Time.strptime(item, TIME_READABLE).strftime(TIME_FOLDER)
129
136
  end
130
137
 
@@ -136,15 +143,15 @@ module Fulmar
136
143
  def last_release
137
144
  list = list_releases
138
145
  current = current_release
139
- current_index = list.index(current)
140
- (current_index.nil? || current_index == 0) ? nil : list[current_index - 1]
146
+ current_index = list.index(current).to_i
147
+ current_index.zero? ? nil : list[current_index - 1]
141
148
  end
142
149
 
143
150
  # Creates all necessary paths on the remote machine
144
151
  # @return [true, false] success
145
152
  def create_paths
146
153
  paths = [@config[:releases_dir], @config[:temp_dir], @config[:shared_dir]]
147
- @remote_shell.run paths.collect { |path| "mkdir -p '#{@config[:remote_path]}/#{path}'" }
154
+ @remote_shell.run(paths.collect { |path| "mkdir -p '#{@config[:remote_path]}/#{path}'" })
148
155
  end
149
156
 
150
157
  def rsync_excludes
@@ -156,7 +163,7 @@ module Fulmar
156
163
  # Builds the rsync command
157
164
  # @return [String] the command
158
165
  def rsync_command
159
- options = %w(-rl --delete-excluded)
166
+ options = %w[-rl --delete-excluded]
160
167
  options << rsync_excludes if rsync_excludes
161
168
  options << "--exclude-from='#{@config[:rsync][:exclude_file]}'" if @config[:rsync][:exclude_file]
162
169
  options << "--chown='#{@config[:rsync][:chown]}'" if @config[:rsync][:chown]
@@ -8,8 +8,8 @@ module Fulmar
8
8
  module Service
9
9
  # Adds entries to the ssh config and checks for existing ones
10
10
  class SSHConfigService
11
- DEFAULT_CONFIG_FILE = "#{ENV['HOME']}/.ssh/config"
12
- DEFAULT_KNOWN_HOSTS_FILE = "#{ENV['HOME']}/.ssh/known_hosts"
11
+ DEFAULT_CONFIG_FILE = "#{ENV['HOME']}/.ssh/config".freeze
12
+ DEFAULT_KNOWN_HOSTS_FILE = "#{ENV['HOME']}/.ssh/known_hosts".freeze
13
13
 
14
14
  attr_accessor :config_file, :known_host_file, :quiet
15
15
 
@@ -55,7 +55,7 @@ module Fulmar
55
55
  input_file = File.open(@known_hosts_file, 'r')
56
56
  output_file = File.open(@known_hosts_file + '.temp', 'w')
57
57
  while (line = input_file.gets)
58
- output_file.puts(line) unless /^\[?#{hostname.gsub('.', '\\.')}(?:\]:\d+)?[ ,]/.match(line)
58
+ output_file.puts(line) unless /^\[?#{hostname.gsub('.', '\\.')}(?:\]:\d+)?[ ,]/ =~ line
59
59
  end
60
60
  input_file.close
61
61
  output_file.close
@@ -77,7 +77,7 @@ module Fulmar
77
77
  def host_exists?(hostname)
78
78
  config_file = File.open(@config_file, 'r')
79
79
  while (line = config_file.gets)
80
- if /\s*Host #{hostname.gsub('.', '\\.')}\s*$/.match(line)
80
+ if /\s*Host #{hostname.gsub('.', '\\.')}\s*$/ =~ line
81
81
  config_file.close
82
82
  return true
83
83
  end
@@ -91,7 +91,7 @@ module Fulmar
91
91
  puts "Adding host #{hostname}..." if @config[:debug]
92
92
  config_file = File.open(@config_file, 'a')
93
93
 
94
- unless ssh_config[:IdentityFile].blank? or ssh_config[:IdentityFile][0, 1] == '/'
94
+ unless ssh_config[:IdentityFile].blank? || ssh_config[:IdentityFile][0, 1] == '/'
95
95
  ssh_config[:IdentityFile] = @config.base_path + '/' + ssh_config[:IdentityFile]
96
96
  end
97
97
 
@@ -108,7 +108,7 @@ module Fulmar
108
108
  protected
109
109
 
110
110
  def host_entry(hostname, ssh_config = {})
111
- unless ssh_config[:IdentityFile].blank? or ssh_config[:IdentityFile][0, 1] == '/'
111
+ unless ssh_config[:IdentityFile].blank? || ssh_config[:IdentityFile][0, 1] == '/'
112
112
  ssh_config[:IdentityFile] = @config.base_path + '/' + ssh_config[:IdentityFile]
113
113
  end
114
114
 
@@ -142,9 +142,7 @@ module Fulmar
142
142
  end
143
143
 
144
144
  def remove_trailing_newlines(data)
145
- while !data.empty? && data.last.strip.empty?
146
- data.pop
147
- end
145
+ data.pop while !data.empty? && data.last.strip.empty?
148
146
  data
149
147
  end
150
148
 
@@ -155,9 +153,7 @@ module Fulmar
155
153
  if line.strip[0] == '#'
156
154
  cache << line
157
155
  else
158
- if /^Host\s#{hostname}$/.match line.strip
159
- return remove_trailing_newlines(before)
160
- end
156
+ return remove_trailing_newlines(before) if /^Host\s#{hostname}$/ =~ line.strip
161
157
  before += cache
162
158
  cache = []
163
159
  before << line
@@ -178,9 +174,7 @@ module Fulmar
178
174
  if line.strip[0] == '#'
179
175
  cache << line
180
176
  else
181
- if /^Host\s/.match line.strip
182
- write = true
183
- end
177
+ write = true if /^Host\s/ =~ line.strip
184
178
  if write
185
179
  after += cache
186
180
  after << line
@@ -1,4 +1,4 @@
1
1
  # Provides a global version number
2
2
  module Fulmar
3
- VERSION = '2.1.2'
3
+ VERSION = '2.2.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fulmar
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Siegl
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-08-10 00:00:00.000000000 Z
12
+ date: 2017-09-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
181
  version: '0'
182
182
  requirements: []
183
183
  rubyforge_project:
184
- rubygems_version: 2.6.11
184
+ rubygems_version: 2.6.13
185
185
  signing_key:
186
186
  specification_version: 4
187
187
  summary: A deployment task manager.