# 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 'digest/md5' require 'digest/sha1' # Tasks specific to Apache projects (license, release, etc). namespace 'apache' do desc 'Upload snapshot packages over to people.apache.org' task 'snapshot'=>['spec', 'package'] do rm_rf 'snapshot' # Always start with empty directory puts "Copying existing gems from Apache" sh 'rsync', '--progress', '--recursive', 'people.apache.org:public_html/buildr/snapshot', './' puts "Copying new gems over" cp FileList['pkg/{*.gem,*.tgz,*.zip}'], 'snapshot/gems' puts "Generating gem index ..." sh 'gem', 'generate_index', '--directory', 'snapshot' puts "Copying gem and index back to Apache" sh 'rsync', '--progress', '--recursive', 'snapshot', 'people.apache.org:public_html/buildr/' end desc 'Check that source files contain the Apache license' task 'license' do |task| print 'Checking that files contain the Apache license ... ' required = task.prerequisites.select { |fn| File.file?(fn) } missing = required.reject { |fn| comments = File.read(fn).scan(/(\/\*(.*?)\*\/)|^#\s+(.*?)$|^-#\s+(.*?)$|/m). map { |match| match.compact }.flatten.join("\n") comments =~ /Licensed to the Apache Software Foundation/ && comments =~ /http:\/\/www.apache.org\/licenses\/LICENSE-2.0/ } fail "#{missing.join(', ')} missing Apache License, please add it before making a release!" unless missing.empty? puts 'OK' end # Staging checks specific for Apache. task 'check'=>'license' do |task, args| args.gpg_user or fail "Please run with gpg_user=" fail "No GPG user #{args.gpg_user}" if `gpg --list-keys #{args.gpg_user}`.empty? end file 'staged/distro'=>'package' do puts 'Copying and signing release files ...' mkpath 'staged/distro' FileList['pkg/*.{gem,zip,tgz}'].each do |pkg| cp pkg, pkg.pathmap('staged/distro/%n-incubating%x') end end task 'sign'=>['etc/KEYS', 'staged/distro'] do |task, args| gpg_user = args.gpg_user or fail "Please run with gpg_user=" puts "Signing packages in staged/distro as user #{gpg_user}" FileList['staged/distro/*.{gem,zip,tgz}'].each do |pkg| bytes = File.open(pkg, 'rb') { |file| file.read } File.open(pkg + '.md5', 'w') { |file| file.write Digest::MD5.hexdigest(bytes) << ' ' << File.basename(pkg) } File.open(pkg + '.sha1', 'w') { |file| file.write Digest::SHA1.hexdigest(bytes) << ' ' << File.basename(pkg) } sh 'gpg', '--local-user', gpg_user, '--armor', '--output', pkg + '.asc', '--detach-sig', pkg, :verbose=>true end cp 'etc/KEYS', 'staged/distro' end # Publish prerequisites to distro server. task 'publish:distro' do |task, args| target = args.incubating ? "people.apache.org:/www/www.apache.org/dist/incubator/#{spec.name}/#{spec.version}-incubating" : "people.apache.org:/www/www.apache.org/dist/#{spec.name}/#{spec.version}" puts 'Uploading packages to Apache distro ...' host, remote_dir = target.split(':') sh 'ssh', host, 'rm', '-rf', remote_dir rescue nil sh 'ssh', host, 'mkdir', remote_dir sh 'rsync', '--progress', '--recursive', 'published/distro/', target puts 'Done' end task 'distro-links'=>'staged/distro' do |task, args| url = args.incubating ? "http://www.apache.org/dist/incubator/#{spec.name}/#{spec.version}-incubating" : "http://www.apache.org/dist/#{spec.name}/#{spec.version}" rows = FileList['staged/distro/*.{gem,tgz,zip}'].map { |pkg| name, md5 = File.basename(pkg), Digest::MD5.file(pkg).to_s %{| "#{name}":#{url}/#{name} | "#{md5}":#{url}/#{name}.md5 | "Sig":#{url}/#{name}.asc |} } textile = <<-TEXTILE h3. #{spec.name} #{spec.version}#{args.incubating && "-incubating"} (#{Time.now.strftime('%Y-%m-%d')}) |_. Package |_. MD5 Checksum |_. PGP | #{rows.join("\n")} p>. ("Release signing keys":#{url}/KEYS) TEXTILE file_name = 'doc/pages/download.textile' print "Adding download links to #{file_name} ... " modified = File.read(file_name).sub(/h2.*binaries.*source.*/i) { |header| "#{header}\n\n#{textile}" } File.open file_name, 'w' do |file| file.write modified end puts 'Done' end file 'staged/site'=>['distro-links', 'staged', 'site'] do rm_rf 'staged/site' cp_r 'site', 'staged' end # Publish prerequisites to Web site. task 'publish:site' do |task, args| target = args.incubating ? "people.apache.org:/www/incubator.apache.org/#{spec.name}" : "people.apache.org:/www/#{spec.name}.apache.org" puts 'Uploading Apache Web site ...' sh 'rsync', '--progress', '--recursive', '--delete', 'published/site/', target puts 'Done' end file 'release-vote-email.txt'=>'CHANGELOG' do |task| # Need to know who you are on Apache, local user may be different (see .ssh/config). whoami = `ssh people.apache.org whoami`.strip base_url = "http://people.apache.org/~#{whoami}/buildr/#{spec.version}" # Need changes for this release only. changelog = File.read('CHANGELOG').scan(/(^(\d+\.\d+(?:\.\d+)?)\s+\(\d{4}-\d{2}-\d{2}\)\s*((:?^[^\n]+\n)*))/) changes = changelog[0][2] previous_version = changelog[1][1] email = <<-EMAIL To: buildr-dev@incubator.apache.org Subject: [VOTE] Buildr #{spec.version} release We're voting on the source distributions available here: #{base_url}/distro/ Specifically: #{base_url}/distro/buildr-#{spec.version}-incubating.tgz #{base_url}/distro/buildr-#{spec.version}-incubating.zip The documentation generated for this release is available here: #{base_url}/site/ #{base_url}/site/buildr.pdf The official specification against which this release was tested: #{base_url}/site/specs.html Test coverage report: #{base_url}/site/coverage/index.html The following changes were made since #{previous_version}: #{changes} EMAIL File.open task.name, 'w' do |file| file.write email end puts "Created release vote email template in '#{task.name}':" puts email end end task 'clobber' do rm_rf 'snapshot' rm_f 'release-vote-email.txt' end task 'stage:check'=>['apache:check'] task 'stage:prepare'=>['staged/distro', 'staged/site'] do |task| # Since this requires input (passphrase), do it at the very end. task.enhance do task('apache:sign').invoke end end task 'stage' do task('apache:snapshot').invoke end task 'stage:wrapup'=>'release-vote-email.txt' task 'release:publish'=>['apache:publish:distro', 'apache:publish:site']