Skip to content

Commit

Permalink
Merge pull request #14 from bibendi/master
Browse files Browse the repository at this point in the history
Many features
  • Loading branch information
bibendi authored Mar 22, 2017
2 parents 776f9d7 + 7c9c3b6 commit d91f71c
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 34 deletions.
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM abakpress/ruby-app:2.3-latest

RUN git config --global user.name "Automated Release" \
&& git config --global user.email [email protected]

ADD . /usr/src/apress-gems

RUN cd /usr/src/apress-gems \
&& gem build -V apress-gems.gemspec \
&& gem install $(ls -t apress-gems*.gem | head -1)

ADD release-gem /usr/local/bin/
23 changes: 18 additions & 5 deletions bin/apress-gem
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ opt_parser = OptionParser.new do |opt|
opt.separator ' build: make gem package'
opt.separator ' upload: upload package to gems.railsc.ru'
opt.separator ' current: show current gem version'
opt.separator ' exist: check for uploaded gem'
opt.separator ''

opt.separator 'Options'

opt.on('-h', '--help', 'help') do
puts opt_parser
options[:show_help] = true
end

opt.on('-v', '--version VERSION', 'new version, ex: -v 1.0.0') do |value|
Expand All @@ -33,7 +34,7 @@ opt_parser = OptionParser.new do |opt|
options[:branch] = value
end

opt.on('-r', '--remote NAME', 'remote server name, default upstream') do |value|
opt.on('-r', '--remote NAME', 'remote server name, default origin') do |value|
options[:remote] = value
end

Expand All @@ -52,14 +53,26 @@ opt_parser = OptionParser.new do |opt|
opt.on('-U', '--no-pull', 'no pull latest changes') do
options[:pull] = false
end

opt.on('-q', '--quiet', 'silence command progress meter') do
options[:quiet] = true
end

opt.on('-s', '--source URL', 'url of gem source, default https://gems.railsc.ru/') do |value|
options[:source] = value
end
end

opt_parser.parse!

cli = Apress::Gems::Cli.new(options)
if options[:show_help]
puts opt_parser
exit
end

if %w(release changelog build upload tag current bump).include?(ARGV[0])
cli.public_send(ARGV[0])
subcmd = ARGV[0]
if %w(release changelog build upload tag current bump exist).include?(subcmd)
Apress::Gems::Cli.new(options).public_send(subcmd)
else
puts opt_parser
end
109 changes: 80 additions & 29 deletions lib/apress/gems/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,25 @@ module Gems
class Cli
GEMS_URL = 'https://gems.railsc.ru/'.freeze

def initialize(options)
@options = {bump: true, changelog: true, pull: true, push: true}.merge!(options)
@options[:version] = find_version unless @options[:bump]
DEFAULT_OPTIONS = {
bump: true,
changelog: true,
pull: true,
push: true,
remote: "origin",
branch: "master",
quiet: false,
source: 'https://gems.railsc.ru/'
}.freeze

load_gemspec
def initialize(options)
@options = DEFAULT_OPTIONS.merge(options)
end

def changelog
Apress::ChangeLogger.new.log_changes
spawn 'git add CHANGELOG.md'
puts 'Changelog generated'
log 'Changelog generated'
end

def bump
Expand All @@ -31,36 +39,46 @@ def bump

if @options[:push]
spawn "git push #{remote} #{branch}"
puts 'Changes pushed to repository'
log 'Changes pushed to repository'
end
end

def build
FileUtils.mkdir_p('pkg')

spawn "gem build -V #{@spec_path}"
built_gem_path = Dir["#{@gemspec.name}-*.gem"].sort_by { |f| File.mtime(f) }.last
spawn "gem build -V #{spec_path}"
built_gem_path = Dir["#{gemspec.name}-*.gem"].sort_by { |f| File.mtime(f) }.last

FileUtils.mv(built_gem_path, 'pkg')
puts 'Package built'
log 'Package built'
end

def upload
tarball_name = "#{@gemspec.name}-#{version}.gem"
upload_gem(upload_uri, tarball_name)
tarball_name = "#{gemspec.name}-#{version_or_current}.gem"
upload_gem(source_uri, tarball_name)
end

def tag
tag_name = "v#{version}"
tag_name = "v#{version_or_current}"

spawn "git tag -a -m \"Version #{version}\" #{tag_name}"
spawn "git tag -a -m \"Version #{version_or_current}\" #{tag_name}"
spawn "git push --tags #{remote}" if @options[:push]

