gemika 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +122 -0
- data/.ruby-version +1 -1
- data/Gemfile.3.2.mysql2 +1 -1
- data/Gemfile.3.2.mysql2.lock +9 -3
- data/Gemfile.4.2.mysql2 +1 -1
- data/Gemfile.4.2.mysql2.lock +3 -3
- data/Gemfile.4.2.pg.lock +1 -1
- data/Gemfile.5.2.mysql2 +1 -1
- data/Gemfile.5.2.mysql2.lock +3 -3
- data/Gemfile.5.2.pg.lock +1 -1
- data/Gemfile.5.2.sqlite3.lock +1 -1
- data/Gemfile.6.0.pg.lock +1 -1
- data/README.md +73 -4
- data/lib/gemika/errors.rb +2 -0
- data/lib/gemika/github_actions_generator.rb +150 -0
- data/lib/gemika/matrix.rb +38 -37
- data/lib/gemika/matrix/github_actions_config.rb +61 -0
- data/lib/gemika/matrix/travis_config.rb +42 -0
- data/lib/gemika/tasks.rb +1 -0
- data/lib/gemika/tasks/gemika.rb +14 -0
- data/lib/gemika/tasks/matrix.rb +4 -4
- data/lib/gemika/version.rb +1 -1
- data/spec/fixtures/github_actions_yml/Gemfile_without_gemika +1 -0
- data/spec/fixtures/github_actions_yml/excludes.yml +13 -0
- data/spec/fixtures/github_actions_yml/gemfile_without_gemika.yml +8 -0
- data/spec/fixtures/github_actions_yml/includes.yml +20 -0
- data/spec/fixtures/github_actions_yml/invalid.yml +8 -0
- data/spec/fixtures/github_actions_yml/missing_gemfile.yml +8 -0
- data/spec/fixtures/github_actions_yml/multiple_jobs.yml +16 -0
- data/spec/fixtures/github_actions_yml/two_by_two.yml +10 -0
- data/spec/fixtures/migrate/expected_github_actions.yml +129 -0
- data/{.travis.yml → spec/fixtures/migrate/travis.yml} +0 -0
- data/spec/gemika/matrix_spec.rb +100 -0
- data/spec/support/database.github.yml +13 -0
- metadata +18 -6
- data/Gemfile.2.3.mysql2 +0 -18
- data/Gemfile.2.3.mysql2.lock +0 -42
- data/spec/support/database.travis.yml +0 -9
data/lib/gemika/matrix.rb
CHANGED
@@ -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
|
data/lib/gemika/tasks.rb
CHANGED
@@ -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
|
data/lib/gemika/tasks/matrix.rb
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
38
|
+
Gemika::Matrix.from_ci_config.each do |row|
|
39
39
|
system("bundle update #{options[:gems]}")
|
40
40
|
end
|
41
41
|
end
|
data/lib/gemika/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
gem 'some-gem'
|
@@ -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,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
|