-
Notifications
You must be signed in to change notification settings - Fork 15
there are already ruby DSL which cover some functionality maven offers. like a RubyGems is a package format which embeds meta data and dependencies about the ruby code. it is like a jar file packed with a pom. or bundler deals with dependencies and how to manage them. instead of creating something new for maven the idea is to just take these existing ones use them with polyglot-maven.
with having a gemspec as pom and you can use polyglot maven (pmaven) to run the test (spec or cucumber features), pack it and install as gem artifact. the description of that RubyGem::Specification. a simple example looks like this:
Gem::Specification.new do |s|
s.name = 'example'
s.version = '1.0'
s.summary = 'Example gem specification'
end
with such gemspec in place you can setup the a local gem repository in target/rubygems
$ pmvn initialize
to run all test, i.e. rspec and cucumber - regular runit test is not yet supported. specs are run if there is a rspec dependency and features are run if there is a cucumber depdencency in the gemspec file.
$ pmvn test
or
$ pmvn rspec:test
$ pmvn cucumber:test
package the gem in target
$ pmvn package
or install into the local maven repository
$ pmvn install
and finally deploy it or push it to rubygems.org
$ pmvn deploy
you can also execute a ruby script in context of the gemspec file, i.e. you can use declared gem dependencies.
$ pmvn gem:exec -Dexec.script="require 'fileutils'; FileUtils.ln_s('my.gemspec.pom', 'pom.xml')"
similar you can start an irb session (i.e. a console) in the gemspec context
$ pmvn gem:irb
or as swing application
$ pmvn gem:irb -Dirb.swing
the common way of declaring dependencies in ruby is something like: rspec ~>2.4.1 which means all version bigger or equals then 2.4.1 and smaller then 2.5.0. so it is a version range and the dependency resolution varies over time depending on the availability of version for a given gem. and this can break your coed !!! bundler does have a possible solution for it - see below.
if you need more control over what pmaven does you can use the file Mavenfile to add more maven specific declarations. for more details see below.
Gemfile can declare dependencies and can group them into profiles (groups in bundler speak and profile in maven speak but with further small differences too). further it can include the dependencies of one or more gemspec files.
one big thing about bundler is that it solves the uncertainty of version ranges. before you can "use" bunlder you need to run bundle install
to set up the dependencies. this will write out a file Gemfile.lock which contains the version resolution of the Gemfile. any successive run will use the versions of that Gemfile.lock instead of resolve them with the latest gems in the repositories. bundler has some more commands to update and check Gemfile and Gemfile.lock.
pmaven just follows what bundler does in a maven way. the main difference is that with pmaven in general you do not need to run bundle install
(only if you use gems from a git repository or from the local filesystem directly). when pmaven sees a Gemfile.lock it will obey these versions otherwise pmaven will resolve them with the version ranges from the Gemfile. so with pmaven to perform an update is to delete Gemfile.lock.
in this sense Gemfile.lock is part of the DSL and helps to keeps things stable and reproducable.
the same goals work with Gemfile in the same manner as with the gemspec from above.
the Gemfile of Rails3 application will be translated to a more suitable pom as in a normal Gemfile project. first the rails3-maven-plugin will be included, the packaging is war not gem as before and it allows to use jetty as development server.
the name follows the Gemfile and you can use the same DSL as you use for Gemfile in Mavenfile.
NOTE: bundler does use ONLY Gemfile and Gemfile.lock and will ignore Mavenfile. that Mavenfile is meant for maven stuff !
For each gem requirement, list a single gem line.
gem "nokogiri"
Each gem MAY have one or more version specifiers.
gem "nokogiri", ">= 1.4.2"
gem "RedCloth", ">= 4.1.0", "< 4.2.0"
For each jar artifact, list a single jar or test_jar line with version (range). the name is the groupId:artifactId
jar "org.slf4r:slf4r-simple", '1.6.2'
jar("org.slf4r:slf4r-simple", '1.6.2').scope = :test
jar("org.slf4r:slf4r-simple", '1.6.2').classifier = :source
or use the nested block (this time as test_jar)
test_jar("org.slf4r:slf4r-simple", '1.6.2') do |simple|
simple.scope :test
simple.classifier :source
end
group_id "rubygems"
artifact_id "one"
version "0.1.0"
packaging "gem"
name "some name"
description "longer description"
url "http://github.com"
developers.new("my name", "[email protected]")
or
developers.new("my name <[email protected]>")
add the license file like
licenses.new("MIT-LICENSE.txt")
or the url
licenses.new("http://www.gnu.org/licenses/gpl.html")
add a repository with defaults
repository("rubygems-releases", "http://gems.saumya.de/releases")
or a snapshot repository for plugins
plugin_repository("sonatype-snapshots") do |sonatype|
sonatype.url "http://oss.sonatype.org/content/repositories/snapshots"
sonatype.releases(:enabled => false)
sonatype.snapshots(:enabled => true)
end
or a full fledge one
repository("jboss-public-repository-group") do |jboss|
jboss.name "JBoss Public Maven Repository Group"
jboss.url "https://repository.jboss.org/nexus/content/groups/public-jboss/"
jboss.releases(:enabled => false, :updatePolicy => :never, :checksumPloicy => :strict)
jboss.snapshots(:enabled => true, :updatePolicy => :daily, :checksumPloicy => :ignore)
end
you can retrieve a hashmap with repositories or plugin repositories with
repositories
respectively
plugin_repositories
it comes with a few default properties which can be overwritten
properties["gem.home"] = "${project.build.directory}/rubygems"
properties["gem.path"] = "${project.build.directory}/rubygems"
properties["jruby.plugins.version"] = "0.27.0-SNAPSHOT"
properties["project.build.sourceEncoding"] = "UTF-8"
to deal with ruby and rubygems specific stuff there are several maven plugins which are used: gem-maven-plugin, rspec-maven-plugin, cucumber-maven-plugin, etc. they are carry the version ${jruby.plugins.version}. you an overwrite this property inside the Mavenfile.
in general you can set properties like above or
properties.merge!({
"gem.home" => "~/gem"
})
or replace the existing through new ones
properties = { "gem.home" => "~/gem" }
in general the build tag of a maven pom gets omited but is actually there. for example plugin(name)
just delegates to build.plugin(name)
.
all example are in context of the project or a profile or a plugin
dependency_management do |deps|
deps.gem "slf4r", "0.4.2"
deps.jar "org.slf4j:slf4j-simple", "1.6.2"
end
and dependencies via the collection
dependencies do |d|
d.gem "rspec"
d.test_jar "org.slf4j:slf4j-noop", "1.6.2"
end
or the same in direct way
gem "rspec"
test_jar "org.slf4j:slf4j-noop", "1.6.2"
and with exclusions
jar 'org.xerial:sqlite-jdbc', '3.6.10' do |j|
j.exclude 'org.xerial.thirdparty:nestedvm'
end
or the same via the exclusions collection
jar 'org.xerial:sqlite-jdbc', '3.6.10' do |j|
j.exclusions << 'org.xerial.thirdparty:nestedvm'
end
the latter can also be written differently. the object created can be used to call methods on it.
sqlite = gem 'sqlite-jdbc', '3.6.10'
sqlite.exclusions << 'nestedvm'
a dependency can be retrieved and call further methods on it.
gem 'sqlite-jdbc', '3.6.10'
gem('sqlite-jdbc').exclusions << 'nestedvm'
add a maven default plugin
plugin 'release'
or a maven default plugin with version
plugin("clean", "2.4.1")
or a maven default plugin with configuration
plugin(:compile, "2.3.2").with :source => "1.5", :target => "1.5"
also the jruby-maven-plugins can have a short name:
-
:jruby
or"jruby"
for jruby-maven-plugin -
:gem
or"gem"
for gem-maven-plugin -
:cucumber
or"cucumber"
for cucumber-maven-plugin -
:rspec
or"rspec"
for rspec-maven-plugin -
:runit
or"runit"
for runit-maven-plugin -
:rake
or"rake"
for rake-maven-plugin -
:rails3
or"rails3"
for rails3-maven-plugin -
:rails2
or"rails2"
for rails2-maven-plugin -
:bundler
or"bundler"
for bundler-maven-plugin -
:gemify
or"gemify"
for gemify-maven-plugin
plugin with extentions
plugin(:gem).extensions true
or any other plugin with execution goals (default execution without id)
plugin('org.codehaus.mojo:gwt-maven-plugin', '2.1.0').execution.goals = ["clean", "compile", "test"]
or you want to execute a goal in a phase
plugin(:gem).in_phase("pre-integration-test").execute_goal(:install)
or a goal in a phase with configuration
plugin(:cucumber).in_phase("integration-test").execute_goal(:test).with(:cucumberArgs => "--no-colors")
if you can not use the short name then the plugin name is the combination of : as with the jar dependencies. use the block notation when you need to do more with the plugin
plugin('org.codehaus.mojo:gwt-maven-plugin', '2.1.0') do |gwt|
gwt.with({ :extraJvmArgs => "-Xmx512m",
:runTarget => "example.html"
})
gwt.execution.goals << ["clean", "compile", "test"]
end
in case the hashmap notation for the configuration part is not sufficient you can pass in XML directly (the hashmap notation does not attributes like implementation in the connector tag)
plugin("org.mortbay.jetty:jetty-maven-plugin", "7.2.2.v20101205").with({
:connectors => <<-XML
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8080</port>
</connector>
<connector implementation="org.eclipse.jetty.server.ssl.SslSelectChannelConnector">
<port>8443</port>
<keystore>${project.basedir}/src/test/resources/server.keystore</keystore>
<keyPassword>123456</keyPassword>
<password>123456</password>
</connector>
XML
})
sometimes you a nested array (here webResources has a list of resource)
plugin(:war).with({
:webResources => Maven::Model::NamedArray.new(:resource) do |l|
l << { :directory => "public" }
l << {
:directory => ".",
:targetPath => "WEB-INF",
:includes => ['app/**', 'config/**', 'lib/**', 'vendor/**', 'Gemfile']
}
l << {
:directory => '${gem.path}',
:targetPath => 'WEB-INF/gems'
}
end
})
you can write ruby code directly inside the Mavenfile which will be executed in the specified phase
execute_in_phase(:verify) do
puts "all OK"
end
profiles and groups from Gemfile are similiar but not the same. in maven you choose one or more profiles to be active and they participate with action you want to perform. the groups with bundler do all participate with dependency resolution so the resovled version are consistent over all groups.
activation of a profile by default
profile(:development).activation.by_default
or by property
profile(:test).activation.property("rails.env", "test")
or via OS (triggered by family
or arch
or name
or version
)
profile("mac").activation.os.family = "mac"
any of these nested attributes can set with the help of the block notation
profile(:production) do |prod|
prod.activation.property("rails.env", "production")
prod.properties.merge!({
"gem.home" => "${project.build.directory}/rubygems-production",
"gem.path" => "${project.build.directory}/rubygems-production"
})
prod.plugin("org.mortbay.jetty:jetty-maven-plugin", "${jetty.version}")
prod.gem "cucumber", nil
prod.dependency_management.gem "cucumber", '0.9.4'
end
the following group notation will add the gem and the jar to the "test" profile:
profile :test do
gem "enforce-ssl"
jar "org.slf4j:slf4j-noop", "1.6.2"
end
there are still missing parts, like the parent tag or the modules or all this report related tags.