puts "Git tag generated to #{tag_name}"
log "Git tag generated to #{tag_name}"
end

def current
puts "Current version is #{find_version}"
puts find_version
end

def exist
if exist?
log "Gem already released"
exit(0)
else
log "Gem is not released"
exit(1)
end
end

def release
Expand All @@ -77,12 +95,16 @@ def version
@version ||= @options.fetch(:version)
end

def version_or_current
@version_or_current ||= @options.fetch(:version, find_version)
end

def branch
@branch ||= @options.fetch(:branch, 'master')
@branch ||= @options.fetch(:branch)
end

def remote
@remote ||= @options.fetch(:remote, 'upstream')
@remote ||= @options.fetch(:remote)
end

def find_version
Expand All @@ -92,25 +114,32 @@ def find_version
end
end

def exist?
cmd = "gem search #{gemspec.name} --clear-sources -s '#{source_uri}' --exact --quiet -a"
output = spawn(cmd)
escaped_version = Regexp.escape(version_or_current)
!!(output =~ /[( ]#{escaped_version}[,)]/)
end

def update_version
Dir['lib/**/version.rb'].each do |file|
contents = File.read(file)
contents.gsub!(/VERSION\s*=\s*(['"])(.*?)\1/m, "VERSION = '#{version}'")
contents.gsub!(/VERSION\s*=\s*(['"])(.*?)\1/m, "VERSION = '#{version}'.freeze")
File.write(file, contents)
spawn "git add #{file}"
puts "Version updated to #{version}"
log "Version updated to #{version}"
end
end

def upload_uri
uri = URI.parse(GEMS_URL)
uri.userinfo = Bundler.settings[GEMS_URL]
uri
def source_uri
return @uri if defined?(@uri)
source_url = @options.fetch(:source)
@uri = URI.parse(source_url)
@uri.userinfo = Bundler.settings[source_url]
@uri
end

def pull_latest
`git rev-parse --abbrev-ref HEAD`.chomp.strip == branch || abort("Can be released only from `#{branch}` branch")
`git remote | grep #{remote}`.chomp.strip == remote || abort("Can be released only with `#{remote}` remote")
spawn "git pull #{remote} #{branch}"
spawn "git fetch --tags #{remote}"
end
Expand All @@ -126,33 +155,50 @@ def validate_version

# run +cmd+ in subprocess, redirect its stdout to parent's stdout
def spawn(cmd)
puts ">> #{cmd}"
log ">> #{cmd}"

cmd += ' 2>&1'
output = ""
PTY.spawn cmd do |r, _w, pid|
begin
r.sync
r.each_char { |chr| STDOUT.write(chr) }
r.each_char do |chr|
STDOUT.write(chr) unless @options[:quiet]
output << chr
end
rescue Errno::EIO
# simply ignoring this
ensure
::Process.wait pid
end
end
abort "#{cmd} failed, exit code #{$? && $?.exitstatus}" unless $? && $?.exitstatus == 0

output.strip
end

def load_gemspec
return if defined?(@gemspec)
gemspecs = Dir[File.join(Dir.pwd, '{,*}.gemspec')]
raise 'Unable to determine name from existing gemspec' unless gemspecs.size == 1
@spec_path = gemspecs.first
@gemspec = Bundler.load_gemspec(@spec_path)
end

def gemspec
load_gemspec
@gemspec
end

def spec_path
load_gemspec
@spec_path
end

def upload_gem(repo_uri, tarball_name)
repo_uri.path = '/upload'

puts "Start uploading gem #{tarball_name} to #{repo_uri.host}"
log "Start uploading gem #{tarball_name} to #{repo_uri.host}"

tarball_path = File.join('pkg', tarball_name)

Expand All @@ -167,13 +213,18 @@ def upload_gem(repo_uri, tarball_name)
end

if [200, 302].include?(res.code.to_i)
puts "#{tarball_name} uploaded successfully"
log "#{tarball_name} uploaded successfully"
else
$stderr.puts "Cannot upload #{tarball_name}. Response status: #{res.code}"
exit(1)
end
end
end

def log(message)
return if @options[:quiet]
puts message
end
end
end
end
3 changes: 3 additions & 0 deletions release-gem
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash -e

apress-gem exist --quiet || apress-gem release --no-bump --no-pull

0 comments on commit d91f71c

Please sign in to comment.