くりにっき

フルスタックキュアエンジニアです

gitpanda v0.8.0をリリースした

リリースノート

https://github.com/sue445/gitpanda/blob/master/CHANGELOG.md#v080

v0.8.0について

社内GitLabのnginx周りの設定を変えた時にAWSからGitLabのAPIが叩けなくなってgitpandaが使えなくなったので、それをちゃんと検知できるようにするためにSentry対応しました

gitpandaについて

inside.pixiv.blog

地域.rbカレンダーのバックエンドをリプレイスした

見た目は変わらないですがバックエンドを変えてます

sue445.github.io

今までの運用

  1. カレンダーに追加したいconnpassやDoorkeeperのグループを condo3 でics取得
  2. 自分のGoogleカレンダーにインポート
  3. https://calendar.google.com/calendar/embedhelper?gsessionid=OK&hl=ja で埋め込み用のスニペットを生成して貼り付け

今までの運用の問題点

自分のGoogleカレンダーにインポートする関係上グループ追加時のみ自分がSPOFになってました。ただし、一度やってしまえばあとは全自動で最新のイベント情報が表示され続けるので問題ではなかったです。

しかしある時いつものように新しい地域.rbのグループを追加した辺りでカレンダーに表示されなくなりました。

公式情報がないので憶測なのですが、上記埋め込みツールで表示できるカレンダーが60個までという制約のため表示できなくなっていました。

たくさんカレンダーを追加しすぎた図

f:id:sue445:20200213011142p:plain

そのためグループの追加方法を変えました

解決方法

すごいシンプルですが、大量のカレンダーを埋め込むのがダメなので複数のグループを1つのicsにまとめることで解決しました。

具体的にはcondo3のAPIを叩いて巨大なicsを生成するウェブアプリをGoogleカレンダーにインポートしています

f:id:sue445:20200213012303p:plain

今はconnpassとDoorkeeperでicsを1つずつ作っているけど、量が増えすぎてタイムアウト起きるようになればさらに分割するかも。

技術的なこと

このウェブアプリ自体はGoogle App Engine/Rubyで作りました。

ソースコードは地域.rbカレンダーと同じリポジトリにあります。

github.com

appengineを採用した理由は今までHeroku + RubyがメインでGoogle App EngineRubyは使ったことがなくて慣れておきたかったためです。*1

新しい運用方法

https://github.com/sue445/regional-rb-calendar のREADMEに書いてますがリポジトリにある設定ファイルとindex.htmlを修正してPRを投げるだけで新しいグループが追加されるようになりました。

PRをアクセプトする部分が自分がSPOFなのは変わらないけど、自分しかできない作業が減ったのは地味に嬉しい。

*1:appengineのJavaとGoは経験済

RubyKaigi 2020のCFPに採択されました

昨年 に続き、今年も登壇させてもらえることになりました!

rubykaigi.org

今回は「Ruby on CI」というタイトルで、CIマニアがRuby製のgemやアプリのCIについて延々と話します。

【TODO】タイムテーブルが出たらここにリンクを貼る

CFPはここにありますがネタバレ情報満載なので現段階では限定公開にしておいて発表後に全公開します。

www.pixiv.net

circleci-ruby-orbs v1.5.0をリリースした

https://circleci.com/orbs/registry/orb/sue445/ruby-orbs

リリースノート

https://github.com/sue445/circleci-ruby-orbs/blob/master/CHANGELOG.md#v150

Ruby 2.7でbundler 2.1.2が入りましたが、bundler 2.1で bundle install --path などの引数がdeprecate*1されてcircleci-ruby-orbsの中でdeprecate warningが出ていたのを対応しています。

ついでに bundle_withoutbundle_with などの引数も追加しています。

1/28 21:00追記

リリースしたもののキャッシュがうまく効かない現象があったのでrevertしたのを1.5.2としてリリースしてますorz

go-mod-tidy-prを作った

GitHub Actions上でgo mod tidyしてPRを作るActionです

github.com

github.com

モチベーション

dependabotでgoのモジュールを定期的にアップデートしていると go.sum に古いバージョンのゴミが残り続けます。

