Skip to content

Instantly share code, notes, and snippets.

@ota42y
Created May 31, 2017 10:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ota42y/2b388f9627ef48690f90cd4fb9557a87 to your computer and use it in GitHub Desktop.
Save ota42y/2b388f9627ef48690f90cd4fb9557a87 to your computer and use it in GitHub Desktop.
# 環境変数GITHUB_TOKENの設定が必要
# todo_labelに設定したラベルが付いているIssueを調べ、
# auto_corrected_labelが付いていないものに対して`rubocop -auto_correct`を実行して結果をPull Requestにする
# 前提条件
# - Issueのタイトルがrubocopの設定名と完全に一致している
# - repo_local_pathフォルダにgit cloneしてある
# - repo_base_branchに設定したブランチが存在する
# - git pushができる
require "open3"
require 'date'
require 'octokit'
require 'yaml'
token = ENV['GITHUB_TOKEN']
client = Octokit::Client.new(:access_token => token)
setting = {
repo_name: 'username/reponame',
repo_local_path: '~/reponame',
repo_base_branch: 'origin/rubocop_fix/base',
branch_prefix: 'rubocop_fix',
todo_label: 'rubocop-todo',
auto_corrected_label: 'rubocop-auto-corrected',
assignee: ['me'],
reviewers: ['me'],
}
class Repository
attr_reader :repo_name
def initialize(setting)
@repo_name = setting[:repo_name]
@repo_local_path = setting[:repo_local_path]
@repo_base_branch = setting[:repo_base_branch]
@branch_prefix = setting[:branch_prefix]
end
def enable_rubocop_config(config_name)
log("enable #{config_name}")
log("cd #{@repo_local_path}")
Dir.chdir(@repo_local_path) do
exec_command("git checkout -f #{@repo_base_branch}")
log("load rubocop yaml")
yaml = YAML.load_file('.rubocop_todo.yml')
log("delete setting")
unless yaml.delete(config_name)
log("#{config_name} isn't exist")
return false
end
log("save rubocop yaml")
File.open('.rubocop_todo.yml', 'w') do |f|
YAML.dump(yaml, f)
end
ignore_exec('bundle exec rubocop -a --fail-level F')
end
log("enable #{config_name} end")
true
end
def push_github(branch_name)
log("push new branch #{branch_name}")
log("cd #{@repo_local_path}")
Dir.chdir(@repo_local_path) do
exec_command("git push origin #{branch_name}")
end
log("push new branch #{branch_name} end")
end
def commit(commit_message, branch_name)
log("commit new branch #{branch_name}")
log("cd #{@repo_local_path}")
Dir.chdir(@repo_local_path) do
exec_command("git checkout -B #{branch_name}")
exec_command("git add -A")
exec_command("git commit -m '#{commit_message}'")
end
log("commit new branch #{branch_name} end")
end
def delete_branch(branch_name)
log("delete local branch #{@repo_local_path}")
log("cd #{@repo_local_path}")
Dir.chdir(@repo_local_path) do
exec_command("git checkout -f #{@repo_base_branch}")
exec_command("git branch -D #{branch_name}")
end
end
def ignore_exec(cmd)
log(cmd)
Bundler.with_clean_env do
o, e, s = Open3.capture3(cmd)
log("---log---")
log(e)
log(o)
log("---log---")
end
end
def exec_command(cmd)
log(cmd)
Bundler.with_clean_env do
o, e, s = Open3.capture3(cmd)
unless s.success?
log("---error---")
log(e)
log(o)
log("---error---")
exit 1
end
end
end
def log(str)
# ファイルに出したければここを変える
puts str
end
end
class AutoRubocop
def initialize(client, repo, issue, setting)
@client = client
@repo = repo
@issue = issue
@repo_name = setting[:repo_name]
@rubocop_config_name = issue.title
@number = issue.number
@auto_corrected_label = setting[:auto_corrected_label]
@todo_label = setting[:todo_label]
@branch_prefix = setting[:branch_prefix]
@assignee = setting[:assignee]
@reviewers = setting[:reviewers]
end
def skip?
return true if @issue.pull_request # skip pull request
return true if @issue.labels.map(&:name).include?(@auto_corrected_label)
false
end
def pull_request_title
"rubocop fix #{@rubocop_config_name} issue ##{@number}"
end
def branch_name
"#{@branch_prefix}/rubocop_issue_#{@number}"
end
def pull_request_body
"rubocop auto fix for ##{@number}"
end
def auto_correct!
@repo.log("auto correct #{@number}, #{@rubocop_config_name}")
return false unless @repo.enable_rubocop_config(@rubocop_config_name)
@repo.commit(pull_request_title, branch_name)
@repo.push_github(branch_name)
create_pull_request
update_issue_label
@repo.delete_branch(branch_name)
true
end
def create_pull_request
@repo.log('create_pull_request')
resp = @client.create_pull_request(@repo_name, "master", branch_name, pull_request_title, pull_request_body)
@client.update_issue(@repo_name, resp.number, assignees: @assignee, labels: [@todo_label, @auto_corrected_label])
@client.pull_request_review_requests(@repo_name, resp.number, reviewers: @reviewers)
@repo.log('create_pull_request end')
end
def update_issue_label
@repo.log('update issue label')
@client.update_issue(@repo_name, @number,
labels: [@todo_label, @auto_corrected_label],
assignees: @assignee
)
@repo.log('update issue label end')
end
end
repo = Repository.new(setting)
page = 1
while true
issues = client.list_issues(setting[:repo_name], labels: setting[:todo_label], page: page)
break if issues.empty?
issues.each do |issue|
rubocop = AutoRubocop.new(client, repo, issue, setting)
next if rubocop.skip?
next unless rubocop.auto_correct!
puts Time.now
puts 'sleep 30 minutes'
sleep 60 * 30
end
sleep 1
page = page + 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment