schema_dev 4.0.0 → 4.1.0

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 (50) 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 +7 -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. metadata +38 -87
  42. data/.travis.yml +0 -4
  43. data/lib/schema_dev/tasks/coveralls.rb +0 -3
  44. data/lib/schema_dev/travis.rb +0 -147
  45. data/spec/config_spec.rb +0 -61
  46. data/spec/gem_spec.rb +0 -77
  47. data/spec/gemfile_sepector_spec.rb +0 -10
  48. data/spec/gemfiles_spec.rb +0 -41
  49. data/spec/runner_spec.rb +0 -106
  50. data/spec/travis_spec.rb +0 -392
@@ -1,38 +1,42 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'shellwords'
2
4
 
3
5
  require_relative 'matrix_executor'
4
- require_relative 'travis'
6
+ require_relative 'github_actions'
5
7
  require_relative 'gemfiles'
6
8
  require_relative 'readme'
7
9
 
8
10
  module SchemaDev
9
11
  class Runner
12
+ attr_reader :config
13
+
10
14
  def initialize(config)
11
15
  @config = config
12
16
  end
13
17
 
14
- def travis(quiet: false)
15
- if Travis.update(@config)
16
- puts "* Updated #{Travis::TRAVIS_FILE}" unless quiet
18
+ def github_actions(quiet: false)
19
+ if GithubActions.update(@config)
20
+ puts "* Updated #{GithubActions::WORKFLOW_FILE}" unless quiet
17
21
  end
18
22
  end
19
23
 
20
24
  def gemfiles(quiet: false)
21
25
  if Gemfiles.build(@config)
22
- puts "* Updated gemfiles" unless quiet
26
+ puts '* Updated gemfiles' unless quiet
23
27
  end
24
28
  end
25
29
 
26
30
  def readme(quiet: false)
27
31
  if Readme.update(@config)
28
- puts "* Updated README" unless quiet
32
+ puts '* Updated README' unless quiet
29
33
  end
30
34
  end
31
35
 
32
36
  def freshen(quiet: false)
33
- self.travis(quiet: quiet)
34
- self.gemfiles(quiet: quiet)
35
- self.readme(quiet: quiet)
37
+ github_actions(quiet: quiet)
38
+ gemfiles(quiet: quiet)
39
+ readme(quiet: quiet)
36
40
  end
37
41
 
38
42
  def run(*args, dry_run: false, quick: false, ruby: nil, activerecord: nil, db: nil, freshen: true)
@@ -43,7 +47,7 @@ module SchemaDev
43
47
  return true if matrix.run(Shellwords.join(args.flatten), dry_run: dry_run)
44
48
 
45
49
  puts "\n*** #{matrix.errors.size} failures:\n\t#{matrix.errors.join("\n\t")}"
46
- return false
50
+ false
47
51
  end
48
52
  end
49
53
  end
@@ -1,49 +1,57 @@
1
- require 'schema_dev/config'
1
+ # frozen_string_literal: true
2
2
 
3
- dbms = SchemaDev::Config.load.dbms
3
+ require 'schema_dev/config'
4
+ require 'schema_dev/rspec'
4
5
 
5
- DATABASES = %w[schema_plus_test]
6
+ dbms = SchemaDev::Config.load.db
6
7
 
7
8
  if dbms.any?
8
- {
9
- postgresql: { uservar: 'POSTGRESQL_DB_USER', defaultuser: 'schema_plus', create: "createdb -U '%{user}' %{dbname}", drop: "dropdb -U '%{user}' %{dbname}" },
10
- mysql: { uservar: 'MYSQL_DB_USER', defaultuser: 'schema_plus', create: "mysqladmin -u '%{user}' create %{dbname}", drop: "mysqladmin -u '%{user}' -f drop %{dbname}" }
11
- }.slice(*dbms).each do |dbm, info|
9
+ (%w[postgresql mysql2] & dbms).each do |dbm|
12
10
  namespace dbm do
