サービス開発部Backlog課の松本です。最近さぬきの夢という小麦粉でうどんを打ちはじめた今日この頃です。先日、Apollo Routerのasdfのプラグインを作って、コマンドラインから追加できるようにしました。そこで、そのときの手順の説明を通してasdfプラグインの作り方を紹介します。
やったこと
- Apollo Routerのasdfプラグインasdf-apollo-routerを作った
- 公式のプラグインリポジトリに登録してもらった
対象の読者
- asdfを使っていてプラグインのつ作り方に興味がある人
前提知識
- asdfの使いかた
- シェルスクリプトがある程度読み書きできること
目次
asdfとは
nodenvやpyenvのように複数のバージョンの言語を管理するためのツールです (anyenvがこれに似たツールです)。また、言語だけではなくawscliやsbtなども管理することができます。
以下はnodeの最新版を入れて使えるようにする例です。詳細はasdfのマニュアルを参照してください。
$ asdf plugin add nodejs $ asdf install nodejs latest $ asdf global nodejs latest
asdfではこれらの言語やツールを管理する機能は個々のプラグインになっています。プラグインを作成するためのテンプレートがasdf開発チームによって用意されていて、ユーザーは雛形から簡単にプラグインを作ることができます。
asdfプラグインのテンプレートから作成する
asdfプラグインの雛形を作成するためにasdf-plugin-templateをクローンして./setup.bashを実行させます。指定すべきパラメータは./setup.bash –helpで参照することができます (引数なしだと対話モードになります)。
$ git clone https://github.com/asdf-vm/asdf-plugin-template apollo-router $ cd apollo-router $ ./setup.bash --help Usage: bash [--github | --gitlab] ./setup.bash PLUGIN_NAME TOOL_TEST GH_USER AUTHOR_NAME TOOL_GH TOOL_PAGE LICENSE All arguments are optional and will be interactively prompted when not given. PLUGIN_NAME. A name for your new plugin always starting with `asdf-` prefix. TOOL_TEST. A shell command used to test correct installation. Normallly this command is something taking `--version` or `--help`. GH_USER. Your GitHub/GitLab username. AUTHOR_NAME. Your name, used for licensing. TOOL_GH. The tool's GitHub homepage. Default installation process will try to use this to access GitHub releases. TOOL_PAGE. Documentation site for tool usage, mostly informative for users. LICENSE. A license keyword. https://help.github.com/en/github/creating-cloning-and-archiving-repositories/licensing-a-repository#searching-github-by-license-type
macOSでは、setup.bash内で使われているsedコマンドが上手く動作しない (標準で付属しているBSD sedだと引数なしの-iがエラーになる) などの理由で./setup.bashが上手く動きません。そこで、docker上のLinuxで実行させることにします。
$ docker run -it --rm -v$PWD:/work -w /work debian:11 /bin/bash bash-4.2$ apt update && apt install -y git curl # 必要なバイナリを入れる : bash-4.2$ git config --global user.email "you@example.com" # 実際のメールアドレスにする bash-4.2$ git config --global user.name "Your Name" # 実際のユーザー名にする
Linuxコンテナ上で./setup.bashを実行します。指定する引数は上のヘルプの通りです。TOOL_TESTにはバージョンをテストするために、バージョンを表示させるために必要なコマンドをパラメータ付きで指定します。
bash-4.2$ ./setup.bash apollo-router 'router --version' you 'Your Name' https://github.com/apollographql/router https://www.apollographql.com/docs/router/ mit Setting up plugin: asdf-apollo-router author: Your Name plugin repo: https://github.com/you/asdf-apollo-router license: https://choosealicense.com/licenses/mit/ apollo-router github: https://github.com/apollographql/router apollo-router docs: https://www.apollographql.com/docs/router/ apollo-router test: `router --version` After confirmation, the `main` will be replaced with the generated template using the above information. Please ensure all seems correct. Type `yes` if you want to continue.
プラグインのセットアップ内容が表示されますので、問題なければyesと入力します。
Type `yes` if you want to continue. > yes Switched to branch 'template' Preparing worktree (detached HEAD dafab40) : All done. Your main branch has been reset to an initial commit. Push to origin/main with `git push --force-with-lease` Review these TODO items: LICENSE:1:TODO: INSERT YOUR NAME COPYRIGHT YEAR LICENSE-2- LICENSE-3-MIT License LICENSE-4- -- :
スクリプトの実行が完了します。git logでコミットも確認しましょう。成功ならrebaseされて1コミットのみになっているはずです。
bash-4.2# git log commit 7e088d91a891d3f8e1b33a149353b42355465b15 (HEAD -> main) Author: Your Name <you@example.com> Date: Sat May 21 07:21:29 2022 +0000 Generate asdf-apollo-router plugin from template.
./setup.bashの実行の最後にも出ているTODOの一覧を再度確認します。これらを解決していくことになります。
$ rg TODO LICENSE 1:TODO: INSERT YOUR NAME COPYRIGHT YEAR lib/utils.bash 5:# TODO: Ensure this is the correct GitHub homepage where releases can be downloaded for apollo-router. 34: # TODO: Adapt this. By default we simply list the tag names from GitHub releases. 44: # TODO: Adapt the release URL convention for apollo-router 64: # TODO: Asert apollo-router executable exists. bin/download 13:# TODO: Adapt this to proper extension and adapt extracting strategy.
プラグインを修正する
テンプレートから作られたプラグインはまだ使える状態になっていないのでコードを修正していきます (プラグイン作成の詳細については公式のドキュメントCreate a Pluginを参照してください)。
まずはasdfコマンドから無理矢理使える状態にしてみましょう。次のようにリポジトリのルートディレクトリから~/.asdf/plugins/にシンボリックリンクを張ることで、お試しで使うことができます。
$ ln -s $PWD ~/.asdf/plugins/apollo-router
続いてasdf list-allでApollo Routerの取得可能なバージョン一覧を表示させてみましょう。雛形を作っただけの時点でもバージョン一覧を取ってくることができます (内部的には指定したリポジトリにgit ls-remote –tagsしているだけなので)。
$ asdf list-all apollo-router 0.1.0-alpha.0 0.1.0-preview.0 0.1.0-alpha.1 0.1.0-preview.1 0.1.0-alpha.2 0.1.0-preview.2 0.1.0-alpha.3 0.1.0-preview.3 0.1.0-alpha.4 0.1.0-prealpha.4 0.1.0-preview.4 0.1.0-alpha.5 0.1.0-prealpha.5 0.1.0-preview.5 0.1.0-alpha.6 0.1.0-preview.6 0.1.0-alpha.7 0.1.0-preview.7 0.1.0-alpha.8 0.1.0-alpha.9 0.1.0-alpha.10 0.9.0-rc.0 0.9.0 0.9.1 0.9.2
ただし、インストールしようとするとエラーになります。雛形の初期状態ではバイナリをダウンロードするのではなく、ソースコードのアーカイブをダウンロードするようになっているからです。
$ asdf install apollo-router 0.9.2 * Downloading apollo-router release 0.9.2... asdf-apollo-router: Expected /Users/matsumoto/.asdf/installs/apollo-router/0.9.2/bin/router to be executable. asdf-apollo-router: An error ocurred while installing apollo-router 0.9.2. zsh: exit 1
ここから、個々のプラグインの目的に応じてシェルスクリプトをがりがり書いていきます。 Apollo Routerのときは次のような変更をしました (変更を詳細はコミットの内容をご覧ください)。
- ダウンロード先を合わせる (ダウンロードセクションにあるバイナリを含んだ書庫ファイルを落としたいのでreleasesを指定しました)
- バイナリはプラットフォームごとに分かれているのでそれを判別する
- ダウンロードしたバイナリを適切な場所に置く
- コピーライト表記を変える
ローカルでテスト実行する
ひとまず完成したと思ったらローカルでテスト実行してみましょう。まずは、先ほど付けたシンボリックリンクを外しておきます。
$ rm ~/.asdf/plugins/apollo-router
そして、asdf plugin testを実行します。
$ asdf plugin test apollo-router https://github.com/safx/asdf-apollo-router router --version --asdf-plugin-gitref main Updating apollo-router... Already on 'main' Your branch is up to date with 'origin/main'. * Downloading apollo-router release 0.9.2... apollo-router 0.9.2 installation was successful! 0.9.2
後方互換性のためにテスト対象となるブランチはデフォルトではmasterになっています。最新のテンプレートから作られたリポジトリではmainブランチしかないので、–asdf-plugin-gitref mainを付ける必要があります。
テストの実行に成功すると、上記のようにinstallation was successful!と表示されます。
実際に利用してみる
ではGitHubにpushして、実際に利用してみましょう。asdf plugin addでプラグイン名の後にリポジトリURLを指定することで利用することができます。
$ asdf plugin add apollo-router https://github.com/safx/asdf-apollo-router $ asdf install apollo-router 0.9.2 * Downloading apollo-router release 0.9.2... apollo-router 0.9.2 installation was successful! $ asdf global apollo-router 0.9.2 $ asdf current apollo-router apollo-router 0.9.2 /Users/matsumoto/.tool-versions $ router --version 0.9.2
GitHub ActionsでCIテストが通るようにする
テンプレートによって作成された雛形内にGitHub Actionsが用意されているので、git pushすると自動でasdf GitHub Actionsが実行されます。shellcheckによるlintなどが行なわれますので、テストが通るようにしましょう。shellcheckはbrewにもありますのでローカルに入れておくと、確認の時間が短くなってよいでしょう。
asdf plugins repositoryに登録する
組織内で利用するだけならここまででもよいでしょう。ただ、asdfユーザー全員が簡単に利用できるようにするにはasdf plugins repositoryに追加してもらう必要があります。
asdf-pluginsにその手順が書かれているのでそれに従います。この記事が書かれている時点では次のような手順になっています (登録する際は最新のドキュメントを必ず参照してください)。
- asdf-vm/asdf-pluginsをフォークする
- repository = <your_repo>という内容でplugins/<plugin_name>というファイルをつくる
- README.mdのリストにプラグインを追加する (アルファベット順)
- PRをつくる。PRにチェックリストがあるのでそれに従う
- リポジトリ内で./test_plugin.sh –file plugins/<plugin_name>してエラーがないことを確認する
Apollo Routerのときは、上の手順でPRを作ったら翌日にマージされました。マージされたので、URLを指定しなくても使えるようになりました。
$ asdf plugin remove apollo-router $ asdf plugin update --all $ asdf plugin list all $ asdf plugin add apollo-router $ asdf install apollo-router 0.9.2 $ asdf global apollo-router 0.9.2 $ router --version 0.9.2
おわりに
Apollo Routerのasdfのプラグインを作ってプラグインリポジトリに追加されるまでの手順を紹介しました。
余談ですが、上記プラグインリポジトリのPRのレビュー時に、ドキュメントにデッドリンクがあるので消しておいてねと言われたので対応しましたが、これは元々テンプレートに紛れ混んでいるもののようだったので、それを消すPRを作ったらそちらも翌日にマージしてもらえました。ささやかながらプラグイン作り以外でもコミュニティに貢献できたのでよかったです。
皆さんも機会がありましたらぜひプラグインを作ってみてください。