parity_logandsprice 3.4.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 +7 -0
- data/README.md +198 -0
- data/bin/development +10 -0
- data/bin/pr_app +24 -0
- data/bin/production +10 -0
- data/bin/staging +10 -0
- data/lib/parity/backup.rb +147 -0
- data/lib/parity/environment.rb +147 -0
- data/lib/parity/heroku_app_name.rb +18 -0
- data/lib/parity/usage.rb +13 -0
- data/lib/parity/version.rb +3 -0
- data/lib/parity.rb +11 -0
- metadata +61 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5fe0758511222cfb3bedfad544400e1eadc25052cd838738ac13df827db8d5e1
|
4
|
+
data.tar.gz: 6b3fa0cd17b949d9ffa022269130be777776e6c50d31ab32707762094be405f6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9f78ca7854a340b404e862d127c8ff2f588d6ea93d59262d2d1a89fbb32e994423b1e0683cd94601dc15b2cfb49256aa8226c7983e09ce9fc0e75f287ea9d211
|
7
|
+
data.tar.gz: bab0ce042de415c8fed0eb2adc3e16be9204ab4bc1216469779d17fd87b404056e89b561c2978f3f8216e13def603ba38f38645b57e52f42c1f805418e0ddbb8
|
data/README.md
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
Parity
|
2
|
+
======
|
3
|
+
|
4
|
+
[](https://houndci.com)
|
5
|
+
|
6
|
+
Shell commands for development, staging, and production parity for Heroku apps.
|
7
|
+
|
8
|
+
Install
|
9
|
+
-------
|
10
|
+
|
11
|
+
gem install parity
|
12
|
+
|
13
|
+
Or bundle it in your project:
|
14
|
+
|
15
|
+
gem "parity"
|
16
|
+
|
17
|
+
[releases]: https://github.com/thoughtbot/parity/releases
|
18
|
+
|
19
|
+
Parity requires these command-line programs:
|
20
|
+
|
21
|
+
git
|
22
|
+
heroku
|
23
|
+
pg_restore
|
24
|
+
|
25
|
+
Usage
|
26
|
+
-----
|
27
|
+
|
28
|
+
Backup a database:
|
29
|
+
|
30
|
+
production backup
|
31
|
+
staging backup
|
32
|
+
|
33
|
+
Restore a production or staging database backup into development:
|
34
|
+
|
35
|
+
development restore production
|
36
|
+
development restore staging
|
37
|
+
|
38
|
+
Or, if `restore-from` reads better to you, it's the same thing:
|
39
|
+
|
40
|
+
development restore-from production
|
41
|
+
development restore-from staging
|
42
|
+
|
43
|
+
* Note that the `restore` command will use the most recent backup (from _staging_ or _production_). You may first need to create a more recent backup before restoring, to prevent download of a very old backup.
|
44
|
+
|
45
|
+
Push your local development database backup up to staging:
|
46
|
+
|
47
|
+
staging restore development
|
48
|
+
|
49
|
+
Deploy main to production (note that prior versions of Parity would run
|
50
|
+
database migrations, that's now better handled using [Heroku release phase]):
|
51
|
+
|
52
|
+
production deploy
|
53
|
+
|
54
|
+
[Heroku release phase]: https://devcenter.heroku.com/articles/release-phase
|
55
|
+
|
56
|
+
Deploy the current branch to staging:
|
57
|
+
|
58
|
+
staging deploy
|
59
|
+
|
60
|
+
_Note that deploys to non-production environments use `git push --force`._
|
61
|
+
|
62
|
+
Open a console:
|
63
|
+
|
64
|
+
production console
|
65
|
+
staging console
|
66
|
+
pr_app 1234 console
|
67
|
+
|
68
|
+
Migrate a database and restart the dynos:
|
69
|
+
|
70
|
+
production migrate
|
71
|
+
staging migrate
|
72
|
+
pr_app 1234 migrate
|
73
|
+
|
74
|
+
Tail a log:
|
75
|
+
|
76
|
+
production tail
|
77
|
+
staging tail
|
78
|
+
pr_app 1234 tail
|
79
|
+
|
80
|
+
The scripts also pass through, so you can do anything with them that you can do
|
81
|
+
with `heroku ______ --remote staging` or `heroku ______ --remote production`:
|
82
|
+
|
83
|
+
watch production ps
|
84
|
+
staging open
|
85
|
+
|
86
|
+
You can optionally parallelize a DB restore by passing `--parallelize`
|
87
|
+
as a flag to the `development` or `production` commands:
|
88
|
+
```
|
89
|
+
development restore-from production --parallelize
|
90
|
+
```
|
91
|
+
|
92
|
+
[2]: http://redis.io/commands
|
93
|
+
|
94
|
+
Convention
|
95
|
+
----------
|
96
|
+
|
97
|
+
Parity expects:
|
98
|
+
|
99
|
+
* A `staging` remote pointing to the staging Heroku app.
|
100
|
+
* A `production` remote pointing to the production Heroku app.
|
101
|
+
```
|
102
|
+
heroku git:remote -r staging -a your-staging-app
|
103
|
+
heroku git:remote -r production -a your-production-app
|
104
|
+
```
|
105
|
+
* There is a `config/database.yml` file that can be parsed as YAML for
|
106
|
+
`['development']['database']` or, alternatively, `['development']['primary']['database']` for multi-database configurations.
|
107
|
+
|
108
|
+
Pipelines
|
109
|
+
---------
|
110
|
+
|
111
|
+
If you deploy review applications with Heroku pipelines, run commands against
|
112
|
+
those applications with the `pr_app` command, followed by the PR number for your
|
113
|
+
application:
|
114
|
+
|
115
|
+
```
|
116
|
+
pr_app 1234 console
|
117
|
+
```
|
118
|
+
|
119
|
+
This command assumes that your review applications have a name derived from the
|
120
|
+
name of the application your `staging` Git remote points at.
|
121
|
+
|
122
|
+
Customization
|
123
|
+
-------------
|
124
|
+
|
125
|
+
If you have Heroku environments beyond staging and production (such as a feature
|
126
|
+
environment for each developer), you can add a [binstub] to the `bin` folder of
|
127
|
+
your application. Custom environments share behavior with staging: they can be
|
128
|
+
backed up and can restore from production.
|
129
|
+
|
130
|
+
Using feature environments requires including Parity as a gem in your
|
131
|
+
application's Gemfile.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
gem "parity"
|
135
|
+
```
|
136
|
+
|
137
|
+
[binstub]: https://github.com/sstephenson/rbenv/wiki/Understanding-binstubs
|
138
|
+
|
139
|
+
Here's an example binstub for a 'feature-geoff' environment, hosted at
|
140
|
+
myapp-feature-geoff.herokuapp.com.
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
#!/usr/bin/env ruby
|
144
|
+
|
145
|
+
require "parity"
|
146
|
+
|
147
|
+
if ARGV.empty?
|
148
|
+
puts Parity::Usage.new
|
149
|
+
else
|
150
|
+
Parity::Environment.new("feature-geoff", ARGV).run
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
Issues
|
155
|
+
------
|
156
|
+
Please fill out our [issues template](.github/issue_template.md) if you are
|
157
|
+
having problems.
|
158
|
+
|
159
|
+
Contributing
|
160
|
+
------------
|
161
|
+
|
162
|
+
Please see [`CONTRIBUTING.md`](CONTRIBUTING.md) for details.
|
163
|
+
|
164
|
+
Version History
|
165
|
+
---------------
|
166
|
+
|
167
|
+
Please see the [releases page](https://github.com/thoughtbot/parity/releases)
|
168
|
+
for the version history, along with a description of the changes in each
|
169
|
+
release.
|
170
|
+
|
171
|
+
Releasing
|
172
|
+
---------
|
173
|
+
|
174
|
+
See guidelines in [`RELEASING.md`](RELEASING.md) for details
|
175
|
+
|
176
|
+
License
|
177
|
+
-------
|
178
|
+
|
179
|
+
Parity is © 2013-2021 thoughtbot, inc.
|
180
|
+
It is free software,
|
181
|
+
and may be redistributed under the terms specified in the [LICENSE] file.
|
182
|
+
|
183
|
+
[LICENSE]: LICENSE
|
184
|
+
|
185
|
+
About thoughtbot
|
186
|
+
----------------
|
187
|
+
|
188
|
+

|
189
|
+
|
190
|
+
Parity is maintained and funded by thoughtbot, inc.
|
191
|
+
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
192
|
+
|
193
|
+
We are passionate about open source software.
|
194
|
+
See [our other projects][community].
|
195
|
+
We are [available for hire][hire].
|
196
|
+
|
197
|
+
[community]: https://thoughtbot.com/community?utm_source=github
|
198
|
+
[hire]: https://thoughtbot.com?utm_source=github
|
data/bin/development
ADDED
data/bin/pr_app
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.join("..", "..", "lib"), __FILE__)
|
4
|
+
require "open3"
|
5
|
+
require "parity"
|
6
|
+
|
7
|
+
if ARGV.empty?
|
8
|
+
puts Parity::Usage.new
|
9
|
+
else
|
10
|
+
review_app_number = ARGV.first
|
11
|
+
staging_git_remote = Open3.capture3("git remote get-url staging")[0].strip
|
12
|
+
review_app_prefix = staging_git_remote[/(?<=https:\/\/git\.heroku\.com\/|git@heroku\.com:)(.*)/].gsub(/-staging.git/, "")
|
13
|
+
|
14
|
+
puts "*"*60
|
15
|
+
puts "review_app_prefix: #{review_app_prefix}"
|
16
|
+
puts "review_app_number: #{review_app_number}"
|
17
|
+
puts "ARGV: #{ARGV}"
|
18
|
+
puts "*"*60
|
19
|
+
exit Parity::Environment.new(
|
20
|
+
"#{review_app_prefix}-pr-#{review_app_number}",
|
21
|
+
ARGV.drop(1),
|
22
|
+
app_argument: "--app",
|
23
|
+
).run
|
24
|
+
end
|
data/bin/production
ADDED
data/bin/staging
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
require "etc"
|
2
|
+
|
3
|
+
module Parity
|
4
|
+
class Backup
|
5
|
+
BLANK_ARGUMENTS = "".freeze
|
6
|
+
DATABASE_YML_RELATIVE_PATH = "config/database.yml".freeze
|
7
|
+
DEVELOPMENT_ENVIRONMENT_KEY_NAME = "development".freeze
|
8
|
+
PRIMARY_DATABASE_KEY_NAME = "primary".freeze
|
9
|
+
DATABASE_KEY_NAME = "database".freeze
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
puts "*"*60
|
13
|
+
puts args
|
14
|
+
puts "*"*60
|
15
|
+
@from, @to = args.values_at(:from, :to)
|
16
|
+
@additional_args = args[:additional_args] || BLANK_ARGUMENTS
|
17
|
+
@parallelize = args[:parallelize] || false
|
18
|
+
@app_argument = args[:app_argument]
|
19
|
+
end
|
20
|
+
|
21
|
+
def restore
|
22
|
+
if to == DEVELOPMENT_ENVIRONMENT_KEY_NAME
|
23
|
+
restore_to_development
|
24
|
+
elsif from == DEVELOPMENT_ENVIRONMENT_KEY_NAME
|
25
|
+
restore_from_development
|
26
|
+
else
|
27
|
+
restore_to_remote_environment
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :additional_args, :from, :to, :parallelize, :app_argument
|
34
|
+
|
35
|
+
alias :parallelize? :parallelize
|
36
|
+
|
37
|
+
def restore_from_development
|
38
|
+
reset_remote_database
|
39
|
+
Kernel.system(
|
40
|
+
"heroku pg:push #{development_db} DATABASE_URL #{app_argument} #{to} "\
|
41
|
+
"#{additional_args}",
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
def restore_to_development
|
46
|
+
ensure_temp_directory_exists
|
47
|
+
download_remote_backup
|
48
|
+
wipe_development_database
|
49
|
+
restore_from_local_temp_backup
|
50
|
+
delete_local_temp_backup
|
51
|
+
delete_rails_production_environment_settings
|
52
|
+
end
|
53
|
+
|
54
|
+
def wipe_development_database
|
55
|
+
Kernel.system(
|
56
|
+
"dropdb --if-exists #{development_db} && createdb #{development_db}",
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
def reset_remote_database
|
61
|
+
Kernel.system(
|
62
|
+
"heroku pg:reset #{app_argument} #{to} #{additional_args} "\
|
63
|
+
"--confirm #{heroku_app_name}",
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def heroku_app_name
|
68
|
+
if app_argument == "--app"
|
69
|
+
to
|
70
|
+
else
|
71
|
+
HerokuAppName.new(to).to_s
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def ensure_temp_directory_exists
|
76
|
+
Kernel.system("mkdir -p tmp")
|
77
|
+
end
|
78
|
+
|
79
|
+
def download_remote_backup
|
80
|
+
Kernel.system(
|
81
|
+
"curl -o tmp/latest.backup \"$(heroku pg:backups:url #{app_argument} #{from})\"",
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
def restore_from_local_temp_backup
|
86
|
+
Kernel.system(
|
87
|
+
"pg_restore tmp/latest.backup --verbose --no-acl --no-owner "\
|
88
|
+
"--dbname #{development_db} --jobs=#{processor_cores} "\
|
89
|
+
"#{additional_args}",
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
def delete_local_temp_backup
|
94
|
+
Kernel.system("rm tmp/latest.backup")
|
95
|
+
end
|
96
|
+
|
97
|
+
def delete_rails_production_environment_settings
|
98
|
+
Kernel.system(<<-SHELL)
|
99
|
+
psql #{development_db} -c "CREATE TABLE IF NOT EXISTS public.ar_internal_metadata (key character varying NOT NULL, value character varying, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL, CONSTRAINT ar_internal_metadata_pkey PRIMARY KEY (key)); UPDATE ar_internal_metadata SET value = 'development' WHERE key = 'environment'"
|
100
|
+
SHELL
|
101
|
+
end
|
102
|
+
|
103
|
+
def restore_to_remote_environment
|
104
|
+
reset_remote_database
|
105
|
+
Kernel.system(
|
106
|
+
"heroku pg:backups:restore #{backup_from} #{app_argument} #{to} "\
|
107
|
+
"#{additional_args}",
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def backup_from
|
112
|
+
"`#{remote_db_backup_url}` DATABASE"
|
113
|
+
end
|
114
|
+
|
115
|
+
def remote_db_backup_url
|
116
|
+
"heroku pg:backups:url #{app_argument} #{from}"
|
117
|
+
end
|
118
|
+
|
119
|
+
def development_db
|
120
|
+
db_configuration = YAML.safe_load(database_yaml_file, aliases: true).
|
121
|
+
fetch(DEVELOPMENT_ENVIRONMENT_KEY_NAME)
|
122
|
+
|
123
|
+
if db_configuration.key?(PRIMARY_DATABASE_KEY_NAME)
|
124
|
+
db_configuration[PRIMARY_DATABASE_KEY_NAME].
|
125
|
+
fetch(DATABASE_KEY_NAME)
|
126
|
+
else
|
127
|
+
db_configuration.fetch(DATABASE_KEY_NAME)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def database_yaml_file
|
132
|
+
ERB.new(IO.read(DATABASE_YML_RELATIVE_PATH)).result
|
133
|
+
end
|
134
|
+
|
135
|
+
def processor_cores
|
136
|
+
if parallelize? && ruby_version_over_2_2?
|
137
|
+
Etc.nprocessors
|
138
|
+
else
|
139
|
+
1
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def ruby_version_over_2_2?
|
144
|
+
Etc.respond_to?(:nprocessors)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require "parity/backup"
|
2
|
+
|
3
|
+
module Parity
|
4
|
+
class Environment
|
5
|
+
def initialize(environment, subcommands, app_argument: "--remote")
|
6
|
+
self.environment = environment
|
7
|
+
self.subcommand = subcommands[0]
|
8
|
+
self.arguments = subcommands[1..-1]
|
9
|
+
self.app_argument = app_argument
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
run_command || false
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
PROTECTED_ENVIRONMENTS = %w(development production)
|
19
|
+
|
20
|
+
attr_accessor :app_argument, :environment, :subcommand, :arguments
|
21
|
+
|
22
|
+
def run_command
|
23
|
+
if self.class.private_method_defined?(methodized_subcommand)
|
24
|
+
send(methodized_subcommand)
|
25
|
+
else
|
26
|
+
run_via_cli
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def open
|
31
|
+
run_via_cli
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_via_cli
|
35
|
+
Kernel.exec("heroku", subcommand, *arguments, app_argument, environment)
|
36
|
+
end
|
37
|
+
|
38
|
+
def backup
|
39
|
+
Kernel.system("heroku pg:backups:capture #{app_argument} #{environment}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def deploy
|
43
|
+
if production?
|
44
|
+
Kernel.system("git push production #{branch_ref}")
|
45
|
+
else
|
46
|
+
Kernel.system(
|
47
|
+
"git push #{environment} HEAD:#{branch_ref} --force",
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def branch_ref
|
53
|
+
main_ref_exists = system("git show-ref --verify --quiet refs/heads/main")
|
54
|
+
master_ref_exists = system(
|
55
|
+
"git show-ref --verify --quiet refs/heads/master",
|
56
|
+
)
|
57
|
+
|
58
|
+
if main_ref_exists && !master_ref_exists
|
59
|
+
"main"
|
60
|
+
else
|
61
|
+
"master"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def restore
|
66
|
+
if production? && !forced?
|
67
|
+
$stdout.puts "Parity does not support restoring backups into your "\
|
68
|
+
"production environment. Use `--force` to override."
|
69
|
+
else
|
70
|
+
Backup.new(
|
71
|
+
from: arguments.first,
|
72
|
+
to: environment,
|
73
|
+
parallelize: parallelize?,
|
74
|
+
additional_args: additional_restore_arguments,
|
75
|
+
app_argument: app_argument
|
76
|
+
).restore
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
alias :restore_from :restore
|
81
|
+
|
82
|
+
def production?
|
83
|
+
environment == "production"
|
84
|
+
end
|
85
|
+
|
86
|
+
def forced?
|
87
|
+
arguments.include?("--force")
|
88
|
+
end
|
89
|
+
|
90
|
+
def parallelize?
|
91
|
+
arguments.include?("--parallelize")
|
92
|
+
end
|
93
|
+
|
94
|
+
def additional_restore_arguments
|
95
|
+
(arguments.drop(1) - ["--force", "--parallelize"] +
|
96
|
+
[restore_confirmation_argument]).compact.join(" ")
|
97
|
+
end
|
98
|
+
|
99
|
+
def restore_confirmation_argument
|
100
|
+
unless PROTECTED_ENVIRONMENTS.include?(environment) || from_development?
|
101
|
+
"--confirm #{app_argument == "--app" ? environment : heroku_app_name}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def from_development?
|
106
|
+
arguments.first == "development"
|
107
|
+
end
|
108
|
+
|
109
|
+
def console
|
110
|
+
Kernel.system(
|
111
|
+
command_for_remote(
|
112
|
+
"run bundle exec rails console #{arguments.join(' ')}",
|
113
|
+
),
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
def migrate
|
118
|
+
Kernel.system(%{
|
119
|
+
#{command_for_remote('run rake db:migrate')} &&
|
120
|
+
#{command_for_remote('restart')}
|
121
|
+
})
|
122
|
+
end
|
123
|
+
|
124
|
+
def tail
|
125
|
+
Kernel.system(
|
126
|
+
command_for_remote("logs --tail #{arguments.join(' ')}"),
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
def heroku_app_name
|
131
|
+
if app_argument == "--app"
|
132
|
+
environment
|
133
|
+
else
|
134
|
+
HerokuAppName.new(environment).to_s
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
def command_for_remote(command)
|
140
|
+
"heroku #{command} #{app_argument} #{environment}"
|
141
|
+
end
|
142
|
+
|
143
|
+
def methodized_subcommand
|
144
|
+
subcommand.gsub("-", "_").to_sym
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Parity
|
2
|
+
class HerokuAppName
|
3
|
+
def initialize(environment)
|
4
|
+
@environment = environment
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_s
|
8
|
+
@heroku_app_name ||= Open3.
|
9
|
+
capture3("heroku info --remote #{environment}")[0].
|
10
|
+
split("\n")[0].
|
11
|
+
gsub(/(\s|=)+/, "")
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :environment
|
17
|
+
end
|
18
|
+
end
|
data/lib/parity/usage.rb
ADDED
data/lib/parity.rb
ADDED
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: parity_logandsprice
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.4.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dan Croak
|
8
|
+
- Geoff Harcourt
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2021-11-10 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: |2
|
15
|
+
Development/staging/production parity makes it easier for
|
16
|
+
those who write the code to deploy the code.
|
17
|
+
email:
|
18
|
+
- logandsprice@gmail.com.com
|
19
|
+
executables:
|
20
|
+
- development
|
21
|
+
- staging
|
22
|
+
- production
|
23
|
+
- pr_app
|
24
|
+
extensions: []
|
25
|
+
extra_rdoc_files: []
|
26
|
+
files:
|
27
|
+
- README.md
|
28
|
+
- bin/development
|
29
|
+
- bin/pr_app
|
30
|
+
- bin/production
|
31
|
+
- bin/staging
|
32
|
+
- lib/parity.rb
|
33
|
+
- lib/parity/backup.rb
|
34
|
+
- lib/parity/environment.rb
|
35
|
+
- lib/parity/heroku_app_name.rb
|
36
|
+
- lib/parity/usage.rb
|
37
|
+
- lib/parity/version.rb
|
38
|
+
homepage: https://github.com/logandsprice/parity
|
39
|
+
licenses:
|
40
|
+
- MIT
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 2.2.0
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubygems_version: 3.1.4
|
58
|
+
signing_key:
|
59
|
+
specification_version: 4
|
60
|
+
summary: Shell commands for development, staging, and production parity.
|
61
|
+
test_files: []
|