excavate 0.2.4 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4dedf2dff68fab0c162340e9dc591f1675612d2b6f46335c6fe599ecead65434
4
- data.tar.gz: 8d8dd45fbe6ba733d4aa759a3f9f1bb5fc457be3fa0ae176b48bc0d1a417c8ec
3
+ metadata.gz: b66a3e8ff5083bd78711cff8289e18f958578d84fea44be53dcd4f5349508755
4
+ data.tar.gz: 1c65ff305ed20893b27470063280f60698d9920db597d42af8e75127c947784a
5
5
  SHA512:
6
- metadata.gz: b3f6c9a0f90d398afe6ee88c64004aaa5aad6ef50382d095e9df67a2841b3ae7c1af46a2f760718837d10350d2de4b90f727b495c2d8fdd6f32ae9dd290b7de1
7
- data.tar.gz: c33b1e35ec3c7478b9236ee705f683b937394f495bb60b57e7602841136e951cbd8eee71ceaabf586548218302e6c495010b7a30020726056d6dd3f47e2bd0ff
6
+ metadata.gz: feac4007753c19cb52d9f32432f96ab2a2cf6553556cb950ad15f210a0e8f3d0209622b81702e17d4a9fef3e975b42f7f97178d7d55dfc914731245093a159f0
7
+ data.tar.gz: 93bed15a89d5f620e45232f9de42afde7efaabc7e79734617c8443f2324858a6a97e6b9e40995ee18ad5bce4d36ea1ac584b238d257accf567e88472ea0fd991
@@ -0,0 +1,76 @@
1
+ name: metanorma
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: '${{ github.workflow }}-${{ github.job }}-${{ github.head_ref || github.ref_name }}'
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ prepare:
14
+ runs-on: ubuntu-latest
15
+ outputs:
16
+ head_tag: ${{ steps.check.outputs.head_tag }}
17
+ foreign_pr: ${{ steps.check.outputs.foreign_pr }}
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v2.3.4
21
+
22
+ - name: Retrieve tags
23
+ run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true
24
+ - name: Set output variables
25
+ id: check
26
+ run: |
27
+ fpr="no"
28
+ tag=""
29
+ if [[ "${{ github.ref }}" == refs/heads/* ]]; then
30
+ tag="$(git tag --points-at HEAD)"
31
+ elif [[ "${{ github.ref }}" == refs/pull/* ]] && [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.event.pull_request.base.repo.full_name }}" ]; then
32
+ fpr="yes"
33
+ fi
34
+ echo "::set-output name=foreign_pr::${fpr}"
35
+ echo "::set-output name=head_tag::${tag}"
36
+
37
+ test:
38
+ name: Test with Metanorma on Ruby ${{ matrix.ruby }} ${{ matrix.os }}
39
+ needs: prepare
40
+ runs-on: ${{ matrix.os }}
41
+ continue-on-error: false
42
+ strategy:
43
+ fail-fast: false
44
+ matrix:
45
+ ruby: [ '2.7', '3.0', '3.1' ]
46
+ os: [ ubuntu-latest, windows-latest, macos-latest ]
47
+ steps:
48
+ - uses: actions/checkout@v3
49
+ with:
50
+ repository: metanorma/metanorma
51
+
52
+ - uses: metanorma/metanorma-build-scripts/inkscape-setup-action@main
53
+
54
+ - uses: actions/checkout@v3
55
+ with:
56
+ path: "excavate"
57
+
58
+ - run: 'echo ''gem "excavate", path: "./excavate"'' > Gemfile.devel'
59
+
60
+ - if: matrix.ruby == '3.0'
61
+ uses: ruby/setup-ruby@v1
62
+ with:
63
+ ruby-version: ${{ matrix.ruby }}
64
+ bundler-cache: false
65
+ rubygems: latest
66
+
67
+ - if: matrix.ruby == '3.0'
68
+ run: bundle
69
+
70
+ - if: matrix.ruby != '3.0'
71
+ uses: ruby/setup-ruby@v1
72
+ with:
73
+ ruby-version: ${{ matrix.ruby }}
74
+ bundler-cache: true
75
+
76
+ - run: bundle exec rake
@@ -0,0 +1,69 @@
1
+ name: test-and-release
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ 'v*' ]
7
+ pull_request:
8
+
9
+ concurrency:
10
+ group: '${{ github.workflow }}-${{ github.job }}-${{ github.head_ref || github.ref_name }}'
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ prepare:
15
+ runs-on: ubuntu-latest
16
+ outputs:
17
+ head_tag: ${{ steps.check.outputs.head_tag }}
18
+ foreign_pr: ${{ steps.check.outputs.foreign_pr }}
19
+ steps:
20
+ - name: Checkout
21
+ uses: actions/checkout@v2.3.4
22
+
23
+ - name: Retrieve tags
24
+ run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true
25
+ - name: Set output variables
26
+ id: check
27
+ run: |
28
+ fpr="no"
29
+ tag=""
30
+ if [[ "${{ github.ref }}" == refs/heads/* ]]; then
31
+ tag="$(git tag --points-at HEAD)"
32
+ elif [[ "${{ github.ref }}" == refs/pull/* ]] && [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.event.pull_request.base.repo.full_name }}" ]; then
33
+ fpr="yes"
34
+ fi
35
+ echo "::set-output name=foreign_pr::${fpr}"
36
+ echo "::set-output name=head_tag::${tag}"
37
+
38
+ test:
39
+ name: Test on Ruby ${{ matrix.ruby }} ${{ matrix.os }}
40
+ needs: prepare
41
+ runs-on: ${{ matrix.os }}
42
+ continue-on-error: false
43
+ strategy:
44
+ fail-fast: false
45
+ matrix:
46
+ ruby: [ '2.6', '2.7', '3.0', '3.1' ]
47
+ os: [ ubuntu-latest, windows-latest, macos-latest ]
48
+
49
+ steps:
50
+ - uses: actions/checkout@v3
51
+
52
+ - uses: ruby/setup-ruby@v1
53
+ with:
54
+ ruby-version: ${{ matrix.ruby }}
55
+ bundler-cache: true
56
+
57
+ - run: bundle exec rspec
58
+
59
+ release:
60
+ name: Release gem
61
+ needs: test
62
+ runs-on: ubuntu-latest
63
+ if: contains(github.ref, 'refs/tags/v')
64
+ steps:
65
+ - uses: actions/checkout@v3
66
+
67
+ - uses: cadwallion/publish-rubygems-action@master
68
+ env:
69
+ RUBYGEMS_API_KEY: ${{secrets.FONTIST_CI_RUBYGEMS_API_KEY}}
data/Gemfile CHANGED
@@ -7,6 +7,6 @@ gemspec
7
7
  gem "gem-release"
8
8
  gem "rake", "~> 13.0"
9
9
  gem "rspec", "~> 3.2"
10
- gem "rubocop", "0.75.0"
10
+ gem "rubocop"
11
11
  gem "rubocop-performance"
12
12
  gem "rubocop-rails"
data/README.adoc CHANGED
@@ -61,6 +61,13 @@ end
61
61
  $ excavate --recursive path/to/archive.cab
62
62
  ----
63
63
 
64
+ It supports recursive extraction of a directory containing archives:
65
+
66
+ [source,sh]
67
+ ----
68
+ $ excavate --recursive path/to/dir_with_archives
69
+ ----
70
+
64
71
  If you'd like to skip extraction of nested archives, just use:
65
72
 
66
73
  [source,sh]
@@ -68,6 +75,26 @@ If you'd like to skip extraction of nested archives, just use:
68
75
  $ excavate path/to/archive.cab
69
76
  ----
70
77
 
78
+ To extract a particular file or files specify them as last arguments:
79
+
80
+ [source,sh]
81
+ ----
82
+ $ excavate --recursive archive.cab file1 dir/file2
83
+ ----
84
+
85
+ Also `excavate` supports extraction from nested archives:
86
+
87
+ [source,sh]
88
+ ----
89
+ $ excavate --recursive archive.cab dir/nested.zip/file
90
+ ----
91
+
92
+ And filtering:
93
+
94
+ [source,sh]
95
+ ----
96
+ $ excavate archive.cab --filter "**/specialfile*.txt"
97
+ ----
71
98
 
72
99
  == Dependencies
73
100
 
data/excavate.gemspec CHANGED
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  require_relative "lib/excavate/version"
4
3
 
5
4
  Gem::Specification.new do |spec|
@@ -31,6 +30,6 @@ Gem::Specification.new do |spec|
31
30
  spec.add_runtime_dependency "libmspack", "~> 0.1"
32
31
  spec.add_runtime_dependency "ruby-ole", "~> 1.0"
33
32
  spec.add_runtime_dependency "rubyzip", "~> 2.3"
34
- spec.add_runtime_dependency "seven_zip_ruby", "~> 1.0"
33
+ spec.add_runtime_dependency "seven-zip", "~> 1.4"
35
34
  spec.add_runtime_dependency "thor", "~> 1.0"
36
35
  end
@@ -1,5 +1,8 @@
1
1
  module Excavate
2
2
  class Archive
3
+ INVALID_MEMORY_MESSAGE =
4
+ "invalid memory read at address=0x0000000000000000".freeze
5
+
3
6
  TYPES = { "cab" => Extractors::CabExtractor,
4
7
  "cpio" => Extractors::CpioExtractor,
5
8
  "exe" => Extractors::SevenZipExtractor,
@@ -14,9 +17,10 @@ module Excavate
14
17
  @archive = archive
15
18
  end
16
19
 
17
- def files(recursive_packages: false)
20
+ def files(recursive_packages: false, files: [], filter: nil)
18
21
  target = Dir.mktmpdir
19
- extract(target, recursive_packages: recursive_packages)
22
+ extract(target, recursive_packages: recursive_packages,
23
+ files: files, filter: filter)
20
24
 
21
25
  all_files_in(target).map do |file|
22
26
  yield file
@@ -25,10 +29,105 @@ module Excavate
25
29
  FileUtils.rm_rf(target)
26
30
  end
27
31
 
28
- def extract(target = nil, recursive_packages: false)
32
+ def extract(target = nil,
33
+ recursive_packages: false,
34
+ files: [],
35
+ filter: nil)
36
+ if files.size.positive?
37
+ extract_particular_files(target, files,
38
+ recursive_packages: recursive_packages)
39
+ elsif filter
40
+ extract_by_filter(target, filter,
41
+ recursive_packages: recursive_packages)
42
+ else
43
+ extract_all(target, recursive_packages: recursive_packages)
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def extract_particular_files(target, files, recursive_packages: false)
50
+ tmp = Dir.mktmpdir
51
+ extract_all(tmp, recursive_packages: recursive_packages)
52
+ found_files = find_files(tmp, files)
53
+ copy_files(found_files, target || Dir.pwd)
54
+ ensure
55
+ FileUtils.rm_rf(tmp)
56
+ end
57
+
58
+ def copy_files(files, target)
59
+ files.map do |file|
60
+ FileUtils.mkdir_p(target)
61
+ target_path = File.join(target, File.basename(file))
62
+ ensure_not_exist(target_path)
63
+
64
+ FileUtils.cp(file, target_path)
65
+
66
+ target_path
67
+ end
68
+ end
69
+
70
+ def ensure_not_exist(path)
71
+ if File.exist?(path)
72
+ type = File.directory?(path) ? "directory" : "file"
73
+ raise(TargetExistsError,
74
+ "Target #{type} `#{File.basename(path)}` already exists.")
75
+ end
76
+ end
77
+
78
+ def find_files(source, files)
79
+ all_files = all_files_in(source)
80
+
81
+ files.map do |target_file|
82
+ found_file = all_files.find do |source_file|
83
+ file_matches?(source_file, target_file, source)
84
+ end
85
+
86
+ unless found_file
87
+ raise(TargetNotFoundError, "File `#{target_file}` not found.")
88
+ end
89
+
90
+ found_file
91
+ end
92
+ end
93
+
94
+ def file_matches?(source_file, target_file, source_dir)
95
+ base_path(source_file, source_dir) == target_file
96
+ end
97
+
98
+ def base_path(path, prefix)
99
+ path.sub(prefix, "").sub(/^\//, "").sub(/^\\/, "")
100
+ end
101
+
102
+ def extract_by_filter(target, filter, recursive_packages: false)
103
+ tmp = Dir.mktmpdir
104
+ extract_all(tmp, recursive_packages: recursive_packages)
105
+ found_files = find_by_filter(tmp, filter)
106
+ copy_files(found_files, target || Dir.pwd)
107
+ end
108
+
109
+ def find_by_filter(source, filter)
110
+ all_files = all_files_in(source)
111
+
112
+ found_files = all_files.select do |source_file|
113
+ file_matches_filter?(source_file, filter, source)
114
+ end
115
+
116
+ if found_files.empty?
117
+ raise(TargetNotFoundError, "Filter `#{filter}` matched no file.")
118
+ end
119
+
120
+ found_files
121
+ end
122
+
123
+ def file_matches_filter?(source_file, filter, source_dir)
124
+ File.fnmatch?(filter, base_path(source_file, source_dir))
125
+ end
126
+
127
+ def extract_all(target, recursive_packages: false)
29
128
  source = File.expand_path(@archive)
30
129
  target ||= default_target(source)
31
- raise(TargetNotEmptyError, "Target directory `#{File.basename(target)}` is not empty.") unless Dir.empty?(target)
130
+ ensure_empty(target)
32
131
 
33
132
  if recursive_packages
34
133
  extract_recursively(source, target)
@@ -39,11 +138,16 @@ module Excavate
39
138
  target
40
139
  end
41
140
 
42
- private
141
+ def ensure_empty(path)
142
+ unless Dir.empty?(path)
143
+ raise(TargetNotEmptyError,
144
+ "Target directory `#{File.basename(path)}` is not empty.")
145
+ end
146
+ end
43
147
 
44
148
  def default_target(source)
45
149
  target = File.expand_path(File.basename(source, ".*"))
46
- raise(TargetExistsError, "Target directory `#{File.basename(target)}` already exists.") if File.exist?(target)
150
+ ensure_not_exist(target)
47
151
 
48
152
  FileUtils.mkdir(target)
49
153
 
@@ -51,7 +155,7 @@ module Excavate
51
155
  end
52
156
 
53
157
  def extract_recursively(archive, target)
54
- extract_once(archive, target)
158
+ extract_to_directory(archive, target)
55
159
 
56
160
  all_files_in(target).each do |file|
57
161
  next unless archive?(file)
@@ -60,14 +164,39 @@ module Excavate
60
164
  end
61
165
  end
62
166
 
167
+ def extract_to_directory(archive, target)
168
+ if File.directory?(archive)
169
+ duplicate_dir(archive, target)
170
+ elsif !archive?(archive)
171
+ copy_file(archive, target)
172
+ else
173
+ extract_once(archive, target)
174
+ end
175
+ end
176
+
177
+ def duplicate_dir(source, target)
178
+ Dir.chdir(source) do
179
+ (Dir.entries(".") - [".", ".."]).each do |entry|
180
+ FileUtils.cp_r(entry, target)
181
+ end
182
+ end
183
+ end
184
+
185
+ def copy_file(archive, target)
186
+ FileUtils.cp(archive, target)
187
+ end
188
+
63
189
  def extract_once(archive, target)
64
190
  extension = normalized_extension(archive)
65
191
  extractor_class = TYPES[extension]
66
- raise(UnknownArchiveError, "Could not unarchive `#{archive}`.") unless extractor_class
192
+ unless extractor_class
193
+ raise(UnknownArchiveError, "Could not unarchive `#{archive}`.")
194
+ end
67
195
 
68
196
  extractor_class.new(archive).extract(target)
69
197
  rescue StandardError => e
70
- raise unless extension == "exe" && e.message.start_with?("Invalid file format")
198
+ raise unless extension == "exe" &&
199
+ e.message.start_with?("Invalid file format")
71
200
 
72
201
  Extractors::CabExtractor.new(archive).extract(target)
73
202
  end
@@ -81,7 +210,7 @@ module Excavate
81
210
  rescue FFI::NullPointerError => e
82
211
  FileUtils.rmdir(target)
83
212
  raise unless normalized_extension(archive) == "exe" &&
84
- e.message.start_with?("invalid memory read at address=0x0000000000000000")
213
+ e.message.start_with?(INVALID_MEMORY_MESSAGE)
85
214
  end
86
215
 
87
216
  def normalized_extension(file)
data/lib/excavate/cli.rb CHANGED
@@ -8,6 +8,13 @@ module Excavate
8
8
  STATUS_UNKNOWN_ERROR = 1
9
9
  STATUS_TARGET_EXISTS = 2
10
10
  STATUS_TARGET_NOT_EMPTY = 3
11
+ STATUS_TARGET_NOT_FOUND = 4
12
+
13
+ ERROR_TO_STATUS = {
14
+ TargetExistsError => STATUS_TARGET_EXISTS,
15
+ TargetNotEmptyError => STATUS_TARGET_NOT_EMPTY,
16
+ TargetNotFoundError => STATUS_TARGET_NOT_FOUND,
17
+ }.freeze
11
18
 
12
19
  def self.exit_on_failure?
13
20
  false
@@ -23,15 +30,22 @@ module Excavate
23
30
  super(args, config)
24
31
  end
25
32
 
26
- desc "extract ARCHIVE", "Extract ARCHIVE to a new directory"
27
- option :recursive, aliases: :r, type: :boolean, default: false, desc: "Also extract all nested archives."
28
- def extract(archive)
29
- target = Excavate::Archive.new(archive).extract(recursive_packages: options[:recursive])
30
- success("Successfully extracted to #{File.basename(target)}/")
31
- rescue TargetExistsError => e
32
- error(e.message, STATUS_TARGET_EXISTS)
33
- rescue TargetNotEmptyError => e
34
- error(e.message, STATUS_TARGET_NOT_EMPTY)
33
+ desc "extract ARCHIVE [FILE...]",
34
+ "Extract FILE or all files from ARCHIVE to a new directory"
35
+ option :recursive, aliases: :r, type: :boolean, default: false,
36
+ desc: "Also extract all nested archives."
37
+ option :filter, type: :string,
38
+ desc: "Filter by pattern (supports **, *, ?, etc)"
39
+ def extract(archive, *files)
40
+ target = Excavate::Archive.new(archive).extract(
41
+ recursive_packages: options[:recursive],
42
+ files: files,
43
+ filter: options[:filter],
44
+ )
45
+
46
+ success("Successfully extracted to #{format_paths(target)}")
47
+ rescue Error => e
48
+ handle_error(e)
35
49
  end
36
50
  default_task :extract
37
51
 
@@ -42,9 +56,24 @@ module Excavate
42
56
  STATUS_SUCCESS
43
57
  end
44
58
 
59
+ def handle_error(exception)
60
+ status = ERROR_TO_STATUS[exception.class]
61
+ raise exception unless status
62
+
63
+ error(exception.message, status)
64
+ end
65
+
45
66
  def error(message, status)
46
67
  say(message, :red)
47
68
  status
48
69
  end
70
+
71
+ def format_paths(path_or_paths)
72
+ paths = Array(path_or_paths).map do |x|
73
+ File.directory?(x) ? "#{File.basename(x)}/" : File.basename(x)
74
+ end
75
+
76
+ paths.join(", ")
77
+ end
49
78
  end
50
79
  end
@@ -15,6 +15,8 @@ module Excavate
15
15
 
16
16
  Ole::Storage.open(@archive) do |ole|
17
17
  children(ole).each do |file|
18
+ next if ole.file.directory?(file)
19
+
18
20
  filename = prepare_filename(file)
19
21
  path = File.join(target, filename)
20
22
  content = ole.file.read(file)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Excavate
4
- VERSION = "0.2.4"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/excavate.rb CHANGED
@@ -8,7 +8,12 @@ require_relative "excavate/utils"
8
8
 
9
9
  module Excavate
10
10
  class Error < StandardError; end
11
- class UnknownArchiveError < Error; end
11
+
12
12
  class TargetExistsError < Error; end
13
+
13
14
  class TargetNotEmptyError < Error; end
15
+
16
+ class TargetNotFoundError < Error; end
17
+
18
+ class UnknownArchiveError < Error; end
14
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: excavate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-02 00:00:00.000000000 Z
11
+ date: 2022-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: arr-pm
@@ -81,19 +81,19 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '2.3'
83
83
  - !ruby/object:Gem::Dependency
84
- name: seven_zip_ruby
84
+ name: seven-zip
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '1.0'
89
+ version: '1.4'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '1.0'
96
+ version: '1.4'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: thor
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -116,8 +116,8 @@ executables:
116
116
  extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
- - ".github/workflows/release.yml"
120
- - ".github/workflows/rspec.yml"
119
+ - ".github/workflows/metanorma.yml"
120
+ - ".github/workflows/test-and-release.yml"
121
121
  - ".gitignore"
122
122
  - ".rspec"
123
123
  - ".rubocop.yml"
@@ -168,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
168
  - !ruby/object:Gem::Version
169
169
  version: '0'
170
170
  requirements: []
171
- rubygems_version: 3.0.3
171
+ rubygems_version: 3.3.7
172
172
  signing_key:
173
173
  specification_version: 4
174
174
  summary: Extract nested archives with a single command.
@@ -1,36 +0,0 @@
1
- name: release
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
-
8
- jobs:
9
- release:
10
- runs-on: ubuntu-18.04
11
- steps:
12
- - uses: actions/checkout@v1
13
-
14
- - uses: ruby/setup-ruby@v1
15
- with:
16
- ruby-version: '2.6'
17
-
18
- - run: bundle config set path 'vendor/bundle'
19
-
20
- - run: bundle install --jobs 4 --retry 3
21
-
22
- - run: bundle exec rspec
23
-
24
- - name: Publish to rubygems.org
25
- env:
26
- RUBYGEMS_API_KEY: ${{secrets.FONTIST_CI_RUBYGEMS_API_KEY}}
27
- run: |
28
- gem install gem-release
29
- touch ~/.gem/credentials
30
- cat > ~/.gem/credentials << EOF
31
- ---
32
- :rubygems_api_key: ${RUBYGEMS_API_KEY}
33
- EOF
34
- chmod 0600 ~/.gem/credentials
35
- git status
36
- gem release
@@ -1,47 +0,0 @@
1
- name: rspec
2
-
3
- on:
4
- push:
5
- branches: [ master, main ]
6
- pull_request:
7
-
8
- jobs:
9
- build:
10
- name: Test on Ruby ${{ matrix.ruby }} ${{ matrix.os }}
11
- runs-on: ${{ matrix.os }}
12
- continue-on-error: ${{ matrix.experimental }}
13
- strategy:
14
- fail-fast: false
15
- matrix:
16
- ruby: [ '2.4', '2.5', '2.6', '2.7' ]
17
- os: [ ubuntu-latest, windows-latest, macos-latest ]
18
- experimental: [ false ]
19
- include:
20
- - ruby: '3.0'
21
- os: 'ubuntu-latest'
22
- experimental: true
23
- - ruby: '3.0'
24
- os: 'windows-latest'
25
- experimental: true
26
- - ruby: '3.0'
27
- os: 'macos-latest'
28
- experimental: true
29
-
30
- steps:
31
- - uses: actions/checkout@master
32
-
33
- - uses: ruby/setup-ruby@v1
34
- with:
35
- ruby-version: ${{ matrix.ruby }}
36
-
37
- - uses: actions/cache@v1
38
- with:
39
- path: vendor/bundle
40
- key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
41
- restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
42
-
43
- - run: bundle config set path 'vendor/bundle'
44
-
45
- - run: bundle install --jobs 4 --retry 3
46
-
47
- - run: bundle exec rspec