ripe 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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