SeeFTで、課題に気づいてから本番に反映するまでの仕事の進め方と、その途中の決まりをまとめた文書です。
ほかの文書との分担は次のとおりです。
| 文書 | 書いてあること |
|---|---|
| onboarding.md | 使っている技術と、その学び方 |
| AGENTS.md | コードの書き方の規約 |
| この文書 | 仕事の進め方(issue・ブランチ・PR・レビュー・マージ・割り振り) |
| docs/operations/ | 技大祭の運用と本番の手順 |
| docs/decisions/ | なぜそう決めたか(ADR) |
この文書の決まりは、チームの約束事です。システムの作りには関わらず、すぐに変えられるので、ADRにはしていません。決まりの横に理由を短く書いています。変えたいときは、この文書を直すPRを出し、なぜ変えるかを本文に書いてください。
課題に気づく → issue を立てる → 割り振る → ブランチを切る → 実装する
→ 自分で点検する → PR を出す → レビュー → マージ → 本番に反映する
(設計や運用の方針を選んだら ADR を書く)
どの変更も、この流れで進めます。
どんな変更もissueから始めます。コードだけでなく、AGENTS.md・README・設定ファイルのような文書の変更も同じです。目的がissueに、議論と確認がPRに残り、CodeRabbitのレビューも受けられるためです。とくにAGENTS.mdは規約そのものなので、変えた理由が残らないと、後から変えてよいかを判断できません。
テンプレートは.github/ISSUE_TEMPLATE/issue-template.mdです。目的(なぜやるか)を必ず書きます。
コードを引用するときは、言語を指定したコードブロックに入れます。「L123: コード」のような箇条書きだと、行番号とコードと説明の境目が見えにくくなるためです。ファイル名と行番号を1つだけ示すなら、インラインのバッククォートで構いません。
**ファイル**: `api/lib/usecase/shift_usecase.go`
```go
// 準々備日は45th(yearID=45)のみ対応
```公開リポジトリなので、書かないものがあります。書いたものは、消しても履歴に残ります。個人名は役職で書き、スプレッドシートやDriveのID、サーバーのIP、委員会の中だけで通じる言葉の意味も書きません。これらは、引き継ぎに要る人だけが読める非公開の資料で渡します。
セキュリティの問題は、公開のissueにしません。公開のissueに書くと、手口がそのまま公開されます。
- admin権限がある人(PMなど)は、リポジトリのSecurityタブ → Advisoriesから、非公開のセキュリティアドバイザリ(下書き)として記録します。
- admin権限がない人は、Securityタブからは報告できません(外部からの非公開の報告機能は無効にしてあります)。見つけたことを、PMにSlackのDMで知らせてください。タスクの割り振りはチャンネルで行いますが(12節)、セキュリティの問題だけは例外です。
直すためのissueとPRも、問題の中身に触れない書き方で出します。「使われていない処理を消す」「入力の検査を足す」のように、変更そのものだけを書きます。差分は公開されるので変更の中身は隠せませんが、どこを狙えばよいかを説明する文章は書かずに済むためです。中身はアドバイザリにだけ書きます。
秘密の値(トークンやWebアプリのURLなど)がすでにコミットされていたときは、コードから消してもgitの履歴に残ります。消しただけで片付いたとはせず、どう扱うかをアドバイザリの中で決めます。
- developから切ります。developに直接コミットしません。
- 名前は
種類/名前/issue番号/内容です。種類はfeat(機能)・fix(修正)・docs(文書)です。例えばfeat/{名前}/123/show-break-cardのように付けます。 - mainは使っていません。2025年8月から更新されておらず、本番はdevelopを動かしています(deploy.md)。
PoC(作ってみないと分からないもの)は、試作用のブランチで自由に試します。形が見えないうちにdevelop向けのブランチで書くと、本番と同じ品質を早い段階から求められすぎて、試作が進まないためです。完成形が見えたら、developから新しいブランチを切り、要るファイルだけをgit checkout <試作用のブランチ> -- <パス>で持ち込んでPRにします。試行錯誤のコミットはdevelopの履歴に入れません。持ち込む時期の目安は、本番に入れると確信できたとき、または試作用のブランチが2か月を超えたときです。
gitの追跡から外したいファイルは、ほかの人も同じものを作るかで置き場所を決めます。誰が作業しても出る生成物(マニュアルの変換の出力など)は、理由のコメントを付けて.gitignoreに書き、自分だけの作業ファイルは手元の.git/info/excludeに書きます。.git/info/excludeはリポジトリに入らないので、みんなが作る生成物をここに書くと、ほかの人の手元では追跡されていないファイルとして溜まり続けます(PR #491で.gitignoreに移しました)。
前は「特定のブランチでしか作らない生成物は.git/info/excludeに書く」という決まりでしたが、この決まりは1人で開発している間しか成り立ちませんでした。ほかの人が同じブランチで作業すると、その人の手元のexcludeには何も書かれていないためです。
- メッセージは日本語で、先頭に
feat:・fix:・docs:を付けます。何をなぜ変えたかが1行で分かるように書きます。 - Wikiにある
[fix]形式のラベルは、2024年までの書き方です。
点検はPRの差分全体を対象にします。主に作ったファイルだけでなく、ついでに直したファイルも見ます。点検の範囲を絞ると、その外で入った誤りは、レビューで指摘されるまで残ります(#564では、点検しなかったファイルに誤りが3件残っていました)。
1か所を直したら、同じ誤りがほかにもないかをgit grepで探し、全部直します。
数字(件数など)は、重複しない方法で数え直し、元のデータと照らし合わせます。例えばgit ls-files 'api/**/*_test.go' | wc -lのように数えます。
resolve #NやClose #Nを書くときは、番号のissueの題名を確かめます。マージすると、中身に関係なくその番号のissueが閉じます。#352では、ブランチ名の番号の並びに引きずられて、直していない#308と#309を閉じてしまいました。
gh issue view 308 --json titleテンプレート(.github/pull_request_template.md)に沿って書きます。「テスト項目」には、自分で確かめたことと、確かめていないことを分けて書くと、レビューする人が見る場所を決めやすくなります。
PRを出すとCIが走ります。何が走るかはonboarding.mdの11節を見てください。ADRの前提の点検(docs-refcheck)は、すべてのPRで走ります。
新しいlintのルールを入れるときは、ルールを入れる変更と、既存の違反を直す変更を分けます。設定が妥当かの確認と、大量の修正の確認を1つのPRでやると、レビューが追いつかないためです。違反を直す変更はルールごとにissueに分けます。自動で直せるものと手で直すものも、危なさと要る知識が違うので混ぜません。
- api(Go)は、CIの
go-lintがPRで新しく増えた違反だけを見るので、設定だけのPRを先に出せます。 - mobileは、CIの
flutter-lintが既存の違反も含めて、infoの指摘1件で落ちます。設定だけのPRは通らないので、先にルールごとのPRで違反を直し、最後にルールを有効にするPRを出します。
45thでmobileにflutter_lintsを入れたときは、まだflutter-lintが無かったので、設定のPR(#280)を先に入れました。242件の違反はルールごとの子issue(#286の下)で直し、違反がなくなってからCIを足しました(#386)。
人が見る前に、機械で拾えるものは機械で拾います。フォーマッタ → linter(CIのgo-lint・flutter-lint)→ AIのレビュー(CodeRabbit。AGENTS.mdの規約も読む)→ 人、の順に通しています。45thは、書く人とレビューする人がほぼ同じ1人で、人のレビューだけに頼れなかったためです。フォーマッタは方針にはありますが、CIにはまだ入っていません。
developには、承認1件と、PR上の会話がすべて解決していることがマージの条件になっています。
44th(2024年)は、PRを出した人以外が手元で動作確認し、Approveしてから、PMがマージしていました(Wikiの「GitとGitHubの使い方(SeeFT)」)。
45th(2026年)は、ほぼPMが1人で開発しました。PMはadmin権限で、承認が0件のまま自分のPRをマージしていました。2026年(9月末まで)にマージしたPR 127本のうち、作った人以外がレビューしたのは19本です。PM以外のメンバーのPRには、保護ルールがそのまま適用されていました。
複数人で開発するなら、人のレビューを受けることを勧めます。どちらで進めるかは、その年のチームで決めて、ADRに書いてください。45thの進め方とその理由はADR 0004にあります。developのブランチ保護の設定に関わるので、チームの約束事ではなく運用の方針として扱います。
PRにはAIのレビュー(CodeRabbit)が付きます。指摘は参考です。スコープ外のものは、理由を書いて見送って構いません。
指摘は「そのPRが持ち込んだか」と「実際に困ることがあるか」の2つで振り分けます。CodeRabbitはPRで触った行を見るので、元からあった問題も、そのPRが作ったように見えます。実際に困ることとは、動かしたときの不具合・ビルドが通らなくなること・情報が漏れることのどれかです。たとえば、Flutterや依存ライブラリを上げたときに削除されていればビルドエラーになる非推奨のAPI(deprecated_member_use。PR #343で直した)は、今は動いていても実際に困るものとして扱います。
- そのPRが持ち込んだものは、そのPRで直す
- 元からあって、実際に困ることがあるものは、PRのスコープ外として、別のissueに切る。範囲が広いときは、親のissueを1つ立て、直す単位ごとに子のissueに分ける(例えば、mobileのlintの違反は、親の#286の下にルールごとの子のissueを立てた)
- 元からあって、見た目や書き方の揃え方だけのものは、スコープ外だと返信して、スレッドを閉じる
無料枠のため、レビューは1時間に1回までです。枠を超えると自動では走らず、PRの要約コメントに「Review limit reached」と出ます。枠が戻ってから、PRに@coderabbitai reviewとコメントすると頼めます。
指摘を直したあとの再レビューは、必要なときだけ頼みます。直し方が提案どおりで、境目のケースをテストで確かめてあるなら、頼みません。1時間に1回の枠は、まだ誰も見ていないPRのために取っておきます。直し方が提案から大きく外れたとき、ほかの場所にも手を入れたとき、テストで確かめられていないときに頼みます。
CodeRabbitは、自分の指摘が直ったと判断すると、スレッドを自分で「Resolve」します。手で閉じる前に、もう閉じられていないかを見てください。CodeRabbitのスレッドに返信するとCodeRabbitが自動で返信してくるので、見送る理由の返信は1回にまとめます。
PRの要約コメントの「Merge Risk」は、最後にレビューできたコミットの時点の評価です(「up to xxxxx」の部分)。
- スカッシュマージ(PRのコミットを1つにまとめる)でdevelopに入れます。
- マージするのはPMです。
作った人が続けられなくなったPRを引き継ぐときは、元のPRのブランチにコミットを積んで、同じPRで作業を続けます。新しいブランチと新しいPRを作って、元のPRを閉じることはしません。最初の議論から引き継いだ後の変更までと、元の作者のコミットが、1つのPRに残るためです(例えば#546)。
元のブランチがdevelopより古いときは、git fetch originで最新を取ってから、git merge origin/developで取り込みます。rebaseしてforce pushはしません。force pushすると、元の作者の手元のブランチと食い違うためです。developへはスカッシュマージなので、mergeで取り込んだコミットはdevelopの履歴に残りません。
PRの本文の冒頭に、引き継いだことと、方針を変えたならその理由を書きます。作った人にもひと言コメントします。
docs/operations/deploy.mdの手順に従います。本番で打つコマンドを人に案内するときの書き方は、docs/operations/README.mdの「書き方」にあります。
機能を足す・見送る、設計や運用の方針を選ぶ、といった判断をしたら、docs/decisions/にADRを書きます。決めたことだけでなく、理由と、選ばなかった候補を書きます。
候補を比べて決めるときは、決める前にADRを「提案」の状態でPRに出し、PRの上で議論します。AGENTS.mdの「Ask First」に当たる変更は、実装の前にこの流れで進めます。
この文書にあるようなチームの約束事は、ADRにしません。この文書に理由と一緒に書きます。
何をADRにするかと書き方は、docs/decisions/README.mdにあります。
割り振りはDMではなく、チームのチャンネルに投稿します。記録が残り、同じ種類のタスクを持つほかのメンバーも、その説明を参考にできるためです。相手へのメンションとissueのリンクに、お手本や設計のリンクも付けます。最後に「質問があれば対面か通話の時間を取ります。なければ次のMTか作業会で」と書き添えます。
対面や通話は、相手が望んだときに取ります。先に日程を押さえると、相手の負担だけが増えます。
同じ種類のタスクを何人かに振るときは、1つずつissueに分け、先にお手本のPRと設計の文書を用意します。各自が同じ形で書けるので、レビューも揃えやすくなります。45thのテストでは、親のissue(#404)の下に1関数ずつ子のissueを切り、お手本のPR(#419)と設計の文書を先に出してから割り振りました。
作業は価値の高い順に並べます。「これしかできないなら、どれを残すか」を考えて、残すものを先頭にします。軽い作業から始めて弾みを付ける、という並べ方はしません。人も時間も限られているので、途中で時間が尽きても価値の高いものが残る順にします。価値は、すぐ役に立つか、後の作業にどれだけ役に立つか、本来の目的にどれだけ直結するか、で見ます。
新しく入った人の最初のタスクは例外です。小さく終わるものから始めて、全体の流れに慣れてもらいます。
44thは、タスクをGitHubのProjectで管理していました(Wikiの「SeeFTのタスク管理のルール」)。
- 全てのタスクに期日を決める
- 毎週、進捗と、各自がこなせる量を共有する(MTに出られない人はSlackで報告する)
- 詰まったらステータスを「Help」にし、余裕のある人が引き取る。いなければ期日を変える
- 優先度は0(最低限)〜3(余裕があれば)の4段階
45thでこのProjectをどこまで使っていたかは、この文書では確かめていません。どう管理するかは、その年のチームで決めてください。
執行部など、開発をしていない人に向けた資料は、技術の前提知識が全く無い人が読んでも分かるように組みます。説明するのは判断してもらうため(予算を出すか、運用を変えるか)で、分からない言葉が入ると、判断に要る情報まで伝わらなくなります。
- 流れは「課題 → やりたいこと → しくみ → メリット → コスト → 日程 → 確かめたいこと」です。
- 技術用語(API、SDK、コマンド名など)は、本当に要るかを考えてから使います。「AI」「Googleドキュメント」「Webページ」くらいの言葉までにします。
- 内部の比較や技術の詳細は、説明の資料から外し、別の文書にします。