[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 group :development, :test do
# This is here because gemspec doesn't support require: false # This is here because gemspec doesn't support require: false
gem 'coveralls', :require => false gem 'coveralls', :require => false
gem "netrc", :require => false
gem "octokit", :require => false
end end
gemspec gemspec

View File

@ -21,7 +21,7 @@ To request a new release please raise an issue.
services) services)
* Ensure working on **master** * Ensure working on **master**
* Update the version number (`lib/fog/version.rb`) * 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: * Run `rake release` to prepare the release which does:
* Prepares the release (`rake release:prepare`) * Prepares the release (`rake release:prepare`)
* Builds the gem * Builds the gem
@ -30,6 +30,7 @@ services)
* Publishes the release (`rake release:publish`) * Publishes the release (`rake release:publish`)
* Pushes commit and tag to Github (Requires Credentials) * Pushes commit and tag to Github (Requires Credentials)
* Pushes gem to Rubygems (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 ## Announce the release

View File

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

View File

@ -8,103 +8,200 @@ module Fog
def initialize def initialize
desc "Update the changelog since the last release" desc "Update the changelog since the last release"
task(:changelog) do 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) @changelog = []
data = github_repo_data.reject {|key, value| !['forks', 'open_issues', 'watchers'].include?(key)} @changelog << "## #{Fog::VERSION} #{timestamp}"
github_collaborator_data = Fog::JSON.decode(Excon.get('https://api.github.com/repos/fog/fog/collaborators', :headers => {'User-Agent' => 'geemus'}).body) @changelog << "*Hash* #{sha}"
data['collaborators'] = github_collaborator_data.length @changelog << blank_line
rubygems_data = Fog::JSON.decode(Excon.get('https://rubygems.org/api/v1/gems/fog.json').body)
data['downloads'] = rubygems_data['downloads'] @changelog << "Statistic | Value"
stats = [] @changelog << "------------- | --------:"
for key in data.keys.sort @changelog << "Collaborators | #{collaborators}"
stats << "'#{key}' => #{data[key]}" @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
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 end
changelog << "Stats! { #{stats.join(', ')} }" @changelog << blank_line
changelog << '' end
end
last_sha = `cat changelog.txt | head -1`.split(' ').last def process_commits
shortlog = `git shortlog #{last_sha}..HEAD` shortlog = `git shortlog #{last_release_sha}..HEAD`
changes = {} @changes = {}
committers = {} @committers = {}
for line in shortlog.split("\n") @committer = nil
if line =~ /^\S/ shortlog.split("\n").each do |line|
committer = line.split(' (', 2).first @current_line = line
committers[committer] = 0 if committer_line?
elsif line =~ /^\s*((Merge.*)|(Release.*))?$/ @committer = committer_match[1]
# skip empty lines, Merge and Release commits add_committer
else elsif !release_merge_line?
unless line[-1..-1] == '.' add_period_if_necessary
line << '.' @current_line.lstrip!
end add_commit_line
line.lstrip! increment_commits
line.gsub!(/^\[([^\]]*)\] /, '')
tag = $1 || 'misc'
changes[tag] ||= []
changes[tag] << (line << ' thanks ' << committer)
committers[committer] += 1
end
end
for committer, commits in committers.to_a.sort {|x,y| y[1] <=> x[1]}
if [
'Aaron Suggs',
'Ash Wilson',
'Brian Hartsock',
'Chris Roberts',
'Christopher Oliver',
'Daniel Reichert',
'Decklin Foster',
'Dylan Egan',
'Erik Michaels-Ober',
'geemus',
'Henry Addison',
'James Bence',
'Kevin Menard',
'Kevin Olbrich',
'Kyle Rames',
'Lincoln Stoll',
'Luqman Amjad',
'Michael Zeng',
'Mike Hagedorn',
'Mike Pountney',
'Nat Welch',
'Nick Osborn',
'nightshade427',
'Patrick Debois',
'Paul Thornthwaite',
'Rodrigo Estebanez',
'Rupak Ganguly',
'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)
end
changelog << ''
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
def add_commit_line
@current_line.gsub!(/^\[([^\]]*)\] /, '')
tag = $1 || 'misc'
@changes[tag] ||= []
@changes[tag] << "#{@current_line} thanks #{@committer}"
end
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',
'Chris Roberts',
'Christopher Oliver',
'Daniel Reichert',
'Decklin Foster',
'Dylan Egan',
'Erik Michaels-Ober',
'geemus',
'Henry Addison',
'James Bence',
'Kevin Menard',
'Kevin Olbrich',
'Kyle Rames',
'Lincoln Stoll',
'Luqman Amjad',
'Michael Zeng',
'Mike Hagedorn',
'Mike Pountney',
'Nat Welch',
'Nick Osborn',
'nightshade427',
'Patrick Debois',
'Paul Thornthwaite',
'Rodrigo Estebanez',
'Rupak Ganguly',
'Stepan G. Fedorov',
'Wesley Beary'
].include?(committer)
end
def mvp
return @mvp if @mvp
committers_sorted_by_commits.each do |committer|
if mvp_eligible?(committer)
@mvp = committer
return @mvp
end
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
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