DEMIENGINEDOCUMENTATION Everything is free
Packages · Ship

Package layout, tests, and the public store.

Publishing packages

Publishing means releasing a reusable package so other DemiEngine projects can depend on it by name and version. Publishing exists to turn "we copy these scripts between games" into "we depend on a versioned release", with an audit of exactly which files ship. This page covers preparing a package, the audited content rules, the release workflow, and how the public store at demiengine.de hosts your work. Examples use "Skyforge" at games/my_game.

Before you publish

A publishable package is a directory with a valid manifest (see Installing packages for the field reference), its declared files, and passing tests:

packages/skyforge-kit/
  demi.package.json
  scripts/
  scenes/
  assets/
  certs/
  packages/
  • demi.package.json — the manifest: format_version, name, version, engine, dependencies, public_modules, files.
  • Each directory below it holds one kind of shippable content. Only audited roots are allowed (see the audit table).

Prove the package before releasing:

demi package test packages/skyforge-kit
  • package test [dir] — runs the package's declared Lua tests. Returns 0 when every test passed, 1 when any failed.
demi validate packages/skyforge-kit
  • validate [path] — validates the package source and everything it references. Returns 1 on validation errors.

Both must pass before the version number is spent.

What may ship: the content audit

Every release is audited before it becomes a .demipkg. The audit exists so a package cannot smuggle build output, editor state, or arbitrary folders into other people's projects. Only these roots are allowed:

RootWhat belongs there
assets/Asset manifests and their sources (images, models, data files).
certs/Certificate material the package declares it needs.
packages/Declared package dependencies' content, when vendored.
scenes/Scene documents.
scripts/Lua gameplay and module sources.
demi.project.jsonThe project root document, when the package is a full project.
demi.packages.lock.jsonThe pinned dependency lock.
cook.manifest.jsonThe cooked-content manifest with paths and hashes.

Anything outside those roots is rejected with BUILD_PACKAGE_CONTENT_UNEXPECTED. Generated output that is not declared by cook.manifest.json does not belong in a release; consumers cook or verify from the manifest instead of trusting loose files.

Creating the release artifact

The release artifact is a .demipkg — a single audited file other projects install:

demi package publish packages/skyforge-kit \
  --registry https://demiengine.de
  • package publish [dir] — audits the package directory, builds the .demipkg, and uploads it to the registry. The default directory is the current one.
  • --registry <url-or-path> — where to publish. https://demiengine.de is the public store; a local path works for a private registry.
  • Returns 0 when the release is registered, 1 when validation or the audit fails.

The same command is the consumer-side pack flow in reverse: exporting and importing packs is covered in Assets & packages.

Releases are immutable

Once a version is published, its content never changes. That immutability is the contract consumers rely on: version 1.2.0 means the same bytes to everyone, forever, and the lock file hash keeps proving it. To change anything, publish a new version:

  1. Fix or extend the package source.
  2. Raise version in the manifest (patch for fixes, minor for additions, major for breaking API changes).
  3. Run package test and validate again.
  4. Publish the new version.

Consumers pick the change up with demi package update inside their declared constraints, exactly as described in Installing packages.

The store at demiengine.de

The public package store is demiengine.de. It serves three audiences:

  • Consumers — browse the catalog, read what a package provides, and copy the package add line for their project.
  • Publishers — use the publishing page to upload a .demipkg, set the release notes, and see which versions exist.
  • Tooling — the same registry endpoint answers package add, install, update, and outdated.

Two entry points exist for publishing:

Entry pointUse it when
Publishing page on demiengine.deYou want a guided upload in the browser with release notes.
bin/publish.pyYou are publishing from a script or continuous integration and want one command.
  • bin/publish.py — the store's command-line publisher. It wraps the same audited upload as demi package publish, so a browser upload and a scripted upload produce identical, immutable releases.

Registry credentials, if your registry requires them, come from environment configuration — never from files inside the package or the repository.

A complete release checklist

  1. Manifest fields filled: format_version, name, version, engine, dependencies, public_modules, files.
  2. Only audited roots are present (assets/, certs/, packages/, scenes/, scripts/, plus the three manifest files).
  3. demi package test passes.
  4. demi validate passes for the package.
  5. Version raised and release notes written.
  6. demi package publish --registry https://demiengine.de (or the publishing page, or bin/publish.py) completes.
  7. A fresh project installs the release and requires one public module successfully.

Related pages: Installing packages for the consumer side, and Build, cook & test for validation and packaging commands.