13
- user = ENV.fetch info[:uservar], info[:defaultuser]
14
- task :create_databases do
15
- DATABASES.each do |dbname|
16
- system(info[:create] % {user: user, dbname: dbname})
17
- end
11
+ task :create_database do
12
+ require 'active_record'
13
+
14
+ config = SchemaDev::Rspec.db_configuration(dbm)
15
+
16
+ ActiveRecord::Tasks::DatabaseTasks.create(config)
18
17
  end
19
18
  task :drop_databases do
20
- DATABASES.each do |dbname|
21
- system(info[:drop] % {user: user, dbname: dbname})
22
- end
19
+ require 'active_record'
20
+
21
+ config = SchemaDev::Rspec.db_configuration(dbm)
22
+
23
+ ActiveRecord::Tasks::DatabaseTasks.drop(config)
23
24
  end
24
25
  end
25
26
  end
26
27
 
28
+ desc 'Create database for CI run'
29
+ task :create_ci_database do
30
+ require 'active_record'
31
+
32
+ config = SchemaDev::Rspec.db_configuration
33
+
34
+ ActiveRecord::Tasks::DatabaseTasks.create(config) unless config['adapter'] == 'sqlite3'
35
+ end
36
+
27
37
  desc 'Create test databases'
28
38
  task :create_databases do
29
- invoke_multiple(dbms, "create_databases")
39
+ invoke_multiple(dbms, 'create_database')
30
40
  end
31
41
 
32
42
  desc 'Drop test databases'
33
43
  task :drop_databases do
34
- invoke_multiple(dbms, "drop_databases")
44
+ invoke_multiple(dbms, 'drop_database')
35
45
  end
36
46
 
37
47
  def invoke_multiple(namespaces, task)
38
- failed = namespaces.reject { |adapter|
39
- begin
40
- Rake::Task["#{adapter}:#{task}"].invoke
41
- true
42
- rescue => e
43
- warn "\n#{e}\n"
44
- false
45
- end
46
- }
48
+ failed = namespaces.reject do |adapter|
49
+ Rake::Task["#{adapter}:#{task}"].invoke
50
+ true
51
+ rescue => e
52
+ warn "\n#{e}\n"
53
+ false
54
+ end
47
55
  fail "Failure in: #{failed.join(', ')}" if failed.any?
48
56
  end
49
57
  end
@@ -1,4 +1,3 @@
1
- require_relative 'tasks/dbms'
2
- require_relative 'tasks/coveralls'
1
+ # frozen_string_literal: true
3
2
 
4
- task :travis => :spec_with_coveralls
3
+ require_relative 'tasks/dbms'
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  module SchemaDev
4
6
  module Templates
5
7
  def self.root
6
- @root ||= Pathname.new(__FILE__).dirname.parent.parent + "templates"
8
+ @root ||= Pathname.new(__FILE__).dirname.parent.parent + 'templates'
7
9
  end
8
10
 
9
11
  def self.install_subtree(src:, dst:, bound: nil)
10
12
  src = root + src
11
- Pathname.glob(src + "**/*").select(&:file?).each do |p|
13
+ Pathname.glob(src + '**/*').select(&:file?).each do |p|
12
14
  _install(p, dst + p.relative_path_from(src).sub_ext(''), bound)
13
15
  end
14
16
  end
@@ -20,7 +22,7 @@ module SchemaDev
20
22
  end
21
23
 
22
24
  def self._install(src, dst, bound)
23
- src = Pathname(src.to_s + ".erb") unless src.file?
25
+ src = Pathname(src.to_s + '.erb') unless src.file?
24
26
  dst.sub_ext '' if dst.extname == '.erb'
25
27
  dst.dirname.mkpath
26
28
  dst.write process(src.read, bound: bound)
@@ -29,7 +31,5 @@ module SchemaDev
29
31
  def self.process(text, bound: nil)
30
32
  ERB.new(text).result(bound)
31
33
  end
32
-
33
-
34
34
  end
35
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SchemaDev
2
- VERSION = "4.0.0"
4
+ VERSION = '4.1.0'
3
5
  end
