schema_dev 3.13.1 → 4.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/prs.yml +49 -0
  3. data/.simplecov +20 -0
  4. data/Gemfile +2 -0
  5. data/README.md +9 -7
  6. data/Rakefile +3 -5
  7. data/bin/schema_dev +25 -21
  8. data/lib/schema_dev/config.rb +62 -44
  9. data/lib/schema_dev/executor.rb +9 -8
  10. data/lib/schema_dev/gem.rb +45 -37
  11. data/lib/schema_dev/gemfile_selector.rb +7 -7
  12. data/lib/schema_dev/gemfiles.rb +6 -5
  13. data/lib/schema_dev/github_actions.rb +266 -0
  14. data/lib/schema_dev/matrix_executor.rb +4 -2
  15. data/lib/schema_dev/readme.rb +17 -10
  16. data/lib/schema_dev/rspec/db.rb +44 -33
  17. data/lib/schema_dev/rspec.rb +4 -9
  18. data/lib/schema_dev/ruby_selector.rb +29 -14
  19. data/lib/schema_dev/runner.rb +14 -10
  20. data/lib/schema_dev/tasks/dbms.rb +34 -26
  21. data/lib/schema_dev/tasks.rb +2 -3
  22. data/lib/schema_dev/templates.rb +5 -5
  23. data/lib/schema_dev/version.rb +3 -1
  24. data/lib/schema_dev.rb +3 -1
  25. data/schema_dev.gemspec +23 -26
  26. data/spec/schema_dev/config_spec.rb +60 -0
  27. data/spec/schema_dev/gem_spec.rb +74 -0
  28. data/spec/schema_dev/gemfile_selector_spec.rb +11 -0
  29. data/spec/schema_dev/gemfiles_spec.rb +41 -0
  30. data/spec/schema_dev/github_actions_spec.rb +818 -0
  31. data/spec/schema_dev/runner_spec.rb +103 -0
  32. data/spec/spec_helper.rb +5 -6
  33. data/templates/README/uses.schema_dev.md.erb +1 -2
  34. data/templates/gem/GEM_NAME.gemspec.erb +15 -14
  35. data/templates/gem/Gemfile.erb +2 -0
  36. data/templates/gem/Gemfile.local.erb +2 -0
  37. data/templates/gem/README.md.erb +1 -2
  38. data/templates/gem/Rakefile.erb +2 -0
  39. data/templates/gem/schema_dev.yml.erb +4 -1
  40. data/templates/gem/simplecov.erb +20 -0
  41. data/templates/gemfiles/{activerecord-5.0 → activerecord-6.0}/Gemfile.base.erb +1 -1
  42. data/templates/gemfiles/{activerecord-5.0 → activerecord-6.0}/Gemfile.mysql2.erb +0 -0
  43. data/templates/gemfiles/{activerecord-5.1 → activerecord-6.0}/Gemfile.postgresql.erb +1 -1
  44. data/templates/gemfiles/{activerecord-5.0 → activerecord-6.0}/Gemfile.sqlite3.erb +0 -0
  45. data/templates/gemfiles/{activerecord-5.1 → activerecord-6.1}/Gemfile.base.erb +1 -1
  46. data/templates/gemfiles/{activerecord-5.1 → activerecord-6.1}/Gemfile.mysql2.erb +0 -0
  47. data/templates/gemfiles/{activerecord-5.0 → activerecord-6.1}/Gemfile.postgresql.erb +1 -1
  48. data/templates/gemfiles/{activerecord-5.1 → activerecord-6.1}/Gemfile.sqlite3.erb +0 -0
  49. metadata +55 -98
  50. data/.travis.yml +0 -4
  51. data/lib/schema_dev/tasks/coveralls.rb +0 -3
  52. data/lib/schema_dev/travis.rb +0 -139
  53. data/spec/config_spec.rb +0 -61
  54. data/spec/gem_spec.rb +0 -77
  55. data/spec/gemfile_sepector_spec.rb +0 -10
  56. data/spec/gemfiles_spec.rb +0 -41
  57. data/spec/runner_spec.rb +0 -106
  58. data/spec/travis_spec.rb +0 -392
