pulsar 1.0.0 → 1.1.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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +282 -9
  4. data/circle.yml +56 -11
  5. data/lib/pulsar.rb +3 -1
  6. data/lib/pulsar/cli.rb +29 -4
  7. data/lib/pulsar/context_error.rb +7 -0
  8. data/lib/pulsar/interactors/add_applications.rb +5 -7
  9. data/lib/pulsar/interactors/cleanup.rb +1 -0
  10. data/lib/pulsar/interactors/clone_repository.rb +3 -8
  11. data/lib/pulsar/interactors/copy_environment_file.rb +15 -11
  12. data/lib/pulsar/interactors/copy_initial_repository.rb +2 -9
  13. data/lib/pulsar/interactors/create_capfile.rb +14 -9
  14. data/lib/pulsar/interactors/create_deploy_file.rb +3 -8
  15. data/lib/pulsar/interactors/create_run_dirs.rb +1 -0
  16. data/lib/pulsar/interactors/identify_repository_location.rb +2 -9
  17. data/lib/pulsar/interactors/identify_repository_type.rb +2 -8
  18. data/lib/pulsar/interactors/run_bundle_install.rb +3 -9
  19. data/lib/pulsar/interactors/run_capistrano.rb +4 -12
  20. data/lib/pulsar/organizers/{deploy.rb → task.rb} +1 -1
  21. data/lib/pulsar/validator.rb +33 -0
  22. data/lib/pulsar/version.rb +1 -1
  23. data/pulsar.gemspec +2 -2
  24. data/spec/features/task_spec.rb +187 -0
  25. data/spec/spec_helper.rb +1 -6
  26. data/spec/support/coverage_setup.rb +39 -0
  27. data/spec/units/cli/deploy_spec.rb +28 -6
  28. data/spec/units/cli/install_spec.rb +22 -0
  29. data/spec/units/cli/list_spec.rb +23 -1
  30. data/spec/units/cli/task_spec.rb +138 -0
  31. data/spec/units/cli/version_spec.rb +13 -0
  32. data/spec/units/interactors/copy_environment_file_spec.rb +25 -0
  33. data/spec/units/interactors/create_capfile_spec.rb +22 -0
  34. data/spec/units/interactors/run_capistrano_spec.rb +75 -15
  35. data/spec/units/organizers/{deploy_spec.rb → task_spec.rb} +1 -1
  36. data/spec/units/validator_spec.rb +31 -0
  37. metadata +40 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49da97e3127c662682484d2c3339d873a2dc7cea
4
- data.tar.gz: ef831d3995741f3fdee35ff56a6c603f5095e649
3
+ metadata.gz: 7d2e3f41d33d1980ca08e0cfb6ad9a79fa74e8d0
4
+ data.tar.gz: e64cdb54592106c7f5690c71e67c435a260bc566
5
5
  SHA512:
6
- metadata.gz: cad9605fa0f1f5e8564e2aa0620d20dea1c50ca5c766a0d4ae524c370c0a7777137390d78b34e0f26d965cebe5637e3bcd6bec2c2cfeac1ee4d87b36625caac3
7
- data.tar.gz: 4cc0710f834e143f5e0b7969e42f03c76334a001ef5782d3d191e47e6c45be16bdcca89e3f338f938d752629045eb746761b6faf67ed5e99447b248ebb205a61
6
+ metadata.gz: 43c48f2e6c411fefc1650918c782ec4bfc78662743ec1ec3c33a69e7616acf9af4dafa9631af6a8280856b472ae85c8e24a310e725843a550a6b480d0afbf55d
7
+ data.tar.gz: 3c926574265223622a691920c39e86a4b02b9c9b6b6d77d456ee59290f5fdad2defb377ff820831943940a2f8bd72fd65593f28e0566a13ed38c0ba60e09f0fa
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
19
  !tmp/.gitkeep
