Skip to content

env-init を flake パッケージとして追加し devbox 開発環境を整備#1

Merged
mackato merged 7 commits into
mainfrom
feat/env-init
Jun 3, 2026
Merged

env-init を flake パッケージとして追加し devbox 開発環境を整備#1
mackato merged 7 commits into
mainfrom
feat/env-init

Conversation

@mackato
Copy link
Copy Markdown
Member

@mackato mackato commented Jun 3, 2026

ユーザー指示の要点

汎用 dev ツールの第一弾として env-init を追加する。devbox で Nix のテスト/リンターを含む開発環境をセットアップしたうえで、移植元から env-init を移植する。

変更の概要

  • pkgs/env-init/env-init: 移植元を verbatim コピー(無改変)。
  • pkgs/env-init/package.nix: makeWrapper で生スクリプトに PATH のみ被せて wrap(中身は無改変)。
  • flake.nix: packages / checks(shellcheck・bats・statix・deadnix・nixfmt)/ formatter(nixfmt-tree)。default は設けず利用側は #<tool> を明示。
  • devbox.json: dev ツール一式 + path:.#env-init の dogfood + init_hook + check/build/fmt scripts。
  • .env.template(ルート): N 算術・変数展開・乱数生成を含む書式の参照例。本 repo の dogfood でも使用。
  • pkgs/env-init/tests/env-init.bats: フルセット(引数/help/冪等性/算術・変数展開/権限600/worktree の N 最小未使用割当・再利用)。
  • CI: check.yml(push/PR で nix flake check)、release.ymlv* タグ駆動で GitHub Release 自動生成)。Action は SHA ピン、最小権限。
  • README/CLAUDE.md: 構成・開発手順・バージョニング(リポジトリ単位の SemVer、安定版は GitHub Releases 参照)を追記。

レビューのポイント

  • makeWrapper 採用: writeShellApplication だとプリアンブルで --help が読む先頭ヘッダコメントが押し下げられ usage が空になる回帰が出たため。$0 が生スクリプトを指すよう makeWrapper にし、shellcheck は flake check に明示追加。
  • bashOptions = [ errexit nounset ]: 元の set -eu に忠実化し、pipefail 由来の挙動変化を回避。
  • devbox に nix を入れない: nix@latest が古い nix を導入し現行 nixpkgs を評価できなかったため、ホストの nix を使用。
  • バージョニング: リポジトリ単位の単一 SemVer + タグ駆動 Release。

検証方法

  • devbox run check(= nix flake check)が all checks passed(bats 8件・shellcheck・statix・deadnix・nixfmt・build)。
  • ルートで dogfood 実行し .env 生成を確認(WORKTREE_N=0 / PORT_APP=3000 / APP_URLDATABASE_URL の変数展開 / 乱数 secret / 権限 600 / .env は ignore)。
  • CI(check.yml)で x86_64-linux 含めて再現。

🤖 Generated with Claude Code

mackato and others added 2 commits June 3, 2026 13:35
汎用 dev ツールの第一弾として env-init を Nix flake で配布する形に移植し、
devbox で Nix の test/lint を含む開発環境を整備した。

