Skip to content
KnowSky404 edited this page Oct 23, 2026 · 1 revision

SubMan CI/CD

English | 简体中文

Continuous integration

The CI workflow runs for pushes to main, pull requests, and manual dispatches. It uses the repository-pinned Bun and Wrangler toolchain and keeps GITHUB_TOKEN read-only. Wrangler is pinned exactly at 4.127.0; the frozen lockfile therefore carries a workerd release new enough to execute the project's compatibility_date = "2026-07-28" locally.

The verification order is intentionally fail-fast:

  1. install the frozen lockfile;
  2. run unit tests and check bilingual documentation links and language pairs;
  3. generate a synthetic local URI/subscription export and validate it with the pinned sing-box 1.14.0 container;
  4. run Svelte and TypeScript checks, including generated Worker type drift;
  5. run Biome;
  6. build the SvelteKit Worker;
  7. run the Cloudflare Durable Object integration suite;
  8. run wrangler deploy --dry-run and retain its bundle under .wrangler/deploy-check;
  9. install Chromium and run Playwright through wrangler dev --local.

The executable exporter gate is available locally as bun run test:sing-box. It calls the real Aggregate and client-export code with an injected, in-memory subscription fixture, then runs sing-box check using an image pinned by tag and multi-architecture digest. It uses no real subscription, user data, credentials, Gist, or remote proxy connection. Docker is the only additional local prerequisite.

Using Wrangler for the browser server validates the generated Worker entrypoint, the WORKSPACE_COORDINATOR class export, the Durable Object migration, and Workers Assets configuration. Plain vite preview is not accepted as evidence for those Cloudflare runtime boundaries.

When Playwright fails, traces, screenshots, videos, and reports are uploaded as a seven-day GitHub Actions artifact. If an earlier gate fails, the workflow does not spend time installing Chromium.

Historical CI failures

Generated Worker type drift

The formal CI run on 2026-08-24 (run #5, commit e82147c5d370734c27a03fa681fccf07028721d8) passed all unit tests, then failed the type and Svelte check stage because check:worker-types detected a stale generated declaration. The same gate failed on 2026-09-30 for commit 81f6a590ac45cdd2725211acd3dcede9982d47b4.

Wrangler includes Cloudflare.GlobalProps only when the configured framework entrypoint exists. Local builds left .svelte-kit/cloudflare/_worker.js present, while CI checked types before building. Merely regenerating the declaration therefore produced different results in a clean checkout and a built checkout.

The generator now omits the entire build-dependent GlobalProps block. The Env.WORKSPACE_COORDINATOR binding still imports the coordinator class from its stable source path and retains its typed Durable Object namespace. A regression test runs the actual generator with and without a framework entrypoint and checks that both results match the committed declaration.

The correction is committed in the current line:

bun run generate:worker-types
bun run check:worker-types

Do not hand-edit the generated declaration. Any future wrangler.toml, Wrangler, binding, migration, or compatibility-date change must regenerate the file and pass the complete CI workflow.

Local Workers runtime behind the compatibility date

The first CI run that replaced vite preview with wrangler dev --local successfully passed unit, type, lint, build, Cloudflare integration, and deployment dry-run gates, but the browser server could not start. The locked Wrangler 4.81.0 bundled a workerd runtime supporting compatibility dates only through 2026-04-12, while SubMan requires 2026-07-28.

The production compatibility date was not rolled back. Wrangler was upgraded and pinned to 4.127.0, whose lockfile resolves workerd 1.20260826.1. This keeps local browser evidence aligned with the checked-in production configuration. Future compatibility-date changes must first update the pinned runtime and pass local Worker startup, deployment dry-run, Cloudflare integration, and browser gates.

Production deployment

Production deployment is intentionally not automatic. Use the Deploy production workflow from the main branch and enter deploy in the confirmation input.

The deployment job references the GitHub production environment. Configure that environment with required reviewers and these environment secrets:

  • CLOUDFLARE_ACCOUNT_ID
  • CLOUDFLARE_API_TOKEN

Scope the API token to the target Cloudflare account and the minimum Workers deployment permissions. The deployment workflow validates both secrets, reruns unit, type, lint, build, Cloudflare integration, and browser checks, creates a deployment dry-run bundle, and then runs:

wrangler deploy --strict

The deployment workflow currently does not repeat test:sing-box; the separate CI / verify workflow provides that gate for the same commit. Require its success before deployment.

Strict mode fails closed when a non-interactive deployment could overwrite conflicting remote settings.

The deployment credentials above are separate from the Worker runtime secrets:

  • GITHUB_TOKEN
  • SUBMAN_API_TOKEN

Runtime secrets remain managed with wrangler secret put; they must not be copied into repository files, workflow inputs, build variables, or test fixtures.

Repository settings

Require the CI / verify check before merging or updating main. Keep direct production deployment behind the production environment rather than a push-triggered workflow. Do not enable automatic deployment until branch protection, required checks, environment approval, rollback, and post-deployment health verification are all configured.

Clone this wiki locally