コントリビューティングガイド¶
clinvoker への貢献に興味を持っていただきありがとうございます。このガイドでは、開発環境セットアップ、プロジェクト構造、コーディング規約、テスト要件、貢献プロセスを説明します。
開発環境セットアップ¶
前提¶
- Go 1.24 以降
- Git
- (任意)再現性のある環境のための Nix
- (任意)Lint 用の golangci-lint
- (任意)Git フック用の pre-commit
Fork と Clone¶
# GitHub 上でリポジトリを fork してから:
git clone https://github.com/YOUR_USERNAME/clinvoker.git
cd clinvoker
git remote add upstream https://github.com/signalridge/clinvoker.git
Nix を使う(推奨)¶
必要なツール一式を再現可能な環境で提供します。
手動セットアップ¶
pre-commit フック¶
プロジェクト構造¶
clinvoker/
├── cmd/
│ └── clinvk/ # メインアプリのエントリポイント
│ └── main.go
├── internal/
│ ├── app/ # CLI コマンド実装
│ ├── backend/ # バックエンド抽象化レイヤ
│ ├── config/ # 設定管理
│ ├── executor/ # コマンド実行
│ ├── output/ # 出力整形
│ ├── server/ # HTTP API サーバー
│ ├── session/ # セッション管理
│ ├── auth/ # API キー管理
│ ├── metrics/ # Prometheus メトリクス
│ └── resilience/ # サーキットブレーカ
├── docs/ # ドキュメント
├── scripts/ # ビルド/ユーティリティスクリプト
└── test/ # 統合テスト
パッケージの責務¶
| パッケージ | 目的 | 主なファイル |
|---|---|---|
app/ |
Cobra を使った CLI コマンド | app.go, cmd_*.go |
backend/ |
バックエンド抽象化 | backend.go, registry.go, claude.go, codex.go, gemini.go |
config/ |
Viper ベースの設定 | config.go, validate.go |
executor/ |
サブプロセス実行 | executor.go, signal.go |
server/ |
HTTP サーバー | server.go, routes.go, handlers/, middleware/ |
session/ |
セッション永続化 | session.go, store.go, filelock.go |
コーディング規約¶
Go のガイドライン¶
Effective Go と Google Go Style Guide に従ってください。
- フォーマット:
gofmtまたはgoimportsを使用 - Lint: コミット前に
golangci-lint runを実行 - 命名: 説明的で Go らしい名前にする
- コメント: export する型/関数には必ずドキュメントコメントを書く
- エラーハンドリング: コンテキストを付けて wrap、naked return を避ける
スタイル例¶
// Good: Clear function name, proper documentation, error handling
// ExecuteCommand runs the given command and returns the output.
func ExecuteCommand(ctx context.Context, cfg *Config, cmd *exec.Cmd) (*Result, error) {
if cfg == nil {
return nil, fmt.Errorf("config is required")
}
// Implementation
result, err := runWithTimeout(ctx, cmd, cfg.Timeout)
if err != nil {
return nil, fmt.Errorf("failed to execute command: %w", err)
}
return result, nil
}
// Bad: Unclear name, missing documentation, poor error handling
func exec(cfg *Config, c *exec.Cmd) (*Result, error) {
res, _ := runWithTimeout(context.Background(), c, cfg.Timeout)
return res, nil
}
エラーハンドリング¶
プロジェクトの errors パッケージを使って、一貫したエラー処理を行います。
import apperrors "github.com/signalridge/clinvoker/internal/errors"
// Create error with context
return apperrors.BackendError("claude", err)
// Check error type
if apperrors.IsCode(err, apperrors.ErrCodeBackendUnavailable) {
// Handle specific error
}
テスト規約¶
新しいコードにはテストが必要です。次の方針に従ってください。
- ファイル名: ソースと同階層に
*_test.go - テーブル駆動テスト: 複数ケースに有効
- 並列テスト: 独立ケースは
t.Parallel()を使う - カバレッジ: 新規コードは 80% 以上を目安
- モック: テスト容易性のためにインターフェースを活用
func TestExecuteCommand(t *testing.T) {
t.Parallel()
tests := []struct {
name string
cfg *Config
cmd *exec.Cmd
wantErr bool
}{
{
name: "valid command",
cfg: &Config{Timeout: 30 * time.Second},
cmd: exec.Command("echo", "hello"),
wantErr: false,
},
{
name: "nil config",
cfg: nil,
cmd: exec.Command("echo", "hello"),
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
ctx := context.Background()
_, err := ExecuteCommand(ctx, tt.cfg, tt.cmd)
if (err != nil) != tt.wantErr {
t.Errorf("ExecuteCommand() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
テスト要件¶
テストの実行¶
# すべてのテスト
go test ./...
# race 検出
go test -race ./...
# カバレッジ
go test -coverprofile=coverage.txt ./...
go tool cover -html=coverage.txt -o coverage.html
# short テストのみ
go test -short ./...
# 特定パッケージ
go test ./internal/backend/...
統合テスト¶
統合テストは実際のバックエンド CLI のインストールが必要です。
# 統合テストを実行
CLINVK_TEST_INTEGRATION=1 go test ./test/...
# 特定バックエンドで実行
CLINVK_TEST_BACKEND=claude go test ./test/...
ベンチマーク¶
ドキュメント要件¶
コードコメント¶
export する型/関数は必ずドキュメントコメントを書いてください。
// Backend represents an AI CLI backend.
type Backend interface {
// Name returns the backend identifier.
Name() string
// IsAvailable checks if the backend CLI is installed.
IsAvailable() bool
}
// NewStore creates a new session store at the given directory.
// The directory is created if it doesn't exist.
func NewStore(dir string) (*Store, error) {
// ...
}
ユーザー向けドキュメント¶
ユーザーに影響する変更を加えた場合、ドキュメントも更新してください。
- Concepts: 設計変更がある場合はアーキテクチャドキュメントを更新
- Guides: 新機能の How-to ガイドを追加/更新
- Reference: API/CLI リファレンスを更新
- Changelog:
CHANGELOG.mdにエントリ追加
ドキュメントスタイル¶
- 明確で簡潔な表現にする
- コード例を含める
- 複雑な概念は図(Mermaid)を使う
- 英語/中国語/日本語の内容が大きく乖離しないようにする
PR プロセス¶
ブランチ命名¶
慣例的なプレフィックスを使ってください。
| Prefix | 用途 | 例 |
|---|---|---|
feat/ |
新機能 | feat/add-gemini-backend |
fix/ |
バグ修正 | fix/session-locking |
docs/ |
ドキュメント | docs/api-examples |
refactor/ |
リファクタ | refactor/executor |
test/ |
テスト追加 | test/backend-coverage |
chore/ |
保守 | chore/update-deps |
コミットメッセージ規約¶
Conventional Commits に従ってください。
Types: feat, fix, docs, style, refactor, test, chore
例:
feat(backend): add support for new AI provider
Add support for the new XYZ AI CLI tool. This includes:
- Backend implementation
- Flag mapping
- Documentation updates
fix(session): handle concurrent access correctly
Fix race condition in session store when multiple processes
attempt to update the same session simultaneously.
docs(readme): update installation instructions
test(backend): add unit tests for registry
chore(deps): update golang.org/x packages
Pull Request テンプレート¶
## Summary
Brief description of changes.
## Changes
- Change 1
- Change 2
## Test Plan
How changes were tested:
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing performed
## Related Issues
Fixes #123
Closes #456
コードレビュー チェックリスト¶
PR を出す前に確認してください。
- [ ] ローカルで全テストが通る
- [ ] スタイルガイドに従っている
- [ ] ドキュメントを更新した
- [ ] コミットメッセージが規約に従っている
- [ ] 不要なファイルを含めていない
- [ ]
CHANGELOG.mdを更新した(必要な場合)
レビュープロセス¶
- PR には少なくとも 1 人の承認が必要です
- マージ前に CI が通る必要があります
- レビューコメントへ迅速に対応してください
- PR は焦点を絞り、適切なサイズにしてください(目安: 500 行未満)
- コンフリクトがあれば main へリベースしてください
リリースプロセス¶
バージョニング¶
clinvoker は Semantic Versioning に従います。
MAJOR: 破壊的変更MINOR: 後方互換な新機能PATCH: 後方互換なバグ修正
release-please による自動リリース¶
自動バージョニングと CHANGELOG 生成に release-please を使います。
仕組み¶
feat: add new feature → push to main → Release PR created automatically
↓
merge Release PR
↓
tag created (v1.1.0)
↓
GoReleaser builds binaries
- Conventional Commits で コミット する
- main へ push - release-please が Release PR を作成/更新
- Release PR をマージ - tag と GitHub Release が作られる
- GoReleaser が起動 - 各プラットフォーム向けバイナリをビルド
Conventional Commits とバージョン番号¶
| コミット種別 | バージョン増分 | CHANGELOG 区分 |
|---|---|---|
feat: |
Minor(0.1.0 → 0.2.0) | Features |
fix: |
Patch(0.1.0 → 0.1.1) | Bug Fixes |
feat!: または BREAKING CHANGE: |
Major(0.1.0 → 1.0.0) | Breaking Changes |
perf: |
Patch | Performance |
refactor: |
Patch | Refactoring |
deps: |
Patch | Dependencies |
security: |
Patch | Security |
docs:, chore:, test:, ci: |
リリースなし | Hidden |
ワークフロー例¶
# 1. 機能ブランチ作成
git checkout -b feat/new-feature
# 2. 変更して conventional 形式でコミット
git commit -m "feat(backend): add support for new AI provider"
# 3. PR を作成して main へマージ
gh pr create && gh pr merge
# 4. release-please が Release PR を自動作成
# Title: "chore: release v0.2.0"
# Contains: Updated CHANGELOG.md and version bumps
# 5. Release PR をレビューしてマージ
# → Tag v0.2.0 created
# → GoReleaser builds and publishes
# 6. 完了。バイナリは次で利用可能:
# - GitHub Releases
# - Homebrew: brew install signalridge/tap/clinvk
# - go install: go install github.com/signalridge/clinvoker/cmd/clinvk@latest
手動リリース(緊急時のみ)¶
自動化が使えない緊急時の手順:
# 1. CHANGELOG.md を手動更新
# 2. tag を作成して push
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3
# 3. GoReleaser ワークフローが自動で起動
質問がありますか?¶
- バグ/機能要望は issue を作成
- 質問は discussion を開始
- 新規作成前に既存 issue を確認
行動規範¶
参加することで、次に同意したものとみなされます。
- 敬意を持ち、包摂的である
- 建設的な批判を受け入れる
- コミュニティにとって最善を優先する
- 他者へ共感を持つ
関連ドキュメント¶
- アーキテクチャ概要 - システムアーキテクチャ
- 設計判断 - アーキテクチャ判断(ADR)
- トラブルシューティング - よくある問題