- pkgs/env-init: 生スクリプトを verbatim 移植し makeWrapper で PATH のみ wrap
- flake.nix: packages / checks (shellcheck・bats・statix・deadnix・nixfmt) / formatter
- devbox.json: dev ツール + path:.#env-init の dogfood + init_hook + scripts
- ルート .env.template: 書式の参照例(本 repo の dogfood でも使用)
- CI: check.yml(nix flake check) と release.yml(タグ駆動の Release 自動生成)
- README/CLAUDE.md: 構成・開発・バージョニング(SemVer)を追記

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Linux の hermetic な nix ビルドサンドボックスには /usr/bin/env が無く、
生スクリプトの `#!/usr/bin/env bash` が bad interpreter で落ちて CI が失敗していた。
インストールした libexec のコピーのみ shebang を bashNonInteractive の絶対パスへ
置換する(リポジトリ上の原本は #!/usr/bin/env bash のまま=非 Nix 利用者向けに可搬)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

この PR は、汎用 dev ツール集約リポジトリの初期整備として env-init を flake package として追加し、devbox ベースでの開発環境(テスト/リンター含む)と CI(check/release)を一式整えるものです。

Changes:

  • env-init 本体スクリプトと bats テストを追加し、worktree ごとの .env 生成を実装
  • Nix flake の packages/checks/formatter を追加し、nix flake check で test/lint を集約
  • devbox 設定・CI workflows・README/CLAUDE.md を追加して開発/リリース手順を整備

Reviewed changes

Copilot reviewed 10 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md リポジトリ構成・開発手順・バージョニング・env-init 利用方法を追加
pkgs/env-init/tests/env-init.bats env-init の bats フルセットテストを追加
pkgs/env-init/package.nix env-init を makeWrapper で wrap する Nix 派生を追加
pkgs/env-init/env-init .env.template から .env を生成するエンジン本体を追加
flake.nix packages/checks/formatter を公開し nix flake check を定義
flake.lock nixpkgs 入力の lock を追加
devbox.lock devbox 依存パッケージの lock を追加
devbox.json 開発環境(lint/test)と dogfooding を追加
CLAUDE.md リポジトリの前提/開発方針を追記(※一部記述に不整合あり)
.gitignore ローカルツール/Claude Code ローカル状態の ignore を追加
.github/workflows/release.yml SemVer タグ push で release 作成する workflow を追加
.github/workflows/check.yml push/PR で nix flake check を回す workflow を追加
.env.template env-init 用テンプレートの書式例を追加

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CLAUDE.md Outdated
Comment on lines +11 to +14
- パッケージは `pkgs/<name>/` に `package.nix`(`writeShellApplication` 派生)と生スクリプトを同居させる。生スクリプトは
`#!/usr/bin/env bash` 始まりで単体実行可能なまま保ち、wrap は外側に被せるだけで中身を書き換えない。
- test / lint の真実は `flake.nix` の `checks`(bats・statix・deadnix・nixfmt、および writeShellApplication build 内包の
shellcheck)に一元化する。`devbox.json` の scripts はそれへの薄い委譲。
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご指摘のとおりです。実装は runCommand + makeWrapper(shellcheck は独立 check)なのに CLAUDE.md が writeShellApplication 前提のままでした。f961ae6 で実態に合わせて修正し、writeShellApplication は本文前にプリアンブルを差し込み $0 依存(env-init の --help)を壊しうるため避ける旨も明記しました。

writeShellApplication 前提の記述だったが、実装は runCommand + makeWrapper で
shellcheck も独立 check。将来のパッケージ作成者を誤導しないよう実態に合わせて
一般化した(Copilot レビュー指摘)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 13 changed files in this pull request and generated 2 comments.

Comment thread devbox.json Outdated
Comment on lines +8 to +10
"nixfmt@latest",
"bats@latest",
"path:.#env-init"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご指摘のとおりです。cfadb4e で devbox.json の packages に openssl@3 を追加しました(devbox.lock も更新)。これでルートの .env.templateopenssl rand が dogfood 環境で常に解決でき、SESSION_SECRET の空生成(silent failure)を防げます。利用側 repo が openssl を供給する設計の、本 repo 版でもあります。

Comment thread pkgs/env-init/env-init Outdated
# bin/env-init --force # 既存 .env を上書き (N は WORKTREE_N から復元)
# bin/env-init -n 3 # worktree 番号 N を手動指定
#
# devbox タスク経由: `task env:init` (引数は `-- --force` のように渡す)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご指摘のとおりです。cfadb4e で --help ヘッダを本リポジトリの実態に更新しました(存在しない task env:init を削除し、コマンド名を env-init・起動例を devbox init_hook の [ -f .env ] || env-init に)。移行後は本リポジトリが正典(移行元の実体は削除される方針)のため、生スクリプトの記述を実態へ合わせました。

mackato and others added 2 commits June 3, 2026 14:02
- env-init の --help ヘッダを本リポジトリの実態に合わせて更新(存在しない
  `task env:init` を削除し、コマンド名を `env-init`・起動は devbox init_hook に)。
  移行後は本リポジトリが正典のため生スクリプトの記述を実態へ更新。
- devbox.json に openssl@3 を追加。ルート .env.template が `openssl rand` を使うため、
  dogfood が環境非依存で SESSION_SECRET を生成できるようにする(空生成の silent failure を防止)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
意図しないメジャーアップグレードで破壊的変更を取り込むのを防ぐため、
shellcheck@0 / statix@0 / deadnix@1 / nixfmt@1 / bats@1 にピン。
解決されるバージョンは従来と同一で、devbox update 時の major 跳ねを抑止する。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 13 changed files in this pull request and generated 2 comments.

Comment thread pkgs/env-init/env-init
Comment on lines +96 to +117
PRIMARY_PATH=$(git worktree list --porcelain | awk '/^worktree / { sub(/^worktree /, ""); print; exit }')
if [ -z "$PRIMARY_PATH" ]; then
echo "error: could not determine primary worktree path" >&2
exit 1
fi

if [ "$REPO_ROOT" = "$PRIMARY_PATH" ]; then
N=0
else
# 他の worktree (自分自身と primary を除く) の .env から WORKTREE_N を読み、
# 使用済み N を集めて {1..99} の最小未使用値を割り当てる。
USED_NS=""
# プロセス置換で直接読む (while を current shell で回し USED_NS を親に残す。
# bash 必須だが本スクリプトは元から bash 前提)。
while IFS= read -r line; do
case "$line" in
"worktree "*)
wt_path=${line#worktree }
if [ "$wt_path" = "$REPO_ROOT" ] || [ "$wt_path" = "$PRIMARY_PATH" ]; then
continue
fi
wt_env="$wt_path/.env"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご指摘のとおりです。妥当なエッジケース(symlink 跨ぎで --force 時に N がズレ得る)として修正しました。canonicalize_dircd … && pwd -P)を追加し、REPO_ROOT / PRIMARY_PATH / 各 worktree パスを物理パスに正規化してから比較するようにしています。あわせて bats は BATS_TEST_TMPDIR(macOS では /var→/private/var の symlink を含む)を正規化せず使い、symlink 跨ぎの primary 判定・sibling 除外を実地で検証するようにしました。

