gemika 0.4.1 → 0.5.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +122 -0
  3. data/.ruby-version +1 -1
  4. data/Gemfile.3.2.mysql2 +1 -1
  5. data/Gemfile.3.2.mysql2.lock +9 -3
  6. data/Gemfile.4.2.mysql2 +1 -1
  7. data/Gemfile.4.2.mysql2.lock +3 -3
  8. data/Gemfile.4.2.pg.lock +1 -1
  9. data/Gemfile.5.2.mysql2 +1 -1
  10. data/Gemfile.5.2.mysql2.lock +3 -3
  11. data/Gemfile.5.2.pg.lock +1 -1
  12. data/Gemfile.5.2.sqlite3.lock +1 -1
  13. data/Gemfile.6.0.pg.lock +1 -1
  14. data/README.md +73 -4
  15. data/lib/gemika/errors.rb +2 -0
  16. data/lib/gemika/github_actions_generator.rb +150 -0
  17. data/lib/gemika/matrix.rb +38 -37
  18. data/lib/gemika/matrix/github_actions_config.rb +61 -0
  19. data/lib/gemika/matrix/travis_config.rb +42 -0
  20. data/lib/gemika/tasks.rb +1 -0
  21. data/lib/gemika/tasks/gemika.rb +14 -0
  22. data/lib/gemika/tasks/matrix.rb +4 -4
  23. data/lib/gemika/version.rb +1 -1
  24. data/spec/fixtures/github_actions_yml/Gemfile_without_gemika +1 -0
  25. data/spec/fixtures/github_actions_yml/excludes.yml +13 -0
  26. data/spec/fixtures/github_actions_yml/gemfile_without_gemika.yml +8 -0
  27. data/spec/fixtures/github_actions_yml/includes.yml +20 -0
  28. data/spec/fixtures/github_actions_yml/invalid.yml +8 -0
  29. data/spec/fixtures/github_actions_yml/missing_gemfile.yml +8 -0
  30. data/spec/fixtures/github_actions_yml/multiple_jobs.yml +16 -0
  31. data/spec/fixtures/github_actions_yml/two_by_two.yml +10 -0
  32. data/spec/fixtures/migrate/expected_github_actions.yml +129 -0
  33. data/{.travis.yml → spec/fixtures/migrate/travis.yml} +0 -0
  34. data/spec/gemika/matrix_spec.rb +100 -0
  35. data/spec/support/database.github.yml +13 -0
  36. metadata +18 -6
  37. data/Gemfile.2.3.mysql2 +0 -18
  38. data/Gemfile.2.3.mysql2.lock +0 -42
  39. data/spec/support/database.travis.yml +0 -9
@@ -1,47 +1,12 @@
1
1
  require 'yaml'
2
2
  require 'gemika/errors'
3
3
  require 'gemika/env'
4
+ require 'gemika/matrix/travis_config'
5
+ require 'gemika/matrix/github_actions_config'
4
6
 
5
7
  module Gemika
6
8
  class Matrix
7
9
 
8
- ##
9
- # Load `.travis.yml` files.
10
- #
11
- # @!visibility private
12
- #
13
- class TravisConfig
14
- class << self
15
-
16
- def load_rows(options)
17
- path = options.fetch(:path, '.travis.yml')
18
- travis_yml = YAML.load_file(path)
19
- rubies = travis_yml.fetch('rvm', [])
20
- gemfiles = travis_yml.fetch('gemfile', [])
21
- matrix_options = travis_yml.fetch('matrix', {})
22
- includes = matrix_options.fetch('include', [])
23
- excludes = matrix_options.fetch('exclude', [])
24
-
25
- rows = []
26
- rubies.each do |ruby|
27
- gemfiles.each do |gemfile|
28
- row = { 'rvm' => ruby, 'gemfile' => gemfile }
29
- rows << row unless excludes.include?(row)
30
- end
31
- end
32
-
33
- rows = rows + includes
34
- rows = rows.map { |row| convert_row(row) }
35
- rows
36
- end
37
-
38
- def convert_row(travis_row)
39
- Row.new(:ruby => travis_row['rvm'], :gemfile => travis_row['gemfile'])
40
- end
41
-
42
- end
43
- end
44
-
45
10
  ##
