You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildr.apache.org by do...@apache.org on 2014/05/11 03:10:50 UTC
[3/3] git commit: Import 'buildr/custom_pom' addon to make it easier
to build POMs for projects publishing to Maven Central.
Import 'buildr/custom_pom' addon to make it easier to build POMs for projects publishing to Maven Central.
Project: http://git-wip-us.apache.org/repos/asf/buildr/repo
Commit: http://git-wip-us.apache.org/repos/asf/buildr/commit/baa269bb
Tree: http://git-wip-us.apache.org/repos/asf/buildr/tree/baa269bb
Diff: http://git-wip-us.apache.org/repos/asf/buildr/diff/baa269bb
Branch: refs/heads/master
Commit: baa269bb3243a7615e05bb95f6c799f112adafec
Parents: 54a832d
Author: Peter Donald <pe...@realityforge.org>
Authored: Sun May 11 11:10:35 2014 +1000
Committer: Peter Donald <pe...@realityforge.org>
Committed: Sun May 11 11:10:35 2014 +1000
----------------------------------------------------------------------
CHANGELOG | 2 +
addon/buildr/custom_pom.rb | 283 +++++++++++++++++++++++++++++++++++++
doc/more_stuff.textile | 72 ++++++++++
spec/addon/custom_pom_spec.rb | 149 +++++++++++++++++++
4 files changed, 506 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/buildr/blob/baa269bb/CHANGELOG
----------------------------------------------------------------------
diff --git a/CHANGELOG b/CHANGELOG
index 3f4a4ce..4aaae82 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,6 @@
1.4.17 (Pending)
+* Added: Import 'buildr/custom_pom' addon to make it easier to
+ build POMs for projects publishing to Maven Central.
* Added: Add flag to allow non portable extensions in wsgen addon.
* Fixed: Avoid nil dereference bug in GWT addon when running GWT in
a project that has no source directory.
http://git-wip-us.apache.org/repos/asf/buildr/blob/baa269bb/addon/buildr/custom_pom.rb
----------------------------------------------------------------------
diff --git a/addon/buildr/custom_pom.rb b/addon/buildr/custom_pom.rb
new file mode 100644
index 0000000..76b51d8
--- /dev/null
+++ b/addon/buildr/custom_pom.rb
@@ -0,0 +1,283 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership. The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+module Buildr
+ class CustomPom
+ Developer = Struct.new(:id, :name, :email, :roles)
+
+ # Specify the name of the project
+ attr_writer :name
+
+ # Retrieve the name of the project, defaulting to the project description or the name if not specified
+ def name
+ @name || @buildr_project.comment || @buildr_project.name
+ end
+
+ # Specify a project description
+ attr_writer :description
+
+ # Retrieve the project description, defaulting to the name if not specified
+ def description
+ @description || name
+ end
+
+ # Property for the projects url
+ attr_accessor :url
+
+ # Return the map of licenses for project
+ def licenses
+ @licenses ||= {}
+ end
+
+ # Add Apache2 to the list of licenses
+ def add_apache_v2_license
+ self.licenses['The Apache Software License, Version 2.0'] = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+ end
+
+ def add_bsd_2_license
+ self.licenses['The BSD 2-Clause License'] = 'http://opensource.org/licenses/BSD-2-Clause'
+ end
+
+ def add_bsd_3_license
+ self.licenses['The BSD 3-Clause License'] = 'http://opensource.org/licenses/BSD-3-Clause'
+ end
+
+ def add_cddl_v1_license
+ self.licenses['Common Development and Distribution License (CDDL-1.0)'] = 'http://opensource.org/licenses/CDDL-1.0'
+ end
+
+ def add_epl_v1_license
+ self.licenses['Eclipse Public License - v 1.0'] = 'http://www.eclipse.org/legal/epl-v10.html'
+ end
+
+ def add_gpl_v1_license
+ self.licenses['GNU General Public License (GPL) version 1.0'] = 'http://www.gnu.org/licenses/gpl-1.0.html'
+ end
+
+ def add_gpl_v2_license
+ self.licenses['GNU General Public License (GPL) version 2.0'] = 'http://www.gnu.org/licenses/gpl-2.0.html'
+ end
+
+ def add_gpl_v3_license
+ self.licenses['GNU General Public License (GPL) version 3.0'] = 'http://www.gnu.org/licenses/gpl-3.0.html'
+ end
+
+ def add_lgpl_v2_license
+ self.licenses['GNU General Lesser Public License (LGPL) version 2.1'] = 'http://www.gnu.org/licenses/lgpl-2.1.html'
+ end
+
+ def add_lgpl_v3_license
+ self.licenses['GNU General Lesser Public License (LGPL) version 3.0'] = 'http://www.gnu.org/licenses/lgpl-3.0.html'
+ end
+
+ def add_mit_license
+ self.licenses['The MIT License'] = 'http://opensource.org/licenses/MIT'
+ end
+
+
+ attr_accessor :scm_url
+ attr_accessor :scm_connection
+ attr_accessor :scm_developer_connection
+
+ attr_accessor :issues_url
+ attr_accessor :issues_system
+
+ # Add a project like add_github_project('realityforge/gwt-appcache')
+ def add_github_project(project_spec)
+ git_url = "git@github.com:#{project_spec}.git"
+ self.scm_connection = self.scm_developer_connection = "scm:git:#{git_url}"
+ self.scm_url = git_url
+ web_url = "https://github.com/#{project_spec}"
+ self.url = web_url
+ self.issues_url = "#{web_url}/issues"
+ self.issues_system = 'GitHub Issues'
+ end
+
+ def developers
+ @developers ||= []
+ end
+
+ def add_developer(id, name = nil, email = nil, roles = nil)
+ self.developers << Developer.new(id, name, email, roles)
+ end
+
+ def provided_dependencies
+ @provided_dependencies ||= []
+ end
+
+ def provided_dependencies=(provided_dependencies)
+ @provided_dependencies = provided_dependencies
+ end
+
+ def runtime_dependencies
+ @runtime_dependencies ||= []
+ end
+
+ def runtime_dependencies=(runtime_dependencies)
+ @runtime_dependencies = runtime_dependencies
+ end
+
+ def optional_dependencies
+ @optional_dependencies ||= []
+ end
+
+ def optional_dependencies=(optional_dependencies)
+ @optional_dependencies = optional_dependencies
+ end
+
+ protected
+
+ def associate_project(buildr_project)
+ @buildr_project = buildr_project
+ end
+
+ def self.pom_xml(project, package)
+ Proc.new do
+ xml = Builder::XmlMarkup.new(:indent => 2)
+ xml.instruct!
+ xml.project('xmlns' => 'http://maven.apache.org/POM/4.0.0',
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xsi:schemaLocation' => 'http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd') do
+ xml.modelVersion '4.0.0'
+ xml.parent do
+ xml.groupId 'org.sonatype.oss'
+ xml.artifactId 'oss-parent'
+ xml.version '7'
+ end
+ xml.groupId project.group
+ xml.artifactId project.id
+ xml.version project.version
+ xml.packaging package.type.to_s
+ xml.classifier package.classifier if package.classifier
+
+ xml.name project.pom.name if project.pom.name
+ xml.description project.pom.description if project.pom.description
+ xml.url project.pom.url if project.pom.url
+
+ xml.licenses do
+ project.pom.licenses.each_pair do |name, url|
+ xml.license do
+ xml.name name
+ xml.url url
+ xml.distribution 'repo'
+ end
+ end
+ end
+
+ if project.pom.scm_url || project.pom.scm_connection || project.pom.scm_developer_connection
+ xml.scm do
+ xml.connection project.pom.scm_connection if project.pom.scm_connection
+ xml.developerConnection project.pom.scm_developer_connection if project.pom.scm_developer_connection
+ xml.url project.pom.scm_url if project.pom.scm_url
+ end
+ end
+
+ if project.pom.issues_url
+ xml.issueManagement do
+ xml.url project.pom.issues_url
+ xml.system project.pom.issues_system if project.pom.issues_system
+ end
+ end
+
+ xml.developers do
+ project.pom.developers.each do |developer|
+ xml.developer do
+ xml.id developer.id
+ xml.name developer.name if developer.name
+ xml.email developer.email if developer.email
+ if developer.roles
+ xml.roles do
+ developer.roles.each do |role|
+ xml.role role
+ end
+ end
+ end
+ end
+ end
+ end
+
+ xml.dependencies do
+ provided_deps = Buildr.artifacts(project.pom.provided_dependencies).collect { |d| d.to_s }
+ runtime_deps = Buildr.artifacts(project.pom.runtime_dependencies).collect { |d| d.to_s }
+ optional_deps = Buildr.artifacts(project.pom.optional_dependencies).collect { |d| d.to_s }
+ deps =
+ Buildr.artifacts(project.compile.dependencies).
+ select { |d| d.is_a?(Artifact) }.
+ collect do |d|
+ f = d.to_s
+ scope = provided_deps.include?(f) ? 'provided' :
+ runtime_deps.include?(f) ? 'runtime' :
+ 'compile'
+ d.to_hash.merge(:scope => scope, :optional => optional_deps.include?(f))
+ end + Buildr.artifacts(project.test.compile.dependencies).
+ select { |d| d.is_a?(Artifact) && !project.compile.dependencies.include?(d) }.collect { |d| d.to_hash.merge(:scope => 'test') }
+ deps.each do |dependency|
+ xml.dependency do
+ xml.groupId dependency[:group]
+ xml.artifactId dependency[:id]
+ xml.version dependency[:version]
+ xml.scope dependency[:scope] unless dependency[:scope] == 'compile'
+ xml.optional true if dependency[:optional]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+module Buildr
+ class Project #:nodoc:
+ def pom
+ unless @pom
+ @pom = parent ? parent.pom.dup : Buildr::CustomPom.new
+ @pom.send :associate_project, self
+ end
+ @pom
+ end
+ end
+end
+
+module Buildr
+ module Package
+ alias :old_package :package
+
+ def package(*args)
+ package = old_package(*args)
+ class << package
+ def pom
+ unless @pom || classifier
+ pom_filename = Util.replace_extension(name, 'pom')
+ spec = {:group => group, :id => id, :version => version, :type => :pom}
+ @pom = Buildr.artifact(spec, pom_filename)
+ buildr_project = Buildr.project(self.scope.join(':'))
+ @pom.content Buildr::CustomPom.pom_xml(buildr_project, self)
+ end
+ @pom
+ end
+ end
+ package.instance_variable_set('@pom', nil)
+ package.enhance([package.pom.to_s]) if package.type.to_s == 'jar' && !package.classifier
+ package
+ end
+ end
+
+ module ActsAsArtifact
+ def pom_xml
+ self.pom.content
+ end
+ end
+end
http://git-wip-us.apache.org/repos/asf/buildr/blob/baa269bb/doc/more_stuff.textile
----------------------------------------------------------------------
diff --git a/doc/more_stuff.textile b/doc/more_stuff.textile
index 1fdeebe..057ddcd 100644
--- a/doc/more_stuff.textile
+++ b/doc/more_stuff.textile
@@ -391,6 +391,78 @@ $ buildr --generate /path/to/my_project
This creates a basic buildfile with a main project called 'my_project'. The buildfile contains a skeleton for compiling the Eclipse projects. If you want to automate dependency tracking via OSGi have a look at the "buildr4osgi":http://oss.intalio.com/buildr4osgi/ project. Support for building Eclipse RCP applications, running PDE tests and P2-sites is currently lacking in Buildr.
+h2(#maven_central). Releasing to Maven Central
+
+Many opensource projects release their artifacts to Maven Central. To release a library to Maven Central, the project needs to provide several elements for each library;
+
+* the jar artifact,
+* the sources artifact,
+* the javadocs artifact,
+* a pom that supplies fields required by Maven Central, and
+* gpg signatures for every file supplied.
+
+Buildr has built-in support for the artifacts and can easily sign the artifacts using the 'buildr/gpg' addon. However it has not always been easy to generate a pom in the required format until the 'buildr/custom_pom' became available.
+
+Below is an extremely verbose example of a project that provides all the elements required to publish to Maven Central.
+
+{% highlight sh %}
+# Include addon to generate GPG Signatures
+require 'buildr/gpg'
+# Include addon to generate custom pom
+require 'buildr/custom_pom'
+
+define 'myproject' do
+ project.group = 'org.myproject'
+ project.version = '1.0'
+
+ pom.licenses['The Apache Software License, Version 2.0'] = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+ pom.scm_connection = pom.scm_developer_connection = 'scm:git:git@github.com:jbloggs/myproject'
+ pom.scm_url = 'git@github.com:jbloggs/myproject'
+ pom.url = 'https://github.com/jbloggs/myproject'
+ pom.issues_url = 'https://github.com/jbloggs/myproject/issues'
+ pom.issues_system = 'GitHub Issues'
+ pom.add_developer('jbloggs', 'Joe Bloggs', 'jbloggs@example.com', ['Project Lead'])
+ pom.provided_dependencies.concat [:javax_servlet]
+ pom.optional_dependencies.concat [:optional_api]
+
+ compile.with :javax_servlet, :some_api, :optional_api
+
+ test.with :mockito
+
+ package(:jar)
+ package(:sources)
+ package(:javadoc)
+end
+{% endhighlight %}
+
+That example is however, extremely verbose and there is a number of helper methods been added to the 'buildr/custom_pom' addon to simplify common scenarios. It would be more common to see the addon used in the following manner;
+
+{% highlight sh %}
+require 'buildr/gpg'
+require 'buildr/custom_pom'
+
+define 'myproject' do
+ project.group = 'org.myproject'
+ project.version = '1.0'
+
+ pom.add_apache2_license
+ pom.add_github_project('jbloggs/myproject')
+ pom.add_developer('jbloggs', 'Joe Bloggs')
+ pom.provided_dependencies.concat [:javax_servlet]
+ pom.optional_dependencies.concat [:optional_api]
+
+ compile.with :javax_servlet, :optional_api
+
+ test.with :mockito
+
+ package(:jar)
+ package(:sources)
+ package(:javadoc)
+end
+{% endhighlight %}
+
+If there are other common scenarios useful for opensource developers, feel free to make a request on buildr mailing list to provide simplified helper methods.
+
h2(#idea). IntelliJ IDEA
If you use IntelliJ IDEA, you can generate project files by issuing:
http://git-wip-us.apache.org/repos/asf/buildr/blob/baa269bb/spec/addon/custom_pom_spec.rb
----------------------------------------------------------------------
diff --git a/spec/addon/custom_pom_spec.rb b/spec/addon/custom_pom_spec.rb
new file mode 100644
index 0000000..e201ad1
--- /dev/null
+++ b/spec/addon/custom_pom_spec.rb
@@ -0,0 +1,149 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with this
+# work for additional information regarding copyright ownership. The ASF
+# licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+
+require File.expand_path('../spec_helpers', File.dirname(__FILE__))
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'xpath_matchers'))
+
+Sandbox.require_optional_extension 'buildr/custom_pom'
+
+describe Buildr::CustomPom do
+
+ def xml_document(filename)
+ File.should be_exist(filename)
+ REXML::Document.new(File.read(filename))
+ end
+
+ def project_pom_xml(project)
+ xml_document(project.packages[0].pom.to_s)
+ end
+
+ def verify_license(pom_xml, name, url)
+ pom_xml.should match_xpath("/project/licenses/license/url[../name/text() = '#{name}']", url)
+ end
+
+ def dependency_xpath(artifact_id)
+ "/project/dependencies/dependency[artifactId/text() = '#{artifact_id}']"
+ end
+
+ def verify_dependency_group(pom_xml, artifact_id, group)
+ pom_xml.should match_xpath("#{dependency_xpath(artifact_id)}/groupId", group)
+ end
+
+ def verify_dependency_version(pom_xml, artifact_id, version)
+ pom_xml.should match_xpath("#{dependency_xpath(artifact_id)}/version", version)
+ end
+
+ def verify_dependency_scope(pom_xml, artifact_id, scope)
+ pom_xml.should match_xpath("#{dependency_xpath(artifact_id)}/scope", scope)
+ end
+
+ def verify_dependency_optional(pom_xml, artifact_id, optional)
+ pom_xml.should match_xpath("#{dependency_xpath(artifact_id)}/optional", optional)
+ end
+
+ def verify_dependency(pom_xml, artifact_id, group, version, scope, optional)
+ verify_dependency_group(pom_xml, artifact_id, group)
+ verify_dependency_version(pom_xml, artifact_id, version)
+ verify_dependency_scope(pom_xml, artifact_id, scope)
+ verify_dependency_optional(pom_xml, artifact_id, optional)
+ end
+
+ describe "with explicitly specified pom details" do
+ before do
+ ['id-provided', 'id-optional', 'id-runtime', 'id-test'].each do |artifact_id|
+ artifact("group:#{artifact_id}:jar:1.0") do |t|
+ mkdir_p File.dirname(t.to_s)
+ Zip::ZipOutputStream.open t.to_s do |zip|
+ zip.put_next_entry 'empty.txt'
+ end
+ end
+ end
+ write 'src/main/java/Example.java', "public class Example {}"
+
+ @foo = define 'foo' do
+ project.group = 'org.myproject'
+ project.version = '1.0'
+
+ pom.licenses['The Apache Software License, Version 2.0'] = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+ pom.licenses['GNU General Public License (GPL) version 3.0'] = 'http://www.gnu.org/licenses/gpl-3.0.html'
+ pom.scm_connection = pom.scm_developer_connection = 'scm:git:git@github.com:jbloggs/myproject'
+ pom.scm_url = 'git@github.com:jbloggs/myproject'
+ pom.url = 'https://github.com/jbloggs/myproject'
+ pom.issues_url = 'https://github.com/jbloggs/myproject/issues'
+ pom.issues_system = 'GitHub Issues'
+ pom.add_developer('jbloggs', 'Joe Bloggs', 'jbloggs@example.com', ['Project Lead'])
+ pom.provided_dependencies = ['group:id-provided:jar:1.0']
+ pom.optional_dependencies = ['group:id-optional:jar:1.0']
+
+ compile.with 'group:id-runtime:jar:1.0', 'group:id-optional:jar:1.0', 'group:id-provided:jar:1.0'
+
+ test.with 'group:id-test:jar:1.0'
+
+ package(:jar)
+ end
+ task('package').invoke
+ @pom_xml = project_pom_xml(@foo)
+ #$stderr.puts @pom_xml.to_s
+ end
+
+ it "has correct static metadata" do
+ @pom_xml.should match_xpath("/project/modelVersion", '4.0.0')
+ @pom_xml.should match_xpath("/project/parent/groupId", 'org.sonatype.oss')
+ @pom_xml.should match_xpath("/project/parent/artifactId", 'oss-parent')
+ @pom_xml.should match_xpath("/project/parent/version", '7')
+ end
+
+ it "has correct project level metadata" do
+ @pom_xml.should match_xpath("/project/groupId", 'org.myproject')
+ @pom_xml.should match_xpath("/project/artifactId", 'foo')
+ @pom_xml.should match_xpath("/project/version", '1.0')
+ @pom_xml.should match_xpath("/project/packaging", 'jar')
+ @pom_xml.should match_xpath("/project/name", 'foo')
+ @pom_xml.should match_xpath("/project/description", 'foo')
+ @pom_xml.should match_xpath("/project/url", 'https://github.com/jbloggs/myproject')
+ end
+
+ it "has correct scm details" do
+ @pom_xml.should match_xpath("/project/scm/connection", 'scm:git:git@github.com:jbloggs/myproject')
+ @pom_xml.should match_xpath("/project/scm/developerConnection", 'scm:git:git@github.com:jbloggs/myproject')
+ @pom_xml.should match_xpath("/project/scm/url", 'git@github.com:jbloggs/myproject')
+ end
+
+ it "has correct issueManagement details" do
+ @pom_xml.should match_xpath("/project/issueManagement/url", 'https://github.com/jbloggs/myproject/issues')
+ @pom_xml.should match_xpath("/project/issueManagement/system", 'GitHub Issues')
+ end
+
+ it "has correct developers details" do
+ @pom_xml.should match_xpath("/project/developers/developer/id", 'jbloggs')
+ @pom_xml.should match_xpath("/project/developers/developer/name", 'Joe Bloggs')
+ @pom_xml.should match_xpath("/project/developers/developer/email", 'jbloggs@example.com')
+ @pom_xml.should match_xpath("/project/developers/developer/roles/role", 'Project Lead')
+ end
+
+ it "has correct license details" do
+ verify_license(@pom_xml, 'The Apache Software License, Version 2.0', 'http://www.apache.org/licenses/LICENSE-2.0.txt')
+ verify_license(@pom_xml, 'GNU General Public License (GPL) version 3.0', 'http://www.gnu.org/licenses/gpl-3.0.html')
+ end
+
+ it "has correct dependency details" do
+ verify_dependency(@pom_xml, 'id-runtime', 'group', '1.0', nil, nil)
+ verify_dependency(@pom_xml, 'id-optional', 'group', '1.0', nil, 'true')
+ verify_dependency(@pom_xml, 'id-provided', 'group', '1.0', 'provided', nil)
+ verify_dependency(@pom_xml, 'id-test', 'group', '1.0', 'test', nil)
+ end
+ end
+end