data/lib/schema_dev.rb CHANGED
@@ -1 +1,3 @@
1
- require "schema_dev/version"
1
+ # frozen_string_literal: true
2
+
3
+ require 'schema_dev/version'
data/schema_dev.gemspec CHANGED
@@ -1,39 +1,36 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'schema_dev/version'
5
6
 
6
7
  Gem::Specification.new do |gem|
7
- gem.name = "schema_dev"
8
+ gem.name = 'schema_dev'
8
9
  gem.version = SchemaDev::VERSION
9
- gem.authors = ["ronen barzel"]
10
- gem.email = ["ronen@barzel.org"]
11
- gem.summary = %q{SchemaPlus development tools}
12
- gem.description = %q{SchemaPlus development tools}
13
- gem.homepage = "https://github.com/SchemaPlus/schema_dev"
14
- gem.license = "MIT"
10
+ gem.authors = ['ronen barzel']
11
+ gem.email = ['ronen@barzel.org']
12
+ gem.summary = 'SchemaPlus development tools'
13
+ gem.description = 'SchemaPlus development tools'
14
+ gem.homepage = 'https://github.com/SchemaPlus/schema_dev'
15
+ gem.license = 'MIT'
15
16
 
16
17
  gem.files = `git ls-files -z`.split("\x0")
17
18
  gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
19
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
- gem.require_paths = ["lib"]
20
+ gem.require_paths = ['lib']
20
21
 
21
- gem.required_ruby_version = ">= 2.5.0"
22
+ gem.required_ruby_version = '>= 2.5.0'
22
23
 
23
- gem.add_dependency "activesupport", ">= 5.2", "< 6.2"
24
- gem.add_dependency "coveralls_reborn", "~> 0.23"
25
- gem.add_dependency "faraday", "~> 0.9"
26
- gem.add_dependency "fastandand", "~> 1.0"
27
- gem.add_dependency "hash_keyword_args", "~> 0.1"
28
- gem.add_dependency "its-it", "~> 1.3"
29
- gem.add_dependency "key_struct", "~> 0.4"
30
- gem.add_dependency "thor", "~> 0.19"
31
- gem.add_dependency "which_works", "~> 1.0"
24
+ gem.add_dependency 'activesupport', '>= 5.2', '< 6.2'
25
+ gem.add_dependency 'faraday', '~> 1.0'
26
+ gem.add_dependency 'simplecov'
27
+ gem.add_dependency 'simplecov-lcov', '~> 0.8.0'
28
+ gem.add_dependency 'thor', '>= 0.19', '< 2.0'
29
+ gem.add_dependency 'which_works', '~> 1.0'
32
30
 
33
- gem.add_development_dependency "bundler"
34
- gem.add_development_dependency "rake", "~> 10.0"
35
- gem.add_development_dependency "rspec", "~> 3.0"
36
- gem.add_development_dependency "rspec-given", "~> 3.8"
37
- gem.add_development_dependency "simplecov"
38
- gem.add_development_dependency "webmock", "~> 2.1"
31
+ gem.add_development_dependency 'bundler'
32
+ gem.add_development_dependency 'rake', '~> 13.0'
33
+ gem.add_development_dependency 'rspec', '~> 3.0'
34
+ gem.add_development_dependency 'rspec-given', '~> 3.8'
35
+ gem.add_development_dependency 'webmock', '~> 3.0'
39
36
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe SchemaDev::Config do
4
+ it 'computes matrix' do
5
+ config = get_config(ruby: %w[1.9.3 2.1.5], activerecord: %w[4.0 4.1], db: %w[sqlite3 postgresql])
6
+ expect(config.matrix).to match_array [
7
+ { ruby: '1.9.3', activerecord: '4.0', db: 'sqlite3' },
8
+ { ruby: '1.9.3', activerecord: '4.0', db: 'postgresql' },
9
+ { ruby: '1.9.3', activerecord: '4.1', db: 'sqlite3' },
10
+ { ruby: '1.9.3', activerecord: '4.1', db: 'postgresql' },
11
+ { ruby: '2.1.5', activerecord: '4.0', db: 'sqlite3' },
12
+ { ruby: '2.1.5', activerecord: '4.0', db: 'postgresql' },
13
+ { ruby: '2.1.5', activerecord: '4.1', db: 'sqlite3' },
14
+ { ruby: '2.1.5', activerecord: '4.1', db: 'postgresql' },
15
+ ]
16
+ end
17
+
18
+ it 'excludes explicit elements from matrix' do
19
+ config = get_config(ruby: %w[1.9.3 2.1.5], activerecord: %w[4.0 4.1], db: %w[sqlite3 postgresql],
20
+ exclude: [
21
+ { ruby: '1.9.3', activerecord: '4.1', db: 'postgresql' },
22
+ { ruby: '2.1.5', activerecord: '4.0', db: 'sqlite3' }
23
+ ])
24
+ expect(config.matrix).to match_array [
25
+ { ruby: '1.9.3', activerecord: '4.0', db: 'sqlite3' },
26
+ { ruby: '1.9.3', activerecord: '4.0', db: 'postgresql' },
27
+ { ruby: '1.9.3', activerecord: '4.1', db: 'sqlite3' },
28
+ # { ruby: "1.9.3", activerecord: "4.1", db: "postgresql" },
29
+ # { ruby: "2.1.5", activerecord: "4.0", db: "sqlite3" },
30
+ { ruby: '2.1.5', activerecord: '4.0', db: 'postgresql' },
31
+ { ruby: '2.1.5', activerecord: '4.1', db: 'sqlite3' },
32
+ { ruby: '2.1.5', activerecord: '4.1', db: 'postgresql' },
33
+ ]
34
+ end
35
+
36
+ it 'excludes slices from matrix' do
37
+ config = get_config(ruby: %w[1.9.3 2.1.5], activerecord: %w[4.0 4.1], db: %w[sqlite3 postgresql],
38
+ exclude: [
39
+ { ruby: '1.9.3', activerecord: '4.1' },
40
+ { ruby: '2.1.5', db: 'sqlite3' }
41
+ ])
42
+ expect(config.matrix).to match_array [
43
+ { ruby: '1.9.3', activerecord: '4.0', db: 'sqlite3' },
44
+ { ruby: '1.9.3', activerecord: '4.0', db: 'postgresql' },
45
+ #{ ruby: "1.9.3", activerecord: "4.1", db: "sqlite3" },
46
+ #{ ruby: "1.9.3", activerecord: "4.1", db: "postgresql" },
47
+ #{ ruby: "2.1.5", activerecord: "4.0", db: "sqlite3" },
48
+ { ruby: '2.1.5', activerecord: '4.0', db: 'postgresql' },
49
+ #{ ruby: "2.1.5", activerecord: "4.1", db: "sqlite3" },
50
+ { ruby: '2.1.5', activerecord: '4.1', db: 'postgresql' },
51
+ ]
52
+ end
53
+
54
+ it 'uses last cell for --quick' do
55
+ config = get_config(ruby: %w[1.9.3 2.1.5], activerecord: %w[4.0 4.1], db: %w[sqlite3 postgresql])
56
+ expect(config.matrix(quick: true)).to match_array [
57
+ { ruby: '2.1.5', activerecord: '4.1', db: 'postgresql' },
58
+ ]
59
+ end
60
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'schema_dev/gem'
4
+
5
+ describe SchemaDev::Gem do
6
+ around(:each) do |example|
7
+ in_tmpdir do
8
+ suppress_stdout_stderr do
9
+ example.run
10
+ end
11
+ end
12
+ end
13
+
14
+ Given(:user_name) { 'My Name' }
15
+ Given(:user_email) { 'my_name@example.com' }
16
+
17
+ Given do
18
+ allow_any_instance_of(described_class).to receive(:`).with('git config user.name').and_return user_name
19
+ allow_any_instance_of(described_class).to receive(:`).with('git config user.email').and_return user_email
20
+ end
21
+
22
+ describe 'builds' do
23
+ Given do
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
+ end
31
+
32
+ When { described_class.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 '<!-- These lines are auto-generated by schema_dev based on schema_dev.yml -->' }
38
+ Invariant { expect(readme).to include '<!-- These lines are auto-inserted from a schema_dev template -->' }
39
+
40
+ Invariant { expect(gemspec).to include "'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 'when a flat gem' do
45
+ Given(:gem_name) { 'new_gem' }
46
+ Then { expect(gemspec).to include "require 'new_gem/version'" }
47
+ Then { expect(File.read('new_gem/lib/new_gem.rb')).to include 'SchemaMonkey.register NewGem' }
48
+ end
49
+
50
+ context 'when a subdir gem' do
51
+ Given(:gem_name) { 'schema_plus_new_gem' }
52
+ Then { expect(gemspec).to include "require 'schema_plus/new_gem/version'" }
53
+ Then { expect(File.read('schema_plus_new_gem/lib/schema_plus_new_gem.rb')).to include "require_relative 'schema_plus/new_gem'" }
54
+ Then { expect(File.read('schema_plus_new_gem/lib/schema_plus/new_gem.rb')).to include 'SchemaMonkey.register SchemaPlus::NewGem' }
55
+ end
56
+ end
57
+
58
+ describe 'complains' do
59
+ context 'when no git user.name' do
60
+ Given(:user_name) { '' }
61
+ Then { expect { described_class.build('NewGem') }.to raise_error SystemExit, /who are you/i }
62
+ end
63
+
64
+ context 'when in git worktree' do
65
+ Given { expect_any_instance_of(described_class).to receive(:system).with(/^git rev-parse/).and_return true }
66
+ Then { expect { described_class.build('NewGem') }.to raise_error SystemExit, /\bgit\b/ }
67
+ end
68
+
69
+ context 'when gem directory exists' do
70
+ Given { FileUtils.touch 'new_gem' }
71
+ Then { expect { described_class.build('NewGem') }.to raise_error SystemExit, /exists/ }
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'schema_dev/gemfile_selector'
4
+
5
+ describe SchemaDev::GemfileSelector do
6
+ it 'infers db from env' do
7
+ test_dbname = 'this_is_a_test'
8
+ ENV['BUNDLE_GEMFILE'] = described_class.gemfile(activerecord: '4.1', db: test_dbname).to_s
9
+ expect(described_class.infer_db).to eq test_dbname
10
+ end
11
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'schema_dev/gemfiles'
4
+
5
+ describe SchemaDev::Gemfiles do
6
+ it 'copies listed files' do
7
+ config = get_config(ruby: %w[1.9.3 2.1.5], activerecord: %w[5.2 6.0], db: %w[sqlite3 postgresql])
8
+ in_tmpdir do
9
+ expect(described_class.build(config)).to be_truthy
10
+ expect(relevant_diff(config, 'gemfiles')).to be_empty
11
+ end
12
+ end
13
+
14
+ it 'only copies files once' do
15
+ config = get_config(ruby: %w[1.9.3 2.1.5], activerecord: %w[5.2 6.0], db: %w[sqlite3 postgresql])
16
+ in_tmpdir do
17
+ expect(described_class.build(config)).to be_truthy
18
+ expect(described_class.build(config)).to be_falsey
19
+ end
20
+ end
21
+
22
+ def relevant_diff(config, dir)
23
+ Dir.mktmpdir do |no_erb_root|
24
+ no_erb_root = Pathname(no_erb_root)
25
+ erb_root = SchemaDev::Templates.root + dir
26
+ Pathname.glob(erb_root + '**/*').select(&:file?).each do |p|
27
+ d = (no_erb_root + p.relative_path_from(erb_root)).sub_ext('')
28
+ d.dirname.mkpath
29
+ d.write p.read
30
+ end
31
+
32
+ diff = `diff -rq #{no_erb_root} #{dir} 2>&1`.split("\n")
33
+
34
+ # expect copy not to have entry for activerecord not in config
35
+ diff.reject! { |d| d =~ %r{Only in #{no_erb_root}: activerecord-(.*)} and not config.activerecord.include? $1 }
36
+
37
+ # expect copy not to have entry for db not in config
38
+ diff.reject! { |d| d =~ %r{Only in #{no_erb_root}.*: Gemfile.(.*)} and not config.db.include? $1 }
39
+ end
40
+ end
41
+ end