参与贡献
如何报告问题、提出建议,或修改 ThirtyFile 代码。
所有参与者都须遵守行为准则。
问题与建议
- 创建 Issue,选择合适的表单:报告问题、Suggest an idea、Report an accessibility barrier、Improve the guides 或 Improve the code。表单会询问协助处理所需的信息。
- 先查看已有 Issue。如果已有相同问题,请补充到该 Issue,而非重复创建。
修改代码
禁止直接推送到 main。每项更改都通过独立分支的 Pull Request 提交。
- 从 Issue 开始。大于小修复的工作,先在 Issue 中讨论并确认方案。
- 从
main创建分支,按用途命名:分支 用途 feat/share-link-editing新增功能 fix/upload-resume问题修复 docs/backup-guide网站与指南 chore/update-actions工具、构建和依赖 - 完成更改,执行下方检查。
- 创建 Pull Request。标题用清晰语言说明改动,并添加一个标签。在说明中写
Closes #123,合并后即可关闭对应 Issue。 - 等待检查。轻量的 Checks passed 检查必须通过才能合并。
- 合并。Pull Request 在
main上压缩为一个提交,随后删除分支。
检查
创建 Pull Request 前,请使用统一脚本在本地运行完整检查。发布和手动完整验证也会运行这些检查;自动 Pull Request 检查更轻量。
scripts/check.sh
| 部分 | 检查内容 |
|---|---|
scripts/check.sh quick | 自动 Pull Request 检查:前端格式、翻译、模块边界、端到端测试结构、类型和 lint;Rust 格式;迁移编号及已发布迁移保持不变;网站链接。不运行单元/浏览器测试、Rust 编译或镜像构建 |
scripts/check.sh web | 界面:按锁文件安装依赖、格式(pnpm format:check)、翻译(node scripts/check-i18n.mjs)、确保 web/src/ooxml 的 Office 代码不导入应用其他模块(node scripts/check-boundaries.mjs)、确保端到端测试没有固定等待且名称包含随机部分(node scripts/check-e2e.mjs)、类型、lint 和单元测试。使用 scripts/check.sh web --coverage 时(与 GitHub 一样),覆盖率低于 web/vitest.config.ts 中的门槛也会失败 |
scripts/check.sh server | 服务器:格式(cargo fmt --check)、cargo test,以及将警告视为错误的 cargo clippy |
scripts/check.sh e2e | 端到端测试:通过真实浏览器(Playwright)对从仓库构建的服务器执行登录、上传和预览。多个测试并行运行(GitHub 上为 4 个),因此每个测试使用独立文件夹,名称含随机部分,操作后等待服务器响应而非固定时间;web/tests/e2e/helpers.ts 提供这些辅助功能。首次运行前,用 cd web && pnpm exec playwright install chromium 安装浏览器 |
scripts/check.sh site | 网站:每种语言都具有全部翻译页面及相互对应的语言链接,站内链接和锚点有效(node scripts/check-site.mjs)。仅需要 Node,修改网站时也会执行 |
Windows 上请在 Git Bash 中运行。GitHub 完整验证还会检查依赖的已知安全问题(cargo deny 和 pnpm audit);服务器测试与端到端测试合计必须覆盖至少 90% 的服务器代码行(cargo llvm-cov,门槛在 .github/workflows/build.yml)。
代码由工具格式化,未符合格式时检查会失败。提交前请格式化:
cd server && cargo fmt
cd web && pnpm format
服务器使用 rustfmt(配置在 server/rustfmt.toml),界面使用 oxfmt(配置在 web/.oxfmtrc.json;格式化 web/src、web/tests 和 web/scripts)。编辑器安装 rustfmt 或 oxfmt 扩展后可按同样设置在保存时格式化。手工排版、每行多项的表格可在上方加 // oxfmt-ignore 保持布局。web/src/lib/i18n/ 中的词典不格式化,保持每行一个条目。
仅调整格式的提交列在 .git-blame-ignore-revs。GitHub blame 视图会跳过这些提交;如需本地 git blame 也跳过,在克隆仓库中执行一次 git config blame.ignoreRevsFile .git-blame-ignore-revs。
- 代码、注释和指南源文使用英文。
- 界面文字在代码中使用英文,译文位于
web/src/lib/i18n/,每种语言一个文件夹,文件名保持一致。繁体中文(zh-TW)、简体中文(zh-CN)和日文(ja)均为必需语言:新增文字须按下方术语表补齐三种译文。node scripts/check-i18n.mjs检查所有语言:必需语言缺项,或保留代码已不再使用的条目时会失败;其他语言仅报告这些问题及占位译文数量。语言列入脚本的COMPLETE后即为必需语言,语言切换器提供的语言也必须完整。可用--require <language>查看新语言尚缺哪些内容。 - 服务器自行生成的邮件文字,以英文定义在
server/src/i18n/texts.rs,各语言译文位于旁边的文件(zh_tw.rs、zh_cn.rs、ja.rs)。缺少译文时使用英文。服务器测试会检查texts.rs中列入COMPLETE,或语言切换器提供的语言;缺少文字或{parameters}与英文不一致时会失败。 - 行为改变时,同步更新
site/docs/中描述该行为的指南。 - 0.4.0 的数据库结构已冻结,确保旧版本创建的数据继续有效。结构修改必须新增
server/migrations/0002_<name>.sql及后续编号的迁移文件,以升级 0.4.0 数据库。禁止修改0001_init.sql和此前版本已发布的迁移文件,检查会阻止这种修改。 - 网页应用的 API 类型(
web/src/api/types.ts)是手写的。服务器有一项测试把主要响应的结构记录在web/tests/contract/shapes.json,结构一改就会失败:在server/运行THIRTYFILE_UPDATE_SHAPES=1 cargo test api_shapes,再修改类型直到pnpm typecheck通过。 - 会更改用户文件的逻辑(公式、工作簿保存、文本编码)须在
web/tests/unit/中添加单元测试。
每个 Pull Request 都运行上述轻量检查。完整测试与镜像构建在正式发布和预发布前运行,也可在 Actions › Build › Run workflow 手动运行;手动验证不发布任何内容。发布前,两种架构的镜像都会使用 compose.yaml 在最新已发布版本的数据上启动。CodeQL 在合并后、每周及发布前扫描 main。合并到 main 不发布任何内容,网站也不发布:指南随版本发布,以描述用户实际可安装的功能。对当前已发布版本也正确的指南修复可手动发布:在 Actions › Website › Run workflow 中选择 main 为要发布的分支或标签。
其他语言的网站
首页和全部 16 篇指南提供英文、繁体中文、简体中文和日文版本。每种语言覆盖相同的 17 个页面:
| 页面 | 英文 | 其他语言 |
|---|---|---|
| 首页 | site/index.html | site/<language>/index.html |
| 安装 | site/docs/index.html | site/<language>/docs/index.html |
| 其他所有指南 | site/docs/<guide>.html | site/<language>/docs/<guide>.html |
指南菜单、相关链接、上一页/下一页链接和章节列表均保持当前语言。切换语言时停留在同一指南,有 JavaScript 时还会保留当前章节。README 也有翻译:README.md 旁有 README.zh-TW.md、README.zh-CN.md 和 README.ja.md,分别链接到对应语言网站。
- 修改翻译页面时,必须在同一个 Pull Request 中更新所有语言。如果不会某种语言,请在 Pull Request 中说明,维护者会安排其他人协助。
- 每个版本都有
<html lang>、独立标题和描述,以及指向所有版本(包括自身)的<link rel="alternate" hreflang>。每页直接写入语言切换器、指南菜单和章节列表,无 JavaScript 时仍可使用。所有语言的章节 ID 及命令/配置示例必须保持相同。 - 语言和所有页面列在
site/assets/site.js顶部的LANGUAGES和TRANSLATED中,该文件也保存菜单与页脚译文。修改导航或指南标题后,运行node scripts/update-site-navigation.mjs更新静态菜单和章节列表。scripts/check.sh site会检查翻译缺漏、错误元数据或语言切换器、缺失章节、改变的代码区块、损坏链接和意外跨语言链接。每次新增页面必须在同一个 Pull Request 中补齐所有支持语言。运行node --test scripts/check-site.test.mjs测试检查器;安装前端的 Playwright 依赖和 Chromium 后,node scripts/check-site-browser.mjs <scratch-directory>可检查实际页面、语言与章节切换、移动布局和无 JavaScript 导航,并将截图保存到网站目录外。 - 用词遵循术语表(
web/src/lib/i18n/glossary.md),与界面译文一致。简体中文使用中国大陆的习惯用语,而非仅转换繁体字;日文句子使用です・ます,并采用 Windows 文件资源管理器与 Finder 的术语。 - 首页主要截图为各语言分别拍摄:本地实例与示例数据、1280 × 720、2 倍缩放,保存为 WebP(
site/assets/files-light-<language>.webp和files-dark-<language>.webp)。其他截图保持英文。
标签
| 标签 | 版本说明中的分类 |
|---|---|
enhancement | 新功能 |
bug | 修复 |
performance | 性能提升 |
accessibility | 更易使用 |
documentation | 指南与网站 |
dependencies | 依赖更新 |
maintenance | 维护 |
发布版本
正式镜像同时发布到 ghcr.io/thirtyfile/thirtyfile 和 docker.io/thirtyfile/thirtyfile。首次向 Docker Hub 发布前,在 Settings › Secrets and variables › Actions 中添加 Actions variable DOCKERHUB_USERNAME 和 secret DOCKERHUB_TOKEN。使用可读写该仓库的 Docker Hub access token。发布流程会在扫描与构建前检查凭据,按 digest 复制已验证的镜像,并在发布 GitHub release 前验证每个 Docker Hub 标签。
合并后的更改累积在 main,由维护者决定何时发布。发布须手动启动:在 GitHub 打开 Actions › Release › Run workflow,保留 main,输入新版本号,例如 1.2.3;预发布使用 1.2.3-rc.1。也可运行:
gh workflow run release.yml -f version=1.2.3
流程对 main 执行 CodeQL 扫描、测试,构建并启动 amd64 与 arm64 镜像。全部通过后才推送尚未附加标签的镜像。接着依序:从镜像提取两种架构的服务器程序,与校验码、许可声明和指向版本系列的 compose.yaml 创建草稿 release(1.0.0 之前为 :1.2,之后为 :1);不重新构建,给镜像添加 1.2.3、1.2、1(从 1.0.0 起)及 latest 标签;发布 release,创建 v1.2.3 标签,说明由上次发布以来合并的 Pull Request 生成;最后从该标签发布网站。如果扫描发现未关闭的 high 或 critical 告警,或者测试或镜像失败,不会推送、添加标签或发布。修复告警,或在不适用时从 Security › Code scanning 中关闭告警,再次运行发布。后续步骤失败时,用相同版本号重试,会发布已标记为 1.2.3 的镜像,而非重新构建。版本号必须比上次发布更新。以 v 开头的标签不能移动或删除。
含 - 的版本号,例如 1.2.3-rc.1,为预发布:镜像仅添加 1.2.3-rc.1 标签,GitHub 将其标为预发布,用户必须主动选择才会获得;预发布不会发布网站。预发布验证通过且之后没有合并新提交时,可从同一提交发布 1.2.3:流程直接为预发布镜像添加标签,不重新构建,确保发布的就是已试用的内容(镜像版本标签仍显示预发布版本)。
| 版本位 | 递增时机 |
|---|---|
第一位(2.0.0) | 修改或移除用户依赖的行为 |
第二位(1.3.0) | 新增功能 |
第三位(1.2.4) | 仅修复问题 |
复制已有版本时,在 Actions › Mirror a release to Docker Hub › Run workflow 中选择 main,填写已发布版本,例如 0.6.0。流程先验证 Git 标签、镜像 revision 和已签名的 GHCR 来源证明,再复制镜像。仅当 GHCR 对应的版本系列、主版本或 latest 标签目前指向同一镜像时,才更新该标签;镜像旧版本不会覆盖更新版本。已有的精确版本标签必须与源 digest 一致,否则流程停止。内容一致的复制可安全重试,不会重新构建镜像。
许可证
ThirtyFile 采用 Apache License 2.0,贡献内容遵循相同条款。
依赖须采用宽松许可证:Rust 依赖按 server/deny.toml 清单检查,server/about.toml 使用相同清单;npm 包按 web/scripts/third-party-notices.mjs 中相同清单(另加字体许可证 OFL-1.1)检查,两者均有测试。镜像构建会把所有 crate、npm 包、musl、证书颁发机构和时区数据库的许可声明汇总为 THIRD-PARTY-NOTICES;出现清单之外的许可证时构建失败。