docs/guidelines-backend.md
This document covers backend-specific architecture and contribution expectations. For the general workflow see CONTRIBUTING.md, and for building and testing see development.md and testing.md.
The backend is written in Go. Web routing is handled by chi and database access goes through the XORM ORM. Understanding how the packages depend on each other is essential before contributing backend code.
The backend is split into top-level packages, each with a focused responsibility:
build: helper scripts used at compile timecmd: subcommands such as web, serv, hooks, doctor, and admin utilitiesmodels: data structures and database operations (XORM); keeps external
dependencies to a minimum
models/db: core database operationsmodels/fixtures: sample data used by testsmodels/migrations: schema migration scriptsmodules: standalone functionality with few dependencies
modules/setting: configuration handlingmodules/git: interaction with the Git command linerouters: request handlers, split into api, web, install, and privateservices: business logic that ties routers and models togethertemplates: Go HTML templatespublic: compiled frontend assetstests: integration and end-to-end test helpersDependencies only flow in one direction:
cmd → routers → services → models → modules
A package on the left may import a package on its right, but never the reverse.
services, models, routers.services/user, models/repository.When packages from different layers share a name, use a snake_case import alias to disambiguate:
import user_service "gitea.dev/services/user"
Operations that must roll back together should run inside db.WithTx() (or
db.WithTx2() when a value must be returned), defined in models/db/context.go.
Functions that participate in a transaction take a context.Context as their first
parameter so the transaction can be propagated.
x.Update(exemplar) without an explicit WHERE clause — it updates
every row in the table.SyncWithOptions(IgnoreDrop...) rather than a
plain Sync.SET IDENTITY_INSERT to be
enabled and PostgreSQL requires the sequence to be updated afterwards.Go dependencies are managed with Go Modules.
Pull requests should only modify go.mod and go.sum where it relates to the
change at hand, be it a bug fix or a new feature. Otherwise, these files should only
be touched by pull requests whose sole purpose is updating dependencies. Run
make tidy after any change to go.mod.
Any go.mod / go.sum update must be justified in the PR description and must be
verified by reviewers and the merger to reference an existing upstream commit.
The API is documented with Swagger and is modelled on the GitHub API.
Gitea's API should use the same endpoints and fields as the GitHub API where possible, unless there is a good reason to deviate.
If you notice a problem that would require a breaking change, leave a comment in the code for a future refactor to API v2 (which is currently not planned) rather than breaking v1.
modules/structs/ and
registered in routers/api/v1/swagger/options.go.modules/structs/ and
registered with its category under routers/api/v1/swagger/.In general, choose HTTP methods as follows:
page and limit query
options) and set the X-Total-Count header via ctx.SetTotalCountHeader(...).