Comment thread pkgs/env-init/env-init
# - それ以外 (if/echo/exit/関数定義などの評価専用ロジック) → .env に出力しない
# (素通しするとシェル構文が .env に混入し、`. ./.env` や dotenv パーサを壊す)
while IFS= read -r line || [ -n "$line" ]; do
if [[ $line =~ ^([A-Za-z_][A-Za-z0-9_]*)= ]]; then
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これはあえての設計です。テンプレートは bash として source 評価されるため、if/for/関数本体などのロジックブロック内の代入(通常インデントされる)まで抽出対象にすると、その分岐が実行されていなくても抽出フェーズの ${!name} が空値を返し、条件付き変数を誤って空のまま .env に固定してしまいます。そのため「列 0 のトップレベル宣言のみ .env に出力/インデント=評価専用ロジックは非出力」という区別にしています(スクリプト冒頭コメントの『それ以外 (if/echo/exit/関数定義などの評価専用ロジック) → .env に出力しない』方針)。インデントしたトップレベル宣言を出力したい場合はテンプレート側で列 0 に置く運用とします。

git rev-parse --show-toplevel と git worktree list --porcelain のパス表現が
symlink でズレる環境(macOS の /var → /private/var 等)で、primary 判定や
sibling 除外を誤り --force 時に worktree N がズレ得るのを修正。canonicalize_dir
で REPO_ROOT / PRIMARY_PATH / 各 worktree パスを pwd -P 正規化してから比較する。
bats も BATS_TEST_TMPDIR を正規化せず使い、symlink 跨ぎの判定を実地検証する。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 13 changed files in this pull request and generated 1 comment.

Comment thread pkgs/env-init/env-init Outdated
Comment on lines +67 to +70
# リポジトリルート (このスクリプトを呼んだ worktree のルート)
REPO_ROOT=$(canonicalize_dir "$(git rev-parse --show-toplevel)")
ENV_PATH="$REPO_ROOT/.env"
TEMPLATE_PATH="$REPO_ROOT/.env.template"
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ご指摘のとおりです。git rev-parse --show-toplevel の失敗を明示的にハンドルし、git の生エラーは抑止して error: not inside a git worktree. Run env-init from within a git repository. を出して exit 1 するようにしました。あわせて bats に git 管理外で実行するケースを追加しています。
(補足: 直前の canonicalize_dir 変更が git 失敗時の set -e 即時終了を握り潰し、的外れな「.env.template not found」を出す退行も生んでいたため、本修正で併せて解消しました。)

git 管理外で実行された場合に git の生 fatal だけが出ていた問題を修正し、
「git worktree 内で実行する」旨のメッセージで exit 1 する。あわせて、直前の
canonicalize_dir 変更が git 失敗時の set -e 即時終了を握り潰して的外れな
「.env.template not found」を出していた退行も解消。bats に git 管理外ケースを追加。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 13 changed files in this pull request and generated no new comments.

@mackato
Copy link
Copy Markdown
Member Author

mackato commented Jun 3, 2026

LGTM ✅

汎用 dev ツール集約リポジトリの第一弾として env-init を Nix flake パッケージ化し、devbox 開発環境・CI・リリース自動化までを一式整備。CI(nix flake check:shellcheck / bats / statix / deadnix / nixfmt / build)green、Copilot レビュー指摘もすべて解決済み。

主な内容

  • pkgs/env-init:エンジンを移植(makeWrapper で wrap、shebang のみ固定)+ bats フルセット
  • flake.nix:packages / checks(test・lint の単一ソース)/ formatter(nixfmt-tree)
  • devbox.json:dev ツール(メジャー指定)+ path:.#env-init dogfood + init_hook
  • ルート .env.template(書式の参照例、dogfood 兼用)
  • CI:check.yml(PR/main)/ release.yml(タグ駆動 Release)
  • README / CLAUDE.md:構成・開発・バージョニング(SemVer)

レビュー対応

  • CLAUDE.md をパッケージ実装に整合
  • dogfood の openssl 提供(secret 空生成防止)
  • --help ヘッダを実態に更新
  • worktree パスの symlink 正規化(--force 時の N ズレ修正)
  • git 管理外実行を明確なエラーで終了
  • インデント代入の非出力は by design として説明

follow-up(依存の定期更新 / メジャー移動タグ)は #2 で別 PR 対応。

@mackato mackato merged commit 6670db6 into main Jun 3, 2026
2 checks passed
@mackato mackato deleted the feat/env-init branch June 3, 2026 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants