Build and release keymap on CircleCI

Build and release keymap on CircleCI

ここ数日、組み立てた Planck キーボードのキーマップをあれこれいじっています。

キーマップはファームウェアの一部として C 言語で書かれているのでコンパイルする必要があります。

私はファームウェアのリポジトリを自分用にクローンして、そのリポジトリに対して PR を出して変更を加え、コンパイル・適用する運用をしています。

あれこれ試しながら楽しく作業しているので、一連の作業を手動で行うことは今のところさほど苦痛では無いのですが、私は PCB のリビジョンが違う2台の Planck (家用、職場用)を使っているし、気に入ったキーマップにはバージョンをつけてちゃんと管理したいです。あとリリースページからコンパイル済みのファイルをダウンロードできたら色々便利そう。

そこで、 CircleCI と連携させて自動的にビルド・リリースすることを思いついたのでやってみました。

実現したかったことは以下。

  • PCB のバージョンにそれぞれ対応させて2台分ビルドしたい
  • GitHub にリリースするところまでやりたい
  • タグをつけた場合のみ、リリース対象としたい
    • ブランチやキーマップ以外の変更でリリースを汚したく無い

結果としてうまくいったので config.yml を晒します。

例えば以下のようにタグ付けをしてプッシュすると、

$ git tag 1.0.0
$ git push origin 1.0.0

以下のリリースが作成されます。

  • rev4_v1.0.0
  • rev5_v1.0.0

実際のリリースは以下です。

Releases · lorentzca/qmk_firmware · GitHub

仕組み

ビルドには qmk_firmware 公式の Docker image (edasque/qmk_firmware) を使う。

defaults: &defaults
  working_directory: ~/qmk

version: 2
jobs:
  build:
    <<: *defaults
    docker:
      - image: edasque/qmk_firmware
    steps:
      - checkout
      - run:
          name: "Workaround `x509: failed to load system roots and no roots provided`"
          command: |
            echo "deb http://security.debian.org/debian-security jessie/updates main" >> /etc/apt/sources.list
            apt-get update
            apt-get install -y ca-certificates
      - run:
          name: Build keymap
          command: |
            make clean ; make keyboard=planck/rev4 keymap=lorentzca
            make keyboard=planck/rev5 keymap=lorentzca
      - persist_to_workspace:
          root: ~/qmk
          paths:
            - .build/planck_rev4_lorentzca.hex
            - .build/planck_rev5_lorentzca.hex

ビルドした成果物は CircleCI の attach_workspace 機能を使って下流のジョブへ共有する。

リリースは circleci/golang:1.8 イメージに ghr をインストールしてそれを使う。

  • タグは CIRCLE_TAG 環境変数で取得できる。便利!
  • GITHUB_TOKEN はあらかじめ GitHub でトークンを取得した上で CircleCI に設定しておく
  publish-github-release:
    <<: *defaults
    docker:
      - image: circleci/golang:1.8
    steps:
      - attach_workspace:
          at: ~/qmk
      - run:
          name: Publish Release on GitHub
          command: |
            go get github.com/tcnksm/ghr
            ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete rev4_v${CIRCLE_TAG} ~/qmk/.build/planck_rev4_lorentzca.hex
            ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete rev5_v${CIRCLE_TAG} ~/qmk/.build/planck_rev5_lorentzca.hex

ワークフローで工程を管理する。

  • ビルドの後にリリースが走るように依存関係を設定する
  • タグがついている場合のみリリースする
  • タグの文字列も正規表現で限定している
workflows:
  version: 2
  main:
    jobs:
      - build:
          filters:
            tags:
              # 1.0.0
              only: /^\d+\.\d+\.\d+$/
      - publish-github-release:
          requires:
            - build
          filters:
            branches:
              ignore: /.*/
            tags:
              # 1.0.0
              only: /^\d+\.\d+\.\d+$/

まとめ

汎用性は割と無視しているけど、少しいじれば他のキーボードでもいけそう。また別の自作キーボードを買ったらなんとかしよう…。

割と雰囲気半分でやったのでもっとスマートなやり方はあるかも。

とにかく、便利になったのでよかった。 CircleCI は便利だなあ。🍻

参考リンク