gemika 0.4.1 → 0.5.0

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