ripe 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f35a6d35553e2be4a3e844dabb53c32e2c1a1f6a
4
- data.tar.gz: bf643294c8bfbe8deacd145beb0bb4d8de221451
3
+ metadata.gz: 2961c4cc93b7823c51c6ef1dc6d717b41de56d58
4
+ data.tar.gz: 5f80f681106b6b747f88fd9a3797ae661db7557f
5
5
  SHA512:
6
- metadata.gz: 28e9487eebc73524e99974fb273ff106ee14c1b7cfcdb22159e2f4571a9abed6356490827261d9c95bbe04695e202906fee3ea22c82cb9baf797faa1354717df
7
- data.tar.gz: 30708a13a9121c3aad6bb2ba23c12adec602468f632f5c4fd381d297c0919ce2b32f3f3670fa63994c6612e105d0fd87ecdee26205127f5884c94460554afb62
6
+ metadata.gz: 8b7edf637ca227eb6ac31ec0dd32bf7efbae0a54fda49e474f313850c554d45c55f03c767b315101f872cf11164c7a500f50b440fd9228f4afb2da42c34fa578
7
+ data.tar.gz: d8829b666f606a54c56c29e5a21a68ca04a177ce4a859fc83a8c9a0758c9d0f86d42e0ba671b31b996ac8313671e8bd849d731f2b8c420693cf0cc9096830534
data/.travis.yml CHANGED
@@ -3,7 +3,8 @@ cache: bundler
3
3
  rvm:
4
4
  - 2.1.5
5
5
  script: bundle exec rake spec
6
+ branches:
7
+ only:
8
+ - develop
6
9
  notifications:
7
10
  email: false
8
- slack:
9
- secure: "RlmKttTKbJlU1xu6blqP3HWwzH4KpvvdatvxkFWB1t3mBE3vRWC8FgiNpxYFs/6+TdctGOWRGW/i6CUaXbPwn3nyrlN+yxHmqNrJFg8dS2jQoM1/xBUZXdDhABMvw8qWzG26RSfGlvvO0P78rILawil+5/2z9e1XcUVmf0RL+gc="
data/Gemfile CHANGED
@@ -1,6 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem "codeclimate-test-reporter", group: :test, require: nil
4
-
5
3
  # Specify your gem's dependencies in ripe.gemspec
6
4
  gemspec
data/Guardfile CHANGED
@@ -1,5 +1,6 @@
1
1
  guard :rspec, cmd: 'rspec' do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
