flutter 0.1.0.pre.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -8
- data/Gemfile +1 -0
- data/README.md +62 -4
- data/Rakefile +35 -1
- data/codecov.yml +13 -0
- data/lib/flutter/minitest.rb +6 -8
- data/lib/flutter/parser.rb +18 -16
- data/lib/flutter/rspec.rb +7 -7
- data/lib/flutter/tracker.rb +1 -0
- data/lib/flutter/version.rb +1 -1
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ca2f5eb98359bf0cbac8abbdedcbe6ca27ec7bf205625f44cf0c4150313eeb4
|
4
|
+
data.tar.gz: 6620320c3c54d63117ddc95550c0d4223411bfe9b6b469336fe9f60ffcddcfe3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f97e5720ea6fd890e4c6283a1193750eea3c1ffa64de2de550793cecb14f8636a205774a08811a3f4aea35ed5a764023603fa91a33bd0b4d00496925f4ab35c
|
7
|
+
data.tar.gz: 7f890be9219df6f89fde38e9bc34479a65c9a3d8d910ec1495732a2a32ac65d33291c507b8e7b6950facca0d02b6a47c726c864ae2abde9a4416ae983096b29c
|
data/CHANGELOG.md
CHANGED
@@ -4,17 +4,27 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
-
##
|
8
|
-
##
|
7
|
+
## Unreleased
|
8
|
+
## 0.2.0
|
9
9
|
### Added
|
10
|
-
|
11
|
-
|
10
|
+
- CI Recipe in README
|
11
|
+
- CI integration for incremental tests in branches/pull requests
|
12
|
+
- Release workflow tasks & github actions integration
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
- Ensure all methods (including inherited ones) are considered when calculating signatures for a class or module.
|
16
|
+
- Fix calculation of total / filtered examples for rspec integration
|
17
|
+
|
18
|
+
## 0.1.0.pre.3
|
19
|
+
### Added
|
20
|
+
- Improved documentation for Persistence classes
|
21
|
+
- Improved documentation for Tracker
|
12
22
|
|
13
23
|
### Changed
|
14
|
-
|
24
|
+
- Pinned dependencies to known working minimum versions
|
15
25
|
|
16
|
-
##
|
26
|
+
## 0.1.0.pre.2
|
17
27
|
### Added
|
18
|
-
|
19
|
-
|
28
|
+
- Minitest integration
|
29
|
+
- RSpec integration
|
20
30
|
|
data/Gemfile
CHANGED
@@ -11,6 +11,7 @@ group :test, :development do
|
|
11
11
|
gem "overcommit", "~> 0.59.1"
|
12
12
|
gem "gem-release", "~> 2.2"
|
13
13
|
gem "guard", "~> 2.18"
|
14
|
+
gem "keepachangelog", "~> 0.6.1"
|
14
15
|
gem "rubocop", "~> 1.21"
|
15
16
|
gem "rubocop-shopify", require: false
|
16
17
|
gem "rubocop-minitest", "~> 0.22.1"
|
data/README.md
CHANGED
@@ -107,7 +107,55 @@ guard :rspec, cmd: "rspec" do
|
|
107
107
|
end
|
108
108
|
```
|
109
109
|
## Configuring flutter in continuous integration
|
110
|
-
|
110
|
+
|
111
|
+
Flutter can be used in continuous integration environments to speed up the turn
|
112
|
+
around time from running tests by only running tests affected by the changes
|
113
|
+
in a pull request.
|
114
|
+
|
115
|
+
### Github Actions
|
116
|
+
The following example workflow with github actions does the following:
|
117
|
+
- Always run all tests on the `main` branch
|
118
|
+
- Only run tests affected by the "current" commit for CI workflows triggered by a `push` event on other branches
|
119
|
+
- If the CI workflow is triggered due to a `pull_request` event, run all tests affected by all commits in the branch
|
120
|
+
(by comparing against the branch point of the pull request)
|
121
|
+
|
122
|
+
```yaml
|
123
|
+
# Get the commit where this branch diverges from origin/main
|
124
|
+
- name: Retrieve branch point
|
125
|
+
if: github.event_name == 'pull_request'
|
126
|
+
run: |
|
127
|
+
echo "::set-output name=KEY::$(diff -u <(git rev-list --first-parent origin/main) <(git rev-list --first-parent HEAD) | sed -ne 's/^ //p' | head -1)"
|
128
|
+
id: cache_keys
|
129
|
+
# Use the always-upload-cache action to:
|
130
|
+
# - Restore the flutter state from cache from either the branch point (if it was set in the previous step)
|
131
|
+
# or the last run in the current branch
|
132
|
+
# - After the run cache the flutter state using the current commit hash as the hash key
|
133
|
+
- name: Setup flutter state
|
134
|
+
id: flutter-state
|
135
|
+
uses: pat-s/always-upload-cache@v2.1.5
|
136
|
+
env:
|
137
|
+
cache-name: cache-flutter-state
|
138
|
+
with:
|
139
|
+
path: .flutter
|
140
|
+
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.ruby-version }}-${{ github.sha }}
|
141
|
+
restore-keys: |
|
142
|
+
${{ runner.os }}-build-${{ env.cache-name }}-${{ matrix.ruby-version }}-${{ steps.cache_keys.outputs.KEY }}
|
143
|
+
# If this is a push event on the main branch, clear the flutter state
|
144
|
+
# so that all tests are run and a full state is cached on the main branch
|
145
|
+
- name: Clear flutter state
|
146
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/main')
|
147
|
+
run: rm -rf .flutter
|
148
|
+
```
|
149
|
+
> **Note**
|
150
|
+
> The exact CI configuration would ofcourse depend on your workflow and confidence in selectively
|
151
|
+
> running tests for pull requests.
|
152
|
+
|
153
|
+
> **Warning**
|
154
|
+
> Selectively running tests in a pull request would show a drop in coverage if you are collecting
|
155
|
+
> and/or using code coverage as a "Check". One way to make Flutter work hand in hand with code
|
156
|
+
> coverage checks is to only validate that the diff in the pull request has a 100% coverage. For
|
157
|
+
> example with [codecov](https://docs.codecov.com/docs/commit-status#section-project-status) this can be
|
158
|
+
> achieved by only enabling the `project` status for the main branch and `patch` status otherwise.
|
111
159
|
|
112
160
|
## Related work
|
113
161
|
|
@@ -119,9 +167,19 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
119
167
|
|
120
168
|
This project uses [overcommit](https://github.com/sds/overcommit) to enforce standards. Enable the precommit hooks in your local checkout by running: `overcommit --sign`
|
121
169
|
|
122
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
123
|
-
|
124
|
-
|
170
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
171
|
+
|
172
|
+
### Releasing a new version
|
173
|
+
- Ensure that the [Unreleased](./CHANGELOG.md#Unreleased) section of the changelog is up to date
|
174
|
+
and contains useful details.
|
175
|
+
- Create a new release using the `release` rake task as follows (for more details about specifying the version change
|
176
|
+
run `gem bump --help` which is the command used by the task):
|
177
|
+
- Patch release `bundle exec rake release["-v patch"]`
|
178
|
+
- Minor release `bundle exec rake release["-v minor"]`
|
179
|
+
- Major release `bundle exec rake release["-v major"]`
|
180
|
+
> **Note**
|
181
|
+
> The `release` rake task automates updating the changelog & version, committing the changes & creating a new tag
|
182
|
+
- Push the tag. The CI workflow for tag pushes will take care of publishing the gem & creating a github release.
|
125
183
|
|
126
184
|
## Contributing
|
127
185
|
|
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "bundler/gem_tasks"
|
4
3
|
require "rake/testtask"
|
4
|
+
require "keepachangelog"
|
5
5
|
|
6
6
|
Rake::TestTask.new(:unit) do |t|
|
7
7
|
t.libs << "test"
|
@@ -22,3 +22,37 @@ RSpec::Core::RakeTask.new(:spec)
|
|
22
22
|
|
23
23
|
task test: [:unit, :spec]
|
24
24
|
task default: [:test, :spec, "rubocop:autocorrect_all"]
|
25
|
+
|
26
|
+
desc "Increment the version, update changelog and create a tag for the release"
|
27
|
+
task :release, [:version] do |_t, args|
|
28
|
+
parser = Keepachangelog::MarkdownParser.load("CHANGELOG.md")
|
29
|
+
log = parser.parsed_content["versions"].delete("Unreleased")
|
30
|
+
sh("gem bump --pretend #{args[:version]}") do |ok, _|
|
31
|
+
if ok
|
32
|
+
new_version = %x(gem bump --no-commit #{args[:version]} | awk '{print $4}' | uniq).chomp
|
33
|
+
parser.parsed_content["versions"]["Unreleased"] = { "url" => nil, "date" => nil, "changes" => {} }
|
34
|
+
parser.parsed_content["versions"][new_version] = log
|
35
|
+
File.open("CHANGELOG.md", "w") do |file|
|
36
|
+
file.write(parser.to_md)
|
37
|
+
end
|
38
|
+
%x(git add CHANGELOG.md lib/flutter/version.rb)
|
39
|
+
%x(git commit -m "Bump flutter to #{new_version}")
|
40
|
+
%x(gem tag -s)
|
41
|
+
Rake::Task["release_notes"].execute({ version: new_version })
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Get release notes for the current or specific version"
|
47
|
+
task :release_notes, [:version] do |_t, args|
|
48
|
+
version = (args[:version] || Flutter::VERSION)
|
49
|
+
parser = Keepachangelog::MarkdownParser.load("CHANGELOG.md")
|
50
|
+
parser.parsed_content.delete("intro")
|
51
|
+
parser.parsed_content.delete("title")
|
52
|
+
parser.parsed_content["versions"] = parser.parsed_content["versions"].select { |k, _v| k == version }
|
53
|
+
lines = parser.to_md.split("\n")
|
54
|
+
chunk = ["## #{version}"] + (
|
55
|
+
lines.slice_after { |line| line.include?("## #{version}") }.to_a[1] || []
|
56
|
+
)
|
57
|
+
puts chunk.join("\n")
|
58
|
+
end
|
data/codecov.yml
ADDED
data/lib/flutter/minitest.rb
CHANGED
@@ -10,7 +10,7 @@ end
|
|
10
10
|
module Flutter
|
11
11
|
module Minitest
|
12
12
|
class << self
|
13
|
-
attr_accessor :filtered
|
13
|
+
attr_accessor :filtered, :total
|
14
14
|
|
15
15
|
def flutter_tracker
|
16
16
|
@tracker ||= Flutter::Tracker.new(
|
@@ -31,7 +31,7 @@ module Flutter
|
|
31
31
|
return unless ::Flutter.enabled
|
32
32
|
|
33
33
|
Flutter::Minitest.flutter_tracker.persist!
|
34
|
-
$stdout.puts "Flutter filtered
|
34
|
+
$stdout.puts "Flutter filtered #{Flutter::Minitest.filtered} / #{Flutter::Minitest.total} tests"
|
35
35
|
if @verbose
|
36
36
|
$stdout.puts "Persisted flutter #{Flutter::Minitest.flutter_tracker}"
|
37
37
|
end
|
@@ -43,17 +43,15 @@ module Flutter
|
|
43
43
|
module ClassMethods
|
44
44
|
def runnable_methods
|
45
45
|
Flutter::Minitest.filtered ||= 0
|
46
|
+
Flutter::Minitest.total ||= 0
|
46
47
|
default = super()
|
48
|
+
Flutter::Minitest.total += default.length
|
47
49
|
default.select do |test|
|
48
|
-
|
50
|
+
!Minitest.flutter_tracker.skip?(
|
49
51
|
"#{name}##{test}",
|
50
52
|
File.absolute_path(instance_method(test).source_location[0]),
|
51
53
|
instance_method(test).source,
|
52
|
-
)
|
53
|
-
if skip
|
54
|
-
Flutter::Minitest.filtered += 1
|
55
|
-
end
|
56
|
-
!skip
|
54
|
+
).tap { |skip| Flutter::Minitest.filtered += 1 if skip }
|
57
55
|
end
|
58
56
|
end
|
59
57
|
end
|
data/lib/flutter/parser.rb
CHANGED
@@ -8,6 +8,11 @@ module Flutter
|
|
8
8
|
class Parser
|
9
9
|
attr_reader :signatures
|
10
10
|
|
11
|
+
@method_cache = {}
|
12
|
+
class << self
|
13
|
+
attr_reader :method_cache
|
14
|
+
end
|
15
|
+
|
11
16
|
def initialize(file)
|
12
17
|
@signatures = {}
|
13
18
|
@targets = Set.new
|
@@ -49,23 +54,17 @@ module Flutter
|
|
49
54
|
require_relative @file
|
50
55
|
@targets.each do |container|
|
51
56
|
instance = Kernel.const_get(container)
|
52
|
-
class_methods =
|
53
|
-
|
54
|
-
) + (
|
55
|
-
instance.private_methods - Object.private_methods
|
56
|
-
)
|
57
|
-
instance_methods = (
|
58
|
-
instance.instance_methods - Object.instance_methods
|
59
|
-
) + (
|
60
|
-
instance.private_instance_methods - Object.private_instance_methods
|
61
|
-
)
|
57
|
+
class_methods = instance.methods + instance.private_methods
|
58
|
+
instance_methods = instance.instance_methods + instance.private_instance_methods
|
62
59
|
|
63
60
|
@signatures.merge!(class_methods.map do |method|
|
64
|
-
|
65
|
-
|
61
|
+
hash = source_hash(instance.method(method))
|
62
|
+
["#{container}::#{method}", hash] if hash
|
63
|
+
end.compact.to_h)
|
66
64
|
@signatures.merge!(instance_methods.map do |method|
|
67
|
-
|
68
|
-
|
65
|
+
hash = source_hash(instance.instance_method(method))
|
66
|
+
["#{container}:#{method}", hash] if hash
|
67
|
+
end.compact.to_h)
|
69
68
|
rescue NameError
|
70
69
|
$stderr.puts "failed to load #{container} in #{@file}"
|
71
70
|
end
|
@@ -74,9 +73,12 @@ module Flutter
|
|
74
73
|
end
|
75
74
|
|
76
75
|
def source_hash(callable)
|
77
|
-
|
76
|
+
return unless callable.source_location
|
77
|
+
|
78
|
+
sep = callable.is_a?(UnboundMethod) ? ":" : "::"
|
79
|
+
Parser.method_cache["#{callable.owner}#{sep}#{callable.name}"] ||= Digest::SHA1.hexdigest(callable.source)
|
78
80
|
rescue MethodSource::SourceNotFoundError
|
79
|
-
|
81
|
+
nil
|
80
82
|
end
|
81
83
|
end
|
82
84
|
end
|
data/lib/flutter/rspec.rb
CHANGED
@@ -5,7 +5,7 @@ require_relative "tracker"
|
|
5
5
|
module Flutter
|
6
6
|
module RSpec
|
7
7
|
class << self
|
8
|
-
attr_accessor :filtered
|
8
|
+
attr_accessor :filtered, :total
|
9
9
|
|
10
10
|
def tracker
|
11
11
|
@tracker ||= Flutter::Tracker.new(
|
@@ -17,20 +17,20 @@ module Flutter
|
|
17
17
|
|
18
18
|
module ClassMethods
|
19
19
|
def filtered_examples
|
20
|
-
Flutter::RSpec.filtered ||=
|
20
|
+
Flutter::RSpec.filtered ||= Set.new
|
21
|
+
Flutter::RSpec.total ||= Set.new
|
21
22
|
Flutter::RSpec.tracker.reset! if Flutter.enabled && Flutter.config.reset_storage
|
22
23
|
|
23
24
|
original = super
|
25
|
+
Flutter::RSpec.total.merge(original)
|
24
26
|
return original unless Flutter.enabled
|
25
27
|
|
26
28
|
original.select do |example|
|
27
|
-
|
29
|
+
!(example.metadata[:block] && Flutter::RSpec.tracker.skip?(
|
28
30
|
example.full_description,
|
29
31
|
example.metadata[:absolute_file_path],
|
30
32
|
example.metadata[:block].source,
|
31
|
-
)
|
32
|
-
Flutter::RSpec.filtered += 1 if skip
|
33
|
-
!skip
|
33
|
+
).tap { |skip| Flutter::RSpec.filtered << example if skip })
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -58,7 +58,7 @@ if defined?(RSpec.configure)
|
|
58
58
|
config.after(:suite) do
|
59
59
|
if Flutter.enabled
|
60
60
|
$stdout.puts
|
61
|
-
$stdout.puts "Flutter filtered
|
61
|
+
$stdout.puts "Flutter filtered #{Flutter::RSpec.filtered.length} / #{Flutter::RSpec.total.length} examples"
|
62
62
|
Flutter::RSpec.tracker.persist!
|
63
63
|
end
|
64
64
|
end
|
data/lib/flutter/tracker.rb
CHANGED
data/lib/flutter/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flutter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ali-Akber Saifee
|
8
8
|
- Ankita Gupta
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-10-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: deep_merge
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- README.md
|
74
74
|
- Rakefile
|
75
75
|
- TODO.md
|
76
|
+
- codecov.yml
|
76
77
|
- lib/flutter.rb
|
77
78
|
- lib/flutter/config.rb
|
78
79
|
- lib/flutter/minitest.rb
|
@@ -90,7 +91,7 @@ metadata:
|
|
90
91
|
homepage_uri: https://github.com/indydevs/flutter
|
91
92
|
source_code_uri: https://github.com/indydevs/flutter
|
92
93
|
changelog_uri: https://github.com/indydevs/flutter/blob/master/CHANGELOG.md
|
93
|
-
post_install_message:
|
94
|
+
post_install_message:
|
94
95
|
rdoc_options: []
|
95
96
|
require_paths:
|
96
97
|
- lib
|
@@ -101,12 +102,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
102
|
version: 2.7.0
|
102
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
104
|
requirements:
|
104
|
-
- - "
|
105
|
+
- - ">="
|
105
106
|
- !ruby/object:Gem::Version
|
106
|
-
version:
|
107
|
+
version: '0'
|
107
108
|
requirements: []
|
108
|
-
rubygems_version: 3.
|
109
|
-
signing_key:
|
109
|
+
rubygems_version: 3.3.7
|
110
|
+
signing_key:
|
110
111
|
specification_version: 4
|
111
112
|
summary: Intelligent test selection based on incremental code changes
|
112
113
|
test_files: []
|