github.com/aws/aws-lambda-go v1.11.1 h1:wuOnhS5aqzPOWns71FO35PtbtBKHr4MYsPVt5qXLSfI=
github.com/aws/aws-lambda-go v1.11.1/go.mod h1:Rr2SMTLeSMKgD45uep9V/NP8tnbCcySgu04cx0k/6cw=
github.com/aws/aws-lambda-go v1.12.0 h1:CgKAMdFIWExd4U6c9DUE+ax8N0fsmkYirqcfmReRCeo=
github.com/aws/aws-lambda-go v1.12.0/go.mod h1:050MeYvnG0NozqUw+ljHH9x0SwxeBnbxHVhcjn9nJFA=
github.com/aws/aws-lambda-go v1.12.1 h1:rMToYOcPFYDixQ7VNNPg78LmiqPgWD5f8zdLL+EsDAk=
github.com/aws/aws-lambda-go v1.12.1/go.mod h1:z4ywteZ5WwbIEzG0tXizIAUlUwkTNNknX4upd5Z5XJM=
github.com/aws/aws-lambda-go v1.13.0 h1:yjvZBGAxmrVQnakZ6/SE2S6L7Iwyx4CkJEcCQCc7WtU=
github.com/aws/aws-lambda-go v1.13.0/go.mod h1:z4ywteZ5WwbIEzG0tXizIAUlUwkTNNknX4upd5Z5XJM=
github.com/aws/aws-lambda-go v1.13.1 h1:qVIOD3UrEUo4amwgEBu6AI0CfnBsp71XJEYU05RbQ1k=
github.com/aws/aws-lambda-go v1.13.1/go.mod h1:z4ywteZ5WwbIEzG0tXizIAUlUwkTNNknX4upd5Z5XJM=
github.com/aws/aws-lambda-go v1.13.2 h1:8lYuRVn6rESoUNZXdbCmtGB4bBk4vcVYojiHjE4mMrM=
github.com/aws/aws-lambda-go v1.13.2/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-lambda-go v1.13.3 h1:SuCy7H3NLyp+1Mrfp+m80jcbi9KYWAs9/BXwppwRDzY=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=

go mod tidy すればゴミは消えるのですが、ローカルで定期的に叩くのも面倒です。

本来ならこの手の機能はdependabotで欲しくて実際に要望は上がってるんですが、dependabot側の対応は割と大変そうな感じがしました。

github.com

そのためGitHub Actionsの勉強がてら自分で作りました。

使い方

下記のようなymlをリポジトリに置くだけです。

パラメータの詳しい説明はMarketplaceかリポジトリを見てください。

# .github/workflows/go-mod-tidy-pr.yml
name: go-mod-tidy-pr

on:
  schedule:
    - cron: "0 0 * * 1" # Weekly build

jobs:
  go-mod-tidy-pr:
    name: go-mod-tidy-pr

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Run go-mod-tidy-pr
        uses: sue445/go-mod-tidy-pr@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          git_user_name: GitHub Actions
          git_user_email: github-actions@example.cpm
          # reviewer: foo
          # assign: foo
          # milestone: some_milestone
          # labels: go-mod-tidy
          # draft: "true"
          # go_mod_directory: "/dir/to/go-mod"
          # debug: "true"
          # duplicate: "true"

技術的なこと

なぜGitHub Actionsを使ったか?

API経由でPullRequestを作るにはトークンが必要なのですが、GitHub Actionsであればパーソナルアクセストークンの発行が不要なので色々便利だからです。

これはCircleCIとかにはないメリットなので、CI上でGitHubAPIを使いたい場合にはGitHub Actions一択だと思います。

余談ですがGitHubのパーソナルアクセストークンはリポジトリ単位の権限の設定がないため発行しないにこしたことはないです。(自分のパーソナルアクセストークンが漏れると自分がアクセス可能なリポジトリが全て第三者からもアクセス可能になるので大惨事)

aptで入るhubが古くてGitHub Actionsで動かなくてハマった

GitHub Actionsで hub pull-request すると下記のようなエラーが出てしばらくハマってました。

> GET https://api.github.com/user
> Authorization: token [REDACTED]
> Accept: application/vnd.github.v3+json;charset=utf-8
< HTTP 403
{"message":"Resource not accessible by integration","documentation_url":"https://developer.github.com/v3/users/#get-the-authenticated-user"}
Error getting current user: Forbidden (HTTP 403)
Resource not accessible by integration

https://github.com/github/hub/releases/tag/v2.12.3 でこの現象の修正が入っているのですが、aptで入るhubが2.7.0なのでaptを使わずにhubを入れる必要があったのがちょっとしたハマりでした

$ apt-cache show hub | grep Version
Version: 2.7.0~ds1-1+b10

使った図

チリツモのゴミが消えてスッキリしました

https://github.com/sue445/gitpanda/pull/186/files

GitHub ActionsでTravis CIのallow_failures的なやつをやりたい

いわゆるジョブが失敗しても成功扱いしたい的なやつ

tl;dr;