- watch(%r{^lib/ripe/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
- watch('spec/spec_helper.rb') { "spec" }
3
+ watch(%r{^lib/ripe/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ watch('spec/testpack.rb') { "spec" }
5
6
  end
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'rspec/core/rake_task'
2
2
  require 'bundler/gem_tasks'
3
- require 'rdoc/task'
4
3
 
5
4
  # Default directory to look in is `/specs`
6
5
  # Run with `rake spec`
@@ -9,8 +8,4 @@ RSpec::Core::RakeTask.new(:spec) do |task|
9
8
  # task.rspec_opts = ['--color', '--format', 'nested']
10
9
  end
11
10
 
12
- RDoc::Task.new(:rdoc => 'rdoc',
13
- :clobber_rdoc => 'rdoc:clean',
14
- :rerdoc => 'rdoc:force')
15
-
16
11
  # task :default => :spec
data/bin/ripe CHANGED
@@ -1,31 +1,31 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require_relative '../lib/ripe'
4
+ require_relative '../lib/ripe/dsl'
5
+ require 'ripl' # REPL
6
+ require 'hirb' # Pretty output for +ActiveRecord+ objects
4
7
  require 'thor'
5
8
 
6
9
  include Ripe
7
-
8
- # Look for workflows and blocks in ./.ripe wherever invoked, then in
9
- # directories specified in the $RIPELIB environment variable.
10
- $RIPELIBS = "#{ENV['PWD']}/.ripe:#{ENV['RIPELIB']}".split(/:/)
11
-
12
- def Task(handle, vars = {})
13
- WorkingBlock.new($RIPELIBS.map{ |path| "#{path}/tasks/#{handle}.sh" }.select{ |path| File.exists? path }.first, vars)
14
- end
10
+ include Ripe::DSL
15
11
 
16
12
  class CLI < Thor
17
13
  desc 'console', 'Enter ripe console'
18
14
  def console
19
- require 'irb'
20
- require 'irbtools'
15
+ repo = Repo.new
16
+ repo.attach
21
17
 
22
- ARGV.clear # This is necessary because otherwise all arguments
23
- # get sent to IRB
18
+ # Do not send arguments to the REPL
19
+ ARGV.clear
24
20
 
25
- $ripe = Controller.new
26
- $ripe.attach
21
+ Ripl.config[:prompt] = proc do
22
+ # This is the only place I could think of placing +Hirb#enable+.
23
+ Hirb.enable unless Hirb::View.enabled?
24
+ 'ripe> '
25
+ end
27
26
 
28
- IRB.start "ripe #{Ripe::VERSION}"
27
+ # Launch the REPL session in the context of +WorkerController+.
28
+ Ripl.start :binding => repo.controller.instance_eval { binding }
29
29
  end
30
30
 
31
31
  desc 'prepare SAMPLES', 'Prepare jobs from template workflow'
@@ -34,7 +34,7 @@ class CLI < Thor
34
34
  option :options, :aliases => '-o', :type => :string, :required => false,
35
35
  :desc => 'Options', :default => ''
36
36
  def prepare(*samples)
37
- return if (samples.length == 0)
37
+ abort "No samples specified." if (samples.length == 0)
38
38
 
39
39
  additional_vars = options[:options].split(/,/).map do |pair|
40
40
  key, value = pair.split(/=/)
@@ -42,15 +42,16 @@ class CLI < Thor
42
42
  end
43
43
  additional_vars = additional_vars.inject(&:merge) || {}
44
44
 
45
- # Expect $callback to be a lambda function that takes one argument (sample)
46
- # and returns a Block, and $vars to be a dictionary mapping arguments to
47
- # values (i.e. resource allocation)
48
- workflows = $RIPELIBS.map{ |path| "#{path}/workflows/#{options[:workflow]}.rb" }
49
- require_relative workflows.select{ |path| File.exists? path }.first
45
+ repo = Repo.new
46
+
47
+ filename = repo.library.find_workflow(options[:workflow])
48
+ abort "Could not find workflow #{@handle}." if filename == nil
49
+ require_relative filename # Imports +$workflow+ from the workflow component
50
50
 
51
- $ripe = Controller.new
52
- $ripe.attach_or_create # Create .ripe if it doesn't exist
53
- $ripe.prepare(samples, $callback, $vars.merge(additional_vars))
51
+ repo.attach_or_create # Create .ripe if it doesn't exist
52
+ repo.controller.prepare(samples,
53
+ $workflow.callback,
54
+ $workflow.params.merge(additional_vars))
54
55
  end
55
56
 
56
57
  desc 'version', 'Retrieve ripe version'
@@ -0,0 +1,84 @@
1
+ module Ripe
2
+
3
+ module DSL
4
+
5
+ ##
6
+ # Create a +WorkingBlock+ using a DSL. It is syntactic sugar for
7
+ #
8
+ # foo = WorkingBlock.new('/path/to/foo', {
9
+ # param1: 'val1',
10
+ # param2: 'val2',
11
+ # })
12
+ #
13
+ # in the form of:
14
+ #
15
+ # foo = task 'foo' do
16
+ # param :param1, 'val1'
17
+ # param :param2, 'val2'
18
+ # end
19
+ #
20
+ # foo = task 'foo' do |t|
21
+ # t.param :param1, 'val1'
22
+ # t.param :param2, 'val2'
23
+ # end
24
+ #
25
+ # It internally uses +Ripe::DSL::TaskDSL+ to provide the DSL.
26
+ #
27
+ # @see Ripe::DSL::TaskDSL
28
+ # @see Ripe::DSL::WorkflowDSL
29
+ # @see Ripe::DSL::task
30
+ #
31
+ # @param handle [String] the name of the task
32
+ # @param block [Proc] executes block in the context of +TaskDSL+
33
+ # @return [WorkingBlock, nil]
34
+
35
+ def task(handle, &block)
36
+ filename = Repo.new.library.find_task(handle)
37
+ abort "Could not find task #{handle}." if filename == nil
38
+
39
+ params = TaskDSL.new(handle, &block).params
40
+ WorkingBlock.new(filename, params)
41
+ end
42
+
43
+ ##
44
+ # This class provides a DSL for defining a task. It should only be called
45
+ # by #task.
46
+
47
+ class TaskDSL
48
+
49
+ attr_reader :params
50
+
51
+ ##
52
+ # Create a new +Task+ DSL
53
+ #
54
+ # @param handle [String] the name of the task
55
+ # @param block [Proc] executes block in the context of +TaskDSL+
56
+
57
+ def initialize(handle, &block)
58
+ @handle = handle
59
+ @params = {}
60
+
61
+ if block_given?
62
+ if block.arity == 1
63
+ yield self
64
+ else
65
+ instance_eval &block
66
+ end
67
+ end
68
+ end
69
+
70
+ ##
71
+ # Register a parameter
72
+ #
73
+ # @param key [Symbol] the parameter name
74
+ # @param value [String] its value
75
+
76
+ def param(key, value)
77
+ @params.merge!({ key => value })
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,92 @@
1
+ module Ripe
2
+
3
+ module DSL
4
+
5
+ ##
6
+ # Create a +Workflow+ using a DSL. It is syntactic sugar for
7
+ #
8
+ # workflow 'foobar' do
9
+ # param :node_count, 1
10
+ # param :ppn, 8
11
+ # param :project_name, 'abc-012-ab'
12
+ # param :queue, 'queue'
13
+ # param :walltime, '12:00:00'
14
+ #
15
+ # describe do |sample, params|
16
+ # # task
17
+ # end
18
+ # end
19
+ #
20
+ # The block given in +describe+ has two mandatory arguments:
21
+ # - sample: the name of the sample
22
+ # - params: the parameters defined at the workflow-level
23
+ #
24
+ # It internally uses +Ripe::DSL::WorkflowDSL+ to provide the DSL.
25
+ #
26
+ # @see Ripe::DSL::TaskDSL
27
+ # @see Ripe::DSL::WorkflowDSL
28
+ # @see Ripe::DSL::workflow
29
+ #
30
+ # @param handle [String] the name of the workflow
31
+ # @param block [Proc] executes block in the context of +WorkflowDSL+
32
+
33
+ def workflow(handle, &block)
34
+ $workflow = WorkflowDSL.new(handle, &block)
35
+ end
36
+
37
+ ##
38
+ # This class provides a DSL for defining a workflow. It should only be
39
+ # called by #workflow.
40
+
41
+ class WorkflowDSL
42
+
43
+ attr_reader :handle, :params, :callback
44
+
45
+ ##
46
+ # Create a new +Workflow+ DSL
47
+ #
48
+ # @param handle [String] the name of the workflow
49
+ # @param block [Proc] executes block in the context of +WorkflowDSL+
50
+
51
+ def initialize(handle, &block)
52
+ @handle = handle
53
+ @params = { handle: handle }
54
+ @callback = nil
55
+
56
+ if block_given?
57
+ if block.arity == 1
58
+ yield self
59
+ else
60
+ instance_eval &block
61
+ end
62
+ end
63
+ end
64
+
65
+ ##
66
+ # Register a parameter
67
+ #
68
+ # @param key [Symbol] the parameter name
69
+ # @param value [String] its value
70
+
71
+ def param(key, value)
72
+ @params.merge!({ key => value })
73
+ end
74
+
75
+ ##
76
+ # Describe the workflow in terms of a task.
77
+ #
78
+ # @see Ripe::WorkerController#prepare
79
+ #
80
+ # @param block [Proc] a callback function that takes as arguments the name
81
+ # of sample and a hash of parameters provided by the workflow and by the
82
+ # command line.
83
+
84
+ def describe(&block)
85
+ @callback = block
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ end
data/lib/ripe/dsl.rb ADDED
@@ -0,0 +1,4 @@
1
+ require_relative 'repo'
2
+ require_relative 'working_block'
3
+ require_relative 'dsl/task_dsl.rb'
4
+ require_relative 'dsl/workflow_dsl.rb'
@@ -0,0 +1,61 @@
1
+ module Ripe
2
+
3
+ ##
4
+ # This class represents a library containing all the components accessible
5
+ # to ripe (tasks and workflows) based on what is contained in the +RIPELIB+
6
+ # environment variable.
7
+
8
+ class Library
9
+
10
+ attr_reader :paths
11
+
12
+ ##
13
+ # Create a new library spanning all paths in the +RIPELIB+ environment
14
+ # variable.
15
+
16
+ def initialize
17
+ # Prepends the working directory to the list of paths so that the
18
+ # working directory is always looked in first.
19
+
20
+ @paths = "#{Dir.pwd}/#{Repo::REPOSITORY_PATH}:#{ENV['RIPELIB']}".split(/:/)
21
+ end
22
+
23
+ ##
24
+ # Search throughout the library for a task component by the name of
25
+ # +handle+. When there is more than one match, give precendence to the
26
+ # component whose path is declared first.
27
+ #
28
+ # @param handle [String] Task to search for
29
+ # @return [String, nil] Return the full path of the component if found,
30
+ # and +nil+ otherwise.
31
+
32
+ def find_task(handle)
33
+ search = @paths.map do |path|
34
+ filename = "#{path}/tasks/#{handle}.sh"
35
+ (File.exists? filename) ? filename : nil
36
+ end
37
+
38
+ search.compact.first
39
+ end
40
+
41
+ ##
42
+ # Search throughout the library for a workflow component by the name of
43
+ # +handle+. When there is more than one match, give precendence to
44
+ # component whose path is declared first.
45
+ #
46
+ # @param handle [String] Workflow to search for
47
+ # @return [String, nil] Return the full path of the component if found,
48
+ # and +nil+ otherwise.
49
+
50
+ def find_workflow(handle)
51
+ search = @paths.map do |path|
52
+ filename = "#{path}/workflows/#{handle}.rb"
53
+ (File.exists? filename) ? filename : nil
54
+ end
55
+
56
+ search.compact.first
57
+ end
58
+
59
+ end
60
+
61
+ end
data/lib/ripe/repo.rb ADDED
@@ -0,0 +1,92 @@
1
+ require 'active_record'
2
+ require 'fileutils'
3
+ require_relative 'block'
4
+ require_relative 'worker'
5
+ require_relative 'worker_controller'
6
+ require_relative 'worker_migration'
7
+ require_relative 'working_block'
8
+ require_relative 'library'
9
+ require_relative 'liquid_block'
10
+ require_relative 'task'
11
+ require_relative 'task_migration'
12
+
13
+ module Ripe
14
+
15
+ ##
16
+ # This class represents a ripe session. It is similar to the concept of a
17
+ # +git+ repository and is the starting point of the package. It
18
+ # instantiates:
19
+ #
20
+ # * a library containing information as to where to retrieve ripe
21
+ # components such as tasks and workflows;
22
+ # * a database that contains all worker metadata; and
23
+ # * a controller that communicates the database with the compute cluster
24
+ # interface.
25
+ #
26
+ # @see Ripe::WorkerController
27
+ # @see Ripe::Library
28
+
29
+ class Repo
30
+
31
+ REPOSITORY_PATH = '.ripe'
32
+ DATABASE_PATH = "#{REPOSITORY_PATH}/meta.db"
33
+ WORKERS_PATH = "#{REPOSITORY_PATH}/workers"
34
+
35
+ attr_reader :library, :controller
36
+
37
+ ##
38
+ # Initialize a repository
39
+
40
+ def initialize
41
+ @has_repository = File.exists? REPOSITORY_PATH
42
+ @library = Library.new
43
+ @controller = WorkerController.instance
44
+ end
45
+
46
+ ##
47
+ # Attach to an existing database
48
+
49
+ def attach
50
+ ActiveRecord::Base.establish_connection({
51
+ adapter: 'sqlite3',
52
+ database: DATABASE_PATH,
53
+ })
54
+ end
55
+
56
+ ##
57
+ # Attach to an existing database, and creates one if none is found.
58
+
59
+ def attach_or_create
60
+ @has_repository ? attach : create
61
+ end
62
+
63
+ ##
64
+ # Create a database
65
+
66
+ def create
67
+ FileUtils.mkdir_p(REPOSITORY_PATH)
68
+ @has_repository = true
69
+
70
+ begin
71
+ attach
72
+
73
+ # Create the tables
74
+ WorkerMigration.up
75
+ TaskMigration.up
76
+ rescue
77
+ destroy
78
+ end
79
+ end
80
+
81
+ ##
82
+ # Destroy the ripe repository, including the database and the worker
83
+ # output.
84
+
85
+ def destroy
86
+ FileUtils.rm(DATABASE_PATH) if File.exists? DATABASE_PATH
87
+ FileUtils.rm(WORKERS_PATH) if Dir.exists? WORKERS_PATH
88
+ end
89
+
90
+ end
91
+
92
+ end
data/lib/ripe/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ripe
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/ripe/worker.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  require 'active_record'
2
2
  require 'fileutils'
3
3
  require_relative 'task'
4
+ require_relative 'worker_controller'
4
5
 
5
6
  module Ripe
6
7
  class Worker < ActiveRecord::Base
7
8
  has_many :tasks, dependent: :destroy
8
9
 
9
10
  def dir
10
- ".ripe/workers/#{self.id}"
11
+ "#{Repo::REPOSITORY_PATH}/workers/#{self.id}"
11
12
  end
12
13
 
13
14
  def sh
@@ -30,27 +31,14 @@ module Ripe
30
31
  FileUtils.rm_r dir if Dir.exists? dir
31
32
  end
32
33
 
33
- def self.sync
34
- WorkerController.instance.sync
35
- end
36
-
37
- def start!
38
- raise "Worker #{id} could not be started: not prepared" unless self.status == 'prepared'
39
- start
40
- end
41
-
42
34
  def start
43
- update(status: :queueing, moab_id: `qsub '#{self.sh}'`.strip.split(/\./).first) # Send to queue first
44
- end
45
-
46
- def cancel!
47
- raise "Worker #{id} could not be cancelled: not started" unless ['queueing', 'idle', 'blocked', 'active'].include? self.status
48
- cancel
35
+ raise "Worker #{id} could not be started: not prepared" unless self.status == 'prepared'
36
+ WorkerController.instance.start(self)
49
37
  end
50
38
 
51
39
  def cancel
52
- `canceljob #{self.moab_id}`
53
- update(status: :cancelled)
40
+ raise "Worker #{id} could not be cancelled: not started" unless ['queueing', 'idle', 'blocked', 'active'].include? self.status
41
+ WorkerController.instance.cancel(self)
54
42
  end
55
43
  end
56
44
  end
@@ -2,9 +2,28 @@ require 'singleton'
2
2
  require_relative 'worker'
3
3
 
4
4
  module Ripe
5
+
6
+ ##
7
+ # This class controls workers as well as their relationship with regards to
8
+ # the compute cluster: worker preparation, submission, cancellation as well
9
+ # as sync.
10
+
5
11
  class WorkerController
12
+
6
13
  include Singleton
7
14
 
15
+ ##
16
+ # Prepares workers by applying the workflow callback and its parameters to
17
+ # each sample.
18
+ #
19
+ # @see Ripe::DSL::WorkflowDSL#describe
20
+ #
21
+ # @param samples [List] list of samples to apply the callback to
22
+ # @param callback [Proc] a callback function that takes as arguments the name
23
+ # of sample and a hash of parameters provided by the workflow and by the
24
+ # command line.
25
+ # @param vars [Hash] a list of worker-wide parameters
26
+
8
27
  def prepare(samples, callback, vars = {})
9
28
  vars = {
10
29
  wd: Dir.pwd,
@@ -78,6 +97,29 @@ module Ripe
78
97
  end
79
98
  end
80
99
 
100
+ ##
101
+ # Submit a job to the compute cluster system
102
+ #
103
+ # @param worker [Worker] the worker to submit
104
+
105
+ def start(worker)
106
+ worker.update(status: :queueing,
107
+ moab_id: `qsub '#{worker.sh}'`.strip.split(/\./).first)
108
+ end
109
+
110
+ ##
111
+ # Cancel a job in the compute cluster system
112
+ #
113
+ # @param worker [Worker] the worker to cancel
114
+
115
+ def cancel(worker)
116
+ `canceljob #{worker.moab_id}`
117
+ worker.update(status: :cancelled)
118
+ end
119
+
120
+ ##
121
+ # Synchronize the status of jobs with the internal list of workers.
122
+
81
123
  def sync
82
124
  lists = {idle: '-i', blocked: '-b', active: '-r'}
83
125
  lists = lists.map do |status, op|
@@ -134,5 +176,15 @@ module Ripe
134
176
  end
135
177
  end
136
178
  end
179
+
180
+ def list(n = 20)
181
+ Worker.last(n)
182
+ end
183
+
184
+ def edit(*args)
185
+ system("$EDITOR #{args.join(' ')}")
186
+ end
187
+
137
188
  end
189
+
138
190
  end
data/lib/ripe.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require_relative 'ripe/version'
2
- require_relative 'ripe/controller'
2
+ require_relative 'ripe/repo'
3
3
 
4
4
  module Ripe
5
5
  PATH = File.expand_path('..', File.dirname(__FILE__))
data/ripe.gemspec CHANGED
@@ -20,17 +20,19 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.7"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "yard", "~> 0.8"
23
24
  spec.add_development_dependency "rspec", "~> 3.2"
24
25
  spec.add_development_dependency "rspec-nc", "~> 0.2"
25
26
  spec.add_development_dependency "guard-rspec", "~> 4.5"
26
- spec.add_development_dependency "rdoc", "~> 4.2"
27
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 0.4"
27
28
 
28
29
  spec.add_runtime_dependency "activerecord", "~> 4.2"
29
30
  spec.add_runtime_dependency "fileutils", "~> 0.7"
30
31
  spec.add_runtime_dependency "liquid", "~> 3.0"
31
32
  spec.add_runtime_dependency "sqlite3", "~> 1.3"
33
+
34
+ spec.add_runtime_dependency "ripl", "~> 0.7"
32
35
  spec.add_runtime_dependency "hirb", "~> 0.7"
33
- spec.add_runtime_dependency "irbtools", "~> 1.7"
36
+
34
37
  spec.add_runtime_dependency "thor", "~> 0.19"
35
- spec.add_runtime_dependency "wirb", "~> 1.0"
36
38
  end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ripe::Library do
4
+ context 'when RIPELIB env is empty' do
5
+ before(:each) do
6
+ ENV['RIPELIB'] = ''
7
+ @library = Ripe::Library.new
8
+ end
9
+
10
+ it 'looks in the working directory' do
11
+ expect(@library.paths).to eql ["#{Dir.pwd}/#{Ripe::Repo::REPOSITORY_PATH}"]
12
+ end
13
+
14
+ it 'cannot resolve components of the test library' do
15
+ expect(@library.find_task('foo')).to eql nil
16
+ expect(@library.find_task('bar')).to eql nil
17
+ expect(@library.find_workflow('foobar')).to eql nil
18
+ end
19
+ end
20
+
21
+ context 'when RIPELIB contains the test library' do
22
+ before(:each) do
23
+ @test = Ripe::TestPack.new
24
+ ENV['RIPELIB'] = @test.path
25
+ @library = Ripe::Library.new
26
+ end
27
+
28
+ it 'looks in two directories' do
29
+ expect(@library.paths.length).to eql 2
30
+ end
31
+
32
+ it 'looks in the working directory first' do
33
+ # It looks in the working directory, and then in the directory
34
+ # specified in RIPELIB.
35
+ expect(@library.paths[0]).to eql "#{Dir.pwd}/#{Ripe::Repo::REPOSITORY_PATH}"
36
+ expect(@library.paths[1]).to eql @test.path
37
+ end
38
+
39
+ it 'resolves task components of the test library' do
40
+ expect(@library.find_task('foo')).to eql @test.tasks['foo']
41
+ expect(@library.find_task('bar')).to eql @test.tasks['bar']
42
+ end
43
+
44
+ it 'resolves workflows components of the test library' do
45
+ expect(@library.find_workflow('foobar')).to eql @test.workflows['foobar']
46
+ end
47
+
48
+ it 'cannot resolve non-existing componenets' do
49
+ expect(@library.find_task('other')).to eql nil
50
+ expect(@library.find_workflow('other')).to eql nil
51
+ end
52
+ end
53
+ end
data/spec/spec_helper.rb CHANGED
@@ -4,3 +4,4 @@ if !ENV['CODECLIMATE_REPO_TOKEN'].nil?
4
4
  end
5
5
 
6
6
  require_relative '../lib/ripe'
7
+ require_relative 'testpack'
@@ -0,0 +1 @@
1
+ One Bar
@@ -0,0 +1 @@
1
+ One Foo
@@ -0,0 +1 @@
1
+ One Foo For You
@@ -0,0 +1 @@
1
+ Two Bar
@@ -0,0 +1 @@
1
+ Two Foo
@@ -0,0 +1 @@
1
+ Two Foo For You
@@ -0,0 +1 @@
1
+ Three Bar
@@ -0,0 +1 @@
1
+ Three Foo
@@ -0,0 +1 @@
1
+ Three Foo For You
@@ -0,0 +1,3 @@
1
+ # Bar is the most important consequence of Foo.
2
+
3
+ echo "$(cut -f1 "$INPUT_BAR") $BAR_MESSAGE" > "$OUTPUT_BAR"
@@ -0,0 +1,3 @@
1
+ # Foo is certainly one of the most important prerequisites to Bar.
2
+
3
+ echo "$(cat "$INPUT_FOO") $FOO_MESSAGE" > "$OUTPUT_FOO"
@@ -0,0 +1,23 @@
1
+ workflow 'foobar' do
2
+ param :node_count, 1
3
+ param :ppn, 8
4
+ param :project_name, 'abc-012-ab'
5
+ param :queue, 'queue'
6
+ param :walltime, '12:00:00'
7
+
8
+ describe do |sample, params|
9
+ foo = task 'foo' do
10
+ param :input_foo, "#{sample}/input_foo"
11
+ param :foo_message, 'FOO'
12
+ param :output_foo, "#{sample}/output_foo"
13
+ end
14
+
15
+ bar = task 'bar' do
16
+ param :input_bar, "#{sample}/input_bar"
17
+ param :bar_message, 'BAR'
18
+ param :output_bar, "#{sample}/output_bar"
19
+ end
20
+
21
+ foo + bar
22
+ end
23
+ end
data/spec/testpack.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Ripe
2
+ class TestPack
3
+ attr_reader :path, :tasks, :workflows
4
+
5
+ def initialize
6
+ @path = "#{Ripe::PATH}/spec/testpack/ripe"
7
+ @tasks = {
8
+ 'foo' => "#{@path}/tasks/foo.sh",
9
+ 'bar' => "#{@path}/tasks/bar.sh",
10
+ }
11
+ @workflows = {
12
+ 'foobar' => "#{@path}/workflows/foobar.rb",
13
+ }
14
+ end
15
+ end
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ripe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas De Jay
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-11 00:00:00.000000000 Z
11
+ date: 2015-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: yard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.8'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -81,19 +95,19 @@ dependencies:
81
95
  - !ruby/object:Gem::Version
82
96
  version: '4.5'
83
97
  - !ruby/object:Gem::Dependency
84
- name: rdoc
98
+ name: codeclimate-test-reporter
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: '4.2'
103
+ version: '0.4'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: '4.2'
110
+ version: '0.4'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: activerecord
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -151,7 +165,7 @@ dependencies:
151
165
  - !ruby/object:Gem::Version
152
166
  version: '1.3'
153
167
  - !ruby/object:Gem::Dependency
154
- name: hirb
168
+ name: ripl
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
171
  - - "~>"
@@ -165,19 +179,19 @@ dependencies:
165
179
  - !ruby/object:Gem::Version
166
180
  version: '0.7'
167
181
  - !ruby/object:Gem::Dependency
168
- name: irbtools
182
+ name: hirb
169
183
  requirement: !ruby/object:Gem::Requirement
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: '1.7'
187
+ version: '0.7'
174
188
  type: :runtime
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: '1.7'
194
+ version: '0.7'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: thor
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -192,20 +206,6 @@ dependencies:
192
206
  - - "~>"
193
207
  - !ruby/object:Gem::Version
194
208
  version: '0.19'
195
- - !ruby/object:Gem::Dependency
196
- name: wirb
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '1.0'
202
- type: :runtime
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - "~>"
207
- - !ruby/object:Gem::Version
208
- version: '1.0'
209
209
  description:
210
210
  email:
211
211
  - ndj+rubygems@pinkfilter.org
@@ -225,10 +225,14 @@ files:
225
225
  - bin/ripe
226
226
  - lib/ripe.rb
227
227
  - lib/ripe/block.rb
228
- - lib/ripe/controller.rb
228
+ - lib/ripe/dsl.rb
229
+ - lib/ripe/dsl/task_dsl.rb
230
+ - lib/ripe/dsl/workflow_dsl.rb
231
+ - lib/ripe/library.rb
229
232
  - lib/ripe/liquid_block.rb
230
233
  - lib/ripe/multi_block.rb
231
234
  - lib/ripe/parallel_block.rb
235
+ - lib/ripe/repo.rb
232
236
  - lib/ripe/serial_block.rb
233
237
  - lib/ripe/task.rb
234
238
  - lib/ripe/task_migration.rb
@@ -240,8 +244,22 @@ files:
240
244
  - ripe.gemspec
241
245
  - share/moab.sh
242
246
  - spec/block_spec.rb
247
+ - spec/library_spec.rb
243
248
  - spec/ripe_spec.rb
244
249
  - spec/spec_helper.rb
250
+ - spec/testpack.rb
251
+ - spec/testpack/case/Sample1/bar_output.txt
252
+ - spec/testpack/case/Sample1/foo_input.txt
253
+ - spec/testpack/case/Sample1/foo_output.txt
254
+ - spec/testpack/case/Sample2/bar_output.txt
255
+ - spec/testpack/case/Sample2/foo_input.txt
256
+ - spec/testpack/case/Sample2/foo_output.txt
257
+ - spec/testpack/case/Sample3/bar_output.txt
258
+ - spec/testpack/case/Sample3/foo_input.txt
259
+ - spec/testpack/case/Sample3/foo_output.txt
260
+ - spec/testpack/ripe/tasks/bar.sh
261
+ - spec/testpack/ripe/tasks/foo.sh
262
+ - spec/testpack/ripe/workflows/foobar.rb
245
263
  homepage: https://github.com/ndejay/ripe
246
264
  licenses:
247
265
  - MIT
@@ -268,5 +286,20 @@ specification_version: 4
268
286
  summary: Abstraction layer between the MOAB/Torque stack and your pipeline.
269
287
  test_files:
270
288
  - spec/block_spec.rb
289
+ - spec/library_spec.rb
271
290
  - spec/ripe_spec.rb
272
291
  - spec/spec_helper.rb
292
+ - spec/testpack.rb
293
+ - spec/testpack/case/Sample1/bar_output.txt
294
+ - spec/testpack/case/Sample1/foo_input.txt
295
+ - spec/testpack/case/Sample1/foo_output.txt
296
+ - spec/testpack/case/Sample2/bar_output.txt
297
+ - spec/testpack/case/Sample2/foo_input.txt
298
+ - spec/testpack/case/Sample2/foo_output.txt
299
+ - spec/testpack/case/Sample3/bar_output.txt
300
+ - spec/testpack/case/Sample3/foo_input.txt
301
+ - spec/testpack/case/Sample3/foo_output.txt
302
+ - spec/testpack/ripe/tasks/bar.sh
303
+ - spec/testpack/ripe/tasks/foo.sh
304
+ - spec/testpack/ripe/workflows/foobar.rb
305
+ has_rdoc:
@@ -1,52 +0,0 @@
1
- require 'active_record'
2
- require 'fileutils'
3
- require_relative 'block'
4
- require_relative 'worker'
5
- require_relative 'worker_controller'
6
- require_relative 'worker_migration'
7
- require_relative 'working_block'
8
- require_relative 'liquid_block'
9
- require_relative 'task'
10
- require_relative 'task_migration'
11
-
12
- module Ripe
13
- class Controller
14
- def initialize
15
- @repository_path = '.ripe'
16
- @has_repository = Dir.exists? @repository_path
17
- end
18
-
19
- def attach
20
- ActiveRecord::Base.establish_connection({
21
- adapter: 'sqlite3',
22
- database: "#{@repository_path}/meta.db"
23
- })
24
- end
25
-
26
- def attach_or_create
27
- @has_repository ? attach : create
28
- end
29
-
30
- def create
31
- FileUtils.mkdir_p(@repository_path)
32
- @has_repository = true
33
-
34
- begin
35
- attach
36
- WorkerMigration.up
37
- TaskMigration.up
38
- rescue
39
- destroy
40
- end
41
- end
42
-
43
- def destroy
44
- FileUtils.rm("#{@repository_path}/meta.db") if File.exists? "#{@repository_path}/meta.db"
45
- FileUtils.rm("#{@repository_path}/workers") if Dir.exists? "#{@repository_path}/workers"
46
- end
47
-
48
- def prepare(samples, callback, vars = {})
49
- WorkerController.instance.prepare(samples, callback, vars)
50
- end
51
- end
52
- end