Octokit.rbとGitHub Appを使ってGitHub Releasesを作成する

2022-12-24

はじめに

この記事は、🎅GMO ペパボエンジニア Advent Calendar 2022の 24 日目の記事です。 前回は、ryuichi1208 による、1TB をネットワーク経由でコピーするのに 5 秒くらいで終わらせることは出来るのかでした。


以前ブログに書いたのですが、Octokit.rbという GitHub の Api をいい感じに触る事ができる Ruby ライブラリがあります。このライブラリは認証にユーザ ID やパスワード、OAuth Application を使う方法など、様々な認証方式に対応しています。これ以外にも GitHub App を使った認証にも対応しています。今回は GitHub App と Octokit.rb を使って GitHub Releases を作成するまでをやってみます。

検証に使ったコードは、こちらのリポジトリにあります。

GitHub App の作成とインストール

まずは、GitHub App を作成します。作成方法はGitHub 公式にあるのでざっくりでいきます。

Developer settingsより GitHub App を作成します。この時、作成したアプリのApp IDと、秘密鍵のダウンロードを忘れないようにして下さい。権限設定も忘れないようにして下さい。

作成したら、リポジトリにインストールします。

動かすコード

実際に GitHub Releases にデプロイしていきます。大まかな処理の流れは以下のとおりです。

  1. JWT を生成
  2. JWT をセットし GitHub App をインストールすると設定される installation_id を取得
    • GitHub App をインストールするとそのオーガナイゼーション(もしくはユーザ)に(おそらく)一意の ID が振り分けれます。この ID を installation_id と呼んでいて、これをもとにアクセストークンをリクエストする必要があります。
  3. 取得した installation_id をもとにアクセストークンをリクエスト
  4. アクセストークンをセットし、GitHub Releases を作成

まずは、必要なライブラリをGemfileに定義します。

Gemfile
source "https://rubygems.org"

gem "octokit"
gem "jwt"
gem "openssl"
ダウンロード
bundle install

実際にコードを書いていきます。GitHub App から JWT を生成するコードは公式のコードをそのまま持ってきています。秘密鍵のファイル名や、App ID は個人のものに書き換えてください。

github_app.rb
require 'jwt'
require 'octokit'

class GitHubApp

  def initialize(repository_name)
    @client = Octokit::Client.new
    @repository_name = repository_name
    create_jwt_token
  end

  # JWT TOKENを生成する
  def create_jwt_token
    # ダウンロードした秘密鍵
    private_pem = File.read("./XXX.pem")
    private_key = OpenSSL::PKey::RSA.new(private_pem)

    # Generate the JWT
    payload = {
      # issued at time, 60 seconds in the past to allow for clock drift
      iat: Time.now.to_i - 60,
      # JWT expiration time (10 minute maximum)
      exp: Time.now.to_i + (10 * 60),
      # 今回作成したGitHub AppのID
      # https://git.pepabo.com/organizations/colorme/settings/apps/colorme-token-app
      iss: "YYY"
    }

    jwt = JWT.encode(payload, private_key, "RS256")
    @client.bearer_token = jwt
  end

  private :create_jwt_token

  # installation_idを取得
  def get_installation_id_from_github_api
    installation_id = @client.find_repository_installation(@repository_name).id
    return installation_id
  end

  # アクセストークンを生成
  def create_access_token(installation_id)
    access_token = @client.create_app_installation_access_token(installation_id).token
    return access_token
  end

  # アクセストークンを生成
  def set_access_token(access_token)
    @client.bearer_token = access_token
  end

  # GitHub Releasesを作成
  def create_github_release(tag_name)
    @client.create_release(@repository_name, tag_name)
  end

end

作成したクラスを呼び出します。リポジトリ名やタグ名は適宜置き換えて下さい。

main.rb
require_relative 'github_app'

if __FILE__ == $0
    github_app = GitHubApp.new('Tatsumi0000/github-app-practice')
    installation_id = github_app.get_installation_id_from_github_api
    access_token = github_app.create_access_token(installation_id)
    github_app.set_access_token(access_token)
    github_app.create_github_release("v3.0.0")
end

実行します。

実行
bundle exec ruby main.rb

これで、実際に GitHub Releases に作成されると思います。今回は、Releases 時のリリースノートなどはパラメータに含めていませんが、実際には含めることもできます。

最後に

GitHub App と Octokit.rb を使い、GitHub Releases にデプロイするまでをやってみました。Ruby は fastlane を触る以外で全く触らないのでちょっと苦労しました。可視性の書き方とかこんなかんじだったな〜と新卒研修で受けた Rails Tutorial の記憶がほんのり蘇ってきました。

Octokit.rb を使いこなせると、GitHub 上の自動化などもかなり楽になると思うので使っていきたいなと思いました。また、セキュリティ面や、利便性でも GitHub App は便利なのでどんどん使っていきたいなと思います。

参考サイト

Tatsumi0000

Written by Tatsumi0000 モバイル開発が好きなエンジニアのブログです. GitHub

Copyright © 2023, Tatsumi0000 All Rights Reserved.