1 Code-Generation
Virgil edited this page 2026-02-21 17:14:21 +00:00

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

go generate ./types/...

This runs the //go:generate directive in types/generate.go:

//go:generate go run ../cmd/forgegen/ -spec ../testdata/swagger.v1.json -out .

You can also run the generator directly:

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:
    go generate ./types/...
    
  4. Verify compilation:
    go build ./...
    
  5. Run tests:
    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:

// 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.