46
11
  # A row in the test matrix
47
12
  #
@@ -129,6 +94,25 @@ module Gemika
129
94
  print_summary
130
95
  end
131
96
 
97
+
98
+ ##
99
+ # Builds a {Matrix} from a `.travis.yml` file, or falls back to a Github Action .yml file
100
+ #
101
+ # @param [Hash] options
102
+ # @option options [String] Path to the `.travis.yml` file.
103
+ #
104
+ def self.from_ci_config
105
+ travis_location = '.travis.yml'
106
+ workflow_location = '.github/workflows/test.yml'
107
+ if File.exists?(travis_location)
108
+ from_travis_yml(:path => travis_location)
109
+ elsif File.exists?(workflow_location)
110
+ from_github_actions_yml(:path => workflow_location)
111
+ else
112
+ raise MissingMatrixDefinition, "expected either a #{travis_location} or a #{workflow_location}"
113
+ end
114
+ end
115
+
132
116
  ##
133
117
  # Builds a {Matrix} from the given `.travis.yml` file.
134
118
  #
@@ -140,8 +124,25 @@ module Gemika
140
124
  new(options.merge(:rows => rows))
141
125
  end
142
126
 
127
+ ##
128
+ # Builds a {Matrix} from the given Github Action workflow definition
129
+ #
130
+ # @param [Hash] options
131
+ # @option options [String] Path to the `.yml` file.
132
+ #
133
+ def self.from_github_actions_yml(options = {})
134
+ rows = GithubActionsConfig.load_rows(options)
135
+ new(options.merge(:rows => rows))
136
+ end
137
+
143
138
  attr_reader :rows, :current_ruby
144
139
 
140
+ def self.generate_github_actions_workflow(options= {})
141
+ require 'gemika/github_actions_generator'
142
+ rows = TravisConfig.load_rows(options)
143
+ GithubActionsGenerator.new(bundler_version: Bundler::VERSION).generate(rows)
144
+ end
145
+
145
146
  private
146
147
 
147
148
  def puts(*args)
