parity 0.1.0 → 0.1.1

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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZWQ5MDcxMzdkOTY3ZDE1OGQzZmJiYzlmMjJlN2U4NTQ4NzBiNWM1Ng==
5
- data.tar.gz: !binary |-
6
- NWI3ZjUyZmNlOTY3Yzc1NjQzNDMwMTc4NzcxMzE4ZGYzMDg1NmIyNA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- YmZhM2U4ZDc0ZDQwM2MzOTlkNTFjZWRjZmJlN2FlOWQ4YmE5NzIyODFjYjBh
10
- MTJhYzEwNTJmMWI2YmJiMWNkYmZhOGY1OGFkYzNmYTQ5NGY1ZTZkODIwMjVh
11
- YjAyMTdhODgyMmRkM2E4ODU0MDMyYjAwMjEyOTRlNmNkODhkOWQ=
12
- data.tar.gz: !binary |-
13
- MTlmMjYyNDg3NzEwY2FjODE1ZTA3MTE3OTdlZTIxZDU5OThmODUxZjUyMDhh
14
- OWIwZjVkM2M4NmRjMmVlNDMwNGIyODljMzE0MTI4MmRhYTM0YTA5MjBiOGM1
15
- Y2JlMDg0NmNhZjEzODAxM2NkNTlmNmI4Y2Q4NTM3ZjA1ZDRjMDQ=
2
+ SHA1:
3
+ metadata.gz: 0698fa82d8c213ab44c52cb3fce810562de1f473
4
+ data.tar.gz: 46a3715c5db2394ae33ad4b6f2de32db42c36206
5
+ SHA512:
6
+ metadata.gz: 3f8d844f83bd34cc98c3d04cb85815fab30b8d0490d7c345b7f92c3a981a66d231ce5d845a9420f965a89d95d5a9ec0eb232191f19ce7f81b6976afee11b86c9
7
+ data.tar.gz: b9d1f976654e6bb6716a07ea03be643f680c9d0b5ff39df916d7a9aeaaf6e4137e332dc8aa1f2f705ac261247492ccbc2b20940baefb8b9e216293b04e24df2d
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ Parity
2
+ ======
3
+
4
+ Shell commands for development, staging, and production parity for Heroku apps.
5
+
6
+ Install
7
+ -------
8
+
9
+ gem install parity
10
+
11
+ This installs three shell commands:
12
+
13
+ development
14
+ staging
15
+ production
16
+
17
+ Your development machine will also need these command-line programs:
18
+
19
+ curl
20
+ heroku
21
+ pg_restore
22
+
23
+ On a Mac, `curl` is installed by default and the other programs can be installed
24
+ with Homebrew:
25
+
26
+ brew install heroku-toolbelt
27
+ brew install postgres --no-python
28
+
29
+ Usage
30
+ -----
31
+
32
+ Backup a database:
33
+
34
+ production backup
35
+ staging backup
36
+
37
+ Restore a production or staging database backup into development:
38
+
39
+ development restore production
40
+ development restore staging
41
+
42
+ Restore a production database backup into staging:
43
+
44
+ staging restore production
45
+
46
+ Open a console:
47
+
48
+ production console
49
+ staging console
50
+
51
+ Open [log2viz][1]:
52
+
53
+ production log2viz
54
+ staging log2viz
55
+
56
+ Migrate a database and restart the dynos:
57
+
58
+ production migrate
59
+ staging migrate
60
+
61
+ Tail a log:
62
+
63
+ production tail
64
+ staging tail
65
+
66
+ The scripts also pass through, so you can do anything with them that you can do
67
+ with `heroku ______ --remote staging` or `heroku ______ --remote production`:
68
+
69
+ watch production ps
70
+ staging open
71
+
72
+ Convention
73
+ ----------
74
+
75
+ Parity expects:
76
+
77
+ * A `staging` remote pointing to the staging Heroku app.
78
+ * A `production` remote pointing to the production Heroku app.
79
+ * There is a `config/database.yml` file that can be parsed as Yaml for
80
+ `['development']['database']`.
81
+ * The Heroku apps are named like `app-staging` and `app-production`
82
+ where `app` is equal to `basename $PWD`.
83
+
84
+ Configuration
85
+ -------------
86
+
87
+ Override some of the conventions:
88
+
89
+ ```ruby
90
+ Parity.configure do |config|
91
+ config.database_config_path = 'different/path.yml'
92
+ config.heroku_app_basename = 'different-base-name'
93
+ end
94
+ ```
95
+
96
+ Credits
97
+ -------
98
+
99
+ Parity is maintained by Dan Croak. It is free software and may be redistributed
100
+ under the terms specified in the LICENSE file.
101
+
102
+ [1]: https://blog.heroku.com/archives/2013/3/19/log2viz
data/bin/development CHANGED
@@ -2,4 +2,8 @@
2
2
 
3
3
  require File.join(File.dirname(__FILE__), '..', 'lib', 'parity')
4
4
 
