fastlaneでmilestoneを追加する

## 概要
fastlaneの勉強を兼ねて、milestoneを追加するActionとlaneを作った

## 成果物

**Action**

```ruby
module Fastlane
  module Actions
    module SharedValues
      # あとで作成したmilestoneのidを使いたかったので用意している
      CREATED_MILESTONE_ID = :CREATED_MILESTONE_ID
    end

    class CreateMilestoneAction < Action
      def self.run(params)
        require 'excon'
        require 'base64'

        UI.message("Creating new milestone of '#{params[:repo]}'")

        url = "#{params[:api_url]}/repos/#{params[:repo]}/milestones"
        headers = { 'User-Agent' => 'fastlane-create_milestone' }
        headers['Authorization'] = "Basic #{Base64.strict_encode64(params[:api_token])}" if params[:api_token]

        data = {
          'title' => params[:title],
        }

        [ :description, :due_on ].each do |n|
            data[n.to_s] = params[n] if params[n]
        end

        response = Excon.post(url, headers: headers, body: data.to_json)

        if response[:status] == 201
          body = JSON.parse(response.body)
          number = body['number']
          html_url = body['html_url']
          id = body['id']
          UI.success("Successfully created milestone ##{number}. You can see it at '#{html_url}'")

          # レスポンスから取得したidをSharedValuesにセットする
          Actions.lane_context[SharedValues::CREATED_MILESTONE_ID] = id
        elsif response[:status] != 200
          UI.error("GitHub responded with #{response[:status]}: #{response[:body]}")
        end
      end

      #####################################################
      # @!group Documentation
      #####################################################

      def self.description
        "This will create a new milestone on GitHub"
      end

      def self.available_options
        [
          FastlaneCore::ConfigItem.new(key: :api_token,
                                       env_name: "GITHUB_MILESTONE_API_TOKEN",
                                       description: "Personal API Token for GitHub - generate one at https://github.com/settings/tokens",
                                       sensitive: true,
                                       default_value: ENV["GITHUB_API_TOKEN"],
                                       is_string: true,
                                       optional: false),
          FastlaneCore::ConfigItem.new(key: :repo,
                                       env_name: "GITHUB_MILESTONE_REPO",
                                       description: "The name of the repository you want to submit the milestone to",
                                       is_string: true,
                                       optional: false),
          FastlaneCore::ConfigItem.new(key: :title,
                                       env_name: "GITHUB_MILESTONE_TITLE",
                                       description: "The title of the milestone",
                                       is_string: true,
                                       optional: false),
          FastlaneCore::ConfigItem.new(key: :description,
                                       env_name: "GITHUB_MILESTONE_DESCTIPTION",
                                       description: "The description of the milestone",
                                       is_string: true,
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :due_on,
                                       env_name: "GITHUB_MILESTONE_DUE_DATE",
                                       description: "The due date of the milestone",
                                       is_string: true,
                                       optional: true),
          FastlaneCore::ConfigItem.new(key: :api_url,
                                       env_name: "GITHUB_MILESTONE_API_URL",
                                       description: "The URL of Github API - used when the Enterprise (default to `https://api.github.com`)",
                                       is_string: true,
                                       default_value: 'https://api.github.com',
                                       optional: true),
        ]
      end

      def self.output
        # あとで作成したmilestoneのidを使いたかったので用意している
        [
          ['CREATED_MILESTONE_ID', 'The id of the created milestone id']
        ]
      end

      def self.authors
        ["macneko-ayu"]
      end

      def self.is_supported?(platform)
        return true
      end
    end
  end
end
```

**lane**

```ruby
desc "Create milestone. Please set option `ver:x.x.x`"
lane :add_milestone do |option|
  ver = option[:ver]

  create_milestone(
    # api_tokenはENVから取得する
    api_token: ENV["GITHUB_ACCESS_TOKEN"],
    repo: 'YOUR_NAME/YOUR_REPOSITORY_NAME',
    title: ver
  )

  # 作成したmilestoneのidをログに出力する
  milestone_id = Actions.lane_context[SharedValues::CREATED_MILESTONE_ID]
  UI.message("export milestone_id: '#{milestone_id}'")
end
```

## 実行結果のログ

```zsh
$ bundle exec fastlane add_milestone ver:1.0.3
[✔] 🚀
[11:21:37]: ------------------------------
[11:21:37]: --- Step: default_platform ---
[11:21:37]: ------------------------------
[11:21:37]: Driving the lane 'ios add_milestone' 🚀
[11:21:37]: ------------------------------
[11:21:37]: --- Step: create_milestone ---
[11:21:37]: ------------------------------
[11:21:37]: Creating new milestone of 'macneko-ayu/fastlane-practice'
[11:21:37]: Successfully created milestone #4. You can see it at 'https://github.com/macneko-ayu/fastlane-practice/milestone/4'
[11:21:37]: export milestone_id: '4997911'

+------+------------------+-------------+
|           fastlane summary            |
+------+------------------+-------------+
| Step | Action           | Time (in s) |
+------+------------------+-------------+
| 1    | default_platform | 0           |
| 2    | create_milestone | 0           |
+------+------------------+-------------+

[11:21:37]: fastlane.tools finished successfully 🎉
```