首页
/ Gitea 源码开发工作流:从 make build 到 Swagger 校验的完整构建与调试指南

Gitea 源码开发工作流:从 make build 到 Swagger 校验的完整构建与调试指南

2026-09-05 15:28:38作者:尤辰城Agatha

Gitea 采用前后端分离的构建体系:Go 编写后端、TypeScript/Vue 编写前端,通过 Makefile 统一编排 make buildmake watchmake lint 等开发命令。本篇基于仓库中的 docs/development.mdMakefile 的实际内容,系统讲解从源码构建、热重载开发,到格式化/Lint 检查、SVG 图标生成、Swagger API 文档更新、配置项扩展与数据库迁移的完整日常开发流程,帮助你在本地环境中独立完成 Gitea 的构建、调试与提交前自检。

从源码构建 Gitea

构建开发版 Gitea 的核心命令只有一条:

make build

开发构建不需要任何 build tags:SQLite 支持默认编译进二进制(在 Makefile 中可以看到 CGO_TAGS := sqlite_mattn pam,只有当 TAGS 中包含这些 tag 时才会自动把 CGO_ENABLED 置为 1),本地开发完全够用。bindata tag 的作用是把前端资源嵌入二进制,仅在制作自包含的分发构建时才需要,日常开发应省略。

Makefile 可以看到 build 目标的实际编排:

build: frontend backend ## build everything
  • frontend:依赖 public/assets/.vite/manifest.json,即执行 pnpm exec vite build,把 web_src/jsweb_src/css 编译产物输出到 public/assets 下(FRONTEND_DEST 变量定义于 Makefile)。
  • backend:先执行 generate-backend(运行 go generate,见 Makefile),再编译出可执行文件 gitea。最终调用为 go build -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)',其中 LDFLAGS 会注入 main.Versionmain.Tags 两个变量——这正是 main.go 中声明的:
// these flags will be set by the build flags
var (
	Version = "development" // program version for this build
	Tags    = ""            // the Golang build tags
)

版本号的推导逻辑也很清晰(Makefile):tag 构建去掉 v 前缀作为正式版本号;release/v1.2 分支会得到 1.2-nightly;普通分支(如 main)则通过 git describe 生成形如 1.28.0+dev-356-ge47d0b66ea 的开发版本号。

