Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
require 'safe_yaml'
require 'uri'
require 'tachikoma'
require 'octokit'
require 'fileutils'
require 'restore_bundled_with'
module Tachikoma
# Main logic of Tachikoma
class Application
include FileUtils
def self.run(strategy)
new.run(strategy)
end
def run(strategy)
load
fetch
send(strategy) if respond_to?(strategy)
pull_request
end
def load
@build_for = ENV['BUILD_FOR']
@github_token = ENV[github_token_key(@build_for)]
base_config_path = File.join(Tachikoma.original_data_path, 'default.yaml')
base_config = YAML.safe_load_file(base_config_path) || {}
user_config_path = File.join(Tachikoma.data_path, '__user_config__.yaml')
user_config = YAML.safe_load_file(user_config_path) if File.exist?(user_config_path)
user_config ||= {}
each_config_path = File.join(Tachikoma.data_path, "#{@build_for}.yaml")
each_config = YAML.safe_load_file(each_config_path) if File.exist?(each_config_path)
unless each_config
fail %(Something wrong, BUILD_FOR: #{@build_for}, your config_path: #{each_config_path})
end
@configure = base_config.merge(user_config).merge(each_config)
@commiter_name = @configure['commiter_name']
@commiter_email = @configure['commiter_email']
@github_account = @configure['github_account']
@url = @configure['url']
@type = @configure['type']
@base_remote_branch = @configure['base_remote_branch']
@authorized_compare_url = authorized_compare_url_with_type(@url, @type, @github_token, @github_account)
@authorized_base_url = authorized_base_url_with_type(@url, @type, @github_token, @github_account)
@timestamp_format = @configure['timestamp_format']
@readable_time = Time.now.utc.strftime(@timestamp_format)
@parallel_option = bundler_parallel_option(Bundler::VERSION, @configure['bundler_parallel_number'])
@depth_option = git_clone_depth_option(@configure['git_clone_depth'])
@bundler_restore_bundled_with = @configure['bundler_restore_bundled_with']
@target_head = target_repository_user(@type, @url, @github_account)
@pull_request_url = repository_identity(@url)
@pull_request_body = @configure['pull_request_body']
@pull_request_base = @configure['pull_request_base']
@pull_request_head = "#{@target_head}:tachikoma/update-#{@readable_time}"
@pull_request_title = (@configure['pull_request_title'] || 'Exec tachikoma update %s') % @readable_time
end
def clean
mkdir_p(Tachikoma.repos_path)
rm_rf(Dir.glob(File.join(Tachikoma.repos_path, '*')))
end
def fetch
clean
sh(*([
'git', 'clone',
*@depth_option,
@authorized_base_url,
"#{Tachikoma.repos_path}/#{@build_for}"
].compact))
end
def bundler
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
Bundler.with_clean_env do
sh(*['ruby', '-i', '-pe', '$_.gsub! /^ruby/, "#ruby"', 'Gemfile'])
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
if File.exist?('Gemfile')
@bundler_key_file = 'Gemfile'
@bundler_lock_file = 'Gemfile.lock'
elsif File.exist?('gems.rb')
@bundler_key_file = 'gems.rb'
@bundler_lock_file = 'gems.locked'
else
@bundler_key_file = 'Gemfile'
@bundler_lock_file = 'Gemfile.lock'
end
sh(*([
'bundle',
'--gemfile', @bundler_key_file,
'--no-deployment',
'--without', 'nothing',
'--path', 'vendor/bundle',
@parallel_option
].compact))
sh(*%w(bundle update))
if @bundler_restore_bundled_with
# restore_bundled_with
lock_file_contents = File.read(@bundler_lock_file)
lock_file = RestoreBundledWith::Lock.restore(
lock_file_contents, @bundler_lock_file)
File.write(@bundler_lock_file, lock_file.body)
end
sh(*['git', 'add', @bundler_lock_file])
sh(*['git', 'commit', '-m', "Bundle update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
end
def bundle
warn '[DEPRECATION] `bundle` is deprecated. Please use `bundler` instead.'
bundler
end
def carton
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
sh(*%w(carton install))
sh(*%w(carton update))
sh(*['git', 'add', 'carton.lock']) if File.exist?('carton.lock')
sh(*['git', 'add', 'cpanfile.snapshot']) if File.exist?('cpanfile.snapshot')
sh(*['git', 'commit', '-m', "Carton update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def none
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
sh(*['git', 'commit', '--allow-empty', '-m', "None update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def david
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
sh(*['david', 'update', '--warn404'])
if File.exist?('npm-shrinkwrap.json')
sh(*['rm', '-rf', 'node_modules/', 'npm-shrinkwrap.json'])
sh(*['npm', 'install'])
sh(*['npm', 'shrinkwrap'])
sh(*['git', 'add', 'package.json'])
sh(*['git', 'add', 'npm-shrinkwrap.json'])
else
sh(*['git', 'add', 'package.json'])
end
sh(*['git', 'commit', '-m', "David update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def composer
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
# FIXME: Use Octokit.api_endpoint for GitHub Enterprise
sh(*['composer', 'config', 'github-oauth.github.com', @github_token])
sh(*['composer', 'install', '--no-interaction'])
sh(*['composer', 'update', '--no-interaction'])
sh(*['git', 'add', 'composer.lock'])
sh(*['git', 'commit', '-m', "Composer update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def carthage
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
sh(*%w(carthage bootstrap))
sh(*%w(carthage update))
sh(*['git', 'add', 'Cartfile.resolved'])
sh(*['git', 'commit', '-m', "Carthage update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def cocoapods
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
sh(*%w(pod install))
sh(*%w(pod update))
sh(*['git', 'add', 'Podfile.lock'])
sh(*['git', 'commit', '-m', "Cocoapods update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def ncu
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
sh(*%w(ncu -u))
sh(*['git', 'add', 'package.json']) if File.exist?('package.json')
sh(*['git', 'commit', '-m', "Ncu update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def yarn
Dir.chdir("#{Tachikoma.repos_path}/#{@build_for}") do
sh(*['git', 'config', 'user.name', @commiter_name])
sh(*['git', 'config', 'user.email', @commiter_email])
sh(*['git', 'checkout', '-b', "tachikoma/update-#{@readable_time}", @base_remote_branch])
sh(*%w(yarn install))
sh(*%w(yarn outdated))
sh(*%w(yarn upgrade))
sh(*['git', 'add', 'package.json'])
sh(*['git', 'add', 'yarn.lock'])
sh(*['git', 'commit', '-m', "Yarn update #{@readable_time}"]) do
# ignore exitstatus
end
sh(*['git', 'push', @authorized_compare_url, "tachikoma/update-#{@readable_time}"])
end
end
def pull_request
@client = Octokit::Client.new access_token: @github_token
@client.create_pull_request(
@pull_request_url,
@pull_request_base,
@pull_request_head,
@pull_request_title,
@pull_request_body
)
rescue Octokit::UnprocessableEntity
end
# build_for = fenix-knight, github_token_key = TOKEN_FENIX_KNIGHT
def github_token_key(build_for)
"TOKEN_#{build_for}".gsub(/-/, '_').upcase
end
def authorized_compare_url_with_type(fetch_url, type, github_token, github_account)
uri = URI.parse(fetch_url)
case type
when 'fork'
%(#{uri.scheme}://#{github_token}:x-oauth-basic@#{uri.host}#{path_for_fork(uri.path, github_account)})
when 'shared'
"#{uri.scheme}://#{github_token}:x-oauth-basic@#{uri.host}#{uri.path}"
else
fail InvalidType, "Invalid type #{type}"
end
end
def authorized_base_url_with_type(fetch_url, type, github_token, _github_account)
uri = URI.parse(fetch_url)
case type
when 'fork', 'shared'
"#{uri.scheme}://#{github_token}:x-oauth-basic@#{uri.host}#{uri.path}"
else
fail InvalidType, "Invalid type #{type}"
end
end
def path_for_fork(path, github_account)
path.sub(%r{^/[^/]+}) { '/' + github_account }
end
def target_repository_user(type, fetch_url, github_account)
case type
when 'fork'
github_account
when 'shared'
URI.parse(fetch_url).path.split('/', 3)[1]
else
fail InvalidType, "Invalid type: #{type}"
end
end
def repository_identity(url)
project_name, user_name, _ = url.split('/').reverse
project_name_identity = strip_extension(project_name)
user_name + '/' + project_name_identity
end
def strip_extension(name)
/\A(?<identity>.*?)(?:\.git)?\z/ =~ name
identity
end
# TODO: refactor to returning command args array like git clone depth option
def bundler_parallel_option(bundler_version, parallel_number)
return if !bundler_parallel_available?(bundler_version) || parallel_number <= 1
"--jobs=#{parallel_number}"
end
def bundler_parallel_available?(bundler_version)
# bundler 1.4.0 gets parallel number option
Gem::Version.create(bundler_version) >= Gem::Version.create('1.4.0')
end
def git_clone_depth_option(depth)
return [nil] unless depth
['--depth', depth.to_s]
end
end
end