Skip to content

Publish flow

This is the present-state pipeline. Public-npm publish is target state and is not exercised today; see the npm publish safety audit.

High-level sequence

1. Build the package (turbo + tsc + each package's build.mjs)
2. Pack the tarball (npm pack)
3. Push to Gitea (npm publish to registry.hivecast.ai)
4. Update discovery-index.json next to the tarball
5. Consumers see the new latest immediately

Step-by-step

1. Build

Standard monorepo build. From the repo root:

bash
pnpm install
pnpm build:affected

Each package builds to its own dist/ according to its build.mjs or package.json build script. The build artifact is what gets packed.

2. Pack

npm pack creates <package>-<version>.tgz containing exactly what npm publish would push:

bash
cd projects/matrix-3/packages/<name>
npm pack --dry-run         # inspect what would be included

The package.json "files" array controls inclusion. The npm publish safety audit lists 9 packages currently lacking "files" — fix those before any publish.

3. Publish

bash
cd projects/matrix-3/packages/<name>
NPM_CONFIG_REGISTRY=https://registry.hivecast.ai/api/packages/hivecast-admin/npm/ \
NPM_CONFIG__AUTH_TOKEN=<gitea-token> \
npm publish

Gitea accepts the tarball, stores it in its blob volume, and updates its package metadata so the version is discoverable via the npm packages API.

4. Update discovery-index.json

The catalog's discovery-index.json is separate from the artifact registry. Updating it is a publish-pipeline responsibility, not Gitea's. The current implementation lives in projects/matrix-3/packages/mx-cli/src/utils/discovery-index.ts.

Roughly:

typescript
// Read existing index
const index = JSON.parse(fs.readFileSync(`${registryRoot}/discovery-index.json`));

// Build new entry from package's matrix.json + package.json
const newEntry = extractDiscoveryMetadata(packagePath);

// Merge into index
index.packages[packageName] ??= { versions: {} };
index.packages[packageName].versions[version] = {
  indexedAt: new Date().toISOString(),
  indexedBy: 'publish-pipeline',
  metadata: newEntry,
};

// Write back
fs.writeFileSync(`${registryRoot}/discovery-index.json`, JSON.stringify(index));

The index is written to the same registry root the SystemPackageRegistryActor reads from (<host-home>/registry/ for local mode, or the equivalent path on the registry server for cloud mode).

5. Visibility

Once Gitea has the tarball and discovery-index.json has the entry:

  • npm install @open-matrix/<pkg> finds the new version (Gitea side).
  • system.packages.registry.search includes the package in results (catalog side).
  • A consumer with a stale lockfile is unaffected until they npm update.

Pre-publish gates

Before running publish, the publish-time pipeline must verify:

GateWhy
pnpm build:affected succeedsTarball must be built
npm pack --dry-run reviewCatch accidental file inclusion
pnpm test:affected greenQuality gate
package.json.version is bumpedOtherwise npm publish rejects "already exists"
package.json.files is setThe npm publish safety audit identifies 9 packages missing this
No build artifacts in dist/matrix-artifact.json leak absolute pathsnpm publish safety audit, item 1

Failure modes

FailureCauseFix
403 Forbidden from GiteaToken lacks write:package scopeIssue new token with correct scope
409 ConflictVersion already publishedBump version
404 from index update step<registry-root>/discovery-index.json missingInitialize empty index file or fix path
Search doesn't see the new versionIndex update step skippedRe-run discovery-index update

Cloud (CI) vs. local publish

The .github/workflows/release.yml workflow is the canonical CI publish path (target state — currently dormant for public npm). For internal Gitea publishes, projects/deploy-cloud/deploy.sh runs publish-equivalent operations as part of the host-deploy pipeline, including the discovery-index update step.

Local manual publishing (developer's machine) is supported but discouraged outside of bootstrapping. CI publishes from a clean checkout to avoid leaking local artifact paths into tarballs.

See also

Source: .github/workflows/release.yml, projects/deploy-cloud/deploy.sh, projects/matrix-3/packages/mx-cli/src/utils/discovery-index.ts.