🐳

PaperWaveのバックエンドをAzureに移行する続き

に公開

https://github.com/nae-lab/paperwave-cli/commit/d13b5855e3d63728d0c07bf31a86f33b572bdaa2

最後に環境変数の設定を追加して完了した.ここで欲が出てしまい,2時間ぐらいを費やしてしまった.このような,どこまでこだわるか,どこで切り上げるかという判断が研究ツール自作,ひいてはAIエージェントと協力した自作ツール開発では重要になるように感じる.60%ぐらいの(値はなんとなくだが)完成度まではAIによってすごく加速される感覚があるが,それ以降詰めるのは依然として時間がかかる.任せきりというより,自分で実装をがっつりチェックしながら修正を繰り返すフェーズに入るのだ.

この感覚については,2025年4月19日にもSlackにつぶやいていた

上記のコミットでは,Azureにデプロイする関連のスクリプトを作成している.もともと類似のスクリプトをGoogle Cloud用に書いていた.それを再現させるぐらいまではそれなりにすぐできるようになった.ただ,その先を今日はやってしまったのだ.具体的には,以下の2つ.

  • 環境変数を .env から読み出す.
  • Google と Azureでユーティリティを共通化

まず1つ目の変更は,もともとGoogleのスクリプトを書いたときにサボってた部分を修正したのだ.コンテナを作る処理では,環境変数として大量の認証情報を設定する.これをスクリプトにハードコードしていた.Gitには登録しないようにして最低限のセキュリティは保っていたが,当然行儀は良くない.修正したかった.Azureのコードもまずはハードコードして作ったが,書き換えたくなった.AIに頼めばすぐできると思った見積もりが甘かった.

まず,以下のように頼む.

User

@create-gce-with-container.sh と @create-azure-container.sh の両方で, .env から環境変数を読み出す.
.env はすでに存在します


Assistant

.envファイルから環境変数を読み出すようにスクリプトを修正します。まず、.envファイルの内容を確認してから、両方のスクリプトを修正します。


        Searched codebase ".env" • **0** results

No results found


        Listed current directory • **24** results
Name
📁 .git

その後,.env に含まれてるコメントや " の取り扱いなどに関してハマった.

User

fix


Assistant

このエラーは、.envファイルの読み込み方法に問題があります。コメント行やスペースを含む行が正しく処理されていないためです。


  # .envファイルから環境変数を読み込み
  if [ -f ".env" ]; then
-     export $(grep -v '^#' .env | xargs)
+     set -a  # 自動的にexportする
+     source <(grep -v '^#' .env | grep -v '^$' | grep '=' | sed 's/^/export /')
+     set +a  # 自動exportを無効化
  fi
  

...

...


User

一旦,変数を列挙してデバッグしたい


Assistant

デバッグのために、環境変数を列挙して確認できるようにスクリプトを修正しましょう。


...

...

User

何もない


Assistant

問題が分かりました!.envファイルから環境変数が全く読み込まれていません。

原因の診断

  1. 引数が渡されていない: EPISODES_COLLECTION_ID=episodes- の後が空
  2. 全ての環境変数が空: .envファイルの読み込みが失敗している

診断用のデバッグを追加しましょう


  #! /bin/bash
  
- # .envファイルから環境変数を読み込み
+ # 引数チェック
...

などなど.自分のプロンプトを振り返ったのは初めてだが,ずいぶんぶっきらぼうである.実際には,これにエラーログが添付されているのだが,それは記録されてないようだ.

最終的にはnodeのdotenvパッケージを使用して処理させたのだが,最初に書くコードには生成AIの自作癖があると感じている.Tinkeringの論文を読んでると透明であることが重要という議論が出てくるので[1],案外それもいいところでは,と頭では思ってしまうのだが,トラブル源になることは多いという感触だ.

やってる途中でエージェントに教えてもらったこと

User

この記法についてくわひく

${ENV_VARS[@]}


Assistant

${ENV_VARS[@]}Bash配列の展開記法 です。詳しく説明します。

