Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions docs/development/manual-html-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,10 @@ PUT https://seeft-api.nutfes.net/manuals/{id}
`--doc-url` にはGoogleドキュメントの共有URLを渡す。⑤で対応表のB列に入れる値になる。

```bash
python3 scripts/automation/upload_manual.py --id en-nichi --doc-url "https://docs.google.com/document/d/xxxx/edit" docs/manuals/45th_企画マニュアル_縁日
python3 scripts/automation/upload_manual.py --base-url https://seeft-api.nutfes.net --id en-nichi --doc-url "https://docs.google.com/document/d/xxxx/edit" docs/manuals/45th_企画マニュアル_縁日
```

トークンは訊かれるので貼り付ける。入力は画面にもシェルの履歴にも残らない。環境変数 `MANUAL_UPLOAD_TOKEN` を設定してあればそちらが使われる。
送り先は `--base-url` で明示する(理由は下の「AI のツールに頼むとき」)。トークンは訊かれるので貼り付ける。入力は画面にもシェルの履歴にも残らない。環境変数 `MANUAL_UPLOAD_TOKEN` を設定してあればそちらが使われる。

送信前にHTMLが `</html>` で閉じているかとサイズ上限を検査するので、壊れたファイルや大きすぎるファイルを配信してしまうことはない。

Expand Down Expand Up @@ -225,6 +225,20 @@ curl -X PUT "https://seeft-api.nutfes.net/manuals/en-nichi" -H "Authorization: B

作業が終わったらターミナルを閉じる。環境変数はそのウィンドウにしか残らないため、閉じれば消える。

### AI のツールに頼むとき

Claude などの AI のツールに作業を頼むときも、トークンを会話に貼らない。会話のログに平文で残るためである。自分のターミナルで、入力を表示しない形で読み、自分だけが読めるファイルに保存する。

```bash
mkdir -p ~/.config/seeft && chmod 700 ~/.config/seeft && printf 'アップロードトークンを貼り付けてEnter: ' && read -rs t && echo && (umask 077 && printf '%s' "$t" > ~/.config/seeft/manual-upload-token) && unset t
```

ツールには、そのファイルを環境変数に読み込んでから実行するように頼む。トークンそのものは会話に出てこない。送り先は `--base-url` で明示する。付けないと、環境変数 `SEEFT_API_BASE_URL` に入っている値が既定の URL より先に使われ、https ならどのホストにもトークンが送られるためである。

```bash
MANUAL_UPLOAD_TOKEN="$(cat ~/.config/seeft/manual-upload-token)" python3 scripts/automation/upload_manual.py --base-url https://seeft-api.nutfes.net --id en-nichi --doc-url "https://docs.google.com/document/d/xxxx/edit" docs/manuals/45th_企画マニュアル_縁日
```

### レスポンス

