schema_dev 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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