5
- Parity::Development.new(ARGV).run
5
+ if ARGV.empty?
6
+ puts Parity::Usage.new
7
+ else
8
+ Parity::Development.new(ARGV).run
9
+ end
data/bin/production CHANGED
@@ -2,4 +2,8 @@
2
2
 
3
3
  require File.join(File.dirname(__FILE__), '..', 'lib', 'parity')
4
4
 
5
- Parity::Production.new(ARGV).run
5
+ if ARGV.empty?
6
+ puts Parity::Usage.new
7
+ else
8
+ Parity::Production.new(ARGV).run
9
+ end
data/bin/staging CHANGED
@@ -2,4 +2,8 @@
2
2
 
3
3
  require File.join(File.dirname(__FILE__), '..', 'lib', 'parity')
4
4
 
5
- Parity::Staging.new(ARGV).run
5
+ if ARGV.empty?
6
+ puts Parity::Usage.new
7
+ else
8
+ Parity::Staging.new(ARGV).run
9
+ end
data/lib/parity.rb CHANGED
@@ -1,3 +1,7 @@
1
+ require 'parity/configuration'
1
2
  require 'parity/development'
2
3
  require 'parity/staging'
3
4
  require 'parity/production'
5
+ require 'parity/usage'
6
+
7
+ Parity.configure
data/lib/parity/backup.rb CHANGED
@@ -2,7 +2,7 @@ require 'yaml'
2
2
 
3
3
  module Parity
4
4
  class Backup
5
- def initialize(from, to)
5
+ def initialize(from: from, to: to)
6
6
  @from = from
7
7
  @to = to
8
8
  end
@@ -20,16 +20,23 @@ module Parity
20
20
  attr_reader :from, :to
21
21
 
22
22
  def restore_to_development
23
- system %{
24
- curl -s `#{db_backup_url}` | \
25
- pg_restore --verbose --clean --no-acl --no-owner -d #{development_db}
26
- }
23
+ Kernel.system "#{curl} | #{pg_restore}"
24
+ end
25
+
26
+ def curl
27
+ "curl -s `#{db_backup_url}`"
28
+ end
29
+
30
+ def pg_restore
31
+ "pg_restore --verbose --clean --no-acl --no-owner -d #{development_db}"
27
32
  end
28
33
 
29
34
  def restore_to_pass_through
30
- system %{
31
- heroku pgbackups:restore DATABASE `#{db_backup_url}` --remote #{to}
32
- }
35
+ Kernel.system "heroku pgbackups:restore #{backup_from} --remote #{to}"
36
+ end
37
+
38
+ def backup_from
39
+ "DATABASE `#{db_backup_url}`"
33
40
  end
34
41
 
35
42
  def db_backup_url
@@ -37,7 +44,8 @@ module Parity
37
44
  end
38
45
 
39
46
  def development_db
40
- YAML.load(IO.read('config/database.yml'))['development']['database']
47
+ yaml_file = IO.read(Parity.config.database_config_path)
48
+ YAML.load(yaml_file)['development']['database']
41
49
  end
42
50
  end
43
51
  end
@@ -0,0 +1,21 @@
1
+ module Parity
2
+ class Configuration
3
+ attr_accessor :database_config_path, :heroku_app_basename
4
+
5
+ def initialize
6
+ @database_config_path = 'config/database.yml'
7
+ end
8
+ end
9
+
10
+ class << self
11
+ attr_accessor :config
12
+ end
13
+
14
+ def self.configure
15
+ self.config ||= Configuration.new
16
+
17
+ if block_given?
18
+ yield config
19
+ end
20
+ end
21
+ end
@@ -4,14 +4,13 @@ require 'parity/environment'
4
4
  module Parity
5
5
  class Development < Environment
6
6
  def initialize(subcommands)
7
- @environment = 'development'
8
- super(subcommands)
7
+ super 'development', subcommands
9
8
  end
10
9
 
11
10
  private
12
11
 
13
12
  def restore
14
- Backup.new(arguments.first, 'development').restore
13
+ Backup.new(from: arguments.first, to: 'development').restore
15
14
  end
16
15
  end
17
16
  end
@@ -1,51 +1,52 @@
1
1
  module Parity
2
2
  class Environment
3
- def initialize(subcommands)
4
- @subcommand = subcommands[0]
5
- @arguments = subcommands[1..-1]
3
+ def initialize(environment, subcommands)
4
+ self.environment = environment
5
+ self.subcommand = subcommands[0]
6
+ self.arguments = subcommands[1..-1]
6
7
  end
7
8
 
8
9
  def run
9
10
  if self.class.private_method_defined?(subcommand)
10
11
  send(subcommand)
11
12
  else
12
- system "heroku #{pass_through} --remote #{environment}"
13
+ Kernel.system "heroku #{pass_through} --remote #{environment}"
13
14
  end
14
15
  end
15
16
 
16
17
  private
17
18
 
18
- attr_reader :environment, :subcommand, :arguments
19
+ attr_accessor :environment, :subcommand, :arguments
19
20
 