@@ -0,0 +1,61 @@
1
+ module Gemika
2
+ class Matrix
3
+
4
+ ##
5
+ # Load Github Action `.yml` files.
6
+ #
7
+ # @!visibility private
8
+ #
9
+ class GithubActionsConfig
10
+ class << self
11
+
12
+ def load_rows(options)
13
+ path = options.fetch(:path, '.github/workflows/test.yml')
14
+ workflow_yml = YAML.load_file(path)
15
+
16
+ matrices = workflow_yml.fetch('jobs', {}).values.map do |job|
17
+ job.fetch('strategy', {})['matrix']
18
+ end.reject(&:nil?)
19
+
20
+ matrices.map do |matrix|
21
+ matrix_to_rows(matrix)
22
+ end.flatten(1)
23
+ end
24
+
25
+ private
26
+
27
+ def matrix_to_rows(matrix)
28
+ if (!matrix['ruby'] || !matrix['gemfile']) && (!matrix['include'])
29
+ raise InvalidMatrixDefinition, 'matrix must use the keys "ruby" and "gemfile"'
30
+ end
31
+
32
+ rubies = matrix.fetch('ruby', [])
33
+ gemfiles = matrix.fetch('gemfile', [])
34
+
35
+ includes = matrix.fetch('include', [])
36
+ excludes = matrix.fetch('exclude', [])
37
+
38
+ rows = []
39
+ rubies.each do |ruby|
40
+ gemfiles.each do |gemfile|
41
+ row = { 'ruby' => ruby, 'gemfile' => gemfile }
42
+ rows << row unless excludes.include?(row)
43
+ end
44
+ end
45
+
46
+ rows = rows + includes
47
+ rows.map { |row| convert_row(row) }
48
+ end
49
+
50
+ def convert_row(row_hash)
51
+ if !row_hash['ruby'] || !row_hash['gemfile']
52
+ raise InvalidMatrixDefinition, 'matrix must use the keys "ruby" and "gemfile"'
53
+ end
54
+ Row.new(:ruby => row_hash['ruby'], :gemfile => row_hash['gemfile'])
55
+ end
56
+
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,42 @@
1
+ module Gemika
2
+ class Matrix
3
+
4
+ ##
5
+ # Load `.travis.yml` files.
6
+ #
7
+ # @!visibility private
8
+ #
9
+ class TravisConfig
10
+ class << self
11
+
12
+ def load_rows(options)
13
+ path = options.fetch(:path, '.travis.yml')
14
+ travis_yml = YAML.load_file(path)
15
+ rubies = travis_yml.fetch('rvm', [])
16
+ gemfiles = travis_yml.fetch('gemfile', [])
17
+ matrix_options = travis_yml.fetch('matrix', {})
18
+ includes = matrix_options.fetch('include', [])
19
+ excludes = matrix_options.fetch('exclude', [])
20
+
21
+ rows = []
22
+ rubies.each do |ruby|
23
+ gemfiles.each do |gemfile|
24
+ row = { 'rvm' => ruby, 'gemfile' => gemfile }
25
+ rows << row unless excludes.include?(row)
26
+ end
27
+ end
28
+
29
+ rows = rows + includes
30
+ rows = rows.map { |row| convert_row(row) }
31
+ rows
32
+ end
33
+
34
+ def convert_row(travis_row)
35
+ Row.new(:ruby => travis_row['rvm'], :gemfile => travis_row['gemfile'])
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -1,2 +1,3 @@
1
1
  require 'gemika/tasks/matrix'
2
2
  require 'gemika/tasks/rspec'
3
+ require 'gemika/tasks/gemika'
@@ -0,0 +1,14 @@
1
+ require 'gemika/env'
2
+ require 'gemika/matrix'
3
+
4
+ ##
5
+ # Rake tasks to run commands for each compatible row in the test matrix.
6
+ #
7
+ namespace :gemika do
8
+
9
+ desc "Generate a github action workflow from a .travis.yml"
10
+ task :generate_github_actions_workflow do
11
+ puts Gemika::Matrix.generate_github_actions_workflow.to_yaml
12
+ end
13
+
14
+ end
@@ -9,7 +9,7 @@ namespace :matrix do
9
9
 
10
10
  desc "Run specs for all Ruby #{RUBY_VERSION} gemfiles"
11
11
  task :spec, :files do |t, options|
