powirb 1.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.
- data/LICENSE +14 -0
- data/README.markdown +57 -0
- data/Rakefile +33 -0
- data/lib/powirb/handler.rb +55 -0
- data/lib/powirb/version.rb +4 -0
- data/lib/powirb/workitem.rb +73 -0
- data/lib/powirb.rb +53 -0
- data/powirb.gemspec +15 -0
- data/test/test_helper.rb +15 -0
- data/test/test_powirb.rb +15 -0
- data/test/test_powirb_handler.rb +28 -0
- data/test/test_powirb_workitem.rb +74 -0
- metadata +91 -0
data/LICENSE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright 2011 Carlo Pecchia
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
14
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
**Powirb** (*PO*larion *W*ork*I*tems handling with *R*u*B*y) aims to offer a Ruby interface to [Polarion ALM](http://www.polarion.com/)™ workitems content, for fast manipulation.
|
2
|
+
|
3
|
+
|
4
|
+
# Installation
|
5
|
+
|
6
|
+
$ gem install powirb
|
7
|
+
|
8
|
+
|
9
|
+
# Intro
|
10
|
+
|
11
|
+
Often when using Polarion ALM and you refine (and redefine) step-by-step you process, or perhaps you need a fine-tune over the way you defines wor items the workflows and so and so. Other time you need to import data from other tools and - again - you need an adjustment on some workitems (eg: author name, status, etc).
|
12
|
+
|
13
|
+
I've fonud extremely valuable and fast to do all this operation in [CLI](http://en.wikipedia.org/wiki/Command-line_interface) with ruby.
|
14
|
+
|
15
|
+
|
16
|
+
# Examples
|
17
|
+
|
18
|
+
First, we need a working copy of the project repository. Usually this live under something like http://yourpolarionserver/repo/ProjectName
|
19
|
+
|
20
|
+
Only basic operation on workitems are implemented, see the example above:
|
21
|
+
|
22
|
+
#!/usr/bin/env ruby
|
23
|
+
|
24
|
+
require 'rubygems'
|
25
|
+
require 'powirb'
|
26
|
+
|
27
|
+
# Set a logger level, on a specified filename (default is STDOUT)
|
28
|
+
Powirb.set_logger(:debug, 'log.txt')
|
29
|
+
|
30
|
+
# this referes to a project working copy of the subversion repository
|
31
|
+
h = Powirb::Handler.new('./SampleProject')
|
32
|
+
|
33
|
+
h.workitems.each do |wi|
|
34
|
+
if wi['status'] == 'closed' and wi[:type] == 'action'
|
35
|
+
wi[:resolution] = 'done'
|
36
|
+
wi.save!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
Please, *remember*: In order to "save" the modification we have to hit a commit with subversion.
|
41
|
+
|
42
|
+
|
43
|
+
# Notes
|
44
|
+
|
45
|
+
* it does work with Polarion 2011
|
46
|
+
* it does **not** support the "old" *LiveDoc* technology
|
47
|
+
* the actual version was tested under Linux and Mac OS X only
|
48
|
+
|
49
|
+
|
50
|
+
# Author
|
51
|
+
|
52
|
+
**Powirb** is written by [Carlo Pecchia](mailto:info@carlopecchia.eu) and released under the terms of Apache License (see LICENSE file).
|
53
|
+
|
54
|
+
|
55
|
+
----
|
56
|
+
|
57
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
5
|
+
require 'powirb/version'
|
6
|
+
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
require 'rake/rdoctask'
|
10
|
+
Rake::RDocTask.new do |rdoc|
|
11
|
+
rdoc.rdoc_dir = 'rdoc'
|
12
|
+
rdoc.title = 'Powirb'
|
13
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'rake/testtask'
|
18
|
+
Rake::TestTask.new(:test) do |t|
|
19
|
+
t.test_files = 'test/**/test_*.rb'
|
20
|
+
t.verbose = false
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
desc "Build gem for release"
|
25
|
+
task :build do
|
26
|
+
system "erb powirb.gemspec.erb > powirb.gemspec"
|
27
|
+
system "gem build powirb.gemspec"
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Release gem to RubyGems.org"
|
31
|
+
task :release => :build do
|
32
|
+
#system "gem push powirb-#{Powirb::VERSION}"
|
33
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
module Powirb
|
3
|
+
|
4
|
+
# This class represent the workitems handler, that is an "iterator"
|
5
|
+
# over workitems in the same projects.
|
6
|
+
#
|
7
|
+
# Author:: Carlo Pecchia (mailto:info@carlopecchia.eu)
|
8
|
+
# Copyright:: Copyright (c) 2011 Carlo Pecchia
|
9
|
+
# License:: See LICENSE file
|
10
|
+
class Handler
|
11
|
+
attr_reader :project_path
|
12
|
+
|
13
|
+
# Initialize the handler with the project path (usually a subversion
|
14
|
+
# working copy)
|
15
|
+
def initialize(project_path)
|
16
|
+
unless File.exist?(project_path)
|
17
|
+
msg = "Invalid project path '#{project_path}'"
|
18
|
+
Powirb.log.error(msg)
|
19
|
+
raise msg
|
20
|
+
end
|
21
|
+
@project_path = project_path
|
22
|
+
Powirb.log.debug("Initialized handler for #{@project_path}")
|
23
|
+
|
24
|
+
@workitems_count = 0
|
25
|
+
self.workitems_paths.each do |path|
|
26
|
+
@workitems_count += Dir[@project_path + path + "/**/workitem.xml"].size
|
27
|
+
end
|
28
|
+
Powirb.log.debug("Found #{@workitems_count} workitems.")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return all workitems in the project
|
32
|
+
def workitems
|
33
|
+
tmp = []
|
34
|
+
self.workitems_paths.each do |path|
|
35
|
+
Dir[@project_path + path + "/**/workitem.xml"].each do |filename|
|
36
|
+
tmp << Workitem.new(filename)
|
37
|
+
Powirb.log.debug("Added workitem from #{filename}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
tmp
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return the number of total workitems found in the project
|
44
|
+
def workitems_count
|
45
|
+
@workitems_count
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the path for workitems in the specified project
|
49
|
+
def workitems_paths
|
50
|
+
["/.polarion/tracker/workitems", "/modules/**/workitems"]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Powirb
|
4
|
+
|
5
|
+
# This class represent a workitem instance, that is serialized in a XML
|
6
|
+
# file under Polarion subversion repository (for us - more conveniently -
|
7
|
+
# a working copy of it).
|
8
|
+
#
|
9
|
+
# Author:: Carlo Pecchia (mailto:info@carlopecchia.eu)
|
10
|
+
# Copyright:: Copyright (c) 2011 Carlo Pecchia
|
11
|
+
# License:: See LICENSE file
|
12
|
+
class Workitem
|
13
|
+
|
14
|
+
# Create a new instance of a workitem belonging to its representation
|
15
|
+
# in the standard way Polarion does it
|
16
|
+
def initialize(filename)
|
17
|
+
@filename = filename
|
18
|
+
Powirb.log.debug("Initializing workitem with #{filename}")
|
19
|
+
end
|
20
|
+
|
21
|
+
# Read workitem content
|
22
|
+
def read
|
23
|
+
Powirb.log.debug("Retrieving workitem from #{@filename}")
|
24
|
+
begin
|
25
|
+
@doc = Nokogiri::XML(open(@filename))
|
26
|
+
rescue Exception => e
|
27
|
+
Powirb.log.error(e)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return a field value
|
32
|
+
def [](fname)
|
33
|
+
fname = fname.to_s
|
34
|
+
node = @doc.xpath("//field[@id=\"#{fname}\"]")
|
35
|
+
return nil if node.text.empty?
|
36
|
+
node.text
|
37
|
+
end
|
38
|
+
|
39
|
+
# Set/remove a field
|
40
|
+
def []=(fname, fvalue)
|
41
|
+
fname = fname.to_s
|
42
|
+
if self[fname].nil?
|
43
|
+
# inserting new field
|
44
|
+
Powirb.log.debug("[#{wid}] adding new field '#{fname}' with value '#{fvalue}'")
|
45
|
+
@doc.xpath('//field[@id="type"]').last.add_next_sibling("\n <field id=\"#{fname}\">#{fvalue}</field>")
|
46
|
+
else
|
47
|
+
if fvalue.nil?
|
48
|
+
# removing existing field
|
49
|
+
Powirb.log.debug("[#{wid}] removing field '#{fname}'")
|
50
|
+
@doc.xpath("//field[@id=\"#{fname}\"]").last.remove
|
51
|
+
else
|
52
|
+
# updating existing field
|
53
|
+
Powirb.log.debug("[#{wid}] updating field '#{fname}' with value '#{fvalue}'")
|
54
|
+
e = @doc.xpath("//field[@id=\"#{fname}\"]").last
|
55
|
+
e.content = fvalue
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Save workitem on filesystem
|
61
|
+
def save!
|
62
|
+
Powirb.log.debug("[#{wid}] saving on #{@filename}")
|
63
|
+
File.open(@filename, 'w+') {|io| io.puts @doc}
|
64
|
+
end
|
65
|
+
|
66
|
+
# Return workitem ID
|
67
|
+
def wid
|
68
|
+
File.basename(File.dirname(@filename))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
data/lib/powirb.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
Dir.glob(File.join('..','vendor','gems','*','lib')).each do |lib|
|
5
|
+
$:.unshift(File.expand_path(lib))
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'powirb/workitem'
|
9
|
+
require 'powirb/handler'
|
10
|
+
require 'logger'
|
11
|
+
|
12
|
+
# This module represent a container for Powirb classes.
|
13
|
+
#
|
14
|
+
# Author:: Carlo Pecchia (mailto:info@carlopecchia.eu)
|
15
|
+
# Copyright:: Copyright (c) 2011 Carlo Pecchia
|
16
|
+
# License:: See LICENSE file
|
17
|
+
module Powirb
|
18
|
+
|
19
|
+
# Set the logger used for all classes under Powirb module.
|
20
|
+
#
|
21
|
+
# +level+ debug, info, warn (default), error, fatal
|
22
|
+
#
|
23
|
+
# +filename+ if not specified STDOUT is used
|
24
|
+
def self.set_logger(level, filename=STDOUT)
|
25
|
+
@logger = Logger.new(filename)
|
26
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
27
|
+
@logger.level = case level.to_s
|
28
|
+
when 'debug'
|
29
|
+
Logger::DEBUG
|
30
|
+
when 'info'
|
31
|
+
Logger::INFO
|
32
|
+
when 'warn'
|
33
|
+
Logger::WARN
|
34
|
+
when 'error'
|
35
|
+
Logger::ERROR
|
36
|
+
when 'fatal'
|
37
|
+
Logger::FATAL
|
38
|
+
else
|
39
|
+
Logger::WARN
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# we have to provide a default logger
|
44
|
+
self.set_logger(:warn)
|
45
|
+
|
46
|
+
# Provide access to internal Logger instance.
|
47
|
+
# Usual classes are used: fatal, error, warn, info, debug
|
48
|
+
#
|
49
|
+
# eg: <tt>Powirb.log.warn("message here...")</tt>
|
50
|
+
def self.log
|
51
|
+
@logger
|
52
|
+
end
|
53
|
+
end
|
data/powirb.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
Gem::Specification.new do |s|
|
3
|
+
s.name = "powirb"
|
4
|
+
s.version = "1.0"
|
5
|
+
s.summary = "POlarion WorkItems handling with RuBy"
|
6
|
+
s.description = <<-EOF
|
7
|
+
Ruby interface to Polarion workitems content, for fast manipulation.
|
8
|
+
EOF
|
9
|
+
s.authors = ["Carlo Pecchia"]
|
10
|
+
s.email = ["info@carlopecchia.eu"]
|
11
|
+
s.homepage = "http://github.com/carlopecchia/powirb"
|
12
|
+
s.add_dependency('nokogiri')
|
13
|
+
s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/powirb/handler.rb", "lib/powirb/version.rb", "lib/powirb/workitem.rb", "lib/powirb.rb", "powirb.gemspec", "test/test_helper.rb", "test/test_powirb.rb", "test/test_powirb_handler.rb", "test/test_powirb_workitem.rb"]
|
14
|
+
end
|
15
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
#require 'ftools'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__),'..','lib'))
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
|
9
|
+
require 'powirb'
|
10
|
+
|
11
|
+
class Test::Unit::TestCase
|
12
|
+
def test_true
|
13
|
+
assert true
|
14
|
+
end
|
15
|
+
end
|
data/test/test_powirb.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
|
4
|
+
class PowirbTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_valid_default_logger
|
7
|
+
assert_not_nil Powirb.log
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_valid_logger
|
11
|
+
Powirb.set_logger(:debug)
|
12
|
+
assert_not_nil Powirb.log
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
|
4
|
+
class PowirbHandlerTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
pp = File.join(File.dirname(__FILE__),'_sample_project')
|
8
|
+
Powirb.set_logger(:debug,'/dev/null')
|
9
|
+
@h = Powirb::Handler.new(pp)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_valid_handler
|
13
|
+
assert_not_nil @h
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_invalid_project_path
|
17
|
+
assert_raise RuntimeError do
|
18
|
+
assert_nil Powirb::Handler.new(File.join('s0m3','n0n','ex1st3nt','p4thn4m3'))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_workitems
|
23
|
+
assert_kind_of Array, @h.workitems
|
24
|
+
assert @h.workitems_count == 4
|
25
|
+
assert @h.workitems.size == 4
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class PowirbWorkitemTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
src = File.join(File.dirname(__FILE__), '_sample_project')
|
7
|
+
dst = File.join(File.dirname(__FILE__), 'sample_project')
|
8
|
+
FileUtils.rm_rf dst
|
9
|
+
FileUtils.cp_r src, dst
|
10
|
+
|
11
|
+
pp = File.join(File.dirname(__FILE__),'sample_project')
|
12
|
+
Powirb.set_logger(:debug,'/dev/null')
|
13
|
+
@h = Powirb::Handler.new(pp)
|
14
|
+
@wi = @h.workitems.first
|
15
|
+
@wi.read
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
FileUtils.rm_rf File.join(File.dirname(__FILE__), 'sample_project')
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_valid_workitem
|
23
|
+
assert_not_nil @wi
|
24
|
+
assert_kind_of Powirb::Workitem, @wi
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_wid
|
28
|
+
assert_not_nil @wi.wid
|
29
|
+
assert_match /(\w+)\-(\d+)/, @wi.wid
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_add_field
|
33
|
+
assert_nil @wi['foo']
|
34
|
+
assert_nil @wi[:foo]
|
35
|
+
@wi['foo'] = 'bar'
|
36
|
+
assert @wi['foo'] == 'bar'
|
37
|
+
assert @wi[:foo] == 'bar'
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_updating_existing_field
|
41
|
+
assert_not_nil @wi['title']
|
42
|
+
@wi['title'] = 'Some silly Title here...'
|
43
|
+
assert @wi['title'] == 'Some silly Title here...'
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_remove_field
|
47
|
+
assert_not_nil @wi['priority']
|
48
|
+
@wi['priority'] = nil
|
49
|
+
assert_nil @wi['priority']
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_change_field_name
|
53
|
+
value = @wi['priority']
|
54
|
+
assert_not_nil value
|
55
|
+
|
56
|
+
@wi['extimatedPriority'] = value
|
57
|
+
@wi['priority'] = nil
|
58
|
+
|
59
|
+
assert_nil @wi['priority']
|
60
|
+
assert @wi['extimatedPriority'] == value
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_save
|
64
|
+
assert_not_nil @wi['priority']
|
65
|
+
@wi['priority'] = nil
|
66
|
+
assert_nil @wi['priority']
|
67
|
+
@wi.save!
|
68
|
+
|
69
|
+
w = @h.workitems.first
|
70
|
+
w.read
|
71
|
+
assert_nil w['priority']
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: powirb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: "1.0"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Carlo Pecchia
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-04-11 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: nokogiri
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
description: " Ruby interface to Polarion workitems content, for fast manipulation.\n"
|
35
|
+
email:
|
36
|
+
- info@carlopecchia.eu
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- LICENSE
|
45
|
+
- README.markdown
|
46
|
+
- Rakefile
|
47
|
+
- lib/powirb/handler.rb
|
48
|
+
- lib/powirb/version.rb
|
49
|
+
- lib/powirb/workitem.rb
|
50
|
+
- lib/powirb.rb
|
51
|
+
- powirb.gemspec
|
52
|
+
- test/test_helper.rb
|
53
|
+
- test/test_powirb.rb
|
54
|
+
- test/test_powirb_handler.rb
|
55
|
+
- test/test_powirb_workitem.rb
|
56
|
+
has_rdoc: true
|
57
|
+
homepage: http://github.com/carlopecchia/powirb
|
58
|
+
licenses: []
|
59
|
+
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 3
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
requirements: []
|
84
|
+
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.3.7
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: POlarion WorkItems handling with RuBy
|
90
|
+
test_files: []
|
91
|
+
|