schema_dev 3.13.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/prs.yml +49 -0
- data/.simplecov +20 -0
- data/Gemfile +2 -0
- data/README.md +12 -10
- data/Rakefile +3 -5
- data/bin/schema_dev +25 -21
- data/lib/schema_dev/config.rb +62 -44
- data/lib/schema_dev/executor.rb +9 -8
- data/lib/schema_dev/gem.rb +45 -37
- data/lib/schema_dev/gemfile_selector.rb +7 -7
- data/lib/schema_dev/gemfiles.rb +6 -5
- data/lib/schema_dev/github_actions.rb +266 -0
- data/lib/schema_dev/matrix_executor.rb +4 -2
- data/lib/schema_dev/readme.rb +17 -10
- data/lib/schema_dev/rspec/db.rb +44 -33
- data/lib/schema_dev/rspec.rb +4 -9
- data/lib/schema_dev/ruby_selector.rb +29 -14
- data/lib/schema_dev/runner.rb +14 -10
- data/lib/schema_dev/tasks/dbms.rb +34 -26
- data/lib/schema_dev/tasks.rb +2 -3
- data/lib/schema_dev/templates.rb +5 -5
- data/lib/schema_dev/version.rb +3 -1
- data/lib/schema_dev.rb +3 -1
- data/schema_dev.gemspec +24 -25
- data/spec/schema_dev/config_spec.rb +60 -0
- data/spec/schema_dev/gem_spec.rb +74 -0
- data/spec/schema_dev/gemfile_selector_spec.rb +11 -0
- data/spec/schema_dev/gemfiles_spec.rb +41 -0
- data/spec/schema_dev/github_actions_spec.rb +818 -0
- data/spec/schema_dev/runner_spec.rb +103 -0
- data/spec/spec_helper.rb +5 -6
- data/templates/README/uses.schema_dev.md.erb +1 -2
- data/templates/gem/GEM_NAME.gemspec.erb +15 -14
- data/templates/gem/Gemfile.erb +2 -0
- data/templates/gem/Gemfile.local.erb +2 -0
- data/templates/gem/README.md.erb +1 -2
- data/templates/gem/Rakefile.erb +2 -0
- data/templates/gem/schema_dev.yml.erb +5 -2
- data/templates/gem/simplecov.erb +20 -0
- data/templates/gemfiles/Gemfile.base.erb +1 -1
- data/templates/gemfiles/activerecord-5.2/Gemfile.base.erb +2 -1
- data/templates/gemfiles/activerecord-5.2/Gemfile.mysql2.erb +2 -2
- data/templates/gemfiles/activerecord-5.2/Gemfile.postgresql.erb +2 -2
- data/templates/gemfiles/activerecord-5.2/Gemfile.sqlite3.erb +3 -3
- data/templates/gemfiles/activerecord-6.0/Gemfile.base.erb +4 -0
- data/templates/gemfiles/activerecord-6.0/Gemfile.mysql2.erb +10 -0
- data/templates/gemfiles/activerecord-6.0/Gemfile.postgresql.erb +10 -0
- data/templates/gemfiles/{activerecord-3.2 → activerecord-6.0}/Gemfile.sqlite3.erb +2 -2
- data/templates/gemfiles/activerecord-6.1/Gemfile.base.erb +4 -0
- data/templates/gemfiles/activerecord-6.1/Gemfile.mysql2.erb +10 -0
- data/templates/gemfiles/activerecord-6.1/Gemfile.postgresql.erb +10 -0
- data/templates/gemfiles/{activerecord-4.0 → activerecord-6.1}/Gemfile.sqlite3.erb +2 -2
- metadata +56 -156
- data/.travis.yml +0 -4
- data/lib/schema_dev/tasks/coveralls.rb +0 -3
- data/lib/schema_dev/travis.rb +0 -118
- data/spec/config_spec.rb +0 -61
- data/spec/gem_spec.rb +0 -77
- data/spec/gemfile_sepector_spec.rb +0 -10
- data/spec/gemfiles_spec.rb +0 -43
- data/spec/runner_spec.rb +0 -106
- data/spec/travis_spec.rb +0 -298
- data/templates/gemfiles/activerecord-3.2/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-3.2/Gemfile.mysql.erb +0 -10
- data/templates/gemfiles/activerecord-3.2/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-3.2/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-4.0/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-4.0/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-4.0/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-4.1/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-4.1/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-4.1/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-4.1/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-4.2/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-4.2/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-4.2/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-4.2/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.0/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-4.2.0/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.0/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.0/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.1/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-4.2.1/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.1/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.1/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.6/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-4.2.6/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.6/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-4.2.6/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.0/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.0/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.0/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.0/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.0/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.0.0/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.0/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.0/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.1/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.0.1/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.1/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.1/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.2/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.0.2/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.2/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.2/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.3/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.0.3/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.3/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.0.3/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.1/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.1/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.1/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.1/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.1.0/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.1.0/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.1.0/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.1.0/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-5.1.1/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-5.1.1/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-5.1.1/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-5.1.1/Gemfile.sqlite3.erb +0 -10
- data/templates/gemfiles/activerecord-edge/Gemfile.base.erb +0 -3
- data/templates/gemfiles/activerecord-edge/Gemfile.mysql2.erb +0 -10
- data/templates/gemfiles/activerecord-edge/Gemfile.postgresql.erb +0 -10
- data/templates/gemfiles/activerecord-edge/Gemfile.sqlite3.erb +0 -10
data/lib/schema_dev/gemfiles.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pathname'
|
2
4
|
require 'tmpdir'
|
3
5
|
|
4
6
|
require_relative 'templates'
|
5
7
|
|
6
8
|
module SchemaDev
|
7
|
-
|
8
9
|
module Gemfiles
|
9
10
|
extend self
|
10
11
|
|
@@ -12,9 +13,9 @@ module SchemaDev
|
|
12
13
|
Dir.mktmpdir do |tmpdir|
|
13
14
|
@tmpdir = Pathname.new(tmpdir).realpath
|
14
15
|
|
15
|
-
gemfiles = Pathname(
|
16
|
+
gemfiles = Pathname('gemfiles')
|
16
17
|
tmp_root = @tmpdir + gemfiles
|
17
|
-
target_root = Pathname.new(
|
18
|
+
target_root = Pathname.new('.').realpath + gemfiles
|
18
19
|
|
19
20
|
_install gemfiles + 'Gemfile.base'
|
20
21
|
|
@@ -22,11 +23,11 @@ module SchemaDev
|
|
22
23
|
activerecord_path = gemfiles + "activerecord-#{activerecord}"
|
23
24
|
_install activerecord_path + 'Gemfile.base'
|
24
25
|
config.db.each do |db|
|
25
|
-
_install
|
26
|
+
_install activerecord_path + "Gemfile.#{db}"
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
if `diff -rq #{tmp_root} #{target_root} 2>&1 | grep -v lock`.
|
30
|
+
if `diff -rq #{tmp_root} #{target_root} 2>&1 | grep -v lock`.empty?
|
30
31
|
return false
|
31
32
|
end
|
32
33
|
|
@@ -0,0 +1,266 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
require_relative 'gemfile_selector'
|
7
|
+
|
8
|
+
module SchemaDev
|
9
|
+
module GithubActions
|
10
|
+
extend self
|
11
|
+
|
12
|
+
WORKFLOW_FILE = '.github/workflows/prs.yml'
|
13
|
+
|
14
|
+
HEADER = <<~YAML
|
15
|
+
# This file was auto-generated by the schema_dev tool, based on the data in
|
16
|
+
# ./schema_dev.yml
|
17
|
+
# Please do not edit this file; any changes will be overwritten next time
|
18
|
+
# schema_dev gets run.
|
19
|
+
YAML
|
20
|
+
|
21
|
+
BASIC_WORKFLOW = {
|
22
|
+
name: 'CI PR Builds',
|
23
|
+
on: {
|
24
|
+
push: {
|
25
|
+
branches: %w[master],
|
26
|
+
},
|
27
|
+
pull_request: nil,
|
28
|
+
},
|
29
|
+
concurrency: {
|
30
|
+
group: '${{ github.head_ref }}',
|
31
|
+
'cancel-in-progress': true,
|
32
|
+
}
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
BASIC_JOB = { 'runs-on': 'ubuntu-latest' }.freeze
|
36
|
+
|
37
|
+
BASIC_ENV = {
|
38
|
+
BUNDLE_GEMFILE: '${{ github.workspace }}/gemfiles/activerecord-${{ matrix.activerecord }}/Gemfile.${{ matrix.db }}'
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
FINISH_STEPS = [
|
42
|
+
{
|
43
|
+
name: 'Coveralls Finished',
|
44
|
+
if: '${{ !env.ACT }}',
|
45
|
+
uses: 'coverallsapp/github-action@master',
|
46
|
+
with: {
|
47
|
+
'github-token': '${{ secrets.GITHUB_TOKEN }}',
|
48
|
+
'parallel-finished': true,
|
49
|
+
}
|
50
|
+
}
|
51
|
+
].freeze
|
52
|
+
|
53
|
+
STEPS = {
|
54
|
+
start: [
|
55
|
+
{
|
56
|
+
uses: 'actions/checkout@v2',
|
57
|
+
},
|
58
|
+
{
|
59
|
+
name: 'Set up Ruby',
|
60
|
+
uses: 'ruby/setup-ruby@v1',
|
61
|
+
with: {
|
62
|
+
'ruby-version': '${{ matrix.ruby }}',
|
63
|
+
'bundler-cache': true,
|
64
|
+
},
|
65
|
+
},
|
66
|
+
{
|
67
|
+
name: 'Run bundle update',
|
68
|
+
run: 'bundle update',
|
69
|
+
},
|
70
|
+
],
|
71
|
+
test: [
|
72
|
+
{
|
73
|
+
name: 'Run tests',
|
74
|
+
run: 'bundle exec rake spec',
|
75
|
+
}
|
76
|
+
],
|
77
|
+
finish: [
|
78
|
+
{
|
79
|
+
name: 'Coveralls Parallel',
|
80
|
+
if: '${{ !env.ACT }}',
|
81
|
+
uses: 'coverallsapp/github-action@master',
|
82
|
+
with: {
|
83
|
+
'github-token': '${{ secrets.GITHUB_TOKEN }}',
|
84
|
+
'flag-name': 'run-${{ matrix.ruby }}-${{ matrix.activerecord }}-${{ matrix.db }}-${{ matrix.dbversion }}',
|
85
|
+
parallel: true,
|
86
|
+
}
|
87
|
+
}
|
88
|
+
],
|
89
|
+
}.freeze
|
90
|
+
|
91
|
+
DB_ENV = {
|
92
|
+
postgresql: {
|
93
|
+
POSTGRESQL_DB_HOST: '127.0.0.1',
|
94
|
+
POSTGRESQL_DB_USER: 'schema_plus_test',
|
95
|
+
POSTGRESQL_DB_PASS: 'database',
|
96
|
+
},
|
97
|
+
mysql2: {
|
98
|
+
MYSQL_DB_HOST: '127.0.0.1',
|
99
|
+
MYSQL_DB_USER: 'root',
|
100
|
+
MYSQL_DB_PASS: 'database',
|
101
|
+
},
|
102
|
+
}.freeze
|
103
|
+
|
104
|
+
DB_STARTUP = {
|
105
|
+
postgresql: [
|
106
|
+
{
|
107
|
+
name: 'Start Postgresql',
|
108
|
+
if: "matrix.db == 'postgresql'",
|
109
|
+
run: <<~BASH
|
110
|
+
docker run --rm --detach \\
|
111
|
+
-e POSTGRES_USER=$POSTGRESQL_DB_USER \\
|
112
|
+
-e POSTGRES_PASSWORD=$POSTGRESQL_DB_PASS \\
|
113
|
+
-p 5432:5432 \\
|
114
|
+
--health-cmd "pg_isready -q" \\
|
115
|
+
--health-interval 5s \\
|
116
|
+
--health-timeout 5s \\
|
117
|
+
--health-retries 5 \\
|
118
|
+
--name database postgres:${{ matrix.dbversion }}
|
119
|
+
BASH
|
120
|
+
},
|
121
|
+
],
|
122
|
+
mysql2: [
|
123
|
+
{
|
124
|
+
name: 'Start Mysql',
|
125
|
+
if: "matrix.db == 'mysql2'",
|
126
|
+
run: <<~BASH
|
127
|
+
docker run --rm --detach \\
|
128
|
+
-e MYSQL_ROOT_PASSWORD=$MYSQL_DB_PASS \\
|
129
|
+
-p 3306:3306 \\
|
130
|
+
--health-cmd "mysqladmin ping --host=127.0.0.1 --password=$MYSQL_DB_PASS --silent" \\
|
131
|
+
--health-interval 5s \\
|
132
|
+
--health-timeout 5s \\
|
133
|
+
--health-retries 5 \\
|
134
|
+
--name database mysql:5.6
|
135
|
+
BASH
|
136
|
+
}
|
137
|
+
],
|
138
|
+
}.freeze
|
139
|
+
|
140
|
+
DB_SETUP_NEEDED = %w[postgresql mysql2].freeze
|
141
|
+
DB_SETUP = [
|
142
|
+
{
|
143
|
+
name: 'Wait for database to start',
|
144
|
+
if: "(matrix.db == 'postgresql' || matrix.db == 'mysql2')",
|
145
|
+
run: <<~BASH
|
146
|
+
COUNT=0
|
147
|
+
ATTEMPTS=20
|
148
|
+
until [[ $COUNT -eq $ATTEMPTS ]]; do
|
149
|
+
[ "$(docker inspect -f {{.State.Health.Status}} database)" == "healthy" ] && break
|
150
|
+
echo $(( COUNT++ )) > /dev/null
|
151
|
+
sleep 2
|
152
|
+
done
|
153
|
+
BASH
|
154
|
+
},
|
155
|
+
{
|
156
|
+
name: 'Create testing database',
|
157
|
+
if: "(matrix.db == 'postgresql' || matrix.db == 'mysql2')",
|
158
|
+
run: 'bundle exec rake create_ci_database',
|
159
|
+
},
|
160
|
+
].freeze
|
161
|
+
DB_TEARDOWN_NEEDED = %w[postgresql mysql2].freeze
|
162
|
+
DB_TEARDOWN = [
|
163
|
+
{
|
164
|
+
name: 'Shutdown database',
|
165
|
+
if: "always() && (matrix.db == 'postgresql' || matrix.db == 'mysql2')",
|
166
|
+
run: 'docker stop database',
|
167
|
+
}
|
168
|
+
].freeze
|
169
|
+
|
170
|
+
def build(config)
|
171
|
+
matrix, env = build_matrices(config)
|
172
|
+
db_setup = []
|
173
|
+
db_teardown = []
|
174
|
+
config.db.each do |db|
|
175
|
+
db_setup.concat DB_STARTUP.fetch(db.to_sym, [])
|
176
|
+
end
|
177
|
+
db_setup.concat(DB_SETUP) if config.db.any? { |e| DB_SETUP_NEEDED.include?(e) }
|
178
|
+
db_teardown.concat(DB_TEARDOWN) if config.db.any? { |e| DB_TEARDOWN_NEEDED.include?(e) }
|
179
|
+
|
180
|
+
strategy = {
|
181
|
+
'fail-fast': false,
|
182
|
+
matrix: matrix,
|
183
|
+
}
|
184
|
+
|
185
|
+
steps = [
|
186
|
+
*STEPS[:start],
|
187
|
+
*db_setup,
|
188
|
+
*STEPS[:test],
|
189
|
+
*db_teardown,
|
190
|
+
*STEPS[:finish],
|
191
|
+
]
|
192
|
+
|
193
|
+
{}.tap do |workflow|
|
194
|
+
workflow.merge!(BASIC_WORKFLOW)
|
195
|
+
workflow[:jobs] = {
|
196
|
+
test: {}.merge(BASIC_JOB)
|
197
|
+
.merge({
|
198
|
+
strategy: strategy,
|
199
|
+
env: env,
|
200
|
+
steps: steps
|
201
|
+
}.compact),
|
202
|
+
finish: {
|
203
|
+
needs: 'test'
|
204
|
+
}.merge(BASIC_JOB)
|
205
|
+
.merge(steps: FINISH_STEPS)
|
206
|
+
}
|
207
|
+
end.deep_stringify_keys
|
208
|
+
end
|
209
|
+
|
210
|
+
def build_matrices(config)
|
211
|
+
include_skip = false
|
212
|
+
|
213
|
+
matrix = {
|
214
|
+
ruby: config.ruby,
|
215
|
+
activerecord: config.activerecord,
|
216
|
+
db: [*config.db],
|
217
|
+
dbversion: [],
|
218
|
+
exclude: [],
|
219
|
+
include: [],
|
220
|
+
}
|
221
|
+
|
222
|
+
if config.exclude.any?
|
223
|
+
matrix[:exclude] = config.exclude.map(&:to_hash).reject { |e| e.key?(:dbversion) }
|
224
|
+
end
|
225
|
+
|
226
|
+
env = {}.merge(BASIC_ENV)
|
227
|
+
config.db.each do |db|
|
228
|
+
env.merge!(DB_ENV.fetch(db.to_sym, {}))
|
229
|
+
end
|
230
|
+
|
231
|
+
if config.db.include?('postgresql')
|
232
|
+
include_skip = true
|
233
|
+
matrix[:db].delete('postgresql')
|
234
|
+
config.matrix(db: 'postgresql', with_dbversion: true).map do |entry|
|
235
|
+
matrix[:include] << entry
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
if include_skip
|
240
|
+
matrix[:db] << 'skip'
|
241
|
+
matrix[:dbversion] << 'skip'
|
242
|
+
matrix[:exclude] << { db: 'skip', dbversion: 'skip' }
|
243
|
+
end
|
244
|
+
|
245
|
+
[
|
246
|
+
matrix.reject { |_, val| val.empty? },
|
247
|
+
env
|
248
|
+
]
|
249
|
+
end
|
250
|
+
|
251
|
+
def update(config)
|
252
|
+
filepath = Pathname.new(WORKFLOW_FILE)
|
253
|
+
filepath.dirname.mkpath
|
254
|
+
newworkflow = build(config)
|
255
|
+
oldworkflow = YAML.safe_load(filepath.read) rescue nil
|
256
|
+
if oldworkflow != newworkflow
|
257
|
+
yaml_output = newworkflow.to_yaml(line_width: -1)
|
258
|
+
# fix for some broken libyaml implementations (< 0.2.5)
|
259
|
+
yaml_output.gsub!('pull_request: ', 'pull_request:')
|
260
|
+
filepath.write HEADER + yaml_output
|
261
|
+
return true
|
262
|
+
end
|
263
|
+
false
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'executor'
|
2
4
|
|
3
5
|
module SchemaDev
|
@@ -16,14 +18,14 @@ module SchemaDev
|
|
16
18
|
db = tuple[:db]
|
17
19
|
|
18
20
|
label = "ruby #{ruby} - activerecord #{activerecord} - db #{db}"
|
19
|
-
msg = "#{label} [#{i+1} of #{@matrix.size}]"
|
21
|
+
msg = "#{label} [#{i + 1} of #{@matrix.size}]"
|
20
22
|
puts "\n\n*** #{msg}\n\n"
|
21
23
|
|
22
24
|
if not Executor.new(ruby: ruby, activerecord: activerecord, db: db).run(cmd, dry_run: dry_run)
|
23
25
|
@errors << label
|
24
26
|
end
|
25
27
|
end
|
26
|
-
|
28
|
+
@errors.empty?
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
data/lib/schema_dev/readme.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pathname'
|
2
4
|
|
3
5
|
module SchemaDev
|
4
6
|
class Readme
|
5
7
|
def self.update(config)
|
6
|
-
new(config.matrix).update
|
8
|
+
new(config.matrix(with_dbversion: true)).update
|
7
9
|
end
|
8
10
|
|
9
11
|
attr_accessor :matrix, :readme
|
@@ -15,13 +17,14 @@ module SchemaDev
|
|
15
17
|
|
16
18
|
def update
|
17
19
|
return false unless readme.exist?
|
20
|
+
|
18
21
|
lines = readme.readlines
|
19
22
|
newlines = sub_matrix(lines.dup)
|
20
23
|
newlines = sub_templates(newlines)
|
21
24
|
newreadme = Gem.new(Pathname.pwd.basename.to_s).erb(newlines.join)
|
22
25
|
if newreadme != lines.join
|
23
26
|
readme.write newreadme
|
24
|
-
|
27
|
+
true
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
@@ -29,8 +32,13 @@ module SchemaDev
|
|
29
32
|
replace_block(lines, %r{^\s*<!-- SCHEMA_DEV: MATRIX}) do |contents|
|
30
33
|
contents << "<!-- SCHEMA_DEV: MATRIX - begin -->\n"
|
31
34
|
contents << "<!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->\n"
|
32
|
-
|
33
|
-
|
35
|
+
matrix.group_by { |e| e.slice(:ruby, :activerecord) }.each do |pair, items|
|
36
|
+
dbs = items.map do |item|
|
37
|
+
db = item[:db]
|
38
|
+
db = "#{db}:#{item[:dbversion]}" if item.key?(:dbversion)
|
39
|
+
"**#{db}**"
|
40
|
+
end.to_sentence(last_word_connector: ' or ')
|
41
|
+
contents << "* ruby **#{pair[:ruby]}** with activerecord **#{pair[:activerecord]}**, using #{dbs}\n"
|
34
42
|
end
|
35
43
|
contents << "\n"
|
36
44
|
contents << "<!-- SCHEMA_DEV: MATRIX - end -->\n"
|
@@ -38,14 +46,14 @@ module SchemaDev
|
|
38
46
|
end
|
39
47
|
|
40
48
|
def sub_templates(lines)
|
41
|
-
Pathname.glob(SchemaDev::Templates.root +
|
49
|
+
Pathname.glob(SchemaDev::Templates.root + 'README' + '*.md.erb').each do |template|
|
42
50
|
lines = sub_template(template, lines)
|
43
51
|
end
|
44
52
|
lines
|
45
53
|
end
|
46
54
|
|
47
55
|
def sub_template(template, lines)
|
48
|
-
key = template.basename(
|
56
|
+
key = template.basename('.md.erb').to_s.upcase.tr('.', ' ')
|
49
57
|
|
50
58
|
replace_block(lines, %r{^\s*<!-- SCHEMA_DEV: TEMPLATE #{key}}) do |contents|
|
51
59
|
contents << "<!-- SCHEMA_DEV: TEMPLATE #{key} - begin -->\n"
|
@@ -57,14 +65,13 @@ module SchemaDev
|
|
57
65
|
end
|
58
66
|
|
59
67
|
def replace_block(lines, pattern)
|
60
|
-
before = lines.take_while
|
68
|
+
before = lines.take_while { |e| e !~ pattern }
|
61
69
|
return lines if before == lines
|
62
|
-
|
70
|
+
|
71
|
+
after = lines.reverse.take_while { |e| e !~ pattern }.reverse
|
63
72
|
contents = []
|
64
73
|
yield contents
|
65
74
|
before + contents + after
|
66
75
|
end
|
67
|
-
|
68
|
-
|
69
76
|
end
|
70
77
|
end
|
data/lib/schema_dev/rspec/db.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logger'
|
2
4
|
require 'pathname'
|
3
5
|
require_relative '../gemfile_selector'
|
@@ -8,81 +10,90 @@ module SchemaDev
|
|
8
10
|
extend self
|
9
11
|
|
10
12
|
def setup
|
11
|
-
@db = GemfileSelector.infer_db
|
12
13
|
set_logger
|
13
14
|
connect
|
14
15
|
RSpec.configure do |config|
|
15
16
|
config.include Helpers
|
16
|
-
config.filter_run_excluding :
|
17
|
-
config.filter_run_excluding :
|
18
|
-
config.filter_run_excluding :
|
19
|
-
config.filter_run_excluding :
|
20
|
-
config.filter_run_excluding :
|
21
|
-
config.filter_run_excluding :
|
17
|
+
config.filter_run_excluding postgresql: :only unless Helpers.postgresql?
|
18
|
+
config.filter_run_excluding postgresql: :skip if Helpers.postgresql?
|
19
|
+
config.filter_run_excluding mysql: :only unless Helpers.mysql?
|
20
|
+
config.filter_run_excluding mysql: :skip if Helpers.mysql?
|
21
|
+
config.filter_run_excluding sqlite3: :only unless Helpers.sqlite3?
|
22
|
+
config.filter_run_excluding sqlite3: :skip if Helpers.sqlite3?
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
26
|
def tmproot
|
26
|
-
@tmproot ||= Pathname.new('tmp').tap
|
27
|
+
@tmproot ||= Pathname.new('tmp').tap(&:mkpath)
|
27
28
|
end
|
28
29
|
|
29
30
|
def logroot
|
30
|
-
@logroot ||= Pathname.new('log').tap
|
31
|
+
@logroot ||= Pathname.new('log').tap(&:mkpath)
|
31
32
|
end
|
32
33
|
|
33
34
|
def database
|
34
|
-
@database ||=
|
35
|
+
@database ||= 'schema_plus_test'
|
35
36
|
# @database ||= (Dir["*.gemspec"].first || "schema_dev_test").sub(/\.gemspec$/, '') + "_test"
|
36
37
|
end
|
37
38
|
|
38
|
-
def configuration
|
39
|
-
case
|
39
|
+
def configuration(db: nil)
|
40
|
+
case db || infer_db
|
40
41
|
when 'mysql'
|
41
42
|
{
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
'adapter' => 'mysql',
|
44
|
+
'database' => database,
|
45
|
+
'host' => ENV['MYSQL_DB_HOST'],
|
46
|
+
'username' => ENV.fetch('MYSQL_DB_USER', 'schema_plus'),
|
47
|
+
'password' => ENV['MYSQL_DB_PASS'],
|
48
|
+
'encoding' => 'utf8',
|
49
|
+
'min_messages' => 'warning'
|
47
50
|
}
|
48
51
|
when 'mysql2'
|
49
52
|
{
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
'adapter' => 'mysql2',
|
54
|
+
'database' => database,
|
55
|
+
'host' => ENV['MYSQL_DB_HOST'],
|
56
|
+
'username' => ENV.fetch('MYSQL_DB_USER', 'schema_plus'),
|
57
|
+
'password' => ENV['MYSQL_DB_PASS'],
|
58
|
+
'encoding' => 'utf8',
|
59
|
+
'min_messages' => 'warning'
|
55
60
|
}
|
56
61
|
when 'postgresql'
|
57
62
|
{
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
63
|
+
'adapter' => 'postgresql',
|
64
|
+
'database' => database,
|
65
|
+
'host' => ENV['POSTGRESQL_DB_HOST'],
|
66
|
+
'username' => ENV['POSTGRESQL_DB_USER'],
|
67
|
+
'password' => ENV['POSTGRESQL_DB_PASS'],
|
68
|
+
'min_messages' => 'warning'
|
62
69
|
}
|
63
70
|
when 'sqlite3'
|
64
71
|
{
|
65
|
-
|
66
|
-
|
72
|
+
'adapter' => 'sqlite3',
|
73
|
+
'database' => tmproot.join("#{database}.sqlite3").to_s
|
67
74
|
}
|
68
75
|
else
|
69
|
-
raise "Unknown db adapter #{
|
70
|
-
end
|
76
|
+
raise "Unknown db adapter #{db.inspect}"
|
77
|
+
end.compact
|
78
|
+
end
|
79
|
+
|
80
|
+
def infer_db
|
81
|
+
@infer_db ||= GemfileSelector.infer_db
|
71
82
|
end
|
72
83
|
|
73
84
|
def connect
|
74
85
|
ActiveRecord::Base.configurations = { 'schema_dev' => configuration }
|
75
86
|
ActiveRecord::Base.establish_connection :schema_dev
|
76
|
-
case
|
87
|
+
case infer_db
|
77
88
|
when 'sqlite3'
|
78
|
-
ActiveRecord::Base.connection.execute
|
89
|
+
ActiveRecord::Base.connection.execute 'PRAGMA synchronous = OFF'
|
79
90
|
end
|
80
91
|
end
|
81
92
|
|
82
93
|
def set_logger
|
83
94
|
ruby = "#{RUBY_ENGINE}#{RUBY_VERSION}"
|
84
95
|
activerecord = "activerecord#{ActiveRecord.version}"
|
85
|
-
ActiveRecord::Base.logger = Logger.new(logroot.join("#{ruby}-#{activerecord}-#{
|
96
|
+
ActiveRecord::Base.logger = Logger.new(logroot.join("#{ruby}-#{activerecord}-#{infer_db}.log").open('w'))
|
86
97
|
end
|
87
98
|
|
88
99
|
module Helpers
|
data/lib/schema_dev/rspec.rb
CHANGED
@@ -1,24 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'rspec/db'
|
2
4
|
|
3
5
|
module SchemaDev
|
4
6
|
module Rspec
|
5
|
-
|
6
7
|
def self.setup
|
7
8
|
Db.setup
|
8
9
|
end
|
9
10
|
|
10
|
-
def self.
|
11
|
-
|
12
|
-
self.setup
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.db_configuration
|
16
|
-
Db.configuration
|
11
|
+
def self.db_configuration(db: nil)
|
12
|
+
Db.configuration(db: db)
|
17
13
|
end
|
18
14
|
|
19
15
|
module Helpers
|
20
16
|
extend Rspec::Db::Helpers
|
21
17
|
end
|
22
18
|
end
|
23
|
-
|
24
19
|
end
|
@@ -1,14 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pathname'
|
2
4
|
require 'which_works'
|
3
5
|
|
4
6
|
module SchemaDev
|
5
7
|
module RubySelector
|
6
8
|
def self.command(ruby)
|
7
|
-
|
8
|
-
|
9
|
+
selector.command ruby
|
10
|
+
end
|
11
|
+
|
12
|
+
# for rspec, to avoid stickiness
|
13
|
+
def self._reset
|
14
|
+
@selector = nil
|
9
15
|
end
|
10
|
-
|
11
|
-
|
16
|
+
|
17
|
+
def self.selector
|
18
|
+
@selector ||= [Chruby, Rvm, Rbenv].find(&:installed?)&.new || abort('No ruby version manager found')
|
12
19
|
end
|
13
20
|
|
14
21
|
class ManagerBase
|
@@ -18,20 +25,27 @@ module SchemaDev
|
|
18
25
|
end
|
19
26
|
|
20
27
|
class Chruby < ManagerBase
|
21
|
-
CORE_COMMAND =
|
28
|
+
CORE_COMMAND = 'chruby-exec'
|
22
29
|
|
23
30
|
def initialize
|
24
|
-
|
31
|
+
super
|
32
|
+
|
33
|
+
@rubies = Pathname.new(ENV['HOME'])
|
34
|
+
.join('.rubies')
|
35
|
+
.entries
|
36
|
+
.map { |e| e.basename.to_s }
|
25
37
|
end
|
38
|
+
|
26
39
|
def command(ruby)
|
27
|
-
bash = Which.which 'bash' || abort(
|
28
|
-
ruby = @rubies.select
|
40
|
+
bash = Which.which 'bash' || abort('no bash shell found')
|
41
|
+
ruby = @rubies.select { |e| e =~ /^(ruby-)?#{ruby}(-p.*)?$/ }
|
42
|
+
.last || ruby
|
29
43
|
"SHELL=#{bash} #{CORE_COMMAND} #{ruby} --"
|
30
44
|
end
|
31
45
|
end
|
32
46
|
|
33
47
|
class Rvm < ManagerBase
|
34
|
-
CORE_COMMAND =
|
48
|
+
CORE_COMMAND = 'rvm'
|
35
49
|
|
36
50
|
def command(ruby)
|
37
51
|
"#{CORE_COMMAND} #{ruby} do"
|
@@ -39,25 +53,26 @@ module SchemaDev
|
|
39
53
|
end
|
40
54
|
|
41
55
|
class Rbenv < ManagerBase
|
42
|
-
CORE_COMMAND =
|
56
|
+
CORE_COMMAND = 'rbenv'
|
43
57
|
|
44
58
|
def initialize
|
59
|
+
super
|
60
|
+
|
45
61
|
# because we're running within a ruby program that was launched by
|
46
62
|
# rbenv, we already have various environment variables set up. need
|
47
63
|
# strip those out so that the forked shell can run a diifferent ruby
|
48
64
|
# version than the one we're in now.
|
49
|
-
ENV['PATH'] = ENV['PATH'].split(':').reject{|dir| dir =~ %r{/\.?rbenv/(?!shims)}}.join(':')
|
50
|
-
ENV['GEM_PATH'] = ENV['GEM_PATH'].split(':').reject{|dir| dir =~ %r{/\.?rbenv}}.join(':') unless ENV['GEM_PATH'].nil?
|
65
|
+
ENV['PATH'] = ENV['PATH'].split(':').reject { |dir| dir =~ %r{/\.?rbenv/(?!shims)} }.join(':')
|
66
|
+
ENV['GEM_PATH'] = ENV['GEM_PATH'].split(':').reject { |dir| dir =~ %r{/\.?rbenv} }.join(':') unless ENV['GEM_PATH'].nil?
|
51
67
|
ENV['RBENV_DIR'] = nil
|
52
68
|
ENV['RBENV_HOOK_PATH'] = nil
|
53
69
|
@versions ||= `rbenv versions --bare`.split
|
54
70
|
end
|
55
71
|
|
56
72
|
def command(ruby)
|
57
|
-
version = @versions.select{|v| v.start_with? ruby}.last || abort("no ruby version '#{ruby}' installed in rbenv")
|
73
|
+
version = @versions.select { |v| v.start_with? ruby }.last || abort("no ruby version '#{ruby}' installed in rbenv")
|
58
74
|
"RBENV_VERSION=#{version}"
|
59
75
|
end
|
60
76
|
end
|
61
|
-
|
62
77
|
end
|
63
78
|
end
|