使用 make help 可以列出全部可用 target(该 target 通过解析 Makefile 中 ## 注释生成帮助文本,见 Makefile)。持续集成如何构建和检查 Gitea,可以直接参考仓库内 .github/workflows 目录下的 workflow 文件(例如 pull-db-tests.yml 等)。

持续构建:让改动自动生效

开发过程中频繁修改源码,可以用 watch 命令实现文件变更自动重新构建:

# 同时监听前端和后端
make watch

# 只监听前端(启动 Vite dev server)
make watch-frontend

# 只监听后端(Go)
make watch-backend

Makefile 可以看到三者的实现细节:

  • make watch 实际是执行 bash tools/watch.sh(见 tools/watch.sh),由脚本协调前后端两个监听进程;
  • make watch-frontend 启动 NODE_ENV=development pnpm exec vite,即 Vite 开发服务器,日志级别由 FRONTEND_DEV_LOG_LEVEL(默认 warn)控制;
  • make watch-backend 则通过 air 工具实现:GITEA_RUN_MODE=dev go run github.com/air-verse/air@v1.67.4 -c .air.toml,监听配置定义在仓库根目录的 .air.toml

一个需要注意的坑:监听全部后端源文件可能触及 macOS / Linux 默认的文件描述符上限(open files limit),导致 air 报 EMFILE 类错误。解决方法是提高当前 shell 的限制,或写入 shell 启动文件使其持久生效:

ulimit -n 12288

格式化、Lint 与一致性检查

持续集成会拒绝未通过格式化、Lint 或一致性检查的 PR,因此提交前务必在本地先跑:

# 1. 先格式化
make fmt

# 2. 再 Lint:全量或分端
make lint            # lint everything
make lint-backend    # 只查后端
make lint-frontend   # 只查前端

make fmt 做了两件事(Makefile):用 golangci-lint 的 fmt 子命令格式化 Go 代码,并用 sed 规则整理 templates 下所有 .tmpl 文件的空白(去除 {{( 之后的以及 }}) 之前的多余空格)。

make lint 的完整覆盖面(Makefile)包括:

目标 检查内容 工具
lint-js web_src/jstoolstests/e2e 下的 JS/TS ESLint(--max-warnings=0)+ vue-tsc
lint-css CSS 及 Vue 组件样式 stylelint
lint-go 全部 Go 源码 通过 tools/lint-go-all.go 调度 golangci-lint
lint-spell 拼写检查(Go 目录 + 模板 + 英文本地化文件等) misspell,自定义字典 assets/misspellings.csv
lint-swagger Swagger/OpenAPI 规范 spectral
lint-yaml / lint-json / lint-shell / lint-actions 各类配置文件 yamllint、ESLint、shellcheck(容器内执行)、actionlint + zizmor

其中 lint-go 的调度脚本是 tools/lint-go-all.go,配置基于仓库根目录的 .golangci.yml;前端则使用 eslint.config.tsstylelint.config.ts

许多问题可以自动修复:

make lint-fix              # 全量自动修复
make lint-backend-fix      # 只修复后端
make lint-frontend-fix     # 只修复前端

CI 所执行的“组合一致性检查”对应 make checks,它在 Makefile 中拆分为两条支线:

checks-frontend: lockfile-check svg-check
checks-backend:  tidy-check swagger-check openapi3-check fmt-check swagger-validate security-check

即后端侧除了格式与 Swagger/OpenAPI 校验,还会检查 go mod tidy 结果是否已提交(tidy-check),并用 govulncheck 做依赖安全扫描(security-check)。

构建与新增 SVG 图标

Gitea 的 SVG 图标通过 make svg 构建:它先清空 public/assets/img/svg,再运行 node tools/generate-svg.ts 把图标源编译到目标目录(Makefile)。

  • 图标源文件目录:web_src/svg
  • 输出目录:public/assets/img/svg 以及 options/fileiconSVG_DEST_DIRS 定义于 Makefile

CI 通过 svg-check 强制图标产物与源保持同步:重新生成后 git add 目标目录并 diff,若存在未提交的差异则直接失败(Makefile)。因此新增自定义图标的正确姿势是:在 web_src/svg 下添加源文件,运行 make svg,把生成的产物一并提交。

更新 API 文档(Swagger)

当你创建或修改 API 路由时,必须使用 go-swagger 注释更新 Swagger 文档。API 路由、请求/响应结构体与 swagger 定义之间的配合方式,详见 后端开发指南

改动端点后,重新生成并校验规范,然后提交更新后的 JSON:

make generate-swagger   # 从代码注释生成规范
make swagger-validate    # 校验规范有效性

Makefile 可以看到生成链的细节:

  • 输入模板:templates/swagger/v1-input.json
  • 产物:templates/swagger/v1-swagger.generated.json(Swagger 2.0)与 templates/swagger/v1-openapi3.generated.json(由 go run build/generate-openapi.go 转换,见 build/generate-openapi.go);
  • 生成时排除 gitea.dev/sdk 包(SWAGGER_EXCLUDE),且要求生成过程零 warning;
  • swagger-validate 会拦截任何 WARNING: 输出,校验失败即退出非零。

CI 用下面的命令验证提交的规范与代码保持同步:

make swagger-check

其实现(Makefile)就是重新执行 generate-swagger,然后对 v1-swagger.generated.jsongit diff——有 diff 就报错要求重新生成并提交。OpenAPI3 规范同理(openapi3-check)。

新增配置项的完整流程

在 Gitea 中增加一个配置项,仅修改 modules/setting 下的解析文件是不够的,完整的清单是:

  1. modules/setting 相应文件中读取新选项;
  2. 更新示例配置文件 custom/conf/app.example.ini,让部署者能看到新选项;
  3. 在官方文档仓库的配置速查表(config cheat sheet)中补充文档说明(该速查表托管在独立的文档仓库中,不在本仓库内)。

这样做的意义在于:Gitea 的安装向导与文档均以 app.example.ini 为配置项的“单一事实来源之一”,遗漏更新会导致新配置无法被自助发现。

数据库迁移

models/ 目录下数据库持久化结构体做了破坏性变更(增删字段、改类型、加索引等)时,需要在 modelmigration/ 下添加一个新的迁移文件。该目录按版本组织为 v1_6/v1_27/ 以及 v28/ 等子包,每个迁移是一个带固定编号的 Go 文件(例如 v1_27/v342.go 是最新编号),迁移注册总表见 modelmigration/migrations.go

迁移的测试运行方式见 测试指南

make test-migration

迁移测试还会用到各迁移对应的 fixture 数据(位于 modelmigration/fixtures)。

测试概览

单元测试、集成测试、端到端测试与迁移测试的详细方法见 docs/testing.md,此处仅给出与日常开发最相关的入口:

make test-backend                    # Go 单元测试(本地默认 SQLite)
make test-backend#TestName           # 跑单个后端测试
make test-integration                # 集成测试
make test-integration#TestName       # 跑单个集成测试
make test-e2e                        # Playwright 端到端测试
make test-migration                  # 迁移测试

值得注意的实现细节:

  • Makefile 中,本地(非 CI)运行 test-* 目标时默认 GITEA_TEST_DATABASE=sqlite,无需任何外部数据库服务;
  • 集成测试使用编译好的 gitea 二进制而非直接 go testMakefile 有注释说明:testlogger 会把 gitea 日志转发到 t.Log,直接 -v 会刷屏);
  • 跑单个测试的 # 选择器本质是把 TestName 转成 go test -run 的正则($(subst .,/,$*))。

IDE 配置

Visual Studio Code

仓库在 contrib/development/vscode 提供了 launch.jsontasks.jsonsettings.json 三个文件。使用方法是:在 Gitea 仓库根目录新建 .vscode 目录,把该目录内容复制进去,之后即可用 Ctrl+Shift+B 构建 gitea 可执行文件、F5 进入调试模式。更多说明见 contrib/development/README.md(该 README 说明支持 Debian、Ubuntu、Red Hat、Fedora、SUSE Linux、macOS 与 Windows)。

GoLand

main.gofunc main() 上点击 Run Application 箭头,即可启动一个可调试的 Gitea 实例。

关键配置:Run/Debug Configuration 中的 Output Directory 必须设置为 Gitea 项目根目录(即包含 main.gogo.mod 的目录)。否则工作目录会是 GoLand 的临时目录,导致 Gitea 在开发模式下无法加载动态资源(如 templates/ 下的模板文件)。

提交你的改动

推送分支并发起 PR 即可;评审流程与 PR 要求见 CONTRIBUTING.md。提交前建议按本文顺序做一次完整自检:

make fmt
make lint
make checks
make test-backend

如果 PR 涉及 API 端点,追加 make generate-swagger && make swagger-validate;涉及 models/ 结构体,追加 make test-migration。需要帮助时可加入官方 Discord 的 #Develop 频道。

登录后查看全文
热门项目推荐
相关项目推荐