prodder 1.7

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.
@@ -0,0 +1,20 @@
1
+ # Will this ever be useful? ...
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :extract_fixtures do
6
+ unless File.directory? 'features/support/blog.git'
7
+ Dir.chdir('features/support') { sh "tar xzf blog.git.tgz" }
8
+ end
9
+ end
10
+
11
+ require 'cucumber/rake/task'
12
+ Cucumber::Rake::Task.new :cucumber => :extract_fixtures
13
+
14
+ namespace :cuke do
15
+ Cucumber::Rake::Task.new(:wip => :extract_fixtures) do |t|
16
+ t.cucumber_opts = '--tags @wip'
17
+ end
18
+ end
19
+
20
+ task :default => [:spec, :cucumber]
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path('../lib', File.dirname(__FILE__))
3
+ require 'prodder/cli'
4
+ Prodder::CLI.start
@@ -0,0 +1,69 @@
1
+ Feature: Commiting updated dumps to a project's repository
2
+
3
+ Background:
4
+ Given a prodder config in "prodder.yml" with project: blog
5
+ And a "blog" git repository
6
+ And I successfully run `prodder init -c prodder.yml`
7
+ And I successfully run `prodder dump -c prodder.yml`
8
+
9
+ Scenario: Structure, seed, quality_checks, permissions and settings files not yet tracked
10
+ When I run `prodder commit -c prodder.yml`
11
+ Then 1 commit by "prodder auto-commit" should be in the "blog" repository
12
+ And the file "db/structure.sql" should now be tracked
13
+ And the file "db/seeds.sql" should now be tracked
14
+ And the file "db/quality_checks.sql" should now be tracked
15
+ And the file "db/permissions.sql" should now be tracked
16
+ And the file "db/settings.sql" should now be tracked
17
+
18
+ Scenario: No changes to any file
19
+ When I run `prodder commit -c prodder.yml`
20
+ Then 1 commit by "prodder auto-commit" should be in the "blog" repository
21
+ When I run `prodder dump -c prodder.yml`
22
+ And I run `prodder commit -c prodder.yml`
23
+ Then 1 commit by "prodder auto-commit" should be in the "blog" repository
24
+
25
+ Scenario: Changes only to the structure
26
+ When I run `prodder commit -c prodder.yml`
27
+ Then 1 commit by "prodder auto-commit" should be in the "blog" repository
28
+ When I create a new table "linkbacks" in the "blog" database
29
+ And I run `prodder dump -c prodder.yml`
30
+ And I run `prodder commit -c prodder.yml`
31
+ And 2 commits by "prodder auto-commit" should be in the "blog" repository
32
+ And the latest commit should have changed "db/structure.sql" to contain "CREATE TABLE linkbacks"
33
+ And the latest commit should not have changed "db/seeds.sql"
34
+ And the latest commit should not have changed "db/quality_checks.sql"
35
+
36
+ Scenario: Changes only to the seed file
37
+ When I run `prodder commit -c prodder.yml`
38
+ Then 1 commit by "prodder auto-commit" should be in the "blog" repository
39
+ When I add a new author "Marley" to the "blog" database
40
+ And I run `prodder dump -c prodder.yml`
41
+ And I run `prodder commit -c prodder.yml`
42
+ Then 2 commits by "prodder auto-commit" should be in the "blog" repository
43
+ And the latest commit should have changed "db/seeds.sql" to contain "Marley"
44
+ And the latest commit should not have changed "db/structure.sql"
45
+ And the latest commit should not have changed "db/quality_checks.sql"
46
+
47
+ Scenario: Changes to both
48
+ When I run `prodder commit -c prodder.yml`
49
+ Then 1 commit by "prodder auto-commit" should be in the "blog" repository
50
+ When I create a new table "captchas" in the "blog" database
51
+ And I add a new author "Bob McBobbington" to the "blog" database
52
+ And I run `prodder dump -c prodder.yml`
53
+ And I run `prodder commit -c prodder.yml`
54
+ Then 2 commits by "prodder auto-commit" should be in the "blog" repository
55
+ And the latest commit should have changed "db/structure.sql" to contain "CREATE TABLE captchas"
56
+ And the latest commit should have changed "db/seeds.sql" to contain "Bob McBobbington"
57
+ And the latest commit should not have changed "db/quality_checks.sql"
58
+
59
+ Scenario: Changes only to permissions
60
+ When I run `prodder commit -c prodder.yml`
61
+ Then 1 commit by "prodder auto-commit" should be in the "blog" repository
62
+ When I create a new table "gotchas" in the "blog" database
63
+ When I grant all permissions on table "gotchas" in the "blog" database to "prodder"
64
+ And I run `prodder dump -c prodder.yml`
65
+ And I run `prodder commit -c prodder.yml`
66
+ And 2 commits by "prodder auto-commit" should be in the "blog" repository
67
+ And the latest commit should have changed "db/permissions.sql" to contain "GRANT ALL ON TABLE gotchas TO prodder"
68
+ And the latest commit should not have changed "db/seeds.sql"
69
+ And the latest commit should not have changed "db/quality_checks.sql"
@@ -0,0 +1,187 @@
1
+ Feature: prodder dump
2
+
3
+ Background:
4
+ Given a prodder config in "prodder.yml" with project: blog
5
+
6
+ Scenario: Happy path: dump structure.sql, listed seed tables, quality_checks.sql, permissions.sql and settings.sql
7
+ When I run `prodder dump -c prodder.yml`
8
+ Then the exit status should be 0
9
+ And the workspace file "blog/db/structure.sql" should match /CREATE TABLE posts/
10
+ And the workspace file "blog/db/structure.sql" should match /CREATE TABLE authors/
11
+ And the workspace file "blog/db/seeds.sql" should match /COPY posts/
12
+ And the workspace file "blog/db/seeds.sql" should match /COPY authors/
13
+ And the workspace file "blog/db/quality_checks.sql" should match /SET search_path/
14
+ And the workspace file "blog/db/quality_checks.sql" should match /CREATE TRIGGER /
15
+ And the workspace file "blog/db/permissions.sql" should match /GRANT /
16
+ And the workspace file "blog/db/settings.sql" should match /ALTER DATABASE /
17
+
18
+ Scenario: Include specified users, exclude other login roles from permissions dump
19
+ When I run `prodder dump -c prodder.yml`
20
+ Then the exit status should be 0
21
+ And the workspace file "blog/db/permissions.sql" should not match /exclude_this/
22
+ And the workspace file "blog/db/permissions.sql" should match /include_this/
23
+
24
+ Scenario: Roles missing ACL must be created, modified and granted if they're granted to non-login/included users
25
+ When I run `prodder dump -c prodder.yml`
26
+ Then the exit status should be 0
27
+ And the workspace file "blog/db/permissions.sql" should match /create_role_if_not_exists\('prodder__blog_prod:read_only'\);/
28
+ And the workspace file "blog/db/permissions.sql" should match /ALTER ROLE "prodder__blog_prod:read_only" WITH NOSUPERUSER/
29
+ And the workspace file "blog/db/permissions.sql" should match /GRANT "prodder__blog_prod:read_only" TO "prodder"/
30
+
31
+ Scenario: Roles are created smartly based on connected components in structure
32
+ When I run `prodder dump -c prodder.yml`
33
+ Then the exit status should be 0
34
+ And the workspace file "blog/db/permissions.sql" should not match /create_role_if_not_exists\('_92b'\);/
35
+ And the workspace file "blog/db/permissions.sql" should not match /create_role_if_not_exists\('_93b'\);/
36
+ And the workspace file "blog/db/permissions.sql" should not match /ALTER ROLE "_92b" WITH/
37
+ And the workspace file "blog/db/permissions.sql" should not match /ALTER ROLE "_93b" WITH/
38
+ And the workspace file "blog/db/permissions.sql" should not match /GRANT "_92b" TO "_93b"/
39
+
40
+ #TODO: Not sure how to test this
41
+ Scenario: All loginable (are there other kinds?) superusers are dumped
42
+ #TODO: Not sure how to test this
43
+ Scenario: Exhaustively test ACL
44
+
45
+ Scenario: Valid until option is quoted
46
+ When I run `prodder dump -c prodder.yml`
47
+ Then the exit status should be 0
48
+ And the workspace file "blog/db/permissions.sql" should match /VALID UNTIL '.*'/
49
+
50
+ Scenario: Exclude passwords from permissions dump
51
+ When I run `prodder dump -c prodder.yml`
52
+ Then the exit status should be 0
53
+ And the workspace file "blog/db/permissions.sql" should not match /PASSWORD '.*'/
54
+
55
+ Scenario: Roles are created if not existing instead of always being created
56
+ When I run `prodder dump -c prodder.yml`
57
+ Then the exit status should be 0
58
+ And the workspace file "blog/db/permissions.sql" should not match /CREATE ROLE \S*;/
59
+ And the workspace file "blog/db/permissions.sql" should match /create_role_if_not_exists\(.*\)/
60
+
61
+ Scenario: Exclude permissions dump if file missing
62
+ Given the prodder config in "prodder.yml" does not include a permissions file for the "blog" project
63
+ When I run `prodder dump -c prodder.yml`
64
+ Then the exit status should be 0
65
+ Then the workspace file "blog/db/permissions.sql" should not exist
66
+
67
+ Scenario: Exclude permissions dump if permissions object is missing
68
+ Given the prodder config in "prodder.yml" does not include permissions for the "blog" project
69
+ When I run `prodder dump -c prodder.yml`
70
+ Then the exit status should be 0
71
+ Then the workspace file "blog/db/permissions.sql" should not exist
72
+
73
+ Scenario Outline: Exhaustively test role creation and altering
74
+ When I run `prodder dump -c prodder.yml`
75
+ Then the exit status should be 0
76
+ And the workspace file "blog/db/permissions.sql" should match /<role_creation>/
77
+ And the workspace file "blog/db/permissions.sql" should match /<role_altering>/
78
+
79
+ Examples:
80
+ | role_creation | role_altering |
81
+ | prodder | ALTER ROLE "prodder" WITH NOSUPERUSER |
82
+ | prodder__blog_prod:read_only | ALTER ROLE "prodder__blog_prod:read_only" WITH NOSUPERUSER |
83
+ | include_this | ALTER ROLE "include_this" WITH NOSUPERUSER |
84
+ | _90enva | ALTER ROLE "_90enva" WITH NOSUPERUSER |
85
+ | _91b | ALTER ROLE "_91b" WITH NOSUPERUSER |
86
+ | _91qa | ALTER ROLE "_91qa" WITH NOSUPERUSER |
87
+ | _91se | ALTER ROLE "_91se" WITH NOSUPERUSER |
88
+ | _92qa | ALTER ROLE "_92qa" WITH NOSUPERUSER |
89
+ | _92se | ALTER ROLE "_92se" WITH NOSUPERUSER |
90
+ | _93se | ALTER ROLE "_93se" WITH NOSUPERUSER |
91
+ | _94se | ALTER ROLE "_94se" WITH NOSUPERUSER |
92
+ |prodder__blog_prod:permissions_test:read_only|ALTER ROLE "prodder__blog_prod:permissions_test:read_only" WITH NOSUPERUSER|
93
+ |prodder__blog_prod:permissions_test:read_only|ALTER ROLE "prodder__blog_prod:permissions_test:read_write" WITH NOSUPERUSER|
94
+
95
+ Scenario Outline: Exhaustively test memeberships
96
+ When I run `prodder dump -c prodder.yml`
97
+ Then the exit status should be 0
98
+ And the workspace file "blog/db/permissions.sql" should match /<membership>/
99
+
100
+ Examples:
101
+ | membership |
102
+ | GRANT "prodder__blog_prod:permissions_test:read_write" TO "include_this" |
103
+ | GRANT "prodder__blog_prod:read_only" TO "prodder" |
104
+ | GRANT "prodder__blog_prod:permissions_test:read_only" TO "prodder__blog_prod:read_only" |
105
+ | GRANT "_90enva" TO "_91se" |
106
+ | GRANT "_90enva" TO "_91qa" |
107
+ | GRANT "_90enva" TO "_91b" |
108
+ | GRANT "_91se" TO "_92se" |
109
+ | GRANT "_91qa" TO "_92se" |
110
+ | GRANT "_91qa" TO "_92qa" |
111
+ | GRANT "_91b" TO "_92qa" |
112
+ | GRANT "_91qa" TO "_94se" |
113
+ | GRANT "_92se" TO "_93se" |
114
+ | GRANT "_93se" TO "_94se" |
115
+
116
+ Scenario: Exclude specified tables from structure dump
117
+ Given the prodder config in "prodder.yml" excludes the table "authors" from the dump of "blog"
118
+ When I run `prodder dump -c prodder.yml`
119
+ Then the exit status should be 0
120
+ And the workspace file "blog/db/structure.sql" should not match /CREATE TABLE authors/
121
+
122
+ Scenario: Verify settings file contents
123
+ Given I add a customer parameter "c.p" with value "v" in the "blog" project's database
124
+ When I run `prodder dump -c prodder.yml`
125
+ Then the workspace file "blog/db/settings.sql" should match /ALTER DATABASE prodder__blog_prod SET c.p=v/
126
+
127
+ Scenario: Exclude specified schemas from structure dump
128
+ Given the prodder config in "prodder.yml" excludes the schema "ads" from the dump of "blog"
129
+ And I add a "ads" schema to the "blog" project's database
130
+ When I run `prodder dump -c prodder.yml`
131
+ Then the exit status should be 0
132
+ And the workspace file "blog/db/structure.sql" should not match /CREATE SCHEMA ads/
133
+
134
+ Scenario: Unspecified tables are not dumped to seeds
135
+ When I run `prodder dump -c prodder.yml`
136
+ Then the exit status should be 0
137
+ And the workspace file "blog/db/seeds.sql" should not match /COPY comments/
138
+
139
+ Scenario: Grant/revoke/ownership are not in the structure dump
140
+ When I run `prodder dump -c prodder.yml`
141
+ Then the workspace file "blog/db/structure.sql" should not match /GRANT/
142
+ And the workspace file "blog/db/structure.sql" should not match /ALTER TABLE.*OWNER TO/
143
+
144
+ Scenario: Ownership is not in the seeds dump
145
+ When I run `prodder dump -c prodder.yml`
146
+ Then the workspace file "blog/db/seeds.sql" should match /Owner: -/
147
+ And the workspace file "blog/db/seeds.sql" should not match /Owner: [^-]/
148
+
149
+ Scenario: Verify quality_checks file contents
150
+ Given I add a foreign key from table "posts" and column "author_id" to table "authors" and column "author_id" in the "blog" project's database
151
+ When I run `prodder dump -c prodder.yml`
152
+ Then the workspace file "blog/db/quality_checks.sql" should match /ADD CONSTRAINT .* FOREIGN KEY/
153
+ Given I add an index to table "posts" on column "author_id" in the "blog" project's database
154
+ When I run `prodder dump -c prodder.yml`
155
+ Then the workspace file "blog/db/quality_checks.sql" should match /CREATE INDEX /
156
+
157
+ Scenario: Maintaining quality checks directly in the structure file
158
+ Given the prodder config in "prodder.yml" does not include a quality check file for the "blog" project
159
+ And I add a foreign key from table "posts" and column "author_id" to table "authors" and column "author_id" in the "blog" project's database
160
+ When I run `prodder dump -c prodder.yml`
161
+ Then the workspace file "blog/db/quality_checks.sql" should not exist
162
+ And the workspace file "blog/db/structure.sql" should match /ADD CONSTRAINT .* FOREIGN KEY/
163
+
164
+ Scenario: Projects can use a YAML file to specify their seed tables
165
+ Given the prodder config in "prodder.yml" says to read the "blog" seed tables from "db/seeds.yml"
166
+ And the "blog" file "db/seeds.yml" contains:
167
+ """
168
+ - posts
169
+ """
170
+ When I run `prodder dump -c prodder.yml`
171
+ Then the exit status should be 0
172
+ And the workspace file "blog/db/seeds.sql" should match /COPY posts/
173
+ But the workspace file "blog/db/seeds.sql" should not match /COPY authors/
174
+
175
+ Scenario: YAML file listing seed tables does not exist
176
+ Given the prodder config in "prodder.yml" says to read the "blog" seed tables from "db/seeds.yml"
177
+ But the "blog" file "db/seeds.yml" does not exist
178
+ When I run `prodder dump -c prodder.yml`
179
+ Then the exit status should be 1
180
+ And the output should contain "No such file: blog/db/seeds.yml"
181
+
182
+ @restore-perms
183
+ Scenario: pg_dump failed
184
+ Given the "prodder" role can not read from the "blog" database's tables
185
+ When I run `prodder dump -c prodder.yml`
186
+ Then the exit status should be 1
187
+ And the output should contain "permission denied"
@@ -0,0 +1,24 @@
1
+ Feature: prodder init
2
+
3
+ Background:
4
+ Given a prodder config in "prodder.yml" with project: blog
5
+ And a "blog" git repository
6
+
7
+ Scenario: Clone a project
8
+ When I run `prodder init -c prodder.yml`
9
+ Then the exit status should be 0
10
+ And a directory named "prodder-workspace/blog" should exist
11
+ And the workspace file "blog/README" should match /Read me/
12
+
13
+ Scenario: Update pre-existing repository on re-initializing
14
+ Given I run `prodder init -c prodder.yml`
15
+ And a new commit is already in the "blog" git repository
16
+ When I run `prodder init -c prodder.yml`
17
+ Then the new commit should be in the workspace copy of the "blog" repository
18
+
19
+ Scenario: Can't clone repository (no such repo, permissions, whatever)
20
+ Given I deleted the "blog" git repository
21
+ When I run `prodder init -c prodder.yml`
22
+ Then the exit status should be 1
23
+ And the output should contain "Failed to run 'git clone ./repos/blog"
24
+ And the output should match /repository.*does not exist/
@@ -0,0 +1,46 @@
1
+ Feature: Configuration lint
2
+ In order to simplify later error handling and hopefully provide
3
+ rapid feedback on configuration issues, the config file is always
4
+ run through a linting process to ensure sanity before any other
5
+ operations are performed.
6
+
7
+ See spec/config_spec for a more detailed test of linting. This
8
+ test only ensures that the CLI reports lint failures reasonably.
9
+
10
+ Background:
11
+ Given a prodder config in "prodder.yml" with project: store
12
+ And no-op versions of these bins are available on my PATH: pg_dump, git
13
+
14
+ Scenario: One of the required project config keys is missing
15
+ But the "store/db/name" key is missing from "prodder.yml"
16
+ When I run `prodder ls -c prodder.yml`
17
+ Then the exit status should be 1
18
+ And the output should contain:
19
+ """
20
+ Missing required configuration key: store/db/name
21
+
22
+ Example configuration:
23
+ """
24
+ And the output should contain the example config contents
25
+
26
+ Scenario: pg_dump is not available
27
+ Given "pg_dump" is not available on my PATH
28
+ When I run `prodder ls -c prodder.yml`
29
+ Then the exit status should be 1
30
+ And the output should contain:
31
+ """
32
+ `pg_dump` could not be found on your $PATH.
33
+
34
+ Current PATH:
35
+ """
36
+
37
+ Scenario: git is not available
38
+ Given "git" is not available on my PATH
39
+ When I run `prodder ls -c prodder.yml`
40
+ Then the exit status should be 1
41
+ And the output should contain:
42
+ """
43
+ `git` could not be found on your $PATH.
44
+
45
+ Current PATH:
46
+ """
@@ -0,0 +1,76 @@
1
+ Feature: Basic CLI usage
2
+
3
+ Scenario: prodder help
4
+ When I run `prodder help`
5
+ Then the output should contain "Tasks:"
6
+
7
+ Scenario: No config file supplied
8
+ When I run `prodder`
9
+ Then the output should contain "required option '--config'"
10
+
11
+ Scenario: Config file not found
12
+ When I run `prodder init -c not-there.yml`
13
+ Then the output should contain exactly "Config file not found: not-there.yml\n"
14
+ And the exit status should be 1
15
+
16
+ Scenario: Malformed config file
17
+ Given a file named "broken.yml" with:
18
+ """
19
+ %this IS NOT VALID YAML
20
+ """
21
+ When I run `prodder init -c broken.yml`
22
+ Then the output should contain:
23
+ """
24
+ Invalid YAML in config file broken.yml. Current file contents:
25
+
26
+ %this IS NOT VALID YAML
27
+ """
28
+
29
+ Scenario: No database defined on project
30
+ Given a file named "prodder.yml" with:
31
+ """
32
+ blog:
33
+ structure_file: db/structure.sql
34
+ seed_file: db/seeds.sql
35
+ quality_check_file: db/quality_checks.sql
36
+ git:
37
+ origin: git@github.com:pd/blog.git
38
+ author: prodder auto-commit <pd+prodder@krh.me>
39
+ """
40
+ When I run `prodder dump blog -c prodder.yml`
41
+ Then the output should contain:
42
+ """
43
+ Missing required configuration key: blog/db
44
+
45
+ Example configuration:
46
+ blog:
47
+ structure_file: db/structure.sql
48
+ seed_file: db/seeds.sql
49
+ quality_check_file: db/quality_checks.sql
50
+ git:
51
+ origin: git@github.com:your/repo.git
52
+ author: prodder <prodder@example.com>
53
+ db:
54
+ name: database_name
55
+ host: database.server.example.com
56
+ user: username
57
+ password: password
58
+ tables:
59
+ - posts
60
+ - authors
61
+ """
62
+
63
+ Scenario: Projects named not defined in config file
64
+ Given a prodder config in "prodder.yml" with project: store
65
+ When I run `prodder init blog api -c prodder.yml`
66
+ Then the output should contain "Project not defined: blog, api"
67
+
68
+ Scenario: Listing projects
69
+ Given a prodder config in "prodder.yml" with projects: store, blog
70
+ When I run `prodder ls -c prodder.yml`
71
+ Then the output should contain exactly:
72
+ """
73
+ store
74
+ blog
75
+
76
+ """
@@ -0,0 +1,25 @@
1
+ Feature: prodder push
2
+
3
+ Background:
4
+ Given a prodder config in "prodder.yml" with project: blog
5
+ And a "blog" git repository
6
+ And I successfully run `prodder init -c prodder.yml`
7
+ And I successfully run `prodder dump -c prodder.yml`
8
+ And I successfully run `prodder commit -c prodder.yml`
9
+
10
+ Scenario: Changes are pushed upstream
11
+ When I successfully run `prodder push -c prodder.yml`
12
+ Then the exit status should be 0
13
+ Then the new commit should be in the remote repository
14
+
15
+ Scenario: Push fails due to permissions
16
+ Given the "blog" git repository does not allow pushing to it
17
+ When I run `prodder push -c prodder.yml`
18
+ Then the exit status should be 1
19
+ And the output should contain "insufficient permission"
20
+
21
+ Scenario: Push fails due to non-fast-forward
22
+ Given a new commit is already in the "blog" git repository
23
+ When I run `prodder push -c prodder.yml`
24
+ Then the exit status should be 1
25
+ And the output should contain "Refusing to push to remote"