Skip to content
Docs

Shared CI

Every Fusion package runs the same checks on every pull request — lint, format, types, tests — without copying a workflow into each repo. The twist: CI is shared differently from the configs.

  • Configs (TypeScript, Oxlint, Oxfmt) ship inside the npm package, so you get them with a bun install and an extends.
  • CI can't travel that way — GitHub Actions never reads node_modules. So fusion-config also hosts a reusable workflow, and each repo calls it with a tiny uses: stub.

Same single source of truth (fusion-config), two different delivery mechanisms:

Loading diagram...

The reusable workflow

package-ci.yml defines the gate once. Each package's ci.yml is a thin caller, so editing the gate updates every repo at once — no copy-paste drift.

Loading diagram...

Add CI to a package

Drop this in as .github/workflows/ci.yml — that is the entire file:

.github/workflows/ci.yml
name: CI
 
on:
  pull_request:
  push:
    branches: [main]
 
jobs:
  ci:
    permissions:
      contents: read
      packages: read
    uses: tikab-interactive/fusion-config/.github/workflows/package-ci.yml@main
    secrets: inherit

The gate runs four scripts, so every package must define them in package.json (the first three come straight from the configs):

ScriptCommand
lintoxlint
fmt:checkoxfmt --check
typechecktsgo --noEmit
testyour tests, or a no-op

No tests yet? Use an empty script

The gate always runs bun run test, so a package without tests just needs a script that exits cleanly:

package.json
{
  "scripts": {
    "test": "echo \"no tests\""
  }
}

Swap it for bun test (or any runner) once you add real tests.

Reusing the gate before a release

A publish workflow can run the exact same checks before shipping — call the reusable workflow as one job, then gate the publish on it with needs:

.github/workflows/release.yml
jobs:
  checks:
    permissions:
      contents: read
      packages: read
    uses: tikab-interactive/fusion-config/.github/workflows/package-ci.yml@main
    secrets: inherit
 
  publish:
    needs: checks
    runs-on: ubuntu-latest
    # ... checkout, install, publish

First-time setup

fusion-config is private, so a few one-time switches are needed:

  • Let other repos call it. fusion-config → Settings → Actions → General → Access → "Accessible from repositories in the organization", or callers fail with "workflow was not found."
  • Let CI read the package. Installing @tikab-interactive/* in Actions needs a read:packages token. The workflow uses secrets.NPM_TOKEN || secrets.GITHUB_TOKEN; add an org NPM_TOKEN secret (a PAT) if the built-in GITHUB_TOKEN can't read the fusion-config package.
  • Push fusion-config first. The @main reference must exist before any caller can resolve it. Pin to a tag or commit SHA instead of @main if you'd rather adopt gate changes deliberately.