denoプロジェクトの依存は積極的に更新していきたい
悩み
一般的なVimmerはDenoを使った開発プロジェクトが増えがちです。
なぜならdenops.vimを使ったプラグイン開発はVimmerの義務です。
Vimmer、あなたはdenops.vimプラグイン開発者ですか?ZAP ZAP ZAP
やがて増えゆくプロジェクト、増え続ける依存。
見たくないから見ない。気がついても更新しない。Dependabotに言われてもマージしない。そして破局を迎える。
udd便利
denoの依存を、一括で更新するuddというツールが便利です。
$ udd ./**/*.ts
とでもしてやれば、配下の.ts
ファイルの依存を更新してくれます。
しかし、プロジェクトが増えてくるとこれを1つ1つのプロジェクトに実行するのも骨が折れる物です。
スクリプトしよう
困ったら、スクリプトでも書けば良いんです。
私の例(zsh
)を貼っておきますが、あくまでも私の例です。次節で少し流れと、肝心な部分を説明します。
function _update_deno_dependencies() {
pushd "$1"
_update_deno_dependencies_core "$1"
ret=$?
popd
return $ret
}
function _update_deno_dependencies_core() {
local dir="$1"
echo "\e[1m\e[31mUpdating $dir...\e[0m"
if [ -n "$(git status --porcelain)" ]; then
echo "\e[31mThere're changes in $dir\e[0m"
return
fi
echo "Pulling $dir..."
git pull
if [ -n "$(git status --porcelain)" ]; then
echo "\e[31mThere're changes in $dir\e[0m"
return
fi
echo "No dirty changes in $dir"
if ! NO_COLOR=1 udd ./**/*.ts; then
echo "\e[31mFailed to update dependencies in $dir\e[0m"
return
fi
if [ -z "$(git status --porcelain)" ]; then
echo "There's no update in $dir"
return
fi
if ! NO_COLOR=1 deno cache ./**/*.ts; then
echo "\e[31mFailed to cache in $dir\e[0m"
return
fi
if ! NO_COLOR=1 deno task check; then
echo "\e[31mThere're problems in $dir\e[0m"
return
fi
if ! NO_COLOR=1 deno task lint; then
echo "\e[31mThere're lints in $dir\e[0m"
return
fi
if [[ -n ./**/*_test.ts(#qN) ]]; then
if ! NO_COLOR=1 deno task test; then
echo "\e[31mFailed to test $dir\e[0m"
return
fi
fi
git --no-pager diff .
read "YN?Process? (y/n/q):"
case "${YN}" in
y|Y)
echo "do"
;;
n|N)
echo "skip"
git restore .
return
;;
q|Q)
echo "quit"
git restore .
return 1
esac
if ! git add .; then
echo "\e[31mFailed to stage changes in $dir\e[0m"
return
fi
if ! git commit -m "Update dependencies"; then
echo "\e[31mFailed to commit changes in $dir\e[0m"
return
fi
if ! git push; then
echo "\e[31mFailed to push changes in $dir\e[0m"
return
fi
}
function update_deno_dependencies() {
# projectのあるディレクトリに移動する
pushd ~/Projects/github.com/kyoh86
# 各ddu-*のディレクトリの中で、dirtyでなければgit pullを実行する。
# pullした時点でもdirtyでなければ、deno dependenciesの更新を実行する。
if _update_deno_dependencies denops-util; then
for dir in {ddu,denops}-*; do
if [ -d "$dir" ]; then
if ! _update_deno_dependencies "$dir"; then
# quit
break
fi
fi
done
fi
git-statuses
popd
}
流れ
このスクリプトでは、私のローカルにおかれたすべてのdeno製プロジェクト(名前がddu-
またはdenops-
で始まる)を順に巡って、次のような処理を行っています。
- git dirtyでないことをチェック、dirtyだったらこのプロジェクトは処理しない
-
udd ./**/*.ts
で依存関係を根こそぎ更新 - git dirtyであることをチェック、更新がなければこのプロジェクトは処理しない
- deno cacheを取得
- deno check, lint, testを実行、問題ないことを確認
- diffを表示してユーザーに
(yes/no/quit)
で問う - git add, commit, pushを実行
要は「ローカルのプロジェクトの依存関係を更新して、更新されたならテストして、テストが通ればプッシュ」ということですね。
肝としては、deno check, lint, testはdeno.jsonc
にtask化しており、必要なチェックをパターン化してある点です。
- checkの前にgenerateを必要とする場合がある
- linterとしてdeno lint以外の何かを回すことがある
- プロジェクトによってはtestには
--allow-*
などを指定する必要がある
もちろん、deno task以外の方法でもいくらでも回避できますが、画一的な処理のためには必要でしょう。
改善点
現状「自分のローカルにあるプロジェクトを横断する」という形を取っていますが、
自分のローカルにあるプロジェクトの状態なんぞ常に安全とは限りませんし、ローカルに常にfetchしておくのも億劫です。
本来ならGitHubのリポジトリにlang=typescriptでクエリをかけて、cloneして以下同文…とでもするべきでしょう。
まあ、雑にやればこんなこともできるよ、という一例として紹介させていただいたので、自分のスタイルに合った何かを作ってみると良いかもしれません。
Discussion