ソースを参照

docs: add CLAUDE.md for AI-assisted development

Add comprehensive documentation for Claude Code to understand the codebase architecture, including:
- Common development commands and workflows
- High-level architecture overview (routing, database, auth, Git operations)
- Key design patterns and conventions
- Important development notes and gotchas

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fszontagh 3 ヶ月 前
コミット
95fb1a2eba
1 ファイル変更495 行追加0 行削除
  1. 495 0
      CLAUDE.md

+ 495 - 0
CLAUDE.md

@@ -0,0 +1,495 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project Overview
+
+Gogs (Go Git Service) is a painless self-hosted Git service written in Go. It provides a GitHub-like web interface for managing Git repositories with minimal resource requirements.
+
+- **Language**: Go 1.20+
+- **Web Framework**: Macaron (v1)
+- **Database**: Dual ORM system - XORM (legacy) transitioning to GORM (new)
+- **Supported Databases**: PostgreSQL, MySQL, SQLite3, MSSQL, TiDB
+- **Version**: 0.14.0+dev
+
+## Common Development Commands
+
+The project uses [Task](https://taskfile.dev) as its build tool. All commands are defined in `Taskfile.yml`.
+
+### Building and Running
+
+```bash
+# Build the binary
+task build
+
+# Build and start the web server
+task web
+
+# Build and start with auto-reload on file changes
+task web --watch
+
+# Run a release build (creates ZIP in release/ directory)
+task release
+```
+
+### Testing
+
+```bash
+# Run all tests with coverage and race detection
+task test
+
+# Drop test databases (PostgreSQL)
+task drop-test-db
+```
+
+### Code Generation
+
+```bash
+# Run all go:generate commands (including mocks)
+task generate
+
+# Generate database schema documentation
+task generate-schemadoc
+
+# Regenerate CSS from LESS files (IMPORTANT: Never edit .css files directly!)
+task less
+```
+
+### Code Quality
+
+```bash
+# Show all FIXME comments
+task fixme
+
+# Show all TODO comments
+task todo
+
+# Show legacy/deprecated code
+task legacy
+
+# Run linter
+golangci-lint run
+
+# Format code
+goimports -w .
+```
+
+### Development Setup
+
+See `docs/dev/local_development.md` for complete setup instructions. Key steps:
+
+1. Install dependencies: Go 1.20+, Git, PostgreSQL/MySQL/SQLite, Task, Less.js, goimports, go-mockgen
+2. Create database and user
+3. Create `custom/conf/app.ini` with database configuration
+4. Run `task web --watch` to start development server
+
+**Important**: Clone outside of `$GOPATH` (Go modules enabled).
+
+## High-Level Architecture
+
+### Application Structure
+
+The application uses a **single binary deployment model** with embedded assets. Entry point is `gogs.go` using `urfave/cli`.
+
+#### Main Commands
+
+- **`web`**: HTTP/HTTPS server (primary mode)
+- **`serv`**: Git operations over SSH (called by SSH server)
+- **`hook`**: Git hooks delegation (pre-receive, update, post-receive)
+- **`admin`**: CLI admin operations
+- **`backup`/`restore`**: Data backup/restore
+- **`import`**: Import repositories
+- **`cert`**: Generate TLS certificates
+
+### Routing Layer (Macaron-based)
+
+Routes are organized by feature domain in `internal/route/`:
+
+```
+internal/route/
+├── home.go              # Home page
+├── install.go           # Installation wizard
+├── admin/               # Admin panel routes
+├── api/v1/              # REST API v1
+├── org/                 # Organization management
+├── repo/                # Repository routes (issues, PRs, settings, etc.)
+├── user/                # User routes (login, settings, profile)
+└── lfs/                 # Git LFS routes
+```
+
+**Middleware Chain** (applied globally):
+```
+Logger → Recovery → GZIP → Static → Renderer → i18n → Session → CSRF → Contexter
+```
+
+**Authentication Middleware**:
+- `reqSignIn`: Requires authenticated user
+- `reqSignOut`: Requires unauthenticated (for login/register pages)
+- `reqAdmin`: Requires site admin
+- `reqRepoAdmin`/`reqRepoWriter`: Repository-level permissions
+
+### Context System
+
+Three main context types in `internal/context/`:
+
+1. **`context.Context`**: Main HTTP context
+   - Wraps `macaron.Context`
+   - User authentication state
+   - Flash messages, localization
+   - Template data management via `c.Data` map
+
+2. **`context.APIContext`**: API-specific context
+   - JSON response helpers
+   - API error handling
+
+3. **Repository Context** (`context.Repository`):
+   - Git repository handle (`GitRepo`)
+   - Access mode (read/write/admin/owner)
+   - Current branch/commit/tag
+
+**Important**: Macaron uses reflection to inject context into handlers:
+```go
+func Handler(c *context.Context, repo *context.Repository) {
+    // Dependencies automatically injected
+}
+```
+
+### Database Architecture
+
+**Dual ORM System** (migration in progress):
+- **XORM** (`internal/database/models.go`): Legacy ORM, being phased out
+- **GORM** (`internal/database/database.go`): New ORM for modern features
+
+**Global Database Handle**:
+```go
+// Access via database.Handle
+database.Handle.Users()          // *UsersStore
+database.Handle.Repositories()   // *RepositoriesStore
+database.Handle.Permissions()    // *PermissionsStore
+database.Handle.AccessTokens()   // *AccessTokensStore
+database.Handle.LoginSources()   // *LoginSourcesStore
+database.Handle.TwoFactors()     // *TwoFactorsStore
+```
+
+**Store Pattern**: Each domain has a dedicated "Store" (repository pattern) in `internal/database/`:
+- Stores encapsulate database operations for a domain
+- Methods accept `context.Context` as first parameter
+- Example: `UsersStore.GetByID()`, `UsersStore.Create()`, `UsersStore.Authenticate()`
+
+**Models** are defined alongside their stores in `internal/database/`:
+- `users.go`: User model + UsersStore
+- `repositories.go`: Repository model + RepositoriesStore
+- `permissions.go`: Access control logic
+- `issue.go`, `pull.go`: Issue and PR models
+- `webhook.go`: Webhook configuration
+
+**Migrations**: Located in `internal/database/migrations/`. Schema versioning via `Version` table.
+
+### Authentication System
+
+**Multi-Source Authentication** via Provider pattern (`internal/auth/`):
+
+Supported authentication types:
+1. **Plain**: Local database (bcrypt hashed passwords)
+2. **LDAP**: LDAP via BindDN
+3. **DLDAP**: LDAP simple auth (direct bind)
+4. **SMTP**: SMTP server authentication
+5. **PAM**: Linux PAM authentication
+6. **GitHub**: GitHub OAuth
+
+**Authentication Flow**:
+1. Check if local account (password hash validation)
+2. If external auth: Query login source from `login_sources` table
+3. Call `Provider.Authenticate()`
+4. Create/update user record
+5. Create session
+
+**Session Management**:
+- Configurable backend: file, Redis, memcache
+- Library: `github.com/go-macaron/session`
+
+**Token Authentication**:
+- Access tokens (SHA1 hashed) in `internal/database/access_tokens.go`
+- Priority: Session cookie → HTTP Basic Auth → Access token
+
+**Two-Factor Authentication**:
+- TOTP-based (Time-based One-Time Password)
+- Implementation in `internal/database/two_factors.go`
+
+### Git Operations
+
+**Git Command Execution**:
+- Wraps `github.com/gogs/git-module` library
+- Process management in `internal/process/` (timeouts, cancellation)
+
+**Git over HTTP** (`internal/route/repo/http.go`):
+- Proxies to `git-http-backend`
+- Operations: `git-upload-pack` (fetch/pull), `git-receive-pack` (push), `git-upload-archive`
+
+**Git over SSH** (`internal/cmd/serv.go`):
+- Called by SSH server via forced commands in `authorized_keys`
+- Parses `SSH_ORIGINAL_COMMAND`
+- Authenticates via public key
+- Executes Git commands directly
+
+**Git Hooks** (auto-generated per repository):
+- Scripts call `gogs hook pre-receive|update|post-receive`
+- Pre-receive: Branch protection, force push prevention
+- Post-receive: Trigger webhooks, update repository statistics
+
+**Repository Structure**:
+```
+<REPO_ROOT>/<owner>/<repo>.git/
+├── hooks/           # Git hooks (generated)
+├── custom_hooks/    # User-defined hooks
+├── objects/, refs/, etc.
+```
+
+### Template & View Rendering
+
+**Template Engine**: Go's `html/template` via Macaron renderer
+
+**Template Organization** (`templates/`):
+```
+templates/
+├── base/           # Layout and base components (head, header, footer)
+├── user/           # User-related pages (auth, settings)
+├── repo/           # Repository pages (home, issues, PRs, settings)
+├── admin/          # Admin panel
+├── org/            # Organization pages
+├── install.tmpl    # Installation wizard
+└── status/         # Error pages (404, 500)
+```
+
+**Custom Template Functions** (`internal/template/template.go`):
+- Config: `AppName()`, `AppURL()`, `AppVer()`
+- User: `AvatarLink()`, `UserProfileLink()`
+- Time: `TimeSince()`, `DateFmtLong()`
+- Git: `ShortSHA1()`, `RenderCommitMessage()`
+- String: `Str2HTML()`, `EllipsisString()`
+
+**Template Data Injection**:
+```go
+c.Data["Title"] = "Page Title"
+c.Data["User"] = user
+c.Success("user/page")  // renders templates/user/page.tmpl
+```
+
+**Localization**: Uses `github.com/go-macaron/i18n` with locale files in `conf/locale/*.ini`
+
+### Configuration System
+
+**INI-based Configuration**:
+- Default: `conf/app.ini` (embedded in binary)
+- User overrides: `custom/conf/app.ini` (runtime)
+- Loaded via `internal/conf/conf.go`
+
+**Custom Directory**: Everything under `custom/` overrides defaults:
+- `custom/conf/app.ini`: Configuration
+- `custom/templates/`: Template overrides
+- `custom/public/`: Static file overrides
+
+**Development Config** (`custom/conf/app.ini`):
+```ini
+RUN_MODE = dev
+
+[server]
+LOAD_ASSETS_FROM_DISK = true  # Load templates/public from disk (no rebuild needed)
+OFFLINE_MODE = true            # Work without internet
+
+[log.xorm]
+MODE = console                 # Enable SQL query logging
+```
+
+## Key Design Patterns
+
+### 1. Repository/Store Pattern
+Domain logic encapsulated in stores:
+```go
+user, err := database.Handle.Users().GetByUsername(ctx, username)
+```
+
+### 2. Middleware Chain Pattern
+Routes composed with middleware functions:
+```go
+m.Group("/user/settings", func() {
+    m.Get("", user.Settings)
+}, reqSignIn)
+```
+
+### 3. Provider Pattern
+Authentication sources implement common `Provider` interface
+
+### 4. Form Binding
+HTTP forms automatically bound to structs with validation:
+```go
+m.Post("/login", binding.Bind(form.SignIn{}), user.LoginPost)
+```
+
+### 5. Context Injection
+Macaron injects dependencies via reflection based on parameter types
+
+### 6. Service Layer
+Background services for long-running operations:
+- Cron jobs (`internal/cron/`): Repository statistics, cleanup
+- Mirror sync: Sync mirror repositories periodically
+- Webhook delivery: Async webhook delivery with retries
+
+## Important Development Notes
+
+### CSS Modifications
+**CRITICAL**: Never edit `.css` files directly! They are generated from `.less` files.
+
+1. Edit files in `public/less/`
+2. Run `task less` to regenerate CSS
+3. The `task less` command uses lessc with clean-css plugin
+
+### Template and Static Asset Development
+When actively developing templates/static files:
+
+1. Enable in `custom/conf/app.ini`:
+   ```ini
+   [server]
+   LOAD_ASSETS_FROM_DISK = true
+   ```
+2. No need to rebuild/restart after template changes
+3. Still run `task generate` if you modify `conf/`, `template/`, or `public/` structure
+
+### Database Testing
+- Use `internal/dbtest` helpers for database tests
+- In-memory SQLite for fast unit tests
+- PostgreSQL for integration tests
+- Run `task drop-test-db` to clean up test databases
+
+### Error Handling Patterns
+```go
+// Check specific error types
+if database.IsErrUserNotExist(err) {
+    c.NotFound()
+    return
+}
+
+// Generic error handling
+c.NotFoundOrError(err, "get user")
+
+// Always wrap errors with context
+return errors.Wrap(err, "description")
+```
+
+### Common Operations
+
+**Checking Permissions**:
+```go
+mode := database.Handle.Permissions().AccessMode(ctx, userID, repoID, options)
+if mode < database.AccessModeWrite {
+    // Deny access
+}
+```
+
+**Database Transactions**:
+```go
+return db.Transaction(func(tx *gorm.DB) error {
+    // Operations
+    return nil
+})
+```
+
+**Redirecting**:
+```go
+c.Redirect("/user/login")
+c.RedirectSubpath("/admin")  // Respects EXTERNAL_URL subpath
+```
+
+## Code Style
+
+- **Formatting**: Use `gofmt` and `goimports`
+- **Linting**: Configured via `.golangci.yml`
+- **Error Wrapping**: Always wrap errors with context
+- **Logging**: Use `log.Trace()`, `log.Info()`, `log.Error()` (from `unknwon.dev/clog/v2`)
+- **Comments**: English only in code comments and docstrings
+- **Style Guide**: Follow Sourcegraph's [Go style guide](https://docs.sourcegraph.com/dev/background-information/languages/go)
+
+## Contributing Guidelines
+
+From `.github/CONTRIBUTING.md`:
+
+- **Talk, then code**: Post proposals for new features to [Discussions - Proposal](https://github.com/gogs/gogs/discussions/categories/proposal)
+- **Self-review**: Always self-review before requesting reviews
+- **Incremental changes**: Make self-contained changes, avoid huge diffs
+- **No force push**: Unless absolutely necessary (makes review harder)
+- **English**: Use English in code comments and docstrings
+- **DO NOT** update locale files except `conf/locale_en-US.ini` (use [Crowdin](https://crowdin.com/project/gogs) instead)
+- **DO NOT** submit Docker compose files
+
+## Directory Structure Reference
+
+```
+/data/gogs/
+├── gogs.go                   # Main entry point
+├── gen.go                    # go:generate directives
+├── Taskfile.yml              # Build tasks
+├── conf/                     # Embedded default configuration and locales
+├── internal/                 # Private application code
+│   ├── cmd/                  # CLI commands (web, serv, hook, admin, etc.)
+│   ├── route/                # HTTP route handlers (admin, api, org, repo, user)
+│   ├── context/              # Request context types
+│   ├── database/             # ORM models and stores
+│   │   ├── migrations/       # Database migrations
+│   │   └── schemadoc/        # Schema documentation generator
+│   ├── auth/                 # Authentication providers (LDAP, SMTP, PAM, GitHub)
+│   ├── conf/                 # Configuration loading and validation
+│   ├── template/             # Template functions
+│   ├── form/                 # Form definitions and validation
+│   ├── gitutil/              # Git utilities
+│   ├── markup/               # Markdown/markup rendering
+│   ├── email/                # Email service
+│   ├── cron/                 # Scheduled tasks
+│   ├── ssh/                  # Built-in SSH server
+│   └── ...util/              # Utility packages (cryptoutil, strutil, pathutil, etc.)
+├── public/                   # Static assets
+│   ├── css/                  # Generated CSS (DO NOT EDIT)
+│   ├── less/                 # LESS source files (EDIT THESE)
+│   ├── js/
+│   └── img/
+├── templates/                # Go templates
+├── scripts/                  # Init scripts (systemd, supervisor, etc.)
+└── docs/                     # Developer documentation
+    └── dev/local_development.md
+```
+
+## Architectural Decisions
+
+### Single Binary Deployment
+- All assets embedded (CSS, JS, templates, locales)
+- SQLite support for zero external dependencies
+- Prioritizes simplicity for self-hosting
+
+### Dual ORM Migration
+- Migrating from XORM to GORM gradually
+- GORM offers better maintenance, features (hooks, preloading), cleaner API
+- Both coexist during transition to avoid breaking changes
+
+### Macaron Framework
+- Lightweight, fast, excellent middleware support
+- Good i18n/session ecosystem
+- Familiar API (similar to Martini)
+
+## Testing
+
+Run tests with:
+```bash
+task test
+```
+
+Tests use:
+- Standard Go testing framework
+- `internal/dbtest` for database test helpers
+- Mock generation via `go-mockgen` (see `mockgen.yaml`)
+- Race detection enabled by default
+
+## Debugging
+
+- **Development Mode**: Set `RUN_MODE = dev` in config
+- **SQL Logging**: Set `[log.xorm] MODE = console` in config
+- **Template Debugging**: Logs template name on render
+- **Logging Levels**: TRACE, INFO, WARN, ERROR, FATAL (configured in app.ini)