flo 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +12 -0
- data/README.md +105 -0
- data/Rakefile +13 -0
- data/flo.gemspec +32 -0
- data/lib/flo/command.rb +115 -0
- data/lib/flo/command_collection.rb +24 -0
- data/lib/flo/config.rb +45 -0
- data/lib/flo/provider/developer.rb +32 -0
- data/lib/flo/runner.rb +94 -0
- data/lib/flo/state.rb +23 -0
- data/lib/flo/task.rb +53 -0
- data/lib/flo/version.rb +8 -0
- data/lib/flo.rb +14 -0
- data/test/fixtures/basic_setup.rb +14 -0
- data/test/fixtures/one_config_call.rb +8 -0
- data/test/flo/command_collection_test.rb +45 -0
- data/test/flo/command_test.rb +95 -0
- data/test/flo/config_test.rb +35 -0
- data/test/flo/flo_test.rb +16 -0
- data/test/flo/runner_integration_test.rb +35 -0
- data/test/flo/runner_test.rb +100 -0
- data/test/flo/state_test.rb +41 -0
- data/test/flo/task_test.rb +63 -0
- data/test/minitest_helper.rb +25 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b84be555cacd1fd27392d83cd39e89c19e9dafd4
|
4
|
+
data.tar.gz: 9cd073f4e4c9ab0da1ea2b816b2cb1e90a579441
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 43b7d50133307857e6a656d5ef99b0c9b8c0e99030541b7c890086d3903e4ca6b4387ea624d060e17d02384b6d6b1e9c0dbad5c22d44809b4f324b920881fd43
|
7
|
+
data.tar.gz: e8ad9ceec8b76344fa641774919a41d38298f2c50d122668e64935175a0c4e61b657a95233746ee8c36cb8f491cd07919a5ec1fc7536f434981396a43664f31b
|
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
source 'https://rubygems.org'
|
7
|
+
|
8
|
+
# Specify your gem's dependencies in flo.gemspec
|
9
|
+
gemspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Copyright (c) 2017, Salesforce.com, Inc.
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
7
|
+
|
8
|
+
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
9
|
+
|
10
|
+
* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# Flo
|
2
|
+
[![Code Climate](https://codeclimate.com/github/codeclimate/codeclimate/badges/gpa.svg)](https://codeclimate.com/github/codeclimate/codeclimate) [![Build Status](https://semaphoreci.com/api/v1/justinpowers/flo/branches/master/shields_badge.svg)](https://semaphoreci.com/justinpowers/flo)
|
3
|
+
|
4
|
+
|
5
|
+
Flo is a local workflow automation tool that helps you get things done. This gem contains the core functionality for Flo, plugins for interacting with various systems can be found in separate provider gems.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```shell
|
12
|
+
gem 'flo'
|
13
|
+
```
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
```shell
|
17
|
+
$ bundle
|
18
|
+
```
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
```shell
|
22
|
+
$ gem install flo
|
23
|
+
```
|
24
|
+
|
25
|
+
## Documentation
|
26
|
+
https://www.rubydoc.info/github/salesforce/flo/
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Command line usage
|
31
|
+
|
32
|
+
COMING SOON!
|
33
|
+
A command line parser has not yet been added. If you require a script that can be invoked from the command line, you can create a ruby script that creates and runs a `Flo::Runner` instance. See [Ruby script usage](#Ruby_script_usage) for more details.
|
34
|
+
|
35
|
+
### Ruby script usage
|
36
|
+
|
37
|
+
Flo has been built with the intention of being easy to use within ruby scripts. `Flo::Runner` is responsible for parsing your custom configuration and invoking the commands. See the following example:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
require 'flo'
|
41
|
+
|
42
|
+
runner = Flo::Runner.new
|
43
|
+
|
44
|
+
# Load your custom command configurations (see .flo file section for more details)
|
45
|
+
runner.load_config_file(File.join(__dir__,'.flo'))
|
46
|
+
|
47
|
+
# Run the something:useful command defined in the .flo file
|
48
|
+
response = runner.execute([:something, :useful], id: '123')
|
49
|
+
```
|
50
|
+
|
51
|
+
|
52
|
+
## .flo configuration file
|
53
|
+
|
54
|
+
Flo makes very few assumptions about what you want to use it for, or how you want to use it. In order for you to use it for anything useful, you will need to provide it some configuration. This is accomplished by loading one or more .flo configuration files. See [Ruby script usage](#Ruby_script_usage) for an example of how to load the file. The .flo file is evaluated in ruby in a cleanroom environment (see the [cleanroom gem](https://github.com/sethvargo/cleanroom) for more information), so you can require any gems or modules needed to accomplish the functionality you are looking for. There are two required sections:
|
55
|
+
* configuration
|
56
|
+
* command registration
|
57
|
+
|
58
|
+
### Configuration
|
59
|
+
|
60
|
+
Before you can do anything useful in your .flo file, you have to declare providers. You can do so using a config block, for example:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
config do |cfg|
|
64
|
+
cfg.provider :developer, {configuration_option: 'value' }
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
### Command registration
|
69
|
+
|
70
|
+
You can register any number of commands. Commands are namespaced to make it easier to group together similar commands. Within a command declaration you declare a set of tasks that will be executed in order when the command is invoked. Here is an overly simple example for starting a feature branch that only uses a single provider. In typical usage you would likely utilize multiple providers within a single command.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# Registers a command for starting a feature - feature:start. This command has
|
74
|
+
# one required argument: 'feature_name'. Note that in order for this to work,
|
75
|
+
# you will need to declare the git_flo provider in the config section.
|
76
|
+
register_command([:feature, :start]) do |feature_name: nil|
|
77
|
+
|
78
|
+
# During command execution, perform the :check_out_or_create_branch method on
|
79
|
+
# the git_flo provider, passing in the :from and :name arguments
|
80
|
+
perform :git_flo, :check_out_or_create_branch, { from: 'master', name: feature_name }
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
## Contributing
|
85
|
+
|
86
|
+
1. Fork it (http://github.com/your-github-username/flo/fork )
|
87
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
88
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
89
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
90
|
+
5. Create new Pull Request
|
91
|
+
|
92
|
+
## License
|
93
|
+
|
94
|
+
>Copyright (c) 2017, Salesforce.com, Inc.
|
95
|
+
>All rights reserved.
|
96
|
+
>
|
97
|
+
>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
98
|
+
>
|
99
|
+
>* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
100
|
+
>
|
101
|
+
>* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
102
|
+
>
|
103
|
+
>* Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
104
|
+
>
|
105
|
+
>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require "bundler/gem_tasks"
|
7
|
+
require "rake/testtask"
|
8
|
+
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.pattern = "test/**/*_test.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :test
|
data/flo.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
3
|
+
# All Rights Reserved.
|
4
|
+
# Licensed under the BSD 3-Clause license.
|
5
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
6
|
+
|
7
|
+
lib = File.expand_path('../lib', __FILE__)
|
8
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
9
|
+
require 'flo/version'
|
10
|
+
|
11
|
+
Gem::Specification.new do |spec|
|
12
|
+
spec.name = "flo"
|
13
|
+
spec.version = Flo::VERSION
|
14
|
+
spec.authors = ["Justin Powers"]
|
15
|
+
spec.email = ["justinspowers@gmail.com"]
|
16
|
+
spec.summary = %q{Simple developer workflow automation}
|
17
|
+
spec.description = %q{Flo is a local workflow automation tool that helps you get things done. This gem contains the core functionality for Flo, plugins for interacting with various systems can be found in separate provider gems.}
|
18
|
+
spec.homepage = "https://github.com/salesforce/flo"
|
19
|
+
spec.license = "BSD-3-Clause"
|
20
|
+
|
21
|
+
spec.files = `git ls-files -z`.split("\x0")
|
22
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.add_dependency "cleanroom"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "minitest"
|
30
|
+
spec.add_development_dependency "pry"
|
31
|
+
spec.add_development_dependency "simplecov"
|
32
|
+
end
|
data/lib/flo/command.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require 'cleanroom'
|
7
|
+
|
8
|
+
module Flo
|
9
|
+
|
10
|
+
# Definition of a single command. In general you should not call {#initialize Command.new}
|
11
|
+
# directly, but instead define the command using {Runner#register_command}.
|
12
|
+
#
|
13
|
+
# When a command is generated using {Runner#register_command} (typically in a
|
14
|
+
# flo configuration file), only the DSL methods will be available
|
15
|
+
#
|
16
|
+
class Command
|
17
|
+
|
18
|
+
include Cleanroom
|
19
|
+
|
20
|
+
# Creates a new command instance
|
21
|
+
# @option opts [Hash] providers ({}) Providers that the command will need
|
22
|
+
# access to
|
23
|
+
#
|
24
|
+
# @yield [args*]The block containing the definition for the command.
|
25
|
+
# Arguments passed into {#call} are available within the block
|
26
|
+
#
|
27
|
+
def initialize(opts={}, &blk)
|
28
|
+
raise ArgumentError.new('.new must be called with a block defining the command') unless blk
|
29
|
+
@state_class = opts[:state_class] || Flo::State
|
30
|
+
@task_class = opts[:task_class] || Flo::Task
|
31
|
+
@providers = opts[:providers] || {}
|
32
|
+
@tasks = []
|
33
|
+
@definition_lambda = convert_block_to_lambda(blk)
|
34
|
+
end
|
35
|
+
|
36
|
+
# @api dsl
|
37
|
+
# DSL method: Define a task that will be performed during the execution stage when
|
38
|
+
# {#call} is invoked.
|
39
|
+
# @param provider_sym [Symbol] The provider to send the message to
|
40
|
+
# @param method_sym [Symbol] The method you wish to call on the provider
|
41
|
+
# @param provider_options [Hash] A hash of options to be passed when
|
42
|
+
# invoking the method on the provider. Any lambda values will be called
|
43
|
+
# during the execution stage when #{#call} is invoked
|
44
|
+
#
|
45
|
+
def perform(provider_sym, method_sym, provider_options={})
|
46
|
+
tasks << @task_class.new(providers[provider_sym], method_sym, provider_options)
|
47
|
+
end
|
48
|
+
expose :perform
|
49
|
+
|
50
|
+
alias :validate :perform
|
51
|
+
expose :validate
|
52
|
+
|
53
|
+
# @api dsl
|
54
|
+
# DSL method: Returns an object representing the current state of the provider during
|
55
|
+
# the execution stage when {#call} is invoked. Any methods called on the
|
56
|
+
# {State} instance will return a lambda. This is intended to be used in the
|
57
|
+
# parameters passed to the {#perform} method, as you often want these
|
58
|
+
# parameters lazily evaluated during the execution stage, not when the
|
59
|
+
# definition is parsed.
|
60
|
+
# @param provider_sym [Symbol] The provider that you wish to query
|
61
|
+
#
|
62
|
+
# @return [State] An object that will return a lambda, delegating the method
|
63
|
+
# call to the provider specified
|
64
|
+
#
|
65
|
+
def state(provider_sym)
|
66
|
+
state_class.new(providers[provider_sym])
|
67
|
+
end
|
68
|
+
expose :state
|
69
|
+
|
70
|
+
# Invoke the command that has already been defined.
|
71
|
+
#
|
72
|
+
# This will run the command, processing any tasks defined by {#perform} and
|
73
|
+
# {#validate} in order, stopping execution if any of the tasks fails.
|
74
|
+
# Arguments passed in here will be merged with the provider options defined
|
75
|
+
# in each task.
|
76
|
+
# @param args [Hash] arguments to be passed to each task
|
77
|
+
#
|
78
|
+
def call(args={})
|
79
|
+
evaluate_command_definition(args)
|
80
|
+
response = tasks.map do |task|
|
81
|
+
|
82
|
+
response = task.call(args)
|
83
|
+
|
84
|
+
# bail early if the task failed
|
85
|
+
return response unless response.success?
|
86
|
+
response
|
87
|
+
end.last
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
attr_reader :tasks, :definition_lambda, :providers, :state_class
|
93
|
+
|
94
|
+
def evaluate_command_definition(*args)
|
95
|
+
cleanroom.instance_exec(*args, &definition_lambda)
|
96
|
+
end
|
97
|
+
|
98
|
+
def convert_block_to_lambda(blk)
|
99
|
+
# jruby and rubinius can convert a proc directly into a lambda
|
100
|
+
if (converted_block = lambda(&blk)).lambda?
|
101
|
+
converted_block
|
102
|
+
else
|
103
|
+
# Otherwise, hacky method to take advantage of #define_method's automatic lambda conversion
|
104
|
+
cleanroom.define_singleton_method(:_command_definition, &blk)
|
105
|
+
cleanroom.method(:_command_definition).to_proc
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def cleanroom
|
110
|
+
@cleanroom ||= self.class.send(:cleanroom).new(self)
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
module Flo
|
7
|
+
CommandNotDefinedError = Class.new(StandardError)
|
8
|
+
class CommandCollection
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@commands = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](*key)
|
15
|
+
raise CommandNotDefinedError.new("#{key} command is not defined") unless @commands.has_key?(key)
|
16
|
+
@commands[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(*key, command)
|
20
|
+
@commands[key] = command
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/lib/flo/config.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
module Flo
|
7
|
+
MissingRequireError = Class.new(StandardError)
|
8
|
+
|
9
|
+
# Instantiates and stores providers for use in command definitions
|
10
|
+
#
|
11
|
+
# @attr_reader providers [Hash] Hash of provider instances
|
12
|
+
#
|
13
|
+
class Config
|
14
|
+
attr_reader :providers
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@providers = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Instantiate a provider and add it to the {#providers} collection
|
21
|
+
# @param provider_sym [Symbol]
|
22
|
+
# @param options [Hash] Options to be passed to provider initialization
|
23
|
+
# @yield Yields the block to the provider initializer, in case the provider
|
24
|
+
# accepts a block
|
25
|
+
#
|
26
|
+
def provider(provider_sym, options={}, &blk)
|
27
|
+
@providers[provider_sym] = provider_class(provider_sym).new(options, &blk)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def provider_class(provider_sym)
|
33
|
+
klass = camel_case(provider_sym.to_s)
|
34
|
+
klass_name = "Flo::Provider::#{klass}"
|
35
|
+
Object.const_get(klass_name)
|
36
|
+
rescue NameError => e
|
37
|
+
raise MissingRequireError.new("#{klass_name} is not loaded. Please require the library before use")
|
38
|
+
end
|
39
|
+
|
40
|
+
def camel_case(str)
|
41
|
+
return str if str !~ /_/ && str =~ /[A-Z]+.*/
|
42
|
+
str.split('_').map{|e| e.capitalize}.join
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
module Flo
|
9
|
+
module Provider
|
10
|
+
Response = Struct.new(:success?)
|
11
|
+
class Developer
|
12
|
+
|
13
|
+
def initialize(options={})
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_successful(opts={})
|
18
|
+
success = opts[:success].nil? ? true : opts[:success]
|
19
|
+
Flo::Provider::Response.new(success)
|
20
|
+
end
|
21
|
+
|
22
|
+
def return_true
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
def echo(opts={})
|
27
|
+
puts opts.inspect
|
28
|
+
Flo::Provider::Response.new(true)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/flo/runner.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require 'flo'
|
7
|
+
require 'flo/command'
|
8
|
+
require 'flo/command_collection'
|
9
|
+
require 'flo/state'
|
10
|
+
require 'flo/config'
|
11
|
+
require 'flo/task'
|
12
|
+
require 'cleanroom'
|
13
|
+
|
14
|
+
module Flo
|
15
|
+
|
16
|
+
# This is the main class for instantiating and performing Flo commands. If
|
17
|
+
# you are wanting to interact with Flo via a ruby script, this is the class
|
18
|
+
# you want. Utilizing Flo through the command line interface will invoke this
|
19
|
+
# class after all of the argument parsing is complete.
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# runner = Runner.new
|
23
|
+
# runner.load_config_file('path/to/config/file')
|
24
|
+
# runner.execute([:issue, :submit], id: '1234', submitter: 'John Doe')
|
25
|
+
#
|
26
|
+
# @attr_reader commands [CommandCollection] List of commands currently defined
|
27
|
+
#
|
28
|
+
class Runner
|
29
|
+
include Cleanroom
|
30
|
+
|
31
|
+
attr_reader :commands
|
32
|
+
|
33
|
+
# Creates a new runner. This object is generally useless until you load
|
34
|
+
# some configuration into it, typically using {#load_config_file}
|
35
|
+
#
|
36
|
+
def initialize(opts={})
|
37
|
+
@config = opts[:config] || Flo::Config.new
|
38
|
+
@command_class = opts[:command_class] || Flo::Command
|
39
|
+
@commands = opts[:command_collection] || Flo::CommandCollection.new
|
40
|
+
end
|
41
|
+
|
42
|
+
# Open and parse a file containing flo configuration. This file is
|
43
|
+
# evaluated within a cleanroom. See the {https://github.com/sethvargo/cleanroom cleanroom gem}
|
44
|
+
# for more information.
|
45
|
+
# @param config_file [String] path to the flo configuration file
|
46
|
+
#
|
47
|
+
def load_config_file(config_file)
|
48
|
+
evaluate_file(config_file)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Executes the command specified, with the arguments specified
|
52
|
+
# @param command_namespace [Array<Symbol>] An array containing the name of
|
53
|
+
# the command as a symbol, including the namespace. For example, the
|
54
|
+
# command "issue submit" would become [:issue, :submit]
|
55
|
+
# @param args={} [Hash] Options that will get passed to the command
|
56
|
+
#
|
57
|
+
def execute(command_namespace, args={})
|
58
|
+
commands[command_namespace].call(args)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @api dsl
|
62
|
+
# DSL method: Returns the instance of {Config} associated with this runner. Exposes the
|
63
|
+
# {Config} instance if a block is used
|
64
|
+
#
|
65
|
+
# @yield [Config]
|
66
|
+
#
|
67
|
+
# @return [Config]
|
68
|
+
#
|
69
|
+
def config
|
70
|
+
yield(@config) if block_given?
|
71
|
+
@config
|
72
|
+
end
|
73
|
+
expose :config
|
74
|
+
|
75
|
+
# @api dsl
|
76
|
+
# DSL method: Creates and defines a {Command}, adding it to the command collection.
|
77
|
+
# Definition for the command should happen inside of the required block.
|
78
|
+
# See {Command} for methods available within the block.
|
79
|
+
# @param command_namespace [Array<Symbol>] Array of symbols representing the
|
80
|
+
# command including the namespace
|
81
|
+
# @yield [args*]The block containing the definition for the command.
|
82
|
+
# Arguments passed into {#execute} are available within the block
|
83
|
+
#
|
84
|
+
def register_command(command_namespace, &blk)
|
85
|
+
commands[command_namespace] = command_class.new(providers: config.providers, &blk)
|
86
|
+
end
|
87
|
+
expose :register_command
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
attr_reader :command_class
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
data/lib/flo/state.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
module Flo
|
7
|
+
class State
|
8
|
+
|
9
|
+
def initialize(provider)
|
10
|
+
@provider = provider
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(meth_sym, *args)
|
14
|
+
lambda do
|
15
|
+
provider.method(meth_sym).call(*args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :provider
|
22
|
+
end
|
23
|
+
end
|
data/lib/flo/task.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
module Flo
|
7
|
+
|
8
|
+
# Definition of a task performed by a {Command}.
|
9
|
+
#
|
10
|
+
class Task
|
11
|
+
|
12
|
+
# Creates a new Task instance
|
13
|
+
#
|
14
|
+
# @param [Provider] provider The provider to send the message to
|
15
|
+
# @param [Symbol] The method you wish to call on the provider
|
16
|
+
# @param [Hash] provider_options={} A hash of options to be passed when
|
17
|
+
# invoking the method on the provider. Any lambda values will be called
|
18
|
+
# during the execution stage when {#call} is invoked
|
19
|
+
#
|
20
|
+
def initialize(provider, method_sym, provider_options={})
|
21
|
+
@provider = provider
|
22
|
+
@method_sym = method_sym
|
23
|
+
|
24
|
+
raise ArgumentError.new("Expected provider_options to be a hash") unless provider_options.is_a? Hash
|
25
|
+
@provider_options = provider_options
|
26
|
+
end
|
27
|
+
|
28
|
+
# Call invokes the task on the provider instance. Additional parameters can be
|
29
|
+
# passed in that are merged into the parameters that were provided in {initialize}.
|
30
|
+
# Proc values will be evaluated before being passed to the provider.
|
31
|
+
#
|
32
|
+
# @param [Hash] args={} Additional arguments to pass to the provider method
|
33
|
+
# @return [#success?] Response of the provider's method
|
34
|
+
def call(args={})
|
35
|
+
@provider.public_send(method_sym, merged_evaluated_args(args))
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
attr_reader :provider, :method_sym, :provider_options
|
40
|
+
|
41
|
+
def merged_evaluated_args(args)
|
42
|
+
evaluate_proc_values(provider_options.merge args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def evaluate_proc_values(args={})
|
46
|
+
hsh = {}
|
47
|
+
args.each do |k, v|
|
48
|
+
hsh[k] = v.is_a?(Proc) ? v.call : v
|
49
|
+
end
|
50
|
+
hsh
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/flo/version.rb
ADDED
data/lib/flo.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require "flo/version"
|
7
|
+
require "flo/runner"
|
8
|
+
|
9
|
+
# Parent module for all Flo related functionality. Should not be used directly.
|
10
|
+
# See {file:README.md} or {Runner} for information on overall usage.
|
11
|
+
#
|
12
|
+
module Flo
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require 'flo/provider/developer'
|
7
|
+
|
8
|
+
config do |cfg|
|
9
|
+
cfg.provider :developer
|
10
|
+
end
|
11
|
+
|
12
|
+
register_command([:task, :start]) do |success: true|
|
13
|
+
perform :developer, :is_successful, { success: state(:developer).return_true }
|
14
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
config do |cfg|
|
7
|
+
cfg.provider :developer
|
8
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo/command_collection'
|
8
|
+
|
9
|
+
module Flo
|
10
|
+
class CommandCollectionTest < Flo::UnitTest
|
11
|
+
|
12
|
+
def subject
|
13
|
+
@subject ||= Flo::CommandCollection.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_a_single_symbol_can_be_used_as_a_storage_key
|
17
|
+
command = Object.new
|
18
|
+
subject[:command_name] = command
|
19
|
+
assert_same command, subject[:command_name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_an_array_of_symbols_can_be_used_as_a_storage_key
|
23
|
+
command = Object.new
|
24
|
+
subject[:name, :spaced, :command] = command
|
25
|
+
assert_same command, subject[:name, :spaced, :command]
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_properly_selects_correct_command
|
29
|
+
command1 = Object.new
|
30
|
+
command2 = Object.new
|
31
|
+
subject[:name, :spaced, :command1] = command1
|
32
|
+
subject[:name, :spaced, :command2] = command2
|
33
|
+
|
34
|
+
assert_same command1, subject[:name, :spaced, :command1]
|
35
|
+
assert_same command2, subject[:name, :spaced, :command2]
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_selecting_a_command_that_doesnt_exist_raises_error
|
39
|
+
assert_raises(Flo::CommandNotDefinedError) do
|
40
|
+
subject[:undefined_command]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo/command'
|
8
|
+
require 'ostruct'
|
9
|
+
|
10
|
+
module Flo
|
11
|
+
class CommandTest < Flo::UnitTest
|
12
|
+
|
13
|
+
def subject
|
14
|
+
@subject_block ||= lambda { }
|
15
|
+
@providers ||= { mocked_provider: mock }
|
16
|
+
@state_class_mock ||= Object
|
17
|
+
@subject ||= Flo::Command.new(
|
18
|
+
providers: @providers,
|
19
|
+
state_class: @state_class_mock,
|
20
|
+
task_class: MockTask,
|
21
|
+
&@subject_block
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def mock
|
26
|
+
@mock ||= MockProvider.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def performer_class_mock
|
30
|
+
@performer_class_mock ||= begin
|
31
|
+
mock = Minitest::Mock.new
|
32
|
+
mock.expect(:new, performer_obj, [Symbol, Symbol, {}, Hash])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def performer_obj
|
37
|
+
@performer_obj ||= lambda { }
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_new_raises_if_no_block_provided
|
41
|
+
assert_raises(ArgumentError) do
|
42
|
+
Flo::Command.new(:foo)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_task_called_with_args
|
47
|
+
@subject_block = lambda do |*args|
|
48
|
+
perform :mocked_provider, :provider_method, baz: 2
|
49
|
+
end
|
50
|
+
|
51
|
+
result = subject.call(bar: 1)
|
52
|
+
|
53
|
+
assert_equal([{ bar: 1 }], result.args_passed)
|
54
|
+
assert_equal({ baz: 2 }, result.args_initialized.last)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_call_stops_and_returns_failure_early_if_task_is_not_successful
|
58
|
+
@subject_block = lambda do |*args|
|
59
|
+
perform :mocked_provider, :failed_provider_method, {success: false}
|
60
|
+
perform :mocked_provider, :provider_method, {fail: true}
|
61
|
+
end
|
62
|
+
|
63
|
+
refute subject.call.success?
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_state_is_not_invoked_during_configuration_phase
|
67
|
+
@state_class_mock = Minitest::Mock.new
|
68
|
+
state_mock = Minitest::Mock.new
|
69
|
+
@state_class_mock.expect(:new, state_mock, [mock])
|
70
|
+
|
71
|
+
state_mock.expect(:state_method, lambda { raise "This should never be evaluated" }, [] )
|
72
|
+
subject.perform :mocked_provider, :provider_method, {evaluated_later: subject.state(:mocked_provider).state_method }
|
73
|
+
end
|
74
|
+
|
75
|
+
class MockProvider
|
76
|
+
attr_reader :args, :state_method_called
|
77
|
+
|
78
|
+
def state_method
|
79
|
+
@state_method_called = true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class MockTask
|
84
|
+
def initialize(*args)
|
85
|
+
@initial_args = args
|
86
|
+
end
|
87
|
+
|
88
|
+
def call(*args)
|
89
|
+
fail("This task should never have been called") if @initial_args.last.fetch(:fail, false)
|
90
|
+
success = @initial_args.last.fetch(:success, true)
|
91
|
+
OpenStruct.new(success?: success, args_passed: args, args_initialized: @initial_args)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo/config'
|
8
|
+
|
9
|
+
module Flo
|
10
|
+
class ConfigTest < Flo::UnitTest
|
11
|
+
|
12
|
+
def subject
|
13
|
+
@subject ||= Flo::Config.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_provider_instantiates_new_provider
|
17
|
+
assert_equal({}, subject.providers)
|
18
|
+
subject.provider(:mock_provider)
|
19
|
+
assert_kind_of Flo::Provider::MockProvider, subject.providers[:mock_provider]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_raises_helpful_error_if_provider_not_required
|
23
|
+
assert_raises(Flo::MissingRequireError) do
|
24
|
+
subject.provider :doesnt_exist
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
module Provider
|
30
|
+
class MockProvider
|
31
|
+
def initialize(args={})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo'
|
8
|
+
require 'flo/provider/developer'
|
9
|
+
|
10
|
+
class FloTest < Flo::UnitTest
|
11
|
+
|
12
|
+
def subject
|
13
|
+
@subject = Flo
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo/runner'
|
8
|
+
require 'flo/config'
|
9
|
+
|
10
|
+
module Flo
|
11
|
+
class RunnerIntegrationTest < Flo::UnitTest
|
12
|
+
|
13
|
+
def subject
|
14
|
+
@subject ||= begin
|
15
|
+
subj = Flo::Runner.new
|
16
|
+
subj.load_config_file(File.join(FIXTURES_ROOT, 'basic_setup.rb'))
|
17
|
+
subj
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_execute_returns_success
|
22
|
+
response = subject.execute([:task, :start])
|
23
|
+
|
24
|
+
assert_equal true, response.success?
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_execute_success_is_false_when_perform_fails
|
28
|
+
response = subject.execute([:task, :start], success: false)
|
29
|
+
|
30
|
+
assert_equal false, response.success?
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo/runner'
|
8
|
+
|
9
|
+
module Flo
|
10
|
+
class RunnerTest < Flo::UnitTest
|
11
|
+
|
12
|
+
def subject
|
13
|
+
@subject ||= Flo::Runner.new(
|
14
|
+
config: config_mock,
|
15
|
+
command_class: command_class_mock,
|
16
|
+
command_collection: command_collection_mock
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_mock
|
21
|
+
@config_mock ||= Minitest::Mock.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def command_class_mock
|
25
|
+
@command_class_mock ||= Minitest::Mock.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def command_collection_mock
|
29
|
+
@command_collection_mock ||= {}
|
30
|
+
end
|
31
|
+
|
32
|
+
def config_file_fixture
|
33
|
+
@config_file_fixture ||= File.expand_path(File.join(FIXTURES_ROOT, 'basic_setup.rb'))
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_config_returns_config_instance
|
37
|
+
# Minitest::Mock undefines #equal?, which causes #assert_same to raise
|
38
|
+
assert_equal config_mock.object_id, subject.config.object_id
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_passing_block_to_config_yields_config_to_block
|
42
|
+
config_mock.expect(:foo, true)
|
43
|
+
|
44
|
+
subject.config do |cfg|
|
45
|
+
cfg.foo
|
46
|
+
end
|
47
|
+
|
48
|
+
config_mock.verify
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_register_command_adds_new_command_to_collection
|
52
|
+
new_command = Object.new
|
53
|
+
command_class_mock.expect(:new, new_command, [{ providers: {} }])
|
54
|
+
|
55
|
+
config_mock.expect(:providers, {})
|
56
|
+
|
57
|
+
subject.register_command(:foo) { }
|
58
|
+
|
59
|
+
assert_equal new_command, subject.commands[:foo]
|
60
|
+
|
61
|
+
command_class_mock.verify
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_register_command_namespaced_adds_new_command_to_collection
|
65
|
+
config_mock.expect(:providers, {})
|
66
|
+
new_command = Object.new
|
67
|
+
command_class_mock.expect(:new, new_command, [{ providers: {} }])
|
68
|
+
|
69
|
+
@command_collection_mock = {}
|
70
|
+
|
71
|
+
subject.register_command([:foo, :bar]) { }
|
72
|
+
|
73
|
+
assert_equal(new_command, subject.commands[[:foo, :bar]])
|
74
|
+
|
75
|
+
command_class_mock.verify
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_execute_calls_command_with_args
|
79
|
+
args = {foo: :bar}
|
80
|
+
providers_hash = Object.new
|
81
|
+
new_command = lambda { |args| true }
|
82
|
+
|
83
|
+
command_class_mock.expect(:new, new_command, [{ providers: providers_hash }])
|
84
|
+
config_mock.expect(:providers, providers_hash)
|
85
|
+
|
86
|
+
subject.register_command(:foo)
|
87
|
+
|
88
|
+
subject.execute(:foo, args)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_load_config_file_evals_file
|
92
|
+
config_mock.expect(:provider, true, [:developer])
|
93
|
+
subject.load_config_file(File.join(FIXTURES_ROOT, 'one_config_call.rb'))
|
94
|
+
|
95
|
+
config_mock.verify
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo/state'
|
8
|
+
|
9
|
+
module Flo
|
10
|
+
class StateTest < Flo::UnitTest
|
11
|
+
|
12
|
+
def subject
|
13
|
+
@mock_provider ||= MockProvider.new
|
14
|
+
@subject ||= Flo::State.new(@mock_provider)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_meth_missing_returns_lambda
|
18
|
+
assert_kind_of Proc, subject.existing_method
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_arguments_are_passed_into_returned_lambda
|
22
|
+
subject.existing_method(:method_arguments).call
|
23
|
+
|
24
|
+
assert_equal([:method_arguments], @mock_provider.args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_provider_method_is_called_when_lambda_is_invoked
|
28
|
+
subject.existing_method.call
|
29
|
+
|
30
|
+
assert @mock_provider.existing_method_called
|
31
|
+
end
|
32
|
+
|
33
|
+
class MockProvider
|
34
|
+
attr_reader :args, :existing_method_called
|
35
|
+
def existing_method(*args)
|
36
|
+
@existing_method_called = true
|
37
|
+
@args = args
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require_relative '../minitest_helper'
|
7
|
+
require 'flo/task'
|
8
|
+
require 'ostruct'
|
9
|
+
|
10
|
+
module Flo
|
11
|
+
class TaskTest < Flo::UnitTest
|
12
|
+
def subject
|
13
|
+
@method_sym ||= :foo
|
14
|
+
@provider_options ||= {}
|
15
|
+
@subject ||= Flo::Task.new(
|
16
|
+
provider,
|
17
|
+
@method_sym,
|
18
|
+
@provider_options
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def provider
|
23
|
+
@provider ||= Minitest::Mock.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_calls_method_on_provider
|
27
|
+
provider.expect(:foo, true, [{}])
|
28
|
+
subject.call()
|
29
|
+
provider.verify
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_passes_on_args
|
33
|
+
provider.expect(:foo, true, [{ bar: 1 }])
|
34
|
+
subject.call(bar: 1)
|
35
|
+
provider.verify
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_merges_args_with_provider_options
|
39
|
+
@provider_options = { baz: 2 }
|
40
|
+
provider.expect(:foo, true, [{ bar: 1, baz: 2 }])
|
41
|
+
subject.call(bar: 1)
|
42
|
+
provider.verify
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_should_raise_if_provider_options_is_not_a_hash
|
46
|
+
@provider_options = :bar
|
47
|
+
assert_raises(ArgumentError) { subject.call(baz: 1) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_called_args_override_provider_options
|
51
|
+
@provider_options = { bar: 2 }
|
52
|
+
provider.expect(:foo, true, [{ bar: 1 }])
|
53
|
+
subject.call(bar: 1)
|
54
|
+
provider.verify
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_procs_in_options_are_evaluated_before_provider_method_is_called
|
58
|
+
@provider_options = { baz: Proc.new { 2 }}
|
59
|
+
provider.expect(:foo, true, [{ bar: 1, baz: 2 }])
|
60
|
+
subject.call(bar: Proc.new { 1 })
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright © 2017, Salesforce.com, Inc.
|
2
|
+
# All Rights Reserved.
|
3
|
+
# Licensed under the BSD 3-Clause license.
|
4
|
+
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
5
|
+
|
6
|
+
require 'simplecov'
|
7
|
+
SimpleCov.start
|
8
|
+
|
9
|
+
SimpleCov.configure do
|
10
|
+
add_filter "/test/"
|
11
|
+
end
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
14
|
+
TEST_ROOT = File.dirname(__FILE__)
|
15
|
+
FIXTURES_ROOT = File.expand_path('../fixtures', __FILE__)
|
16
|
+
ENV["MT_NO_SKIP_MSG"] = "true"
|
17
|
+
|
18
|
+
require 'minitest/autorun'
|
19
|
+
require 'pry'
|
20
|
+
|
21
|
+
module Flo
|
22
|
+
class UnitTest < Minitest::Test
|
23
|
+
self.parallelize_me!
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: flo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Powers
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-05-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cleanroom
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Flo is a local workflow automation tool that helps you get things done. This
|
98
|
+
gem contains the core functionality for Flo, plugins for interacting with various
|
99
|
+
systems can be found in separate provider gems.
|
100
|
+
email:
|
101
|
+
- justinspowers@gmail.com
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- ".gitignore"
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- flo.gemspec
|
112
|
+
- lib/flo.rb
|
113
|
+
- lib/flo/command.rb
|
114
|
+
- lib/flo/command_collection.rb
|
115
|
+
- lib/flo/config.rb
|
116
|
+
- lib/flo/provider/developer.rb
|
117
|
+
- lib/flo/runner.rb
|
118
|
+
- lib/flo/state.rb
|
119
|
+
- lib/flo/task.rb
|
120
|
+
- lib/flo/version.rb
|
121
|
+
- test/fixtures/basic_setup.rb
|
122
|
+
- test/fixtures/one_config_call.rb
|
123
|
+
- test/flo/command_collection_test.rb
|
124
|
+
- test/flo/command_test.rb
|
125
|
+
- test/flo/config_test.rb
|
126
|
+
- test/flo/flo_test.rb
|
127
|
+
- test/flo/runner_integration_test.rb
|
128
|
+
- test/flo/runner_test.rb
|
129
|
+
- test/flo/state_test.rb
|
130
|
+
- test/flo/task_test.rb
|
131
|
+
- test/minitest_helper.rb
|
132
|
+
homepage: https://github.com/salesforce/flo
|
133
|
+
licenses:
|
134
|
+
- BSD-3-Clause
|
135
|
+
metadata: {}
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
requirements: []
|
151
|
+
rubyforge_project:
|
152
|
+
rubygems_version: 2.5.2
|
153
|
+
signing_key:
|
154
|
+
specification_version: 4
|
155
|
+
summary: Simple developer workflow automation
|
156
|
+
test_files:
|
157
|
+
- test/fixtures/basic_setup.rb
|
158
|
+
- test/fixtures/one_config_call.rb
|
159
|
+
- test/flo/command_collection_test.rb
|
160
|
+
- test/flo/command_test.rb
|
161
|
+
- test/flo/config_test.rb
|
162
|
+
- test/flo/flo_test.rb
|
163
|
+
- test/flo/runner_integration_test.rb
|
164
|
+
- test/flo/runner_test.rb
|
165
|
+
- test/flo/state_test.rb
|
166
|
+
- test/flo/task_test.rb
|
167
|
+
- test/minitest_helper.rb
|