Moves the "Hacking on Gitea" page out of the documentation website and into the repository as `docs/development.md`, so contributors find build and test instructions next to the code. The content has been cleaned up and corrected for in-repo use. --------- Signed-off-by: bircni <bircni@icloud.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
5.3 KiB
Backend development guidelines
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.
Background
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.
Package design
Package layout
The backend is split into top-level packages, each with a focused responsibility:
build: helper scripts used at compile timecmd: subcommands such asweb,serv,hooks,doctor, and admin utilitiesmodels: data structures and database operations (XORM); keeps external dependencies to a minimummodels/db: core database operationsmodels/fixtures: sample data used by testsmodels/migrations: schema migration scripts
modules: standalone functionality with few dependenciesmodules/setting: configuration handlingmodules/git: interaction with the Git command line
routers: request handlers, split intoapi,web,install, andprivateservices: business logic that ties routers and models togethertemplates: Go HTML templatespublic: compiled frontend assetstests: integration and end-to-end test helpers
Dependency direction
Dependencies 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.
Naming conventions
- Top-level packages use the plural form:
services,models,routers. - Subpackages use the singular form:
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"
Database transactions
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.
XORM gotchas
- Never call
x.Update(exemplar)without an explicitWHEREclause — it updates every row in the table. - Partial table migrations must use
SyncWithOptions(IgnoreDrop...)rather than a plainSync. - When inserting rows with preset IDs, MSSQL requires
SET IDENTITY_INSERTto be enabled and PostgreSQL requires the sequence to be updated afterwards.
Dependencies
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.
API v1
The API is documented with Swagger and is modelled on the GitHub API.
GitHub API compatibility
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 Gitea offers functionality GitHub does not, a new endpoint may be added.
- If Gitea exposes information the GitHub API does not, a new field may be added as long as it does not collide with a GitHub field.
- Existing fields should not be removed unless there is a strong reason; the same applies to status responses.
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.
Adding and maintaining API routes
- All possible results (errors, success, and failure messages) must be documented in the swagger comments on the route.
- Every JSON request body must be defined as a struct in
modules/structs/and registered inrouters/api/v1/swagger/options.go. - Every JSON response must be defined as a struct in
modules/structs/and registered with its category underrouters/api/v1/swagger/.
HTTP methods and status codes
In general, choose HTTP methods as follows:
- GET returns the requested object(s) with status 200 OK.
- POST creates a new object (e.g. a user) and returns 201 Created with the created object.
- PUT adds or assigns an existing object (e.g. a user to a team) and returns 204 No Content with no body.
- PATCH edits an existing object and returns the changed object with 200 OK.
- DELETE removes an object and returns 204 No Content with no body.
Requirements for API routes
- All parameters of endpoints that edit an object must be optional, except those needed to identify the object, which are required.
- Endpoints returning lists must support pagination (
pageandlimitquery options) and set theX-Total-Countheader viactx.SetTotalCountHeader(...).