Artifact Reference#

Every cs build writes a runtime plus metadata files. The runtime is the final stamped binary artifact. Downstream signing and attestation workflows run after conda-ship writes these files.

conda-ship Release Assets#

Tagged conda-ship releases publish the builder assets that the GitHub Action downloads:

cs-<target>

Builder CLI for the target platform.

cs-template-<target>

Generic runtime template for the target platform.

SHA256SUMS

Checksums for release assets.

The PyPI release for the same tag publishes platform wheels that install cs and cs-template into the Python environment’s scripts directory, plus a source distribution for packaging systems. Published release assets are immutable. Fixes use a new tag rather than replacing files under an existing tag.

Layouts#

Layout

Runtime

Bundle file

Network during bootstrap

online

RUNTIME

none

yes

external

RUNTIME

RUNTIME.bundle.tar.zst

optional

embedded

RUNTIME

embedded in binary

no

When [tool.conda-ship].artifact-name or --artifact-name is set, all layouts use that value for the staged runtime and metadata stem. On Windows, binary filenames also include .exe.

For the difference between runtime-name and artifact-name, see Runtime And Artifact Names.

Runtime Update Packages#

cs package-update writes a dependency-free native .conda package from a finalized update-enabled online or embedded runtime. Run it separately after cs build. By default, it writes next to the .info.json passed through --info. Use --out-dir to write update packages to a separate directory.

The package contains one executable payload plus normal conda package metadata:

  • bin/ARTIFACT_NAME on Unix

  • ARTIFACT_NAME.exe on Windows

The package name, version, build number, and platform come from the executable stamp and its artifact info JSON. The package has no runtime dependencies. It is transport for the executable update engine and is not installed into the managed prefix.

The command refuses to overwrite an existing output. Its --json result reports SHA256 and size values for both the package and finalized executable payload. Channel indexing and upload remain downstream release operations.

Bundle Contents#

Bundles are a transport for the conda package archives already named in the runtime lock. They are not channel mirrors and do not use a linux-64/ or noarch/ directory layout.

external and embedded bundles contain top-level .conda and .tar.bz2 package archive files. The runtime matches those filenames against the stamped lockfile and verifies package SHA256 values before installing from them.

External bundle directories may contain unrelated files, but conda-ship only indexes top-level conda package archives and skips symbolic links. Embedded bundles are stricter because they are extracted from a tar archive: every entry must be a top-level regular .conda or .tar.bz2 file. Directory entries, nested paths, symbolic links, hard links, and other file types are rejected.

Metadata Files#

For an online build with runtime demo, conda-ship stages:

  • demo or demo.exe

  • demo.runtime.lock

  • demo.packages.txt

  • demo.cdx.json

  • demo.info.json

  • demo.sha256

When --target-label is used, the label is inserted into the stem, for example demo-linux-64.info.json.

If artifact-name = "demo-cli" or --artifact-name demo-cli is set, the artifact stem uses that explicit name for any layout, for example demo-cli.info.json or demo-cli-linux-64.info.json.

For an external build, conda-ship also stages demo.bundle.tar.zst or a target-qualified equivalent. Rebuilding the same artifact stem as online or embedded retires any previous external bundle before publishing the new checksum manifest.

These files describe the staged release output. During automatic first-run bootstrap, the generated runtime also writes managed-prefix metadata such as conda-meta/history and conda-meta/initial-state.explicit.txt inside the install path.

CycloneDX SBOM#

Every staged build writes a CycloneDX 1.7 JSON SBOM named ARTIFACT.cdx.json. The document identifies the staged runtime as the root application and includes every conda package for the target platform in the derived runtime lock. Package components include the exact version, build, subdir, channel, filename, download URL, SHA256 and MD5 hashes, and license value when those fields are available. Direct dependency edges come from the solved package records. Dependency sets containing conditional or unparseable MatchSpecs are marked unknown rather than inventing relationships that the runtime lock cannot prove.

Channel and remote download URLs are sanitized before they are written. URL credentials, Anaconda /t/<token> path segments, queries, and fragments are removed. Local paths and file: URLs are omitted.

This mapping follows the conda specifications for package identifiers, MatchSpecs, package metadata, and repodata records. No accepted conda CEP currently defines an environment SBOM format or CRA profile.

The derived runtime lock does not currently retain the original requested MatchSpecs. The root component therefore points to graph roots inferred from the resolved package edges, plus a representative of any otherwise unreachable dependency cycle. Every resolved package remains present even when that inference cannot reproduce the user’s declared top-level set.