jobs:
  test:
    runs-on: ubuntu-latest

    container: ${{ matrix.ruby }}

    strategy:
      fail-fast: false

      matrix:
        ruby:
          - ruby:2.2
          - ruby:2.3
          - ruby:2.4
          - ruby:2.5
          - ruby:2.6
          - ruby:2.7
          - rubylang/ruby:master-nightly-bionic
        include:
          - ruby: rubylang/ruby:master-nightly-bionic
            allow_failures: "true"

    steps:
      - uses: actions/checkout@v2

      - name: Cache vendor/bundle
        uses: actions/cache@v1
        id: cache_gem
        with:
          path: vendor/bundle
          key: v1-gem-${{ runner.os }}-${{ matrix.ruby }}-${{ github.sha }}
          restore-keys: |
            v1-gem-${{ runner.os }}-${{ matrix.ruby }}-
        continue-on-error: ${{ matrix.allow_failures == 'true' }}

https://github.com/sue445/rubicure/blob/c32525010361837a1afe05e1d1217a0f9e4321e0/.github/workflows/test.yml#L12-L45

解説

  • include で任意のmatrixに変数を突っ込むことができる
    • 上の例だと ruby:ubylang/ruby:master-nightly-bionic の時だけ matrix.allow_failures"true" で設定される *1
    • ちゃんと調べていないけど include で明示的に変数セットされてない場合はエラーにならない(空文字で評価されてる?)
  • continue-on-error: true にしてると中で失敗(赤色)しても成功扱い(緑色)にしてくれる
  • fail-fast: false はなくてもいいです
    • 僕はデフォルトの fail-fast: true (どれか1つでもジョブが失敗したら他のジョブを全部キャンセルする)が嫌いなので無効にしてます

*1:trueはyaml特殊文字なのでダブルクォーテーションで囲まないと多分ダメ

plant_erd v0.2.0をリリースした

sue445.hatenablog.com

github.com

リリースノート

https://github.com/sue445/plant_erd/blob/master/CHANGELOG.md#v020

v0.2.0のトピックスはOracle対応です。ブコメとかでちょいちょいOracle対応してほしいっていうのは観測してたんですが、なんやかんやで作り切るのに1ヶ月くらいかかってました

ただし実行に Oracle Instant Client のsoファイルやDLLファイルが必要になる関係で、Oracle専用の実行ファイル( plant_erd-oracle)を用意しています

苦労点

https://github.com/sue445/plant_erd/pull/50 からかいつまんで説明。

実はOracle対応だけなら3日くらいで実装できたのですが、実装以外の部分で大半の時間を使いました。

ロスコンパイルができない

Oracle Instant Clientを含んだ実行ファイルのビルドにはOracle Instant Clientが必要になります。

しかし https://www.oracle.com/database/technologies/instant-client/downloads.html を見てもらえれば分かるようにOracle Instant Clientは対応OSが限定されているため、さすがのGoでもUbuntu上でWindowsMacの実行ファイルはビルドできませんでした。*1

幸いにもGitHub ActionsではUbuntu, Windows, MacのRunnerが提供されていたため、それぞれのOS上でビルドすることができて非常に助かりました。

初めてのWindows上でのCI

UbuntuMacであればビルドスクリプトbashでいいのですが、Windows上でのCIは今回初めてだったので試行錯誤しました。

https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idstepsrun にあるようにWindowsだとPowerShell, cmd, Git Bashが使えます。

最初Git Bashでビルドスクリプトを書いてたもののWindows固有の問題にぶつかってうまく動かずにPowerShellで書き直しつつ、PowerShellでもうまくいかなくて結局Git Bashでビルドスクリプトで書きました。

ここのWindowsビルドだけで1〜2週間くらいかかったと思います。

途中で実行ファイルを分けた

Oracle対応ができていざ動作確認をしようとしたところ、plant_erd mysqlplant_erd postgresql のようにOracleと関係ない機能を使うだけでもInstant Clientが必要なことが判明したので苦肉の策でOracleだけ実行ファイルを分けました。

ライセンスをどうするか

Oracle Instant Clientは OTNライセンス です。

Oracle Instant Clientは再配布可能 *2 なので実行ファイルに含めて配布することは問題ありません。

しかしその場合リポジトリ上でのライセンスの表記を

  1. MITライセンスのままでいい
  2. MITライセンスをやめてOTNライセンスにする
  3. MITライセンスとOTNライセンスのデュアルライセンスにする

のどれにすればいいかで悩みました。

OTNのサポートに問い合わせたところ、MITライセンスとInstant Clientに付随するOTNライセンスは別に扱ってほしいとの回答をもらったのでREADMEにも「The program is available as open source under the terms of the MIT License. But plant_erd-oracle contains Oracle Instant Client. Oracle Instant Client is under OTN License.」(本ソフトウェアにはMITライセンスが適用されるが、実行ファイルに内包されているInstant ClientにはOTNライセンスが適用される)のような書き方になりました。

*1:余談ですがここに気づくまでに数日かかりました

*2:https://www.oracle.com/technetwork/jp/database/features/ic-faq-094177-ja.html#A4379