20
21
  def backup
21
- system "heroku pgbackups:capture --expire --remote #{environment}"
22
+ Kernel.system "heroku pgbackups:capture --expire --remote #{environment}"
22
23
  end
23
24
 
24
25
  def console
25
- system "heroku run console --remote #{environment}"
26
+ Kernel.system "heroku run console --remote #{environment}"
26
27
  end
27
28
 
28
29
  def log2viz
29
- system "open https://log2viz.herokuapp.com/app/#{heroku_app_name}"
30
+ Kernel.system "open https://log2viz.herokuapp.com/app/#{heroku_app_name}"
30
31
  end
31
32
 
32
33
  def migrate
33
- system %{
34
+ Kernel.system %{
34
35
  heroku run rake db:migrate --remote #{environment} &&
35
36
  heroku restart --remote #{environment}
36
37
  }
37
38
  end
38
39
 
39
40
  def tail
40
- system "heroku logs --tail --remote #{environment}"
41
+ Kernel.system "heroku logs --tail --remote #{environment}"
41
42
  end
42
43
 
43
44
  def heroku_app_name
44
- [app_name, environment].join('-')
45
+ [basename, environment].join('-')
45
46
  end
46
47
 
47
- def app_name
48
- Dir.pwd.split('/').last
48
+ def basename
49
+ Parity.config.heroku_app_basename || Dir.pwd.split('/').last
49
50
  end
50
51
 
51
52
  def pass_through
@@ -3,8 +3,7 @@ require 'parity/environment'
3
3
  module Parity
4
4
  class Production < Environment
5
5
  def initialize(subcommands)
6
- @environment = 'production'
7
- super(subcommands)
6
+ super 'production', subcommands
8
7
  end
9
8
  end
10
9
  end
@@ -4,14 +4,13 @@ require 'parity/environment'
4
4
  module Parity
5
5
  class Staging < Environment
6
6
  def initialize(subcommands)
7
- @environment = 'staging'
8
- super(subcommands)
7
+ super 'staging', subcommands
9
8
  end
10
9
 
11
10
  private
12
11
 
13
12
  def restore
14
- Backup.new(arguments.last, 'staging').restore
13
+ Backup.new(from: arguments.last, to: 'staging').restore
15
14
  end
16
15
  end
17
16
  end
@@ -0,0 +1,13 @@
1
+ module Parity
2
+ class Usage
3
+ def to_s
4
+ File.read(readme).match(/Usage\n-----\n([^\/.]*)Convention/)[1]
5
+ end
6
+
7
+ private
8
+
9
+ def readme
10
+ File.join(File.dirname(__FILE__), '..', '..', 'README.md')
11
+ end
12
+ end
13
+ end
metadata CHANGED
@@ -1,19 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Croak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-13 00:00:00.000000000 Z
11
+ date: 2013-08-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: ! " Devevelopment/staging/production parity is intended to decrease
14
- the time\n between a developer writing code and having it deployed, make it possible\n
15
- \ for the same people who wrote the code to deploy it and watch its behavior\n
16
- \ in production, and reduce the number of tools necessary to manage.\n"
13
+ description: |2
14
+ Devevelopment/staging/production parity is intended to decrease the time
15
+ between a developer writing code and having it deployed, make it possible
16
+ for the same people who wrote the code to deploy it and watch its behavior
17
+ in production, and reduce the number of tools necessary to manage.
17
18
  email:
18
19
  - dan@thoughtbot.com
19
20
  executables:
@@ -23,12 +24,15 @@ executables:
23
24
  extensions: []
24
25
  extra_rdoc_files: []
25
26
  files:
27
+ - README.md
26
28
  - lib/parity.rb
27
29
  - lib/parity/backup.rb
30
+ - lib/parity/configuration.rb
28
31
  - lib/parity/development.rb
29
32
  - lib/parity/environment.rb
30
33
  - lib/parity/production.rb
31
34
  - lib/parity/staging.rb
35
+ - lib/parity/usage.rb
32
36
  - bin/development
33
37
  - bin/staging
34
38
  - bin/production
@@ -42,19 +46,18 @@ require_paths:
42
46
  - lib
43
47
  required_ruby_version: !ruby/object:Gem::Requirement
44
48
  requirements:
45
- - - ! '>='
49
+ - - '>='
46
50
  - !ruby/object:Gem::Version
47
51
  version: '0'
48
52
  required_rubygems_version: !ruby/object:Gem::Requirement
49
53
  requirements:
50
- - - ! '>='
54
+ - - '>='
51
55
  - !ruby/object:Gem::Version
52
56
  version: '0'
53
57
  requirements: []
54
58
  rubyforge_project:
55
- rubygems_version: 2.0.0
59
+ rubygems_version: 2.0.5
56
60
  signing_key:
57
61
  specification_version: 4
58
62
  summary: Shell commands for development, staging, and production parity.
59
63
  test_files: []
60
- has_rdoc: