[core] updated rake releases to generate markdown; added github_release task to publish to release feed.

This commit is contained in:
Kyle Rames 2014-03-24 09:12:19 -05:00
parent 2be37279e0
commit 15c6f40825
5 changed files with 260 additions and 92 deletions

View File

@ -3,6 +3,8 @@ source "https://rubygems.org"
group :development, :test do
# This is here because gemspec doesn't support require: false
gem 'coveralls', :require => false
gem "netrc", :require => false
gem "octokit", :require => false
end
gemspec

View File

@ -21,7 +21,7 @@ To request a new release please raise an issue.
services)
* Ensure working on **master**
* Update the version number (`lib/fog/version.rb`)
* Run `rake changelog` to update `changelog.txt`
* Run `rake changelog` to update `CHANGELOG.md`
* Run `rake release` to prepare the release which does:
* Prepares the release (`rake release:prepare`)
* Builds the gem
@ -30,6 +30,7 @@ services)
* Publishes the release (`rake release:publish`)
* Pushes commit and tag to Github (Requires Credentials)
* Pushes gem to Rubygems (Requires Credentials)
* Run `rake github_release` to add release to [github release feed](https://github.com/fog/fog/releases.atom) (Requires Credentials)
## Announce the release

View File

@ -208,6 +208,7 @@ YARD::Rake::YardocTask.new do |t|
end
require "tasks/changelog_task"
require "tasks/github_release_task"
Fog::Rake::ChangelogTask.new
task :coveralls_push_workaround do

View File

@ -8,50 +8,98 @@ module Fog
def initialize
desc "Update the changelog since the last release"
task(:changelog) do
timestamp = Time.now.utc.strftime('%m/%d/%Y')
sha = `git log | head -1`.split(' ').last
changelog = ["#{Fog::VERSION} #{timestamp} #{sha}"]
changelog << ('=' * changelog[0].length)
changelog << ''
github_repo_data = Fog::JSON.decode(Excon.get('https://api.github.com/repos/fog/fog', :headers => {'User-Agent' => 'geemus'}).body)
data = github_repo_data.reject {|key, value| !['forks', 'open_issues', 'watchers'].include?(key)}
github_collaborator_data = Fog::JSON.decode(Excon.get('https://api.github.com/repos/fog/fog/collaborators', :headers => {'User-Agent' => 'geemus'}).body)
data['collaborators'] = github_collaborator_data.length
rubygems_data = Fog::JSON.decode(Excon.get('https://rubygems.org/api/v1/gems/fog.json').body)
data['downloads'] = rubygems_data['downloads']
stats = []
for key in data.keys.sort
stats << "'#{key}' => #{data[key]}"
end
changelog << "Stats! { #{stats.join(', ')} }"
changelog << ''
@changelog = []
@changelog << "## #{Fog::VERSION} #{timestamp}"
@changelog << "*Hash* #{sha}"
@changelog << blank_line
last_sha = `cat changelog.txt | head -1`.split(' ').last
shortlog = `git shortlog #{last_sha}..HEAD`
changes = {}
committers = {}
for line in shortlog.split("\n")
if line =~ /^\S/
committer = line.split(' (', 2).first
committers[committer] = 0
elsif line =~ /^\s*((Merge.*)|(Release.*))?$/
# skip empty lines, Merge and Release commits
else
unless line[-1..-1] == '.'
line << '.'
@changelog << "Statistic | Value"
@changelog << "------------- | --------:"
@changelog << "Collaborators | #{collaborators}"
@changelog << "Downloads | #{downloads}"
@changelog << "Forks | #{forks}"
@changelog << "Open Issues | #{open_issues}"
@changelog << "Watchers | #{watchers}"
@changelog << blank_line
process_commits
@changelog << "**MVP!** #{mvp}" if mvp
@changelog << blank_line
add_commits_to_changelog
save_changelog
end
line.lstrip!
line.gsub!(/^\[([^\]]*)\] /, '')
end
private
def save_changelog
old_changelog = File.read('CHANGELOG.md')
File.open('CHANGELOG.md', 'w') do |file|
file.write(@changelog.join("\n"))
file.write("\n\n")
file.write(old_changelog)
end
end
def blank_line
''
end
def add_commits_to_changelog
@changes.keys.sort.each do |tag|
@changelog << "#### [#{tag}]"
@changes[tag].each do |commit|
@changelog << "* #{commit}"
end
@changelog << blank_line
end
end
def process_commits
shortlog = `git shortlog #{last_release_sha}..HEAD`
@changes = {}
@committers = {}
@committer = nil
shortlog.split("\n").each do |line|
@current_line = line
if committer_line?
@committer = committer_match[1]
add_committer
elsif !release_merge_line?
add_period_if_necessary
@current_line.lstrip!
add_commit_line
increment_commits
end
end
end
def add_commit_line
@current_line.gsub!(/^\[([^\]]*)\] /, '')
tag = $1 || 'misc'
changes[tag] ||= []
changes[tag] << (line << ' thanks ' << committer)
committers[committer] += 1
end
@changes[tag] ||= []
@changes[tag] << "#{@current_line} thanks #{@committer}"
end
for committer, commits in committers.to_a.sort {|x,y| y[1] <=> x[1]}
if [
def increment_commits
@committers[@committer] += 1
end
def add_committer
@committers[@committer] = 0
end
def committers_sorted_by_commits
committer_pairs = @committers.to_a.sort {|x,y| y[1] <=> x[1]}
committer_pairs.reject! {|pair| pair.last < 1 }
committer_pairs.collect {|pair| pair.first }
end
def mvp_eligible?(committer)
[
'Aaron Suggs',
'Ash Wilson',
'Brian Hartsock',
@ -82,29 +130,78 @@ module Fog
'Stepan G. Fedorov',
'Wesley Beary'
].include?(committer)
next
end
changelog << "MVP! #{committer}"
changelog << ''
break
end
for tag in changes.keys.sort
changelog << ('[' << tag << ']')
for commit in changes[tag]
changelog << (' ' << commit)
def mvp
return @mvp if @mvp
committers_sorted_by_commits.each do |committer|
if mvp_eligible?(committer)
@mvp = committer
return @mvp
end
changelog << ''
end
nil
end
def add_period_if_necessary
@current_line << "." unless @current_line[-1] == '.'
end
def release_merge_line?
@current_line =~ /^\s*((Merge.*)|(Release.*))?$/
end
def committer_line?
committer_match != nil
end
def committer_match
@current_line.match /([\w\s]+)\s+\(\d+\)/
end
def last_release_sha
`cat changelog.md | head -2`.split(' ').last
end
def downloads
repsonse = Excon.get('https://rubygems.org/api/v1/gems/fog.json')
data = Fog::JSON.decode(repsonse.body)
data['downloads']
end
def collaborators
response = Excon.get('https://api.github.com/repos/fog/fog/collaborators', :headers => {'User-Agent' => 'geemus'})
data = Fog::JSON.decode(response.body)
data.length
end
def forks
repo_metadata['forks']
end
def open_issues
repo_metadata['open_issues']
end
def watchers
repo_metadata['watchers']
end
def repo_metadata
return @repo_metadata if @repo_metadata
response = Excon.get('https://api.github.com/repos/fog/fog', :headers => {'User-Agent' => 'geemus'})
data = Fog::JSON.decode(response.body)
@repo_metadata = data.select {|key, value| ['forks', 'open_issues', 'watchers'].include?(key)}
end
def sha
`git log | head -1`.split(' ').last
end
def timestamp
@time ||= Time.now.utc.strftime('%m/%d/%Y')
end
old_changelog = File.read('changelog.txt')
File.open('changelog.txt', 'w') do |file|
file.write(changelog.join("\n"))
file.write("\n\n")
file.write(old_changelog)
end
end
end
end
end
end

View File

@ -0,0 +1,67 @@
require "rake"
require "rake/tasklib"
require 'octokit'
require 'netrc'
module Fog
module Rake
class ChangelogTask < ::Rake::TaskLib
def initialize
desc "Update the changelog since the last release"
task(:github_release) do
File.open('CHANGELOG.md', 'r') do |file|
file.each_line do |line|
@current_line = line
if release_header?
create_release if !release_exists? && @release
@release_tag = release_match[1]
@release = line
else
@release << line
end
end
end
end
end
private
def create_release
github.create_release "fog/fog", "v#{@release_tag}", {:name => "v#{@release_tag}", :body => @release}
puts "creating release #{@release_tag}"
end
def releases
return @releases if @releases
response = github.releases("fog/fog")
@releases = response.collect {|r| r.tag_name }
end
def release_exists?
releases.find {|r| r == "v#{@release_tag}" } != nil
end
def release_header?
release_match != nil
end
def release_match
@current_line.match /## (\d+\.\d+\.\d+) \d+\/\d+\d+/
end
def github
unless @github
Octokit.auto_paginate = true
@github = Octokit::Client.new :netrc => true
unless @github.login
@github = nil
raise "Please create a ~.netrc file to authenticate with github. For more information please see https://github.com/octokit/octokit.rb/blob/master/README.md#using-a-netrc-file"
end
end
@github
end
end
end
end