@@ -1,139 +0,0 @@
1
- require 'pathname'
2
- require 'yaml'
3
-
4
- require_relative 'gemfile_selector'
5
-
6
- module SchemaDev
7
- module Travis
8
- extend self
9
-
10
- TRAVIS_FILE = ".travis.yml"
11
-
12
- CONFIG_TEMPLATES = {
13
- postgresql: {
14
- default: {
15
- env: 'POSTGRESQL_DB_USER=postgres'
16
- },
17
- '10' => {
18
- addons: { apt: { packages: %w[postgresql-10 postgresql-client-10] } },
19
- env: 'POSTGRESQL_DB_USER=postgres'
20
- },
21
- '11' => {
22
- addons: { apt: { packages: %w[postgresql-11 postgresql-client-11] } },
23
- env: 'POSTGRESQL_DB_USER=travis PGPORT=5433'
24
- },
25
- '12' => {
26
- addons: { apt: { packages: %w[postgresql-12 postgresql-client-12] } },
27
- env: 'POSTGRESQL_DB_USER=travis PGPORT=5433'
28
- },
29
- }
30
- }.freeze
31
-
32
- def template_for_db(db, version)
33
- {
34
- addons: {
35
- db => version
36
- }
37
- }.deep_merge(CONFIG_TEMPLATES[db][version] || CONFIG_TEMPLATES[db][:default])
38
- .deep_stringify_keys
39
- end
40
-
41
- def build(config)
42
- env = []
43
- include = []
44
- addons = {}
45
- services = []
46
- skip_gemfiles = []
47
- if config.dbms.include?(:postgresql)
48
- versions = config.dbms_versions_for(:postgresql, ['9.6'])
49
- if config.db.count == 1
50
- if versions.count == 1
51
- # only PG and only 1 DB do it globally
52
- template = template_for_db(:postgresql, versions.first)
53
- env << template['env']
54
- addons.merge!(template['addons'])
55
- else
56
- # we only have one DB so we can greatly simplify our include matrix
57
- include.concat versions.map {|version|
58
- {}.merge(template_for_db(:postgresql, version))
59
- }
60
- end
61
- else
62
- # we need to include against the various gemfiles so we only use PG for PG tests (and not other DBs)
63
- config.matrix(db: 'postgresql').map { |entry|
64
- gemfile = GemfileSelector.gemfile(entry.slice(:activerecord, :db)).to_s
65
- skip_gemfiles << gemfile
66
- include.concat versions.map {|version|
67
- {
68
- "gemfile" => gemfile,
69
- "rvm" => entry[:ruby],
70
- }.merge(template_for_db(:postgresql, version))
71
- }
72
- }
73
- end
74
- end
75
- if config.dbms.include?(:mysql)
76
- if config.db.count == 1
77
- env << 'MYSQL_DB_USER=travis'
78
- services << 'mysql'
79
- else
80
- config.matrix(db: 'mysql2').map do |entry|
81
- gemfile = GemfileSelector.gemfile(entry.slice(:activerecord, :db)).to_s
82
- skip_gemfiles << gemfile
83
- include << {
84
- "gemfile" => gemfile,
85
- "rvm" => entry[:ruby],
86
- "services" => ['mysql'],
87
- "env" => 'MYSQL_DB_USER=travis',
88
- }
89
- end
90
- end
91
- end
92
- env = env.join(' ')
93
-
94
- gemfiles = config.matrix.map{|entry| GemfileSelector.gemfile(entry.slice(:activerecord, :db)).to_s}.uniq
95
- gemfiles.reject! { |gemfile| skip_gemfiles.include?(gemfile) }
96
-
97
- exclude = config.matrix(excluded: :only).map { |entry| {}.tap {|ex|
98
- ex["rvm"] = entry[:ruby]
99
- ex["gemfile"] = GemfileSelector.gemfile(entry.slice(:activerecord, :db)).to_s
100
- }}.reject{|ex| not gemfiles.include? ex["gemfile"]}
101
-
102
- {}.tap { |travis|
103
- travis["rvm"] = config.ruby.sort
104
- travis["gemfile"] = gemfiles.sort unless gemfiles.empty?
105
- travis["env"] = env unless env.empty?
106
- travis["addons"] = addons unless addons.empty?
107
- travis["services"] = services unless services.empty?
108
- if config.dbms.any?
109
- travis["before_script"] = 'bundle exec rake create_databases'
110
- travis["after_script"] = 'bundle exec rake drop_databases'
111
- end
112
- travis["script"] = "bundle exec rake travis"
113
- travis["notifications"] = { "email" => config.notify } if config.notify.any?
114
- travis["jobs"] = {}
115
- travis["jobs"]["exclude"] = exclude.sort_by{|ex| [ex["rvm"], ex["gemfile"]]} if exclude.any?
116
- if include.any?
117
- travis["jobs"]["include"] = include.sort_by{|ex| [ex.fetch('rvm', ''), ex.fetch('gemfile', '')]}
118
- end
119
- travis.delete("jobs") if travis["jobs"].empty?
120
- }
121
- end
122
-
123
- def update(config)
124
- filepath = Pathname.new(TRAVIS_FILE)
125
- newtravis = build(config)
126
- oldtravis = YAML.load(filepath.read) rescue nil
127
- if oldtravis != newtravis
128
- header = <<-ENDYAML
129
- # This file was auto-generated by the schema_dev tool, based on the data in
130
- # ./schema_dev.yml
131
- # Please do not edit this file; any changes will be overwritten next time
132
- # schema_dev gets run.
133
- ENDYAML
134
- filepath.write header + newtravis.to_yaml
135
- return true
136
- end
137
- end
138
- end
139
- end
data/spec/config_spec.rb DELETED
@@ -1,61 +0,0 @@
1
- describe SchemaDev::Config do
2
-
3
- it "computes matrix" do
4
- config = get_config(ruby: %W[1.9.3 2.1.5], activerecord: %W[4.0 4.1], db: %W[sqlite3 postgresql])
5
- expect(config.matrix).to match_array [
6
- { ruby: "1.9.3", activerecord: "4.0", db: "sqlite3" },
7
- { ruby: "1.9.3", activerecord: "4.0", db: "postgresql" },
8
- { ruby: "1.9.3", activerecord: "4.1", db: "sqlite3" },
9
- { ruby: "1.9.3", activerecord: "4.1", db: "postgresql" },
10
- { ruby: "2.1.5", activerecord: "4.0", db: "sqlite3" },
11
- { ruby: "2.1.5", activerecord: "4.0", db: "postgresql" },
12
- { ruby: "2.1.5", activerecord: "4.1", db: "sqlite3" },
13
- { ruby: "2.1.5", activerecord: "4.1", db: "postgresql" },
14
- ]
15
- end
16
-
17
- it "excludes explicit elements from matrix" do
18
- config = get_config(ruby: %W[1.9.3 2.1.5], activerecord: %W[4.0 4.1], db: %W[sqlite3 postgresql],
19
- exclude: [
20
- { ruby: "1.9.3", activerecord: "4.1", db: "postgresql" },
21
- { ruby: "2.1.5", activerecord: "4.0", db: "sqlite3" } ]
22
- )
23
- expect(config.matrix).to match_array [
24
- { ruby: "1.9.3", activerecord: "4.0", db: "sqlite3" },
25
- { ruby: "1.9.3", activerecord: "4.0", db: "postgresql" },
26
- { ruby: "1.9.3", activerecord: "4.1", db: "sqlite3" },
27
- # { ruby: "1.9.3", activerecord: "4.1", db: "postgresql" },
28
- # { ruby: "2.1.5", activerecord: "4.0", db: "sqlite3" },
29
- { ruby: "2.1.5", activerecord: "4.0", db: "postgresql" },
30
- { ruby: "2.1.5", activerecord: "4.1", db: "sqlite3" },
31
- { ruby: "2.1.5", activerecord: "4.1", db: "postgresql" },
32
- ]
33
- end
34
-
35
- it "excludes slices from matrix" do
36
- config = get_config(ruby: %W[1.9.3 2.1.5], activerecord: %W[4.0 4.1], db: %W[sqlite3 postgresql],
37
- exclude: [
38
- { ruby: "1.9.3", activerecord: "4.1"},
39
- { ruby: "2.1.5", db: "sqlite3" } ]
40
- )
41
- expect(config.matrix).to match_array [
42
- { ruby: "1.9.3", activerecord: "4.0", db: "sqlite3" },
43
- { ruby: "1.9.3", activerecord: "4.0", db: "postgresql" },
44
- #{ ruby: "1.9.3", activerecord: "4.1", db: "sqlite3" },
45
- #{ ruby: "1.9.3", activerecord: "4.1", db: "postgresql" },
46
- #{ ruby: "2.1.5", activerecord: "4.0", db: "sqlite3" },
47
- { ruby: "2.1.5", activerecord: "4.0", db: "postgresql" },
48
- #{ ruby: "2.1.5", activerecord: "4.1", db: "sqlite3" },
49
- { ruby: "2.1.5", activerecord: "4.1", db: "postgresql" },
50
- ]
51
- end
52
-
53
- it "uses last cell for --quick" do
54
- config = get_config(ruby: %W[1.9.3 2.1.5], activerecord: %W[4.0 4.1], db: %W[sqlite3 postgresql])
55
- expect(config.matrix quick: true).to match_array [
56
- { ruby: "2.1.5", activerecord: "4.1", db: "postgresql" },
57
- ]
58
- end
59
-
60
-
61
- end
data/spec/gem_spec.rb DELETED
@@ -1,77 +0,0 @@
1
- require 'schema_dev/gem'
2
-
3
- describe SchemaDev::Gem do
4
-
5
- around(:each) do |example|
6
- in_tmpdir do
7
- suppress_stdout_stderr do
8
- example.run
9
- end
10
- end
11
- end
12
-
13
- Given(:user_name) { "My Name" }
14
- Given(:user_email) { "my_name@example.com" }
15
-
16
- Given {
17
- allow_any_instance_of(SchemaDev::Gem).to receive(:`).with("git config user.name").and_return user_name
18
- allow_any_instance_of(SchemaDev::Gem).to receive(:`).with("git config user.email").and_return user_email
19
- }
20
-
21
- context "builds" do
22
-
23
- Given {
24
- stub_request(:get, 'https://rubygems.org/api/v1/versions/schema_plus_core.json').to_return body: JSON.generate([
25
- { number: "1.0.0.pre", prerelease: true},
26
- { number: "0.2.1"},
27
- { number: "0.1.2"},
28
- { number: "0.1.1" },
29
- ])
30
- }
31
-
32
- When { SchemaDev::Gem.build gem_name }
33
-
34
- When(:gemspec) { File.read "#{gem_name}/#{gem_name}.gemspec" }
35
- When(:readme) { File.read "#{gem_name}/README.md" }
36
-
37
- Invariant { expect(readme).to include %q{<!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->} }
38
- Invariant { expect(readme).to include %q{<!-- These lines are auto-inserted from a schema_dev template -->} }
39
-
40
- Invariant { expect(gemspec).to include %q{"schema_plus_core", "~> 0.2", ">= 0.2.1"} }
41
- Invariant { expect(gemspec).to match %r{authors.*#{user_name}} }
42
- Invariant { expect(gemspec).to match %r{email.*#{user_email}} }
43
-
44
- context "flat gem" do
45
- Given(:gem_name) { "new_gem" }
46
- Then { expect(gemspec).to include %q{require 'new_gem/version'} }
47
- Then { expect(File.read "new_gem/lib/new_gem.rb").to include %q{SchemaMonkey.register NewGem} }
48
- end
49
-
50
- context "subdir gem" do
51
- Given(:gem_name) { "schema_plus_new_gem" }
52
- Then { expect(gemspec).to include %q{require 'schema_plus/new_gem/version'} }
53
- Then { expect(File.read "schema_plus_new_gem/lib/schema_plus_new_gem.rb").to include %q{require_relative 'schema_plus/new_gem'} }
54
- Then { expect(File.read "schema_plus_new_gem/lib/schema_plus/new_gem.rb").to include %q{SchemaMonkey.register SchemaPlus::NewGem} }
55
- end
56
- end
57
-
58
-
59
- context "complains" do
60
-
61
- context "when no git user.name" do
62
- Given(:user_name) { "" }
63
- Then { expect{SchemaDev::Gem.build("NewGem")}.to raise_error SystemExit, /who are you/i }
64
- end
65
-
66
- context "when in git worktree" do
67
- Given { expect_any_instance_of(SchemaDev::Gem).to receive(:system).with(/^git rev-parse/).and_return true }
68
- Then { expect{SchemaDev::Gem.build("NewGem")}.to raise_error SystemExit, /\bgit\b/ }
69
- end
70
-
71
- context "when gem directory exists" do
72
- Given { FileUtils.touch "new_gem" }
73
- Then { expect{SchemaDev::Gem.build("NewGem")}.to raise_error SystemExit, /exists/ }
74
- end
75
- end
76
-
77
- end
@@ -1,10 +0,0 @@
1
- require 'schema_dev/gemfile_selector'
2
-
3
- describe SchemaDev::GemfileSelector do
4
-
5
- it "infers db from env" do
6
- test_dbname = 'this_is_a_test'
7
- ENV['BUNDLE_GEMFILE'] = SchemaDev::GemfileSelector.gemfile(activerecord: '4.1', db: test_dbname).to_s
8
- expect(SchemaDev::GemfileSelector.infer_db).to eq test_dbname
9
- end
10
- end
@@ -1,41 +0,0 @@
1
- require 'schema_dev/gemfiles'
2
-
3
- describe SchemaDev::Gemfiles do
4
-
5
- it "copies listed files" do
6
- config = get_config(ruby: %W[1.9.3 2.1.5], activerecord: %W[5.1 5.2], db: %W[sqlite3 postgresql])
7
- in_tmpdir do
8
- expect(SchemaDev::Gemfiles.build(config)).to be_truthy
9
- expect(relevant_diff(config, "gemfiles")).to be_empty
10
- end
11
- end
12
-
13
- it "only copies files once" do
14
- config = get_config(ruby: %W[1.9.3 2.1.5], activerecord: %W[5.1 5.2], db: %W[sqlite3 postgresql])
15
- in_tmpdir do
16
- expect(SchemaDev::Gemfiles.build(config)).to be_truthy
17
- expect(SchemaDev::Gemfiles.build(config)).to be_falsey
18
- end
19
- end
20
-
21
- def relevant_diff(config, dir)
22
- Dir.mktmpdir do |no_erb_root|
23
- no_erb_root = Pathname(no_erb_root)
24
- erb_root = SchemaDev::Templates.root + dir
25
- Pathname.glob(erb_root + "**/*").select(&:file?).each do |p|
26
- d = (no_erb_root+p.relative_path_from(erb_root)).sub_ext('')
27
- d.dirname.mkpath
28
- d.write p.read
29
- end
30
-
31
- diff = `diff -rq #{no_erb_root} #{dir} 2>&1`.split("\n")
32
-
33
- # expect copy not to have entry for activerecord not in config
34
- diff.reject!{ |d| d =~ %r[Only in #{no_erb_root}: activerecord-(.*)] and not config.activerecord.include? $1 }
35
-
36
- # expect copy not to have entry for db not in config
37
- diff.reject!{ |d| d =~ %r[Only in #{no_erb_root}.*: Gemfile.(.*)] and not config.db.include? $1 }
38
- end
39
- end
40
-
41
- end
data/spec/runner_spec.rb DELETED
@@ -1,106 +0,0 @@
1
- require 'schema_dev/runner'
2
- require 'which_works'
3
- require 'pathname'
4
-
5
- describe SchemaDev::Runner do
6
-
7
- it "creates gemfiles" do
8
- config = get_config(ruby: "2.1.3", activerecord: "5.2", db: "sqlite3")
9
- runner = SchemaDev::Runner.new(config)
10
- in_tmpdir do
11
- expect{ runner.gemfiles }.to output("* Updated gemfiles\n").to_stdout
12
- expect(Pathname.new("gemfiles")).to be_directory
13
- end
14
- end
15
-
16
- it "creates travis" do
17
- config = get_config(ruby: "2.1.3", activerecord: "5.2", db: "sqlite3")
18
- runner = SchemaDev::Runner.new(config)
19
- in_tmpdir do
20
- expect{ runner.travis }.to output("* Updated .travis.yml\n").to_stdout
21
- expect(Pathname.new(".travis.yml")).to be_file
22
- end
23
- end
24
-
25
- Selectors = {
26
- 'chruby-exec' => "SHELL=/usr/local/bin/bash chruby-exec ruby-#{RUBY_VERSION} --",
27
- 'rvm' => "rvm #{RUBY_VERSION} do",
28
- 'rbenv' => "RBENV_VERSION=#{RUBY_VERSION}"
29
- }
30
-
31
- Selectors.each do |selector, selection_command|
32
-
33
- describe "matrix (#{selector})" do
34
- before(:each) do
35
- # mocking Which.which to find selector
36
- SchemaDev::RubySelector._reset
37
- allow(Which).to receive(:which) {|cmd| ["bash", selector].include?(cmd) ? "/usr/local/bin/#{cmd}" : nil }
38
- case selector
39
- when 'chruby-exec'
40
- expect_any_instance_of(Pathname).to receive(:entries).and_return [Pathname.new("ruby-#{RUBY_VERSION}")]
41
- when 'rbenv'
42
- expect_any_instance_of(SchemaDev::RubySelector::Rbenv).to receive(:`).with("rbenv versions --bare").and_return RUBY_VERSION
43
- end
44
-
45
- # mocking execution
46
- original_popen2e = Open3.method(:popen2e)
47
- allow(Open3).to receive(:popen2e) { |cmd, &block|
48
- cmd = case cmd
49
- when /false$/ then "false"
50
- when /true$/ then "true"
51
- else cmd.sub(/.*echo/, "echo")
52
- end
53
- original_popen2e.call(cmd, &block)
54
- }
55
- end
56
-
57
- let(:config) { get_config(ruby: RUBY_VERSION, activerecord: "5.2", db: %W[sqlite3 postgresql]) }
58
- let(:runner) { SchemaDev::Runner.new(config) }
59
-
60
-
61
- let(:expected_output) { <<ENDOUTPUT.strip }
62
- * Updated .travis.yml
63
- * Updated gemfiles
64
-
65
-
66
- *** ruby #{RUBY_VERSION} - activerecord 5.2 - db sqlite3 [1 of 2]
67
-
68
- * /usr/bin/env BUNDLE_GEMFILE=gemfiles/activerecord-5.2/Gemfile.sqlite3 #{selection_command} %{cmd}
69
- %{output}
70
-
71
- *** ruby #{RUBY_VERSION} - activerecord 5.2 - db postgresql [2 of 2]
72
-
73
- * /usr/bin/env BUNDLE_GEMFILE=gemfiles/activerecord-5.2/Gemfile.postgresql #{selection_command} %{cmd}
74
- %{output}
75
- ENDOUTPUT
76
-
77
- it "runs successfully" do
78
- in_tmpdir do
79
- expect{ runner.run("true") }.to output(expected_output % {cmd: 'true', output: nil}).to_stdout
80
- end
81
- end
82
-
83
- it "reports error exits" do
84
- in_tmpdir do
85
- expect{ runner.run("false") }.to output(expected_output % {cmd: 'false', output: nil} + <<-ENDERR).to_stdout
86
-
87
- *** 2 failures:
88
- \truby #{RUBY_VERSION} - activerecord 5.2 - db sqlite3
89
- \truby #{RUBY_VERSION} - activerecord 5.2 - db postgresql
90
- ENDERR
91
- end
92
- end
93
-
94
- it "reports error messages" do
95
- in_tmpdir do
96
- expect{ runner.run("echo", "LoadError") }.to output(expected_output % {cmd: 'echo LoadError', output: "LoadError\n"} + <<-ENDERR).to_stdout
97
-
98
- *** 2 failures:
99
- \truby #{RUBY_VERSION} - activerecord 5.2 - db sqlite3
100
- \truby #{RUBY_VERSION} - activerecord 5.2 - db postgresql
101
- ENDERR
102
- end
103
- end
104
- end
105
- end
106
- end