成功すると `201 Created` で、次のJSONが返る。
Expand Down
5 changes: 4 additions & 1 deletion docs/development/onboarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,9 @@ for rows.Next() { // 行を1つずつ読む

**何か。** Flutter は Google の UI フレームワークで、言語は Dart です。1つのコードから Android / iOS / Web などを作れますが、**SeeFT は Web としてだけ動かしています。** 参加者はアプリをインストールせず、スマホのブラウザで URL を開きます。`mobile/` の下に `android/`・`ios/`・`macos/`・`windows/` も残っていますが、使っていません。

**Flutter のバージョンは [fvm](https://fvm.app/) で固定しています**(`mobile/.fvmrc` で 3.27.3)。`flutter` コマンドは必ず `fvm flutter ...` の形で打ってください。素の `flutter` を打つと、手元に入っている別のバージョンが動き、依存ライブラリの解決やビルド結果が変わります。Flutter 自体を上げる作業は、他の変更と混ぜず、専用のブランチで行います(#514)。
**Flutter のバージョンは [fvm](https://fvm.app/) で固定しています**(`mobile/.fvmrc` で 3.27.3)。`flutter` コマンドは必ず `fvm flutter ...` の形で打ってください。素の `flutter` を打つと、手元に入っている別のバージョンが動き、依存ライブラリの解決やビルド結果が変わります。バージョンを書いている場所は3か所あり、正は `mobile/.fvmrc` です。本番のコンテナのビルド(`mobile/Dockerfile` の `FLUTTER_VERSION`)と CI(`.github/workflows/flutter-lint.yml` の `flutter-version`)は fvm を使わず、それぞれに同じ値を書いています。上げるときは3か所を同時に上げてください。1か所だけ上げると、手元・CI・本番で別のバージョンが動きます。

Flutter 自体を上げる作業は、lint の導入や機能の追加などのほかの変更と混ぜず、専用のブランチで行います(#514)。3.27 から 3.35 のように大きく上げると、壊れたときに、原因がバージョンなのか一緒に入れた変更なのかを切り分けられなくなるためです。

**画面は Widget の木です。** 画面のすべて(文字、ボタン、余白、並べ方)が Widget で、Widget の中に Widget を入れて画面を組み立てます。

Expand Down Expand Up @@ -515,6 +517,7 @@ cd mobile && fvm flutter test
- `mobile/` を変えたとき:`flutter analyze --fatal-infos`(`flutter-lint.yml`。最も軽い info レベルの指摘でも落ちる)。**テスト(`flutter test`)は走りません。** mobile を変えたら、10節のコマンドで手元で実行してください。45th では、別々の PR で変わったボタンの文言とテストが食い違ったまま develop に入り、マージ後に気づきました(#516)
- `gas/` を変えたとき:GAS のコードを検査するものは走らない
- どの PR でも:ADR(`docs/decisions/`)に書いた前提のファイルや関数がまだあるかの点検(`docs-refcheck.yml`)
- **lint は言語ごとに選んでいます。** Go は golangci-lint、Dart は `flutter analyze`(flutter_lints のルール)です。ESLint は JavaScript 専用なので、Go や Dart には使えません。GAS(JavaScript)には今は lint がありません(`gas/package.json` に入っているのは clasp だけです)。入れるなら ESLint ですが、`gas/` はある時点の写しなので([ADR 0007](../decisions/0007-gas-live-is-source.md))、clasp でライブの版を取ってきてから、それに対して実行します。
- **CodeRabbit**:PR に AI がレビューコメントを付けます。指摘は参考です。すべてに従う必要はなく、スコープ外のものは理由を書いて見送って構いません。
- **Git**:issue を立て、`種類/名前/issue番号/内容` のブランチで作業し、PR を出します。種類は `feat`(機能)・`fix`(修正)・`docs`(文書)です。コミットメッセージは日本語で、`feat:` / `fix:` / `docs:` を付けます。PR はスカッシュマージ(コミットを1つにまとめる)で develop に入り、マージするのは PM です。詳しくは [開発の進め方](workflow.md)。

Expand Down
8 changes: 5 additions & 3 deletions docs/development/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,16 @@ SeeFT で、課題に気づいてから本番に反映するまでの仕事の
- **セキュリティの問題は、公開の issue にしません。** 公開の issue に書くと、手口がそのまま公開されます。
- admin 権限がある人(PM など)は、リポジトリの Security タブ → Advisories から、非公開のセキュリティアドバイザリ(下書き)として記録します。
- admin 権限がない人は、Security タブからは報告できません(外部からの非公開の報告機能は無効にしてあります)。見つけたことを、PM に Slack の DM で知らせてください。タスクの割り振りはチャンネルで行いますが(12節)、セキュリティの問題だけは例外です。
- 直すための issue と PR も、問題の中身に触れない書き方で出します。「使われていない処理を消す」「入力の検査を足す」のように、変更そのものだけを書きます。差分は公開されるので変更の中身は隠せませんが、どこを狙えばよいかを説明する文章は書かずに済むためです。中身はアドバイザリにだけ書きます。
- 秘密の値(トークンや Web アプリの URL など)がすでにコミットされていたときは、コードから消しても git の履歴に残ります。消しただけで片付いたとはせず、どう扱うかをアドバイザリの中で決めます。

## 3. ブランチ

- **develop から切ります。** develop に直接コミットしません。
- 名前は `種類/名前/issue番号/内容` です。種類は `feat`(機能)・`fix`(修正)・`docs`(文書)です。例:`feat/{名前}/123/show-break-card`。
- **main は使っていません。** 2025 年 8 月から更新されておらず、本番は develop を動かしています([deploy.md](../operations/deploy.md))。
- **PoC(作ってみないと分からないもの)は、試作用のブランチで自由に試します**。形が見えないうちに develop 向けのブランチで書くと、本番と同じ品質を早い段階から求められすぎて、試作が進まないためです。完成形が見えたら、develop から新しいブランチを切り、要るファイルだけを `git checkout <試作用のブランチ> -- <パス>` で持ち込んで PR にします。試行錯誤のコミットは develop の履歴に入れません。持ち込む時期の目安は、本番に入れると確信できたとき、または試作用のブランチが2か月を超えたときです。
- **git の追跡から外したいファイルは、ほかの人も同じものを作るかで置き場所を決めます。** 誰が作業しても出る生成物(マニュアルの変換の出力など)は、理由のコメントを付けて `.gitignore` に書きます。自分だけの作業ファイルは、手元の `.git/info/exclude` に書きます。`.git/info/exclude` はリポジトリに入らないので、みんなが作る生成物をここに書くと、ほかの人の手元では追跡されていないファイルとして溜まり続けます(PR #491 で `.gitignore` に移しました)。
- **git の追跡から外したいファイルは、ほかの人も同じものを作るかで置き場所を決めます。** 誰が作業しても出る生成物(マニュアルの変換の出力など)は、理由のコメントを付けて `.gitignore` に書きます。自分だけの作業ファイルは、手元の `.git/info/exclude` に書きます。`.git/info/exclude` はリポジトリに入らないので、みんなが作る生成物をここに書くと、ほかの人の手元では追跡されていないファイルとして溜まり続けます(PR #491 で `.gitignore` に移しました)。前は「特定のブランチでしか作らない生成物は `.git/info/exclude` に書く」という決まりでしたが、これは1人で開発している間しか成り立ちませんでした。ほかの人が同じブランチで作業すると、その人の手元の exclude には何も書かれていないためです。

## 4. コミット

Expand Down Expand Up @@ -97,9 +99,9 @@ develop には、**承認1件と、PR 上の会話がすべて解決している
PR には AI のレビュー(CodeRabbit)が付きます。

- 指摘は参考です。スコープ外のものは、理由を書いて見送って構いません。
- **指摘は「その PR が持ち込んだか」と「実害があるか」の2つで振り分けます。** CodeRabbit は PR で触った行を見るので、元からあった問題も、その PR が作ったように見えます。実害は、動かしたときの不具合・ビルドが壊れること・情報が漏れることのどれかです。
- **指摘は「その PR が持ち込んだか」と「実害があるか」の2つで振り分けます。** CodeRabbit は PR で触った行を見るので、元からあった問題も、その PR が作ったように見えます。実害は、動かしたときの不具合・ビルドが壊れること・情報が漏れることのどれかです。たとえば、Flutter や依存ライブラリを上げると使えなくなる非推奨の API(`deprecated_member_use`。PR #343 で直した)は、今は動いていても実害があるものとして扱います。
- その PR が持ち込んだもの:その PR で直す
- 元からあって、実害があるもの:PR のスコープ外として、別の issue に切る
- 元からあって、実害があるもの:PR のスコープ外として、別の issue に切る。範囲が広いときは、親の issue を1つ立て、直す単位ごとに子の issue に分ける(例:mobile の lint の違反は、親の #286 の下にルールごとの子の issue を立てた)
- 元からあって、見た目や書き方の揃え方だけのもの:スコープ外だと返信して、スレッドを閉じる
- 無料枠のため、**レビューは1時間に1回まで**です。枠を超えると自動では走らず、PR の要約コメントに「Review limit reached」と出ます。枠が戻ってから、PR に `@coderabbitai review` とコメントすると頼めます。
- **指摘を直したあとの再レビューは、必要なときだけ頼みます**。直し方が提案どおりで、境目のケースをテストで確かめてあるなら、頼みません。1時間に1回の枠は、まだ誰も見ていない PR のために取っておきます。直し方が提案から大きく外れたとき、ほかの場所にも手を入れたとき、テストで確かめられていないときに頼みます。
Expand Down
6 changes: 6 additions & 0 deletions docs/operations/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ git diff --name-only HEAD..origin/develop
| `postgresql/` | **この手順ではない。** DB の変更を伴うので、中身を確かめてから別に計画する |
| `gas/` | コンテナとは関係ない。`clasp` で反映する([gas/README.md](../../gas/README.md)) |

**DB の変更があるか(`postgresql/` の行に当たるか)は、PR の最終版の差分で確かめる。** ほかの人や AI のツールの「DB の変更は無い」という説明を、そのまま信じない。途中のコミットで足したファイルを、最後のコミットで消している PR もある(45th の #546 は、途中でテーブルを足すファイルを入れ、最後に消していた)。PR ごとに、最終版で変わるファイルの一覧を見る。`gh pr view <番号> --json files` は 100 件までしか返さないので、ページを全部取る次の形で見る。

```bash
gh api --paginate repos/NUTFes/SeeFT/pulls/<PR の番号>/files --jq '.[].filename'
```

### 2. ディスクの空きを確かめる

```bash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ sheets_client.read_row(manual_name)

- git の事故防止(誤コミットで認証情報が公開される事態を避ける)
- 新 PM 引き継ぎ時に「このディレクトリをコピーすれば動く」状態にできる
- メモリ `project/ignore_convention.md` の「ブランチ依存生成物は `.git/info/exclude` に寄せる」原則を、認証情報には拡張適用
- 認証情報は、追跡から外すだけでなく、リポジトリの中に置かない(追跡から外すファイルの置き場所の決まりは `docs/development/workflow.md` の「3. ブランチ」)

### 5-3. 初回起動フロー

Expand Down
Loading