基本的な意味

  • ENV_VARS = 配列名
  • [@] = 配列のすべての要素を展開
  • ${} = 変数展開の構文
  • "${ENV_VARS[@]}" = 配列の全要素を個別の引数として展開

具体例で理解

配列の定義

ENV_VARS=(
  "KEY1=value1"
  "KEY2=value2"
  "KEY3=value3"
)

展開の動作

# この書き方:
command --option "${ENV_VARS[@]}"

# は以下と同じ:
command --option "KEY1=value1" "KEY2=value2" "KEY3=value3"

類似記法との違い

1. ${ENV_VARS[@]} vs ${ENV_VARS[*]}

ENV_VARS=("apple pie" "banana cake" "cherry tart")

# [@] の場合(推奨)
echo "${ENV_VARS[@]}"
# 出力: apple pie banana cake cherry tart
# 各要素が個別の引数として扱われる

# [*] の場合
echo "${ENV_VARS[*]}"
# 出力: apple pie banana cake cherry tart
# 全要素が1つの文字列として結合される

2. ダブルクォートの重要性

# ダブルクォートあり(正しい)
for item in "${ENV_VARS[@]}"; do
    echo "$item"
done
# 出力:
# apple pie
# banana cake
# cherry tart

# ダブルクォートなし(問題あり)
for item in ${ENV_VARS[@]}; do
    echo "$item"
done
# 出力:
# apple
# pie
# banana
# cake
# cherry
# tart

実際の動作確認

# テスト用スクリプト
#!/bin/bash
ENV_VARS=(
  "EPISODES_COLLECTION_ID=episodes-dev"
  "OPENAI_API_KEY=sk-test-123"
  "LOG_DIR=logs"
)

# 展開結果を確認
echo "配列の要素数: ${#ENV_VARS[@]}"
echo "展開結果:"
printf "'%s'\n" "${ENV_VARS[@]}"

実行結果:

配列の要素数: 3
展開結果:
'EPISODES_COLLECTION_ID=episodes-dev'
'OPENAI_API_KEY=sk-test-123'
'LOG_DIR=logs'

Azure CLIでの実際の動作

# この記法:
az container create --environment-variables "${ENV_VARS[@]}"

# は以下に展開される:
az container create --environment-variables \
  "EPISODES_COLLECTION_ID=episodes-dev" \
  "OPENAI_API_KEY=sk-test-123" \
  "LOG_DIR=logs"

まとめ

  • [@] = 配列の全要素を個別の引数として展開
  • "${配列名[@]}" = 空白を含む要素も正しく処理
  • コマンドライン引数として複数の値を渡すのに最適
  • 配列の要素数が動的に変わっても対応可能

この記法により、環境変数の数が変わってもコマンド部分を変更する必要がなくなります!

このノートを書くプロセス

PaperGarage Diaryを発案したときに,AIとの会話履歴にアノテーションをつける,という日記の書き方を試したいと思っていた.今日は記録をかかずに一気に作業を進めてたので,この方法を採ることになった.詰めの作業をしてる終盤は逐一記録をかかずに試行錯誤に夢中になることが自分の場合多い気がする.

実際の作業画面はこれ.SpecStoryで記録してるchat履歴を見ながら日記を書いてる.全文は引用できないので一部を抜粋しながらノートを書いている.断片的なメモからフィールドノーツを清書するのとは逆の作業という感覚だ.

脚注を書いたときに,Obsidianのリンクはつけておいても,そんなに問題ないことに気づいた.文献情報には著者のリンクが自動でつくようにZoteroを設定してるのだが,Zennではwiki linkが処理されないので単に [[]] が出力されるだけだった.多少可読性は落ちるが,将来の自分と他のメンバーを主要な読者として想定する日記なので,このぐらいは不問とする.これによってObsidian内に記事を置いておくことのメリットが増えた.Obisidianの大きなvaultのノートネットワークの一部として両方向にリンクを貼ることができる.

リンクがプレーンテキストになってるだけの画像↓

脚注
  1. [[Turkle Sherry]]. 1998. 接続された心 : インターネット時代のアイデンティティ. 早川書房. ↩︎

PaperGararge Diary

Discussion