Repository navigation
Preserve unchanged issue comments during incremental GitHub sync #152
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| # dev 也要跑,为的是缓存:GitHub 只让 PR 读到自己、base 分支和默认分支的缓存, | |
| # 而此前没有任何一次 CI 在 dev 上跑过,于是 PR 之间互相看不见对方存的东西, | |
| # 每次都从零编 300 多个依赖——今天 12 次 backend 运行,恢复缓存全是 No cache found。 | |
| # 顺带把「合并后的 dev 从没被 CI 跑过」这个口子堵上(见下面 migrations job 的注释) | |
| branches: [main, dev] | |
| pull_request: | |
| # **显式只读。** 没有这一块时它继承仓库级默认,而那个默认要为 | |
| # star-history 改成读写——CI 是每次推送、每个 PR 都跑的那个 workflow, | |
| # 不该因为别处的需要顺带拿到写权限。写在这里,仓库默认怎么变都与它无关 | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| # lint / test / build 三个 job 并行。它们互不共享产物:clippy 是 check 模式,build 是 | |
| # 非测试的 codegen,test 是 test profile——串在一个 job 里只是把 clippy 和 build | |
| # 排到了关键路径上(缓存命中后各 36s 和 39s,未命中 143s 和 51s)。 | |
| # 分支保护按名字要求 backend 与 web 通过,所以 backend 保留为下面的汇总 job; | |
| # 直接改名会让 clippy 和 build 悄悄退出合并门槛 | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| # 只有 push(dev / main)那次运行才写缓存,PR 只读。此前每个 PR 各存约 2GB, | |
| # 仓库上限 10GB,五六个 PR 就挤满,按 LRU 淘汰——同一个 PR 第二次跑时自己上次 | |
| # 存的也已经没了:17 条缓存的最后访问时间全等于创建时间,从来没人读到过 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.event_name == 'push' }} | |
| - name: Format | |
| run: cargo fmt --all --check | |
| - name: Clippy | |
| run: cargo clippy --workspace --all-targets -- -D warnings | |
| # 连库测试在这里跑。从前它们放在下面的 migrations job:那边有库、这边没有, | |
| # 于是同一批测试二进制被编了两遍——`cargo test --workspace` 编一遍然后全部跳过, | |
| # migrations 再编一遍才真的跑。给这个 job 也起一个 Postgres,一次编译全部跑完, | |
| # migrations job 只留迁移本身的检查。连库测试由此进了 backend 汇总,才真正成为合并门槛 | |
| test: | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: pgvector/pgvector:pg16 | |
| env: | |
| POSTGRES_USER: utopia | |
| POSTGRES_PASSWORD: utopia | |
| POSTGRES_DB: utopia | |
| ports: ["5432:5432"] | |
| options: >- | |
| --health-cmd pg_isready --health-interval 5s | |
| --health-timeout 5s --health-retries 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| # 只在 push 时写缓存,理由见 lint job 同一处的注释 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.event_name == 'push' }} | |
| - name: Install PDF text extraction tools | |
| run: sudo apt-get update && sudo apt-get install -y poppler-utils poppler-data | |
| # 库要先迁移好:store 的一百多个集成测试和 server 的多数 fixture 不自己跑迁移, | |
| # 对着空库并发起几百个测试会成片撞 relation "organizations" does not exist(#869)。 | |
| # 不用 sqlx-cli——装它要一分多钟,而这个 job 在关键路径上;这个 example 复用 | |
| # 测试本来就要编的 utopia-store,几乎不花额外时间 | |
| - name: 迁移测试库 | |
| run: cargo run -p utopia-store --example migrate | |
| env: | |
| UTOPIA_DATABASE_URL: postgres://utopia:utopia@localhost:5432/utopia | |
| - name: Test | |
| run: cargo test --workspace | |
| # 装了 Poppler 就必须真的用它测:没有它时 PDF 回退的那个测试会跳过, | |
| # 而一个静静跳过的测试等于没写(#248)。库同理:有库就**必须**连 | |
| # (UTOPIA_TEST_REQUIRE_DB),连库测试没跑成要红,不能跳过显示绿色 | |
| env: | |
| UTOPIA_TEST_REQUIRE_PDFTOTEXT: "1" | |
| UTOPIA_DATABASE_URL: postgres://utopia:utopia@localhost:5432/utopia | |
| UTOPIA_TEST_REQUIRE_DB: "1" | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| # 只在 push 时写缓存,理由见 lint job 同一处的注释 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.event_name == 'push' }} | |
| - name: Build | |
| run: cargo build --workspace | |
| # 汇总。分支保护要求的检查名是 backend,上面三个 job 任何一个不是 success 它就红—— | |
| # `if: always()` 是为了上游失败或取消时它也跑,而不是被跳过后显示为「未报告」 | |
| backend: | |
| runs-on: ubuntu-latest | |
| needs: [lint, test, build] | |
| if: always() | |
| steps: | |
| - name: 汇总 | |
| run: | | |
| echo "lint=${{ needs.lint.result }} test=${{ needs.test.result }} build=${{ needs.build.result }}" | |
| test "${{ needs.lint.result }}" = success | |
| test "${{ needs.test.result }}" = success | |
| test "${{ needs.build.result }}" = success | |
| # 迁移得真的在库上跑一遍。此前 CI 只有 fmt/clippy/test/build,于是两个 PR | |
| # 各带一个 0025、各自通过,合进 main 之后服务直接起不来——sqlx 按版本号索引, | |
| # 而**合并后的状态从来没有被任何一次 CI 跑过**。 | |
| migrations: | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: pgvector/pgvector:pg16 | |
| env: | |
| POSTGRES_USER: utopia | |
| POSTGRES_PASSWORD: utopia | |
| POSTGRES_DB: utopia | |
| ports: ["5432:5432"] | |
| options: >- | |
| --health-cmd pg_isready --health-interval 5s | |
| --health-timeout 5s --health-retries 10 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # 撞号在文件层面不是冲突,git 合得干干净净——只能显式查 | |
| - name: 版本号不得重复 | |
| run: | | |
| dupes=$(ls migrations/ | cut -d_ -f1 | sort | uniq -d) | |
| if [ -n "$dupes" ]; then | |
| echo "::error::迁移版本号重复:$dupes" | |
| ls migrations/ | |
| exit 1 | |
| fi | |
| - uses: dtolnay/rust-toolchain@stable | |
| # 只在 push 时写缓存,理由见 backend job 同一处的注释 | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.event_name == 'push' }} | |
| - name: 装 sqlx-cli | |
| run: cargo install sqlx-cli --no-default-features --features rustls,postgres --locked | |
| - name: 全新库上跑一遍 | |
| run: sqlx migrate run --database-url postgres://utopia:utopia@localhost:5432/utopia | |
| # 第二遍必须也过:迁移改号后要能在已经跑过旧号的库上安全重放 | |
| - name: 再跑一遍 | |
| run: sqlx migrate run --database-url postgres://utopia:utopia@localhost:5432/utopia | |
| # 连库测试不在这里:它们随 backend job 的 `cargo test --workspace` 一起跑, | |
| # 那边同样有库、同样设了 UTOPIA_TEST_REQUIRE_DB。曾经放在这里是因为只有这个 job | |
| # 有库,代价是同一批测试二进制编两遍;这个 job 现在只管迁移本身能不能跑、能不能重放 | |
| web: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: web | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # 版本来自 web/package.json 的 packageManager 字段——这里再写一次 | |
| # 就成了第二个事实来源,两边迟早分叉(镜像构建就是这么炸的)。 | |
| # package_json_file 必须显式给:上面的 working-directory 只管 run 步骤, | |
| # 这个 action 默认在仓库根找 package.json,而根目录是 Cargo workspace。 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| package_json_file: web/package.json | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: pnpm | |
| cache-dependency-path: web/pnpm-lock.yaml | |
| - name: Install | |
| run: pnpm install --frozen-lockfile | |
| - name: Test | |
| run: pnpm test | |
| - name: Build (含类型检查) | |
| run: pnpm build |