ryz310/rubocop_challenger

View on GitHub
lib/rubocop_challenger/pull_request.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

module RubocopChallenger
  # Creates a pull request
  class PullRequest
    # @param user_name [String]
    #   The author name which use at the git commit
    # @param user_email [String]
    #   The email address which use at the git commit
    # @param options [Hash]
    #   Optional parameters
    # @option base_branch [String]
    #   The Branch to merge into
    # @option labels [Array<String>]
    #   Will create a pull request with the labels
    # @option dry_run [Boolean]
    #   Does not create a pull request when given `true`
    # @option project_column_name [String]
    #   A project column name. You can add the created PR to the GitHub project
    # @option project_id [Integer]
    #   A target project ID. If does not supplied, this method will find a
    #   project which associated the repository. When the repository has
    #   multiple projects, you should supply this.
    # @option verbose [Boolean]
    #   Displays executing command.
    def initialize(user_name:, user_email:, **options) # rubocop:disable Metrics/MethodLength
      @pr_comet = PrComet.new(
        base: options[:base_branch],
        branch: "rubocop-challenge/#{timestamp}",
        user_name: user_name,
        user_email: user_email,
        verbose: options[:verbose]
      )
      @labels = options[:labels]
      @dry_run = options[:dry_run]
      @project_column_name = options[:project_column_name]
      @project_id = options[:project_id]
    end

    # Add and commit local files to the pull request
    #
    # @param message [String] The commit message
    # @yield Some commands where modify local files
    # @return [Object] Return result of yield if you use &block
    def commit!(message, &block)
      pr_comet.commit message, &block
    end

    # Creates a pull request for the Rubocop Challenge
    #
    # @param rule [Rubocop::Rule]
    #   The corrected rule
    # @param template_file_path [String, nil]
    #   The template file name which use to generate the pull request body
    # @return [Boolean]
    #   Return true if its successed
    def create_rubocop_challenge_pr!(rule, template_file_path = nil)
      create_pull_request!(
        title: "#{rule.title}-#{timestamp}",
        body: Github::PrTemplate.new(rule, template_file_path).generate
      )
    end

    # Creates a pull request which re-generate ".rubocop_todo.yml" with new
    # version RuboCop.
    #
    # @param before_version [String]
    #   The version of RuboCop which created ".rubocop_todo.yml" before
    #   re-generate.
    # @param after_version [String]
    #   The version of RuboCop which created ".rubocop_todo.yml" after
    #   re-generate
    # @return [Boolean]
    #   Return true if its successed
    def create_regenerate_todo_pr!(before_version, after_version)
      create_pull_request!(
        title: "Re-generate .rubocop_todo.yml with RuboCop v#{after_version}",
        body: generate_pull_request_body(before_version, after_version)
      )
    end

    private

    attr_reader :pr_comet, :labels, :dry_run, :project_column_name, :project_id

    # Create a PR with description of what modification were made.
    #
    # @params pr_comet_options [Hash]
    def create_pull_request!(pr_comet_options)
      options = {
        labels: labels,
        project_column_name: project_column_name,
        project_id: project_id
      }.merge(pr_comet_options)

      pr_comet.create!(**options) unless dry_run
    end

    # @param before_version [String]
    # @param after_version [String]
    def generate_pull_request_body(before_version, after_version)
      <<~MARKDOWN
        Re-generated the .rubocop_todo.yml because it was generated by old version RuboCop.

        * Using RuboCop version: [`#{before_version}...#{after_version}`](#{compare_page_url(before_version, after_version)})
        * [Release Note](#{release_page_url(after_version)})

        Auto generated by [rubocop_challenger](https://github.com/ryz310/rubocop_challenger)
      MARKDOWN
    end

    RUBOCOP_REPO_URL = 'https://github.com/rubocop-hq/rubocop'

    # Generates GitHub release note page URL
    #
    # @param after_version [String]
    def release_page_url(after_version)
      "#{RUBOCOP_REPO_URL}/releases/tag/v#{after_version}"
    end

    # Generates GitHub compare page URL
    #
    # @param before_version [String]
    # @param after_version [String]
    def compare_page_url(before_version, after_version)
      "#{RUBOCOP_REPO_URL}/compare/v#{before_version}...v#{after_version}"
    end

    def timestamp
      @timestamp ||= Time.now.strftime('%Y%m%d%H%M%S')
    end
  end
end