<!-- Source: https://docs.biosimulant.com/how-to/package-and-publish -->

# Package & Publish with Biosimulant

Use the canonical `biosimulant` CLI for local validation and release work, or connect the Biosimulant GitHub App for push-to-deploy publishing from a branch.

## GitHub App auto-deploy

Install the Biosimulant GitHub App from the Deployments screen. Pick one
repository, one branch, and a lab manifest path such as `labs/my-lab/lab.yaml`,
then link it to an existing lab or give a package name for a new one.

Each push to that branch validates the selected `lab.yaml`, builds one `.bsilab`
archive, and publishes it to the Package Registry. Deployment history in the web
app shows each stage, the commit SHA, and any failure reason. To deploy several
labs from one branch, add one source per lab manifest path. Auto-deploy publishes
Labs only.

## CLI workflow

Use the CLI when you want to validate or publish locally, wire it into CI yourself, or test packages before enabling auto-deploy. For single-lab work, prefer the lab-centered flow:

```bash
biosimulant auth login
biosimulant labs init ./my-lab --name "My Lab"
biosimulant labs add-model ./models/my-model --lab ./my-lab --alias model
biosimulant labs validate ./my-lab
biosimulant labs serve ./my-lab
biosimulant labs run ./my-lab --results-file results.json --json
biosimulant labs publish ./my-lab --visibility private
```

Biosimulant Hub is the default registry. To publish to another Registry API v1
service, authenticate to its origin and pass a registry-qualified package
reference:

```bash
printf '%s\n' "$TOKEN" | \
  biosimulant auth login registry.example.com --token-stdin
biosimulant labs publish ./my-lab registry.example.com/your-org/my-lab@1.0.0 --json
```

Registry credentials are stored separately by origin. Never place a token in a package reference, command history, or
lab manifest.

## Declare packages

Create a `biosimulant-packages.yaml` at the repository root:

```yaml
schema_version: "1"
namespace: your-org
default_visibility: public
packages:
  - id: my-lab
    package: your-org/my-lab
    version: 1.0.0
    type: lab
    path: labs/my-lab
    visibility: public
```

Each package entry points to a lab source tree containing `lab.yaml`.

## Validate

```bash
biosimulant labs release validate biosimulant-packages.yaml
```

Validation checks package names, exact SemVer versions, source paths, manifests, dependency pins, embedded paths, and duplicate `package@version` entries.

## Build

```bash
biosimulant labs release build biosimulant-packages.yaml --out dist/biosimulant-packages
```

The build creates `.bsilab` archives under the output directory. Each archive contains `package.yaml`, `payload/`, and `integrity/sha256sums.txt`.

## Publish

Publish builds, validates, uploads each artifact, and writes `dist/package-report.json`:

```bash
biosimulant labs release publish biosimulant-packages.yaml
```

Use `--dry-run` to validate and build locally without uploading:

```bash
biosimulant labs release publish biosimulant-packages.yaml --dry-run
```

Publishing the same `package@version` with different content fails on the backend. Re-uploading the same content reuses the existing artifact.

## Pull and run versions

Consumers can use an exact package ref or leave the version out:

```bash
LAB_REF="your-org/my-lab@1.0.0"

biosimulant labs search "my lab"
biosimulant labs info "$LAB_REF"
biosimulant labs pull "$LAB_REF"
biosimulant labs run ./my-lab --results-file results.json --json
```

On the command line, `namespace/name@x.y.z` pins a version and `namespace/name`
resolves the latest accessible version for `labs pull` and `labs run`. That only
applies to CLI refs. Versions written in `biosimulant-packages.yaml`, `model.yaml`,
and `lab.yaml` children must be exact.

## Local CI

```bash
biosimulant labs release ci biosimulant-packages.yaml
biosimulant labs release ci biosimulant-packages.yaml --publish
biosimulant labs release ci biosimulant-packages.yaml --publish --json
```

The same command can run locally first and later move into GitHub Actions. All package commands exit non-zero on validation, build, or upload failure.

Use `--json` for one schema-v1 result or `--json-stream` for ordered progress followed by one terminal result. See
[Machine-readable output](/references/cli#machine-output) for the envelope and exit-code contract.

## Compatibility Smoke

Before publishing a model or lab that should also run through the open-source
Python package flow, build and run the package locally:

```bash
biosimulant labs package path/to/lab --out dist
biosimulant labs validate dist/your-package.bsilab --json
biosimulant labs run dist/your-package.bsilab --no-install-deps --json
```

This catches entrypoint loading, typed run input payloads, child-lab
flattening, and `io.maps_to` remapping issues before the same package reaches
remote execution. GPU or otherwise heavy packages can keep full
execution in remote smoke tests, but should still validate manifests and
entrypoints locally.

## Next Steps

- [model.yaml Schema](/references/model-manifest): manifest fields and package identity
- [Use a BioWorld](/how-to/use-bioworld): run model code in local workflows
- [CLI Command Reference](/references/cli#commands): full `biosimulant labs` command catalog
