From 1c9846dc57f8ce37c2a1669780e166006fd31695 Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Fri, 11 Sep 2026 11:28:50 +0800 Subject: [PATCH] fix(ci): remove Cargo-backed docs export smoke --- .github/workflows/ci.yml | 91 +------------------ .../docs-export/__tests__/exportSmoke.spec.ts | 53 ----------- crates/dbx-core/examples/docs_export_smoke.rs | 89 ------------------ 3 files changed, 2 insertions(+), 231 deletions(-) delete mode 100644 apps/desktop/src/docs-export/__tests__/exportSmoke.spec.ts delete mode 100644 crates/dbx-core/examples/docs_export_smoke.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a66a09b77..bb14fa4c7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,12 +21,6 @@ jobs: env: # The workspace intentionally contains platform-specific CLI/MCP packages for every release target. NPM_CONFIG_LOGLEVEL: error - # Same two-layer cache as rust-test/rust-fmt-clippy: sccache cannot - # reuse Cargo incremental artifacts, so avoid generating them in CI. - CARGO_INCREMENTAL: "0" - RUSTC_WRAPPER: sccache - # Fork PRs cannot read repository secrets, so retain the GHA backend for them. - SCCACHE_GHA_ENABLED: ${{ secrets.SCCACHE_S3_BUCKET == '' && 'true' || 'false' }} steps: - uses: actions/checkout@v5 @@ -44,92 +38,11 @@ jobs: - name: Install frontend dependencies run: pnpm --filter dbx... install --frozen-lockfile - - name: Setup Rust - uses: dtolnay/rust-toolchain@1.97.1 - - - name: Setup sccache - uses: mozilla-actions/sccache-action@9e7fa8a12102821edf02ca5dbea1acd0f89a2696 # v0.0.10 - with: - version: "v0.10.0" - - - name: Configure S3 sccache - if: env.SCCACHE_GHA_ENABLED != 'true' - shell: bash - env: - CACHE_BUCKET: ${{ secrets.SCCACHE_S3_BUCKET }} - CACHE_ENDPOINT: ${{ secrets.SCCACHE_S3_ENDPOINT }} - CACHE_REGION: ${{ secrets.SCCACHE_S3_REGION }} - CACHE_KEY_PREFIX: ${{ secrets.SCCACHE_S3_KEY_PREFIX }} - CACHE_ACCESS_KEY_ID: ${{ secrets.SCCACHE_S3_ACCESS_KEY_ID }} - CACHE_SECRET_ACCESS_KEY: ${{ secrets.SCCACHE_S3_SECRET_ACCESS_KEY }} - run: | - { - echo "SCCACHE_BUCKET=${CACHE_BUCKET}" - echo "SCCACHE_ENDPOINT=${CACHE_ENDPOINT}" - echo "SCCACHE_REGION=${CACHE_REGION}" - echo "SCCACHE_S3_KEY_PREFIX=${CACHE_KEY_PREFIX}" - echo "SCCACHE_S3_USE_SSL=true" - echo "AWS_ACCESS_KEY_ID=${CACHE_ACCESS_KEY_ID}" - echo "AWS_SECRET_ACCESS_KEY=${CACHE_SECRET_ACCESS_KEY}" - # Keep the server alive through post-compile test/lint phases so - # "Show sccache stats" reflects the real counters. - echo "SCCACHE_IDLE_TIMEOUT=0" - # Also cache the C/C++ compilation of -sys crates. These jobs are - # native Linux builds, so plain CC/CXX select the target compiler. - echo "CC=${SCCACHE_PATH} cc" - echo "CXX=${SCCACHE_PATH} c++" - } >> "$GITHUB_ENV" - - - name: Rust cache - uses: swatinem/rust-cache@v2 - with: - workspaces: "./ -> target" - # Own key: this job builds one crate with --no-default-features, - # a different fingerprint than either Rust job's feature set, so - # sharing their key would only ever miss and waste cache space. - shared-key: ci-frontend-docs-export-smoke-x86_64-unknown-linux-gnu - # Preserve completed dependency builds when a later step fails. - cache-on-failure: true - # PR caches are large and branch-scoped; restore them from main without saving per-PR copies. - save-if: ${{ github.ref == 'refs/heads/main' }} - - # exportSmoke.spec.ts shells out to this example to build a real - # to_standalone_html fixture. Built here, before `pnpm check`, so the - # test's own `cargo run` (same flags — see the spec's comment) is a - # cache hit rather than a fresh compile of dbx-core inside a vitest - # hook. `--no-default-features`: the docs module needs none of - # duckdb-sidecar, mq-admin, sqlite-sqlcipher or system-fonts, so this - # avoids requiring any system dev packages this job doesn't already - # install. - - name: Build the docs export smoke fixture example - run: cargo build -p dbx-core --locked --no-default-features --example docs_export_smoke - - # Guards that the committed bundle (crates/dbx-core/assets/docs-export.*) - # matches the sources under apps/desktop/ it was built from. This job is - # what runs on a frontend-only change, so the guard has to run here too — - # rust-test is gated on crates/**/src-tauri/**/Cargo.*, none of which a - # frontend-only PR touches. Same `--no-default-features` fingerprint as - # the prebuild step above, so this is a cache hit, not a fresh compile. - - name: Guard the committed docs export bundle - run: cargo test -p dbx-core --locked --no-default-features --lib docs::export - - - name: Show sccache stats - if: always() - continue-on-error: true - run: ${SCCACHE_PATH} --show-stats - - name: Frontend check run: pnpm check - # Advisory, not a guard: the manifest guard above hashes INPUTS, so it - # cannot see a hand-edited artefact (no source hash moves) or a - # toolchain bump (vite, tailwindcss and @vitejs/plugin-vue are - # plugins, not modules — they never enter the graph). Rebuilding and - # diffing checks the relationship between inputs and output instead, - # closing both gaps. Must run last: it overwrites the committed - # bundle, and both the guard above and `pnpm check` above (whose - # exportSmoke.spec.ts executes the *committed* bundle) need it - # untouched to be testing what is actually checked in. + # Rebuild and diff the committed docs-export bundle after the frontend + # checks so source changes cannot silently leave stale generated assets. - name: Rebuild the docs export bundle run: pnpm build:docs-export diff --git a/apps/desktop/src/docs-export/__tests__/exportSmoke.spec.ts b/apps/desktop/src/docs-export/__tests__/exportSmoke.spec.ts deleted file mode 100644 index 2806674ee4..0000000000 --- a/apps/desktop/src/docs-export/__tests__/exportSmoke.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { execFileSync } from "node:child_process"; -import { readFileSync } from "node:fs"; -import os from "node:os"; -import path from "node:path"; -import { beforeAll, describe, expect, it } from "vitest"; - -// @vitest-environment happy-dom - -// Not under the workspace's `target/`: this repo's global `~/.cargo/config.toml` -// can redirect cargo's target-dir elsewhere (to dedupe build artefacts across -// worktrees), so a path assuming `/target/` is not portable. `os.tmpdir()` -// has no such dependency on cargo configuration. -const htmlPath = path.join(os.tmpdir(), "docs-export-smoke.html"); - -describe("the exported file", () => { - beforeAll(() => { - // Generated by a small Rust example so the test exercises the REAL - // to_standalone_html output rather than a hand-built approximation. - // - // `--no-default-features`: the docs module doesn't touch duckdb-sidecar, - // mq-admin, sqlite-sqlcipher or system-fonts, and matching that flag here - // to the CI workflow's prebuild step (same cargo invocation, same - // fingerprint) is what makes this a cache hit instead of a fresh compile - // of dbx-core inside the hook. If this flag ever drifts from the - // workflow's build step, the hook goes back to compiling from scratch - // and risks the 120s timeout below. - execFileSync("cargo", ["run", "-p", "dbx-core", "--no-default-features", "--example", "docs_export_smoke", "--", htmlPath], { stdio: "inherit" }); - // The CI workflow prebuilds this example in its own step so this hook - // only pays for a freshness check and a run (well under a second warm, - // measured locally). 120s covers a slow/cold worst case without making - // an unrelated hook's timeout wait this long by raising it globally. - }, 120_000); - - it("mounts and renders a table name", async () => { - // The route is read from `location.hash` at mount time (ExportApp.vue), - // so landing directly on the table page is what makes the assertion - // below check rendered CONTENT rather than merely an element's presence: - // the index page lists "orders" and "public" as separate text nodes - // (a schema header, then a bare table name), never the joined string - // "public.orders" that only the table page's heading produces. - location.hash = "#/table/public.orders"; - document.documentElement.innerHTML = readFileSync(htmlPath, "utf8"); - for (const script of Array.from(document.querySelectorAll("script"))) { - if (script.getAttribute("type") === null) new Function(script.textContent ?? "")(); - } - await new Promise((resolve) => setTimeout(resolve, 100)); - const rendered = document.querySelector("#app")?.textContent ?? ""; - expect(rendered).toContain("public.orders"); - // Column data, not just the heading — proves the fixture's real - // structure (built by the Rust example, not this test) reached the DOM. - expect(rendered).toContain("customer_id"); - }); -}); diff --git a/crates/dbx-core/examples/docs_export_smoke.rs b/crates/dbx-core/examples/docs_export_smoke.rs deleted file mode 100644 index a6669c1ca3..0000000000 --- a/crates/dbx-core/examples/docs_export_smoke.rs +++ /dev/null @@ -1,89 +0,0 @@ -//! Builds a small two-table snapshot and writes the real -//! `to_standalone_html` output to `argv[1]`. -//! -//! Exists so `exportSmoke.spec.ts` can execute genuine export output in -//! happy-dom rather than a hand-built approximation of it. - -use std::collections::BTreeMap; -use std::env; -use std::fs; - -use dbx_core::docs::annotations::AnnotationFile; -use dbx_core::docs::{ - to_standalone_html, Cardinality, DocTable, FieldRef, ProjectMeta, Relationship, SchemaSnapshot, TableKind, -}; -use dbx_core::types::ColumnInfo; - -fn main() { - let out_path = env::args().nth(1).expect("usage: docs_export_smoke "); - - let orders = DocTable { - schema: Some("public".into()), - name: "orders".into(), - kind: TableKind::Table, - columns: vec![ - ColumnInfo { name: "id".into(), data_type: "bigint".into(), is_primary_key: true, ..Default::default() }, - ColumnInfo { name: "customer_id".into(), data_type: "bigint".into(), ..Default::default() }, - ], - indexes: vec![], - foreign_keys: vec![], - group_id: None, - note: Some("Checkout rows.".into()), - note_source: dbx_core::docs::NoteSource::Database, - shadowed_note: None, - column_notes: BTreeMap::new(), - estimated_rows: Some(2_400_000), - view_definition: None, - }; - - let customers = DocTable { - schema: Some("public".into()), - name: "customers".into(), - kind: TableKind::Table, - columns: vec![ColumnInfo { - name: "id".into(), - data_type: "bigint".into(), - is_primary_key: true, - ..Default::default() - }], - indexes: vec![], - foreign_keys: vec![], - group_id: None, - note: None, - note_source: dbx_core::docs::NoteSource::None, - shadowed_note: None, - column_notes: BTreeMap::new(), - estimated_rows: Some(50_000), - view_definition: None, - }; - - let snapshot = SchemaSnapshot { - format_version: 1, - project: ProjectMeta { - name: "shop".into(), - database_type: "postgres".into(), - database: Some("shop".into()), - schemas: vec!["public".into()], - generated_at: "2026-08-06T00:00:00Z".into(), - note: None, - }, - tables: vec![orders, customers], - relationships: vec![Relationship { - id: "orders.customer_id->customers.id".into(), - name: None, - from: FieldRef { schema: Some("public".into()), table: "orders".into(), column: "customer_id".into() }, - to: FieldRef { schema: Some("public".into()), table: "customers".into(), column: "id".into() }, - cardinality: Cardinality::ManyToOne, - on_update: None, - on_delete: None, - }], - groups: vec![], - enums: vec![], - warnings: vec![], - }; - - let annotations = AnnotationFile { format_version: 1, project: None, groups: Vec::new(), tables: BTreeMap::new() }; - - let html = to_standalone_html(&snapshot, &annotations, "en").expect("export"); - fs::write(&out_path, html).expect("write output file"); -}