Seven pages covering Home, Architecture, Services, Code Generation, Configuration, Error Handling, and Development. Co-Authored-By: Virgil <virgil@lethean.io> Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
125 lines
3.6 KiB
Markdown
125 lines
3.6 KiB
Markdown
# Code Generation
|
|
|
|
All Go types in the `types/` package are generated from the Forgejo Swagger 2.0 specification. This page explains how the pipeline works and how to regenerate types.
|
|
|
|
## Pipeline
|
|
|
|
```
|
|
testdata/swagger.v1.json
|
|
|
|
|
v
|
|
cmd/forgegen/parser.go (parse spec, extract types, detect CRUD pairs)
|
|
|
|
|
v
|
|
cmd/forgegen/generator.go (group types by domain, emit Go source)
|
|
|
|
|
v
|
|
types/*.go (229 types across 36 files)
|
|
```
|
|
|
|
## Regenerating Types
|
|
|
|
```bash
|
|
go generate ./types/...
|
|
```
|
|
|
|
This runs the `//go:generate` directive in `types/generate.go`:
|
|
|
|
```go
|
|
//go:generate go run ../cmd/forgegen/ -spec ../testdata/swagger.v1.json -out .
|
|
```
|
|
|
|
You can also run the generator directly:
|
|
|
|
```bash
|
|
go run ./cmd/forgegen/ -spec testdata/swagger.v1.json -out types/
|
|
```
|
|
|
|
## Upgrading Forgejo Version
|
|
|
|
1. Download the new `swagger.v1.json` from your Forgejo instance at `/swagger.json`.
|
|
2. Replace `testdata/swagger.v1.json` with the new file.
|
|
3. Regenerate types:
|
|
```bash
|
|
go generate ./types/...
|
|
```
|
|
4. Verify compilation:
|
|
```bash
|
|
go build ./...
|
|
```
|
|
5. Run tests:
|
|
```bash
|
|
go test ./...
|
|
```
|
|
6. Review the diff for new, changed, or removed types.
|
|
|
|
## How It Works
|
|
|
|
### Parser (`cmd/forgegen/parser.go`)
|
|
|
|
- **`LoadSpec`** — reads and parses the JSON spec file.
|
|
- **`ExtractTypes`** — converts all `definitions` into `GoType` structs with fields, JSON tags, and Go type mappings.
|
|
- **`DetectCRUDPairs`** — finds matching `Create*Option`/`Edit*Option` pairs (e.g. `CreateRepoOption` + `EditRepoOption` = base `Repo`).
|
|
|
|
Type mapping rules:
|
|
|
|
| Swagger Type | Go Type |
|
|
|--------------------|----------------|
|
|
| `string` | `string` |
|
|
| `string` + `date-time` | `time.Time` |
|
|
| `string` + `binary` | `[]byte` |
|
|
| `integer` + `int64` | `int64` |
|
|
| `integer` + `int32` | `int32` |
|
|
| `boolean` | `bool` |
|
|
| `number` + `float` | `float32` |
|
|
| `number` | `float64` |
|
|
| `array` | `[]<item type>`|
|
|
| `object` | `map[string]any`|
|
|
| `$ref` | `*<TypeName>` |
|
|
|
|
### Generator (`cmd/forgegen/generator.go`)
|
|
|
|
- **`classifyType`** — assigns each type to a domain file (e.g. `Repository` -> `repo.go`, `Issue` -> `issue.go`).
|
|
- **`Generate`** — groups types by file, sorts alphabetically, and writes each file.
|
|
- **`writeFile`** — uses `text/template` to emit valid Go with `package types`, conditional `import "time"`, and `// Code generated` headers.
|
|
|
|
### Type Grouping
|
|
|
|
Types are grouped by prefix matching against a domain map:
|
|
|
|
| Prefix/Name | File |
|
|
|------------------|-----------------|
|
|
| `Repository`, `Repo` | `repo.go` |
|
|
| `Issue` | `issue.go` |
|
|
| `PullRequest`, `Pull` | `pr.go` |
|
|
| `User` | `user.go` |
|
|
| `Organization`, `Org` | `org.go` |
|
|
| `Team` | `team.go` |
|
|
| `Branch` | `branch.go` |
|
|
| `Release` | `release.go` |
|
|
| `Hook` | `hook.go` |
|
|
| `Commit`, `Git` | `commit.go`/`git.go` |
|
|
| `Package` | `package.go` |
|
|
| `Action`, `Secret`, `Variable` | `action.go` |
|
|
| `Notification` | `notification.go` |
|
|
| `Wiki` | `wiki.go` |
|
|
| (unmatched) | `misc.go` |
|
|
|
|
## Generated File Format
|
|
|
|
Each file follows this structure:
|
|
|
|
```go
|
|
// Code generated by forgegen from swagger.v1.json — DO NOT EDIT.
|
|
|
|
package types
|
|
|
|
import "time" // only if time.Time fields are present
|
|
|
|
// TypeName — description from swagger spec.
|
|
type TypeName struct {
|
|
FieldName GoType `json:"field_name,omitempty"`
|
|
}
|
|
```
|
|
|
|
Fields marked as `required` in the spec omit the `,omitempty` JSON tag option.
|