20
+ coverage/
data/README.md CHANGED
@@ -1,21 +1,294 @@
1
- # Pulsar
1
+ # Pulsar [![Gem Version](https://badge.fury.io/rb/pulsar.svg)](https://badge.fury.io/rb/pulsar) [![CircleCI](https://img.shields.io/circleci/project/github/nebulab/pulsar/master.png)](https://circleci.com/gh/nebulab/pulsar/tree/master) [![Coverage Status](https://coveralls.io/repos/github/nebulab/pulsar/badge.svg?branch=master)](https://coveralls.io/github/nebulab/pulsar?branch=master)
2
2
 
3
- The easy [Capistrano](https://rubygems.org/gems/capistrano) deploy and configuration manager.
3
+ The easy [Capistrano][cap-gem] deploy and configuration manager.
4
4
 
5
- Pulsar allows you to run capistrano tasks via a separate repository where all your deploy configurations are stored.
6
- Once you have your own repository, you can gradully add configurations and recipes so that you never have to duplicate code again.
5
+ Pulsar allows you to run Capistrano tasks via a separate repository where all
6
+ your deploy configurations are stored. Once you have your own repository, you
7
+ can gradually add configurations and recipes so that you never have to duplicate
8
+ code again.
7
9
 
8
- The way Pulsar works means that you can deploy without actually having the application on your local machine (and neither
9
- have all your application dependencies installed). This lets you integrate Pulsar with nearly any deploy strategy you can think of.
10
+ The way Pulsar works means that you can deploy without actually having the
11
+ application on your local machine (and neither have all your application
12
+ dependencies installed). This lets you integrate Pulsar with nearly any deploy
13
+ strategy you can think of.
10
14
 
11
15
  Some of the benefits of using Pulsar:
12
- * No capistrano configurations in the application code
16
+ * No Capistrano configurations in the application code
13
17
  * No need to have the application locally to deploy
14
18
  * Every recipe can be shared between all applications
15
19
  * Can easily be integrated with other tools
16
20
  * Write the least possible code to deploy
17
21
 
22
+ *DISCLAIMER*: Understanding Capistrano is strongly suggested before using
23
+ Pulsar.
24
+
18
25
  ## Capistrano support
19
26
 
20
- This version of Pulsar, version `1.0.0` only supports Capistrano v3. If you're looking for Capistrano v2 support you can
21
- use Pulsar version `0.3.5` but, take care, that version is not maintained anymore.
27
+ This version of Pulsar (version `>= 1.0.0`) only supports Capistrano v3. If
28
+ you're looking for Capistrano v2 support you can use Pulsar version `0.3.5` but,
29
+ take care, that version is not maintained anymore.
30
+
31
+ ## Installation
32
+
33
+ The most useful way of installing Pulsar is as a system gem:
34
+
35
+ ```bash
36
+ $ gem install pulsar
37
+ ```
38
+
39
+ This will install the `pulsar` command which will be used to for everything,
40
+ from running Capistrano to listing your configurations.
41
+
42
+ ---
43
+
44
+ The first thing you'll need to do is to create your own configuration repo:
45
+
46
+ ```bash
47
+ $ pulsar install ~/Desktop/pulsar-conf
48
+ ```
49
+
50
+ This will create a basic starting point for building your configuration
51
+ repository. As soon as you're done configuring you should consider transforming
52
+ this folder to a git repository.
53
+
54
+ You can have a look at how your repository should look like by browsing the
55
+ [Pulsar Conf Demo][pulsar-conf-demo].
56
+
57
+ **NOTE**: Pulsar only supports git.
58
+
59
+ ## Configuration
60
+
61
+ This is an example repository configuration layout:
62
+
63
+ ```bash
64
+ pulsar-conf/
65
+ |── Gemfile
66
+ ├── Gemfile.lock
67
+ ├── apps
68
+ │ ├── Capfile
69
+ │ ├── deploy.rb
70
+ │ └── my_application
71
+ │ ├── Capfile
72
+ │ ├── deploy.rb
73
+ │ ├── production.rb
74
+ │ └── staging.rb
75
+ └── recipes
76
+ ├── generic
77
+ │ ├── maintenance_mode.rake
78
+ │ ├── notify.rake
79
+ │ └── utils.rake
80
+ ├── rails
81
+ │ ├── passenger.rake
82
+ │ ├── repair_permissions.rake
83
+ │ ├── symlink_configs.rake
84
+ │ ├── unicorn.rake
85
+ │ └── whenever.rake
86
+ └── spree_1
87
+ └── symlink_assets.rake
88
+ ```
89
+
90
+ Pulsar uses these files to build Capistrano configurations on the fly, depending
91
+ on how you invoke the `pulsar` command. Since Pulsar it's basically a Capistrano
92
+ wrapper, the content of these files is plain old Capistrano syntax.
93
+
94
+ ### _apps_ directory
95
+
96
+ This directory contains your application configurations. You'll have one
97
+ directory per application.
98
+
99
+ * `Capfile` is the generic Capfile shared by all applications
100
+ * `deploy.rb` has configurations that are shared by all applications
101
+ * `my_application/Capfile` is the Capfile that will be used for this particular
102
+ application
103
+ * `my_application/deploy.rb` includes configuration shared by every stage of the
104
+ application
105
+ * `my_application/staging.rb` and `my_application/production.rb` files include
106
+ stage configurations
107
+
108
+ ### _recipes_ directory
109
+
110
+ This directory contains your recipes. You can create any number of directories
111
+ to organize your recipes. In Capistrano v3 fashion, all the files are plain old
112
+ rake tasks (make sure to name them with the `.rake` extension).
113
+
114
+ The recipes contained in this folder are **always included** in each stage for
115
+ each application.
116
+
117
+ ---
118
+
119
+ Another way to include your recipes is by using the `Gemfile`. Many gems already
120
+ include custom recipes for Capistrano so you just need to require those. An
121
+ example with [Whenever][whenever]:
122
+
123
+ ```ruby
124
+ #
125
+ # Inside Gemfile
126
+ #
127
+ gem 'whenever'
128
+
129
+ #
130
+ # Inside some Capfile (either generic or application specific)
131
+ #
132
+ require 'whenever/capistrano'
133
+
134
+ #
135
+ # Inside some .rb configuration file (either generic or application specific)
136
+ #
137
+ set :whenever_command, "bundle exec whenever"
138
+ ```
139
+
140
+ ### Loading the repository
141
+
142
+ Once the repository is ready, you'll need to tell Pulsar where it is. The
143
+ repository location can be specified either as a full git path or a GitHub
144
+ repository path (*i.e.* `gh-user/pulsar-conf`).
145
+
146
+ Since Pulsar requires the repository for everything, there are multiple ways to
147
+ store this information so that you don't have to type it everytime. You can also
148
+ use local repository, which is useful while developing your deployment.
149
+
150
+ You have three possibilities:
151
+
152
+ * `-c` command line option
153
+ * `PULSAR_CONF_REPO` environment variable
154
+ * `~/.pulsar/config` configuration file
155
+
156
+ The fastest way is probably the `.pulsar/config` file inside your home
157
+ directory:
158
+
159
+ ```bash
160
+ #
161
+ # Inside ~/.pulsar/config
162
+ #
163
+ PULSAR_CONF_REPO="gh-user/pulsar-conf"
164
+
165
+ #
166
+ # You can use local repository for development so you don't need to push changes
167
+ # every time
168
+ #
169
+ # PULSAR_CONF_REPO="/full/path/to/repository"
170
+
171
+ #
172
+ # Also supported
173
+ #
174
+ # PULSAR_CONF_REPO="git://github.com/gh-user/pulsar-conf.git"
175
+ ```
176
+
177
+ Pulsar will read this file and set the environment variables properly.
178
+
179
+ ---
180
+
181
+ If you don't want to add another file to your home directory you can export the
182
+ variables yourself:
183
+
184
+ ```bash
185
+ #
186
+ # Inside ~/.bash_profile or ~/.zshrc
187
+ #
188
+ export PULSAR_CONF_REPO="gh-user/pulsar-conf"
189
+ ```
190
+
191
+ ## Usage
192
+
193
+ After the repository is ready, running Pulsar is straightforward. You can either
194
+ list your applications or build a configuration and run Capistrano on it.
195
+
196
+ ### Deploy
197
+
198
+ Running the `deploy` command really means running Capistrano on a certain
199
+ configuration.
200
+
201
+ To deploy `my_application` to `production`:
202
+
203
+ ```bash
204
+ $ pulsar deploy my_application production
205
+ ```
206
+
207
+ The above command will fetch the Pulsar configuration repository, run
208
+ `bundle install`, combine the generic `Capfile` and `deploy.rb` files with the
209
+ `my_application` specific ones and add specific `production.rb` stage
210
+ configuration. At last it will run `cap deploy` on it.
211
+
212
+ Right now Pulsar does not support tasks other then deploy. Support for running
213
+ other Capistrano taks will come, state tuned!
214
+
215
+ ### Listing applications
216
+
217
+ Pulsar can fetch your configuration repository and list the application and
218
+ stages you can run deploys on:
219
+
220
+ ```bash
221
+ $ pulsar list
222
+ ```
223
+
224
+ This will fetch the Pulsar configuration repository and list everything that's
225
+ inside, like this:
226
+
227
+ ```
228
+ my_application: production, staging
229
+ awesome_startup: dev, production, staging
230
+ ```
231
+
232
+ ### Execute arbitrary Capistrano tasks
233
+
234
+ You can launch any Capistrano task via `task` command. You can also
235
+ pass arguments in _Rake style_ (i.e. via square brackets after task name)
236
+
237
+ ```
238
+ $ pulsar task mycustom:task[argumen1,argument2] my_application staging
239
+ ```
240
+
241
+ or via environment variables.
242
+
243
+ ```
244
+ $ TASK_ARG1=arg1 TASK_ARG2=arg2 pulsar task mycustom:task my_application staging
245
+ ```
246
+
247
+ ## Integrations
248
+
249
+ Pulsar is easy to integrate, you just need access to the configurations
250
+ repository and the ability to run a command.
251
+
252
+ Right now there are no integrations for Pulsar v1 but there are some built for
253
+ the old v0.3 version that can be used as an example.
254
+
255
+ ### Chat Bots
256
+
257
+ - https://gist.github.com/mtylty/5324075: a [hubot][hubot] script that runs
258
+ Pulsar via the command line
259
+ - [hubot-pulsar][hubot-pulsar]: a [hubot][hubot] plugin for integrating via
260
+ [Pulsar REST API][pulsar-rest-api]
261
+ - [lita-pulsar][lita-pulsar]: a [Lita][lita] plugin for integrating via the
262
+ command line
263
+
264
+
265
+ ### Pulsar REST API service
266
+
267
+ [Pulsar REST API][pulsar-rest-api] is a service to provide a REST API for
268
+ executing pulsar jobs.
269
+
270
+ Here is a [real-life example][pulsar-rest-api-blogpost] of how you can integrate
271
+ and simplify your Pulsar workflow.
272
+
273
+ ## About
274
+
275
+ [![Nebulab][nebulab-logo]][nebulab]
276
+
277
+ Pulsar is funded and maintained by the [Nebulab][nebulab] team.
278
+
279
+ We firmly believe in the power of open-source. [Contact us][contact-us] if you
280
+ like our work and you need help with your project design or development.
281
+
282
+ [license]: MIT-LICENSE
283
+ [cap-gem]: https://rubygems.org/gems/capistrano
284
+ [nebulab]: http://nebulab.it/
285
+ [nebulab-logo]: http://nebulab.it/assets/images/public/logo.svg
286
+ [contact-us]: http://nebulab.it/contact-us/
287
+ [pulsar-conf-demo]: http://github.com/nebulab/pulsar-conf-demo
288
+ [whenever]: https://github.com/javan/whenever
289
+ [hubot]: https://hubot.github.com
290
+ [hubot-pulsar]: https://github.com/cargomedia/hubot-pulsar
291
+ [pulsar-rest-api]: https://github.com/cargomedia/pulsar-rest-api
292
+ [pulsar-rest-api-blogpost]: http://www.cargomedia.ch/2015/06/23/pulsar-rest-api.html
293
+ [lita]: https://www.lita.io
294
+ [lita-pulsar]: http://github.com/nebulab/lita-pulsar
data/circle.yml CHANGED
@@ -1,16 +1,61 @@
1
+ machine:
2
+ post:
3
+ - |
4
+ if [[ -e ~/rvm_binaries/ruby-2.0.0-p648.tar.bz2 ]]
5
+ then
6
+ rvm mount ~/rvm_binaries/ruby-2.0.0-p648.tar.bz2
7
+ else
8
+ mkdir -p ~/rvm_binaries
9
+ rvm install 2.0.0 --disable-binary
10
+ cd ~/rvm_binaries && rvm prepare 2.0.0
11
+ fi
12
+ - |
13
+ if [[ -e ~/rvm_binaries/ruby-2.1.10.tar.bz2 ]]
14
+ then
15
+ rvm mount ~/rvm_binaries/ruby-2.1.10.tar.bz2
16
+ else
17
+ mkdir -p ~/rvm_binaries
18
+ rvm install 2.1.10 --disable-binary
19
+ cd ~/rvm_binaries && rvm prepare 2.1.10
20
+ fi
21
+ - |
22
+ if [[ -e ~/rvm_binaries/ruby-2.2.6.tar.bz2 ]]
23
+ then
24
+ rvm mount ~/rvm_binaries/ruby-2.2.6.tar.bz2
25
+ else
26
+ mkdir -p ~/rvm_binaries
27
+ rvm install 2.2.6 --disable-binary
28
+ cd ~/rvm_binaries && rvm prepare 2.2.6
29
+ fi
30
+ - |
31
+ if [[ -e ~/rvm_binaries/ruby-2.3.3.tar.bz2 ]]
32
+ then
33
+ rvm mount ~/rvm_binaries/ruby-2.3.3.tar.bz2
34
+ else
35
+ mkdir -p ~/rvm_binaries
36
+ rvm install 2.3.3 --disable-binary
37
+ cd ~/rvm_binaries && rvm prepare 2.3.3
38
+ fi
39
+ - |
40
+ if [[ -e ~/rvm_binaries/ruby-2.4.0.tar.bz2 ]]
41
+ then
42
+ rvm mount ~/rvm_binaries/ruby-2.4.0.tar.bz2
43
+ else
44
+ mkdir -p ~/rvm_binaries
45
+ rvm install 2.4.0 --disable-binary
46
+ cd ~/rvm_binaries && rvm prepare 2.4.0
47
+ fi
1
48
  dependencies:
49
+ cache_directories:
50
+ - ~/rvm_binaries
2
51
  pre:
3
- - rvm install 2.0.0
4
- - rvm install 2.1.10
5
- - rvm install 2.2.6
6
- - rvm install 2.3.3
7
- - rvm install 2.4.0
52
+ - mkdir $CIRCLE_ARTIFACTS/coverage
8
53
  override:
9
- - rvm-exec 2.0.0 bash -c "bundle check --path=vendor/bundle || bundle install --path=vendor/bundle"
10
- - rvm-exec 2.1.10 bash -c "bundle check --path=vendor/bundle || bundle install --path=vendor/bundle"
11
- - rvm-exec 2.2.6 bash -c "bundle check --path=vendor/bundle || bundle install --path=vendor/bundle"
12
- - rvm-exec 2.3.3 bash -c "bundle check --path=vendor/bundle || bundle install --path=vendor/bundle"
13
- - rvm-exec 2.4.0 bash -c "bundle check --path=vendor/bundle || bundle install --path=vendor/bundle"
54
+ - rvm-exec 2.0.0 bash -c "gem install bundler && (bundle check --path=vendor/bundle || bundle install --path=vendor/bundle)"
55
+ - rvm-exec 2.1.10 bash -c "gem install bundler && (bundle check --path=vendor/bundle || bundle install --path=vendor/bundle)"
56
+ - rvm-exec 2.2.6 bash -c "gem install bundler && (bundle check --path=vendor/bundle || bundle install --path=vendor/bundle)"
57
+ - rvm-exec 2.3.3 bash -c "gem install bundler && (bundle check --path=vendor/bundle || bundle install --path=vendor/bundle)"
58
+ - rvm-exec 2.4.0 bash -c "gem install bundler && (bundle check --path=vendor/bundle || bundle install --path=vendor/bundle)"
14
59
  test:
15
60
  pre:
16
61
  - git config --global user.email "circleci@nebulab.it" && git config --global user.name "Circle CI"
@@ -19,4 +64,4 @@ test:
19
64
  - rvm-exec 2.1.10 bash -c "bundle exec rspec --color --format documentation spec"
20
65
  - rvm-exec 2.2.6 bash -c "bundle exec rspec --color --format documentation spec"
21
66
  - rvm-exec 2.3.3 bash -c "bundle exec rspec --color --format documentation spec"
22
- - rvm-exec 2.4.0 bash -c "bundle exec rspec --color --format documentation spec"
67
+ - rvm-exec 2.4.0 bash -c "COVERAGE=true bundle exec rspec --color --format documentation spec"
@@ -8,6 +8,8 @@ module Pulsar
8
8
  require 'interactor'
9
9
  require 'fileutils'
10
10
 
11
+ require 'pulsar/context_error'
12
+ require 'pulsar/validator'
11
13
  require 'pulsar/interactors/cleanup'
12
14
  require 'pulsar/interactors/create_run_dirs'
13
15
  require 'pulsar/interactors/add_applications'
@@ -23,7 +25,7 @@ module Pulsar
23
25
 
24
26
  require 'pulsar/organizers/list'
25
27
  require 'pulsar/organizers/install'
26
- require 'pulsar/organizers/deploy'
28
+ require 'pulsar/organizers/task'
27
29
 
28
30
  require 'pulsar/constants'
29
31
  require 'pulsar/cli'
@@ -1,3 +1,8 @@
1
+ if ENV['COVERAGE']
2
+ ENV['FEATURE_TESTS'] = 'true'
3
+ require_relative '../../spec/support/coverage_setup'
4
+ end
5
+
1
6
  module Pulsar
2
7
  class CLI < Thor
3
8
  map %w[--version -v] => :__print_version
@@ -50,9 +55,10 @@ module Pulsar
50
55
  option :conf_repo, aliases: '-c'
51
56
  def deploy(application, environment)
52
57
  load_config
53
- result = Pulsar::Deploy.call(
58
+ result = Pulsar::Task.call(
54
59
  repository: load_option_or_env!(:conf_repo),
55
- application: application, environment: environment
60
+ application: application, environment: environment,
61
+ task: 'deploy'
56
62
  )
57
63
 
58
64
  if result.success?
@@ -63,6 +69,24 @@ module Pulsar
63
69
  end
64
70
  end
65
71
 
72
+ desc 'task APPLICATION ENVIRONMENT TASK', 'Run Capistrano task for APPLICATION on ENVIRONMENT'
73
+ option :conf_repo, aliases: '-c'
74
+ def task(application, environment, task)
75
+ load_config
76
+ result = Pulsar::Task.call(
77
+ repository: load_option_or_env!(:conf_repo),
78
+ application: application, environment: environment,
79
+ task: task
80
+ )
81
+
82
+ if result.success?
83
+ puts "Executed task #{task} for #{application} on #{environment}!"
84
+ else
85
+ puts "Failed to execute task #{task} for #{application} on #{environment}."
86
+ puts result.error
87
+ end
88
+ end
89
+
66
90
  desc "--version, -v", "print the version"
67
91
  def __print_version
68
92
  puts Pulsar::VERSION
@@ -71,6 +95,8 @@ module Pulsar
71
95
  private
72
96
 
73
97
  def load_config
98
+ return unless File.exist?(PULSAR_CONF) && File.stat(PULSAR_CONF).readable?
99
+
74
100
  Dotenv.load(PULSAR_CONF) # Load configurations for Pulsar
75
101
  end
76
102
 
@@ -81,8 +107,7 @@ module Pulsar
81
107
  option_value = options[option] || ENV[env_option]
82
108
 
83
109
  if option_value.nil? || option_value.empty?
84
- fail RequiredArgumentMissingError,
85
- exception_text
110
+ fail RequiredArgumentMissingError, exception_text
86
111
  end
87
112
 
88
113
  option_value