lib/capistrano-maven.rb in capistrano-maven-0.0.6 vs lib/capistrano-maven.rb in capistrano-maven-0.0.7

- old
+ new

@@ -1,8 +1,292 @@ -require "capistrano-maven/deploy" require "capistrano-maven/version" +require "capistrano" +require "capistrano/configuration/actions/file_transfer_ext" +require "capistrano/configuration/resources/file_resources" +require "uri" module Capistrano module Maven - # Your code goes here... + def self.extended(configuration) + configuration.load { + namespace(:mvn) { + _cset(:mvn_version, '3.0.4') + _cset(:mvn_major_version) { + mvn_version.split('.').first.to_i + } + _cset(:mvn_archive_url) { + "http://www.apache.org/dist/maven/maven-#{mvn_major_version}/#{mvn_version}/binaries/apache-maven-#{mvn_version}-bin.tar.gz" + } + _cset(:mvn_archive_file) { + File.join(shared_path, 'tools', 'mvn', File.basename(URI.parse(mvn_archive_url).path)) + } + _cset(:mvn_archive_file_local) { + File.join(File.expand_path('.'), 'tools', 'mvn', File.basename(URI.parse(mvn_archive_url).path)) + } + _cset(:mvn_checksum_url) { + "#{mvn_archive_url}.md5" + } + _cset(:mvn_checksum_file) { + File.join(shared_path, 'tools', 'mvn', File.basename(URI.parse(mvn_checksum_url).path)) + } + _cset(:mvn_checksum_file_local) { + File.join(File.expand_path('.'), 'tools', 'mvn', File.basename(URI.parse(mvn_checksum_url).path)) + } + _cset(:mvn_checksum_cmd) { + case File.extname(File.basename(URI.parse(mvn_checksum_url).path)) + when '.md5' then 'md5sum' + when '.sha1' then 'sha1sum' + end + } + _cset(:mvn_path) { + File.join(shared_path, 'tools', 'mvn', File.basename(URI.parse(mvn_archive_url).path, "-bin.tar.gz")) + } + _cset(:mvn_path_local) { + File.join(File.expand_path('.'), 'tools', 'mvn', File.basename(URI.parse(mvn_archive_url).path, "-bin.tar.gz")) + } + _cset(:mvn_bin) { + File.join(mvn_path, 'bin', 'mvn') + } + _cset(:mvn_bin_local) { + File.join(mvn_path_local, 'bin', 'mvn') + } + _cset(:mvn_cmd) { + if fetch(:mvn_java_home, nil) + "env JAVA_HOME=#{mvn_java_home} #{mvn_bin} #{mvn_options.join(' ')}" + else + "#{mvn_bin} #{mvn_options.join(' ')}" + end + } + _cset(:mvn_cmd_local) { + if fetch(:mvn_java_home_local, nil) + "env JAVA_HOME=#{mvn_java_home_local} #{mvn_bin_local} #{mvn_options_local.join(' ')}" + else + "#{mvn_bin_local} #{mvn_options_local.join(' ')}" + end + } + _cset(:mvn_project_path) { + release_path + } + _cset(:mvn_project_path_local) { + Dir.pwd + } + _cset(:mvn_target_path) { + File.join(mvn_project_path, 'target') + } + _cset(:mvn_target_path_local) { + File.join(mvn_project_path_local, File.basename(mvn_target_path)) + } + _cset(:mvn_template_path, File.join(File.dirname(__FILE__), 'templates')) + _cset(:mvn_update_settings, false) + _cset(:mvn_update_settings_locally, false) + _cset(:mvn_settings_path) { mvn_project_path } + _cset(:mvn_settings_path_local) { mvn_project_path_local } + _cset(:mvn_settings, %w(settings.xml)) + _cset(:mvn_settings_local, %w(settings.xml)) + _cset(:mvn_cleanup_settings, []) + _cset(:mvn_cleanup_settings_local, []) + _cset(:mvn_compile_locally, false) # perform precompilation on localhost + _cset(:mvn_goals, %w(clean package)) + _cset(:mvn_common_options) { + options = [] + options << "-P#{mvn_profiles.join(',')}" unless fetch(:mvn_profiles, []).empty? + options << "-Dmaven.test.skip=true" if fetch(:mvn_skip_tests, false) + options << "-U" if fetch(:mvn_update_snapshots, false) + options << "-B" + options + } + _cset(:mvn_options) { + options = mvn_common_options + fetch(:mvn_extra_options, []) + if mvn_update_settings + settings = File.join(mvn_settings_path, mvn_settings.first) + options << "--settings=#{settings}" + end + options + } + _cset(:mvn_options_local) { + options = mvn_common_options + fetch(:mvn_extra_options_local, []) + if mvn_update_settings_locally + settings = File.join(mvn_settings_path_local, mvn_settings_local.first) + options << "--settings=#{settings}" + end + options + } + + desc("Setup maven.") + task(:setup, :roles => :app, :except => { :no_release => true }) { + transaction { + install + update_settings if mvn_update_settings + setup_locally if mvn_compile_locally + } + } + after 'deploy:setup', 'mvn:setup' + + desc("Setup maven locally.") + task(:setup_locally, :except => { :no_release => true }) { + transaction { + install_locally + update_settings_locally if mvn_update_settings_locally + } + } + + def _validate_archive(archive_file, checksum_file) + if cmd = fetch(:mvn_checksum_cmd, nil) + "test `#{cmd} #{archive_file} | cut -d' ' -f1` = `cat #{checksum_file}`" + else + "true" + end + end + + def _install(options={}) + path = options.delete(:path) + bin = options.delete(:bin) + checksum_file = options.delete(:checksum_file) + checksum_url = options.delete(:checksum_url) + archive_file = options.delete(:archive_file) + archive_url = options.delete(:archive_url) + dirs = [ File.dirname(checksum_file), File.dirname(archive_file), File.dirname(path) ].uniq() + execute = [] + execute << "mkdir -p #{dirs.join(' ')}" + execute << (<<-EOS).gsub(/\s+/, ' ').strip + if ! test -f #{archive_file}; then + ( rm -f #{checksum_file}; wget --no-verbose -O #{checksum_file} #{checksum_url} ) && + wget --no-verbose -O #{archive_file} #{archive_url} && + #{_validate_archive(archive_file, checksum_file)} || ( rm -f #{archive_file}; false ) && + test -f #{archive_file}; + fi + EOS + execute << (<<-EOS).gsub(/\s+/, ' ').strip + if ! test -x #{bin}; then + ( test -d #{path} || tar xf #{archive_file} -C #{File.dirname(path)} ) && + test -x #{bin}; + fi + EOS + execute.join(' && ') + end + + task(:install, :roles => :app, :except => { :no_release => true }) { + run(_install(:path => mvn_path, :bin => mvn_bin, + :checksum_file => mvn_checksum_file, :checksum_url => mvn_checksum_url, + :archive_file => mvn_archive_file, :archive_url => mvn_archive_url)) + run("#{mvn_cmd} --version") + } + + task(:install_locally, :except => { :no_release => true }) { + run_locally(_install(:path => mvn_path_local, :bin => mvn_bin_local, + :checksum_file => mvn_checksum_file_local, :checksum_url => mvn_checksum_url, + :archive_file => mvn_archive_file_local, :archive_url => mvn_archive_url)) + run_locally("#{mvn_cmd_local} --version") + } + + task(:update_settings, :roles => :app, :except => { :no_release => true }) { + mvn_settings.each do |f| + safe_put(template(f, :path => mvn_template_path), File.join(mvn_settings_path, f)) + end + run("rm -f #{mvn_cleanup_settings.map { |x| x.dump }.join(' ')}") unless mvn_cleanup_settings.empty? + } + + task(:update_settings_locally, :except => { :no_release => true }) { + mvn_settings_local.each do |f| + File.write(File.join(mvn_settings_path_local, f), template(f, :path => mvn_template_path)) + end + run_locally("rm -f #{mvn_cleanup_settings_local.map { |x| x.dump }.join(' ')}") unless mvn_cleanup_settings_local.empty? + } + + desc("Update maven build.") + task(:update, :roles => :app, :except => { :no_release => true }) { + transaction { + if mvn_compile_locally + update_locally + else + execute + end + } + } + after 'deploy:finalize_update', 'mvn:update' + + desc("Update maven build locally.") + task(:update_locally, :except => { :no_release => true }) { + transaction { + execute_locally + upload_locally + } + } + + def _mvn(cmd, path, goals=[]) + "cd #{path.dump} && #{cmd} #{goals.map { |s| s.dump }.join(' ')}" + end + + def _mvn_parse_version(s) + # FIXME: is there any better way to get project version? + s.split(/(?:\r?\n)+/).reject { |line| /^\[[A-Z]+\]/ =~ line }.last + end + + _cset(:mvn_release_build, false) + _cset(:mvn_snapshot_pattern, /-SNAPSHOT$/i) + _cset(:mvn_project_version) { + _mvn_parse_version(capture(_mvn(mvn_cmd, mvn_project_path, %w(-Dexpression=project.version help:evaluate)))) + } + _cset(:mvn_project_version_local) { + _mvn_parse_version(run_locally(_mvn(mvn_cmd_local, mvn_project_path_local, %w(-Dexpression=project.version help:evaluate)))) + } + + def _validate_project_version(version_key) + if mvn_release_build + version = fetch(version_key) + if mvn_snapshot_pattern === version + abort("Skip to build project since \`#{version}' is a SNAPSHOT version.") + end + end + end + + desc("Perform maven build.") + task(:execute, :roles => :app, :except => { :no_release => true }) { + on_rollback { + run(_mvn(mvn_cmd, mvn_project_path, %w(clean))) + } + _validate_project_version(:mvn_project_version) + run(_mvn(mvn_cmd, mvn_project_path, mvn_goals)) + } + + desc("Perform maven build locally.") + task(:execute_locally, :roles => :app, :except => { :no_release => true }) { + on_rollback { + run_locally(_mvn(mvn_cmd_local, mvn_project_path_local, %w(clean))) + } + _validate_project_version(:mvn_project_version_local) + cmdline = _mvn(mvn_cmd_local, mvn_project_path_local, mvn_goals) + logger.info(cmdline) + abort("execution failure") unless system(cmdline) + } + + _cset(:mvn_tar, 'tar') + _cset(:mvn_tar_local, 'tar') + _cset(:mvn_target_archive) { + "#{mvn_target_path}.tar.gz" + } + _cset(:mvn_target_archive_local) { + "#{mvn_target_path_local}.tar.gz" + } + task(:upload_locally, :roles => :app, :except => { :no_release => true }) { + on_rollback { + run("rm -rf #{mvn_target_path} #{mvn_target_archive}") + } + begin + run_locally("cd #{File.dirname(mvn_target_path_local)} && #{mvn_tar_local} chzf #{mvn_target_archive_local} #{File.basename(mvn_target_path_local)}") + upload(mvn_target_archive_local, mvn_target_archive) + run("cd #{File.dirname(mvn_target_path)} && #{mvn_tar} xzf #{mvn_target_archive} && rm -f #{mvn_target_archive}") + ensure + run_locally("rm -f #{mvn_target_archive_local}") + end + } + } + } + end end end + +if Capistrano::Configuration.instance + Capistrano::Configuration.instance.extend(Capistrano::Maven) +end + +# vim:set ft=ruby :