When a package record names a dependency that is absent from the target platform’s resolved package set, the SBOM records the number of omitted edges on the root and marks the affected package dependency sets as incomplete. It does not invent a component without an exact package record.

For a product that falls within the EU Cyber Resilience Act, this file can provide the resolved conda environment portion of its technical documentation. The CRA requires a commonly used, machine-readable SBOM that covers at least top-level dependencies. It does not mandate CycloneDX 1.7. conda-ship chooses the CycloneDX 1.7 JSON schema and records the resolved target-platform package graph to the extent that package records permit.

The SBOM composition is deliberately marked incomplete. Conda package records do not describe every operating-system component or every dependency vendored or statically linked into a package. Rust crates linked into cs-template are also outside the resolved conda graph. The broader package metadata gap is discussed in conda/ceps#127. The generated file is therefore a CRA-oriented inventory of the resolved conda environment, not proof of complete product coverage or legal conformity.

Conda package PURLs follow the current package-url conda type. License values are kept as named licenses because historical repodata does not guarantee a valid SPDX expression.

conda-ship does not infer an SBOM author or product manufacturer from a channel or package record. Compliance profiles that require author, manufacturer, or contact metadata need additional information from the downstream project. Do not edit the staged SBOM in place because its checksum is recorded in .info.json and .sha256.

SOURCE_DATE_EPOCH controls the SBOM timestamp when set. Otherwise the build time is recorded in UTC. Rebuild the SBOM whenever the runtime or package set changes.

Stamped Runtime Data#

conda-ship stamps runtime data into every staged runtime. On macOS, it extends the Mach-O __LINKEDIT segment over an appended block before native signing. On Windows, it writes the footer into a read-only .cship PE section and appends the JSON header and optional bundle. The data contains the runtime lock, runtime and artifact identity, version, platform, delegate executable, install scheme, install name, docs URL, installer, optional executable update configuration, bundle and offline environment variable names, and the embedded bundle bytes for embedded builds. The universal CONDA_SHIP_PREFIX override is runtime behavior rather than a stamped variable name.

The format-specific footer records:

  • format version

  • header length

  • bundle length

  • header SHA256

  • bundle SHA256, or the SHA256 of empty bytes when no embedded bundle is present

  • conda-ship runtime-data magic bytes

The generated runtime validates the stamped header at startup. For embedded artifacts, it copies the embedded bundle to a temporary snapshot while checking its checksum, then extracts package archives only from that verified snapshot.

The binary checksum in .sha256 covers the final stamped artifact. The conda-ship release workflow also publishes GitHub Artifact Attestations for the cs CLI, runtime templates, and SHA256SUMS manifest.

If signing or another downstream step changes the staged executable, the original .sha256 and the executable checksum inside .info.json continue to describe the cs build output. Attest the finalized executable separately or generate a downstream final manifest. Pass the finalized file to cs package-update --binary when building an executable update package. The command snapshots those bytes and reports the finalized payload digest in its JSON output, but does not rewrite the original metadata files.

Verify assets published after the move to conda-incubator with:

gh attestation verify ./cs-x86_64-unknown-linux-gnu \
  -R conda-incubator/conda-ship \
  --signer-workflow conda-incubator/conda-ship/.github/workflows/release.yml

Releases through 0.9.0 were published by jezdez/conda-ship. Their signed repository and workflow identities retain that name, and GitHub serves their attestation bundles from the original owner’s account. For example, verify the 0.9.0 checksum manifest in an otherwise empty directory with:

gh release download 0.9.0 -R conda-incubator/conda-ship --pattern SHA256SUMS
gh attestation download ./SHA256SUMS --owner jezdez
gh attestation verify ./SHA256SUMS \
  --bundle ./*.jsonl \
  -R jezdez/conda-ship \
  --signer-workflow jezdez/conda-ship/.github/workflows/release.yml \
  --source-ref refs/tags/0.9.0

Use the same bundle-download and verification commands for each binary. Change --source-ref to its exact release tag. The current composite action handles the published pre-transfer tags explicitly. It does not accept the original signer for new release tags.

Downstream distributions can add their own attestations or platform signing after conda-ship finishes staging their runtime artifacts.

Info JSON#

The info JSON contains:

  • schema version

  • artifact stem, artifact name, and runtime name

  • runtime version

  • layout

  • conda platform

  • optional executable update configuration

  • runtime filename

  • optional external bundle filename

  • lock filename

  • package list filename

  • SBOM filename

  • package count

  • SHA256 checksums

Package List#

The package list is tab-separated and contains:

  • package name

  • version

  • build string

  • package URL

  • SHA256, when available from the lockfile