Continuously validates published releases and source-built @utoo/pack candidates against Umi, Ant Design Pro, Ant Design, Father, Dumi, and EVJS. Each suite injects the candidate into a fresh consumer checkout, runs its real utoopack build or E2E workflow in isolation, and verifies the expected output.
| Suite | Consumer | E2E coverage |
|---|---|---|
umi |
umijs/umi@master |
Runs Umi's native utoopack browser E2E, framework routing, CLI fallback and dev shutdown regressions, plus its qiankun slave and utoopack master E2Es |
ant-design-pro |
ant-design/ant-design-pro@master |
Runs the production Umi Max + utoopack build and starts its utoopack dev server |
ant-design |
ant-design/ant-design@7793cab |
Runs the production Dumi site build and the exact utoopack dev startup from utooland/utoo#3332 |
father |
umijs/father@master |
Builds Father, then builds its utoopack UMD example |
dumi |
umijs/dumi@master |
Builds Dumi from source, then builds and starts a minimal site based on Dumi's official template with utoopack |
evjs |
afx-team/evjs@main |
Builds EVJS packages, starts its basic app with ev dev, and runs its bundler-utoopack Playwright project |
evjs-shared-runtime |
afx-team/evjs@main |
Enables sharedRuntime in the disposable two-page MPA example, runs its Chromium E2E, and verifies both pages load the same runtime asset last |
Every suite verifies that its expected output directory exists and is non-empty. Node.js 22 is used in CI, satisfying utoopack's Node.js 20+ requirement.
Selecting umi or all also runs Umi's dev/browser E2E on Windows x64 through the same CI matrix and success check. The seven Linux suites retain their coverage, including Umi's qiankun E2Es.
The Umi dev E2E targets only the parent CLI PID for termination and checks that both parent and worker exit and that the Umi HTTP port and utoopack's actual server port are reusable. Linux checks graceful parent SIGINT shutdown and IPC disconnect after parent SIGKILL, including asynchronous onExit, existing signal listeners, and completion of the real utoopack close(). On Windows, libuv's Job Object can forcibly terminate the non-detached worker when its parent is killed, so the SIGKILL case checks process exit and port reuse without requiring JavaScript cleanup hooks. It does not verify Windows graceful shutdown or simulate console Ctrl+C. Temporary plugins and configuration changes are restored after the run.
The routing regressions run on both Linux and Windows. Umi must retain control of
its post-bundler middleware and nested routes, including direct navigation and a
browser refresh when the internal output contains index.html. A separate
fixture starts the actual candidate up dev binary: SPA fallback must work by
default, --no-history-api-fallback must restore the missing-route response, and
missing JS/CSS files must remain errors in both modes. The CLI fixture verifies
that the CLI resolves the same bundler candidate installed for Umi.
For EVJS, the runner also verifies the candidate from packages/bundler-utoopack's module-resolution context. Its upstream lockfile currently contains a workspace-local @utoo/pack entry, so the disposable checkout removes that stale generated copy after installation before running E2E; this prevents the root override from producing a false-positive result.
Requirements: Node.js 22, Git, and Utoo 1.1.8 or newer. The project self-pins to Utoo 1.1.8.
ut install
ut test
ut lint
ut check:workflow
# Show suites
ut ecosystem -- --list
# Test a published version or dist-tag
ut ecosystem -- --suite father --pack latest
ut ecosystem -- --suite ant-design-pro --pack 1.5.3
ut ecosystem -- --suite ant-design --pack latest
ut ecosystem -- --suite evjs --pack latest
# Run the shared runtime regression alone against a candidate containing the feature
ut ecosystem -- --suite evjs-shared-runtime --pack /path/to/utoo-pack.tgz --pack-shared /path/to/utoo-pack-shared.tgz
# Inspect the exact plan without cloning or installing
ut ecosystem -- --suite dumi --pack latest --dry-runTo test locally built tarballs:
node scripts/prepare-candidate.mjs \
--source /path/to/utoo \
--out candidate-artifacts
ut ecosystem -- \
--suite umi \
--pack candidate-artifacts/utoo-pack.tgz \
--pack-shared candidate-artifacts/utoo-pack-shared.tgz \
--pack-cli candidate-artifacts/utoo-pack-cli.tgzConsumer checkouts are disposable and live under workspace/. Use --keep to reuse an existing checkout, --ref <branch|tag|commit> to test a consumer ref, or --repo <owner/repo> to test a fork.
The Umi suite also installs @utoo/pack-cli. Registry runs default its version or
tag to --pack; local tarball runs require --pack-cli explicitly so the CLI
regression cannot accidentally exercise a published CLI instead of the candidate.
The Utoopack ecosystem CI workflow supports four entry points:
- Daily schedule: the seven suites in
allagainst the npmlatesttag. - Manual run: choose npm/source mode, an individual suite or
all, and optionally a harness branch to validate. repository_dispatch: event typeutoopack-ecosystem-ciwith the same values inclient_payload.- Reusable workflow: call it directly from the utoo repository so the result appears on the originating PR or commit.
In npm mode, pack_spec is an npm version or dist-tag. In source mode, the workflow checks out utoo_repository@utoo_ref, initializes the next.js submodule, builds the Linux x64 native package once, packs @utoo/pack, @utoo/pack-shared, and @utoo/pack-cli, and shares those tarballs with the selected consumer jobs.
Source runs selecting Windows also prepare a Windows candidate using Utoo's existing cross-compilation scripts. Linux and Windows tarballs are separate artifacts; the Windows binding is embedded in the CJS and ESM wrappers. npm runs install the published binding normally.
The workflow's all selector runs all seven suites, including evjs-shared-runtime, on the daily schedule and for Utoopack releases. It is a workflow input, not a name accepted by the local ut ecosystem -- --suite CLI. To run only the shared runtime check, select evjs-shared-runtime (or use source mode with a Utoo ref containing the feature before its npm release). The npm latest package must contain sharedRuntime for the scheduled all run to pass.
Add a small workflow to the utoo repository:
name: Ecosystem CI
on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
permissions:
contents: read
jobs:
ecosystem:
uses: utooland/utoo-ecosystem-ci/.github/workflows/ecosystem-ci.yml@main
with:
candidate_mode: source
utoo_repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
utoo_ref: ${{ github.event.pull_request.head.sha || github.sha }}
suite: all
harness_repository: utooland/utoo-ecosystem-ci
harness_ref: mainFor a published Utoopack release, set candidate_mode: npm, pack_spec to the newly published version, and suite: all in the reusable workflow call. The harness ref must contain the evjs-shared-runtime suite.
No secrets are required for public repositories. GitHub-hosted runners need enough time and disk for the one-time Rust/NAPI source build; the source preparation job has a three-hour timeout and frees unused runner images first.
gh api --method POST repos/utooland/utoo-ecosystem-ci/dispatches \
-f event_type=utoopack-ecosystem-ci \
-f 'client_payload[candidate_mode]=npm' \
-f 'client_payload[pack_spec]=latest' \
-f 'client_payload[suite]=all'This repository itself uses Utoo (ut install, ut test, and ut lint) and keeps an npm-compatible package-lock.json, which Utoo reads and updates. JavaScript is linted with @utoo/lint; its files, ignores, and rules live in utlint.config.ts. ut check:workflow separately enforces the GitHub Actions SHA policy. Consumer checkouts generally use the package manager declared by each upstream repository; the large Ant Design and Ant Design Pro dependency graphs use Utoo for faster installation while retaining their upstream npm scripts and npm-compatible dependency overrides.
Suite commands live in src/suites.mjs. Keep them aligned with the consumer repositories' own CI and examples. External GitHub Actions are pinned to full commit SHAs; ut check:workflow enforces that policy.