Deno+daxでDotfilesのセットアップ用CLIツールを整備する
はじめに
Dotfilesのセットアップ用のスクリプトはシェルスクリプトで整備するのが一般的です。簡単な処理であれば問題ありませんが、シェルスクリプトは複雑な処理を記述するには癖が強く、保守が大変になるという課題が知られています。
そこで、シェルスクリプトではなくDenoとdaxでDotfilesのセットアップ用CLIツールを整備したところ、良い開発体験が得られたため、使用した技術を紹介します。
デモ
技術概要
Deno
DenoはJavaScript/TypeScriptランタイムの実装のひとつです。Denoには以下のような特徴があり、Node.jsの反省を生かして開発されています。
- ES Moduleのみをサポート
-
node_module/
,package.json
の代わりに、依存関係を直接コード内にURLで記述するかdeno.json
を使用する - パーミッションの明示的な指定を強制
- TypeScriptの直接実行をサポート
- トップレベルの
await
をサポート - フォーマッタ、リンタ、テストランナー、実行ファイルへのコンパイラをランタイムに同梱
詳細や使用例は他の記事をご参照ください。
Node.jsよりも後発のランタイムとしてはBunにもBun Shellというものがありますが、まだ発展途上の機能であることや、tsconfig.json
, package.json
などが散らからず、フォーマッタやリンタなどの設定を別で行う必要がないため、軽量のツールの開発については現状はDenoの方が優勢であると考え、こちらを採用しました。
dax
daxはDenoで動作するクロスプラットフォームのシェルツールです。Googleのzxから影響を受けており、インスピレーション元と同様にシェルスクリプトとTypeScriptを組み合わせたスクリプトの開発が行えます。詳細は以下のリポジトリのREADMEをご覧ください。
#!/usr/bin/env -S deno run --allow-all
import $ from "@david/dax"; // "dax-sh" in Node
// run a command
await $`echo 5`; // outputs: 5
// outputting to stdout and running a sub process
await $`echo 1 && deno run main.ts`;
// parallel
await Promise.all([
$`sleep 1 ; echo 1`,
$`sleep 2 ; echo 2`,
$`sleep 3 ; echo 3`,
]);
Inquirer.js
Inquirer.jsは対話型インターフェースを実装するためのライブラリです。daxにも対話型インターフェースは実装されていますが、こちらの方が高機能です。
import { $ } from "https://deno.land/x/dax@0.39.1/mod.ts"
import { input } from "npm:@inquirer/prompts@4.3.2"
await $.prompt({
message: "What's your name?",
default: "dax",
noClear: true,
});
await input({
message: "What's your name?",
default: "inquirer"
});
daxとInquirer.jsの入力の比較
実行可能ファイルの継続的デリバリー
ここでは、GitHub ActionsでDenoのスクリプトを実行可能ファイルにコンパイルし、GitHub Pagesでデプロイする方法を紹介します。他にはReleaseで実行ファイルを生成するなどの方法も良いと思います。
Denoではスクリプトの実行可能ファイルへのコンパイルを行えるため、生成した実行ファイルをデプロイすることで、Denoが存在しない環境においても実行ファイルをダウンロードすることでDenoのスクリプトを実行できるようになります。
これを行うには以下のようなワークフローを作成します。
name: CD
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
actions: read
jobs:
compile:
runs-on: ubuntu-22.04
steps:
- name: Checkout your repository using git
uses: actions/checkout@v4
- name: Setup Deno
uses: denoland/setup-deno@v1
- name: Compile install script
run: deno compile --allow-all --output dist/setup scripts/setup.ts
- name: Upload Pages Artifact
uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: compile
runs-on: ubuntu-22.04
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
リポジトリ名がdotfiles
のとき、実行可能ファイルはドメインを設定していなければhttps://username.github.io/dotfiles/setup
で公開されます。これにより、セットアップを行いたい環境で以下のようなコマンドを実行することで、Denoによるセットアップ用のスクリプトを実行できます。
wget https://username.github.io/dotfiles/setup
chmod u+x setup
./setup
おわりに
私の作成したセットアップ用のスクリプトは以下の通りです。
みなさんも是非Deno+daxでCLIツールを開発してみてください。
Discussion