diff --git a/tasks/diff_task.rb b/tasks/diff_task.rb index d3f42b9..721eb6f 100644 --- a/tasks/diff_task.rb +++ b/tasks/diff_task.rb @@ -1,8 +1,9 @@ require "pathname" require "tempfile" -require_relative "translated_file" require_relative "source_file" +require_relative "translated_file" +require_relative "translation_pr" class DiffTask include Rake::DSL @@ -23,7 +24,14 @@ def define translated_file = source_file.find_translated_file(translated_files) next unless translated_file - diff_content = diff(source_file, translated_file) + source_latest_commit, diff_content = diff(source_file, translated_file) + next unless diff_content + + translation_pr = TranslationPr.new(translation_repository_path, + translated_file, + diff_content, + source_latest_commit) + translation_pr.create_or_update end end end @@ -34,6 +42,7 @@ def define def diff(source_file, translated_file) translated_commit = translated_file.front_matter[:commit] return unless translated_commit + return if translated_commit == source_latest_commit Tempfile.open("diff.txt") do |tempfile| sh("git", @@ -43,7 +52,7 @@ def diff(source_file, translated_file) "#{translated_commit}..#{source_latest_commit}", source_file.path.to_s, {out: tempfile}) - tempfile.open.read + [source_latest_commit, tempfile.open.read] end end diff --git a/tasks/translated_file.rb b/tasks/translated_file.rb index 240d0cf..bffbf41 100644 --- a/tasks/translated_file.rb +++ b/tasks/translated_file.rb @@ -2,11 +2,25 @@ require "yaml" class TranslatedFile - attr_reader :path, :front_matter + attr_reader :path, :project, :category, :topic def initialize(path) @path = Pathname.new(path) @front_matter = parse_front_matter + @project, @category, @topic = parse_metadata + end + + def content + path.read + end + + def front_matter + parse_front_matter + end + + def update_commit_hash(new_commit) + updated_content = content.sub(/(commit:\s*")[^"]+(")/, "\\1#{new_commit}\\2") + path.write(updated_content) end private @@ -14,7 +28,6 @@ def initialize(path) FRONT_MATTER_REGEXP = /\A---\s*\n(.*?)\n---\s*\n/m def parse_front_matter - content = path.read front_matter_section = content.match(FRONT_MATTER_REGEXP)[0] if front_matter_section YAML.safe_load(front_matter_section, symbolize_names: true) @@ -22,4 +35,10 @@ def parse_front_matter {} end end + + def parse_metadata + project, category, filename = path.to_s.split("/").last(3) + topic = filename.sub(".md", "") + [project, category, topic] + end end diff --git a/tasks/translation_pr.rb b/tasks/translation_pr.rb new file mode 100644 index 0000000..7d5f159 --- /dev/null +++ b/tasks/translation_pr.rb @@ -0,0 +1,146 @@ +require "json" +require "rake" + +class TranslationPr + include Rake::FileUtilsExt + + def initialize(repository_path, translated_file, diff_content, source_latest_commit) + @repository_path = repository_path + @translated_file = translated_file + @diff_content = diff_content + @source_latest_commit = source_latest_commit + end + + def create_or_update + current_title, current_description = find_existed_pr + Dir.chdir(repository_path) do + if current_title && current_description + update_pr(branch, + update_description(current_description, diff_content), + source_latest_commit) + else + create_pr(branch, + title, + generate_description(diff_content), + source_latest_commit) + end + end + end + + private + + attr_reader :translated_file, :repository_path, :diff_content, :source_latest_commit + + DIFF_START = "## Diff (Please don't change this section. It will be automatically updated.)" + DIFF_END = "" + + def repo + "#{onwer}/#{repository}" + end + + def owner + ENV["TRANSLATED_OWNER"] || "everyleaf" + end + + def repository + ENV["TRANSLATED_REPOSIOTRY"] || "hotwire_ja" + end + + def branch + "update-translation-" + + "#{translated_file.project}-" + + "#{translated_file.category}-" + + "#{translated_file.topic}" + end + + def title + "#{translated_file.project} " + + "#{translated_file.category} " + + "#{translated_file.topic}: " + + "updated translation" + end + + def generate_description(diff) +<<-DESCRIPTION +#{DIFF_START} + +~~~diff +#{diff} +~~~ + +#{DIFF_END} + +DESCRIPTION + end + + def update_description(description, diff) + lines = description.lines + diff_start = lines.index { |line| line.strip == DIFF_START } + diff_end = lines.index { |line| line.strip == DIFF_END } + + if diff_start && diff_end && diff_start < diff_end + before_diffs = lines[0...diff_start].join + after_diffs = lines[(diff_end).next..-1].join + + before_diffs + generate_description(diff) + after_diffs + else + generate_description(diff) + end + end + + def find_existed_pr + pr_raw_info = Tempfile.open("pr.json") do |pr| + sh("gh", + "pr", + "view", + branch, + "--json", "closed,title,body", + "--repo", repo, + {out: pr} + ) + pr.open.read + end + if pr_raw_info.empty? + [nil, nil] + else + pr_info = JSON.parse(pr_raw_info, symbolize_names: true) + return [nil, nil] if pr_info[:closed] + [pr_info[:title], pr_info[:body]] + end + end + + def commit_latest_hash(source_latest_commit) + translated_file.update_commit_hash(source_latest_commit) + sh("git", "add", translated_file.path.to_s) + sh("git", + "commit", + "-m", + "updated translation target commit") + end + + def update_pr(branch, description, source_latest_commit) + sh("git", "fetch") + sh("git", "switch", "-c", branch, "origin/#{branch}") + commit_latest_hash(source_latest_commit) + sh("git", "push", "origin", branch) + sh("gh", + "pr", + "edit", + "--body", description, + "--repo", repo) + end + + def create_pr(branch, title, description, source_latest_commit) + sh("git", "switch", "-c", branch) + commit_latest_hash(source_latest_commit) + sh("git", "push", "origin", branch) + sh("gh", + "pr", + "create", + "--title", title, + "--body", description, + "--base", "auto-translations-update", + "--head", branch, + "--repo", repo) + end +end