12
- Gemika::Matrix.from_travis_yml.each do |row|
12
+ Gemika::Matrix.from_ci_config.each do |row|
13
13
  options = options.to_hash.merge(
14
14
  :gemfile => row.gemfile,
15
15
  :fatal => false,
@@ -21,21 +21,21 @@ namespace :matrix do
21
21
 
22
22
  desc "Install all Ruby #{RUBY_VERSION} gemfiles"
23
23
  task :install do
24
- Gemika::Matrix.from_travis_yml.each do |row|
24
+ Gemika::Matrix.from_ci_config.each do |row|
25
25
  system('bundle install')
26
26
  end
27
27
  end
28
28
 
29
29
  desc "List dependencies for all Ruby #{RUBY_VERSION} gemfiles"
30
30
  task :list do
31
- Gemika::Matrix.from_travis_yml.each do |row|
31
+ Gemika::Matrix.from_ci_config.each do |row|
32
32
  system('bundle list')
33
33
  end
34
34
  end
35
35
 
36
36
  desc "Update all Ruby #{RUBY_VERSION} gemfiles"
37
37
  task :update, :gems do |t, options|
38
- Gemika::Matrix.from_travis_yml.each do |row|
38
+ Gemika::Matrix.from_ci_config.each do |row|
39
39
  system("bundle update #{options[:gems]}")
40
40
  end
41
41
  end
@@ -1,3 +1,3 @@
1
1
  module Gemika
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -0,0 +1,13 @@
1
+ jobs:
2
+ first_job:
3
+ strategy:
4
+ matrix:
5
+ ruby:
6
+ - "2.1.8"
7
+ - "2.3.1"
8
+ gemfile:
9
+ - gemfiles/Gemfile1
10
+ - gemfiles/Gemfile2
11
+ exclude:
12
+ - ruby: 2.1.8
13
+ gemfile: gemfiles/Gemfile1
@@ -0,0 +1,8 @@
1
+ jobs:
2
+ first_job:
3
+ strategy:
4
+ matrix:
5
+ ruby:
6
+ - 2.1.8
7
+ gemfile:
8
+ - spec/fixtures/travis_yml/Gemfile_without_gemika
@@ -0,0 +1,20 @@
1
+ matrix:
2
+ jobs:
3
+ first_job:
4
+ strategy:
5
+ matrix:
6
+ ruby:
7
+ - "2.1.8"
8
+ - "2.3.1"
9
+ gemfile:
10
+ - gemfiles/Gemfile1
11
+ - gemfiles/Gemfile2
12
+ include:
13
+ - ruby: 2.6.3
14
+ gemfile: gemfiles/Gemfile3
15
+ second_job:
16
+ strategy:
17
+ matrix:
18
+ include:
19
+ - ruby: 2.7.1
20
+ gemfile: gemfiles/Gemfile3
@@ -0,0 +1,8 @@
1
+ jobs:
2
+ first_job:
3
+ strategy:
4
+ matrix:
5
+ ruby_version:
6
+ - "2.1.8"
7
+ gemfile:
8
+ - gemfiles/Gemfile1
@@ -0,0 +1,8 @@
1
+ jobs:
2
+ first_job:
3
+ strategy:
4
+ matrix:
5
+ ruby:
6
+ - 2.1.8
7
+ gemfile:
8
+ - gemfiles/nonexisting_gemfile
@@ -0,0 +1,16 @@
1
+ jobs:
2
+ first_job:
3
+ strategy:
4
+ matrix:
5
+ ruby:
6
+ - "2.1.8"
7
+ gemfile:
8
+ - gemfiles/Gemfile1
9
+
10
+ second_job:
11
+ strategy:
12
+ matrix:
13
+ ruby:
14
+ - "2.3.1"
15
+ gemfile:
16
+ - gemfiles/Gemfile2
@@ -0,0 +1,10 @@
1
+ jobs:
2
+ first_job:
3
+ strategy:
4
+ matrix:
5
+ ruby:
6
+ - "2.1.8"
7
+ - "2.3.1"
8
+ gemfile:
9
+ - gemfiles/Gemfile1
10
+ - gemfiles/Gemfile2
@@ -0,0 +1,129 @@
1
+ name: Tests
2
+ 'on':
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
7
+ branches:
8
+ - master
9
+ jobs:
10
+ test_mysql:
11
+ runs-on: ubuntu-20.04
12
+ services:
13
+ mysql:
14
+ image: mysql:5.6
15
+ env:
16
+ MYSQL_ROOT_PASSWORD: password
17
+ options: --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout
18
+ 5s --health-retries 5
19
+ ports:
20
+ - 3306:3306
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ include:
25
+ - ruby: 1.8.7
26
+ gemfile: Gemfile.2.3.mysql2
27
+ - ruby: 1.8.7
28
+ gemfile: Gemfile.3.2.mysql2
29
+ - ruby: 2.1.8
30
+ gemfile: Gemfile.3.2.mysql2
31
+ - ruby: 2.2.4
32
+ gemfile: Gemfile.3.2.mysql2
33
+ - ruby: 2.1.8
34
+ gemfile: Gemfile.4.2.mysql2
35
+ - ruby: 2.2.4
36
+ gemfile: Gemfile.4.2.mysql2
37
+ - ruby: 2.3.1
38
+ gemfile: Gemfile.4.2.mysql2
39
+ - ruby: 2.2.4
40
+ gemfile: Gemfile.5.2.mysql2
41
+ - ruby: 2.3.1
42
+ gemfile: Gemfile.5.2.mysql2
43
+ env:
44
+ BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
45
+ steps:
46
+ - uses: actions/checkout@v2
47
+ - name: Install ruby
48
+ uses: ruby/setup-ruby@v1
49
+ with:
50
+ ruby-version: "${{ matrix.ruby }}"
51
+ - name: Setup database
52
+ run: |
53
+ sudo apt-get install -y mysql-client libmariadbclient-dev
54
+ mysql -e 'create database IF NOT EXISTS test;' -u root --password=password -P 3306 -h 127.0.0.1
55
+ - name: Bundle
56
+ run: |
57
+ gem install bundler:1.17.3
58
+ bundle install --no-deployment
59
+ - name: Run tests
60
+ run: bundle exec rspec
61
+ test_pg:
62
+ runs-on: ubuntu-20.04
63
+ services:
64
+ postgres:
65
+ image: postgres
66
+ env:
67
+ POSTGRES_PASSWORD: postgres
68
+ options: "--health-cmd pg_isready --health-interval 10s --health-timeout 5s
69
+ --health-retries 5"
70
+ ports:
71
+ - 5432:5432
72
+ strategy:
73
+ fail-fast: false
74
+ matrix:
75
+ include:
76
+ - ruby: 2.1.8
77
+ gemfile: Gemfile.4.2.pg
78
+ - ruby: 2.2.4
79
+ gemfile: Gemfile.4.2.pg
80
+ - ruby: 2.3.1
81
+ gemfile: Gemfile.4.2.pg
82
+ - ruby: 2.2.4
83
+ gemfile: Gemfile.5.2.pg
84
+ - ruby: 2.3.1
85
+ gemfile: Gemfile.5.2.pg
86
+ - ruby: 2.6.4
87
+ gemfile: Gemfile.6.0.pg
88
+ env:
89
+ BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
90
+ steps:
91
+ - uses: actions/checkout@v2
92
+ - name: Install ruby
93
+ uses: ruby/setup-ruby@v1
94
+ with:
95
+ ruby-version: "${{ matrix.ruby }}"
96
+ - name: Setup database
97
+ run: |
98
+ sudo apt-get install -y postgresql-client
99
+ PGPASSWORD=postgres psql -c 'create database test;' -U postgres -p 5432 -h localhost
100
+ - name: Bundle
101
+ run: |
102
+ gem install bundler:1.17.3
103
+ bundle install --no-deployment
104
+ - name: Run tests
105
+ run: bundle exec rspec
106
+ test_sqlite:
107
+ runs-on: ubuntu-20.04
108
+ strategy:
109
+ fail-fast: false
110
+ matrix:
111
+ include:
112
+ - ruby: 2.2.4
113
+ gemfile: Gemfile.5.2.sqlite3
114
+ - ruby: 2.3.1
115
+ gemfile: Gemfile.5.2.sqlite3
116
+ env:
117
+ BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
118
+ steps:
119
+ - uses: actions/checkout@v2
120
+ - name: Install ruby
121
+ uses: ruby/setup-ruby@v1
122
+ with:
123
+ ruby-version: "${{ matrix.ruby }}"
124
+ - name: Bundle
125
+ run: |
126
+ gem install bundler:1.17.3
127
+ bundle install --no-deployment
128
+ - name: Run tests
129
+ run: bundle exec rspec