Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/ISSUE_TEMPLATE/0_bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ body:
Provide minimal steps to reproduce the behavior.

```bash
<runtime> bootstrap
<runtime> <delegate-command>
# ...
```
render: shell
Expand All @@ -40,7 +40,8 @@ body:
Please run the following and paste the output below.

```bash
<runtime> --version && <runtime> status
<runtime> --version
<runtime> info
```
render: shell
- type: textarea
Expand Down
14 changes: 9 additions & 5 deletions .github/workflows/canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ jobs:
else
BIN="./dist/demo-${TARGET}"
fi
"$BIN" --path "$RUNNER_TEMP/demo-smoke" bootstrap
"$BIN" --path "$RUNNER_TEMP/demo-smoke" status
DEMO_PREFIX="$RUNNER_TEMP/demo-smoke" "$BIN" info --json
DEMO_PREFIX="$RUNNER_TEMP/demo-smoke" "$BIN" list --json

- name: Build embedded bundle
if: matrix.target == 'x86_64-unknown-linux-gnu'
Expand All @@ -122,8 +122,8 @@ jobs:
if: matrix.target == 'x86_64-unknown-linux-gnu'
shell: bash
run: |
./dist/demoz-"$TARGET" --path "$RUNNER_TEMP/demoz-smoke" bootstrap
./dist/demoz-"$TARGET" --path "$RUNNER_TEMP/demoz-smoke" status
DEMO_PREFIX="$RUNNER_TEMP/demoz-smoke" ./dist/demoz-"$TARGET" info --json
DEMO_PREFIX="$RUNNER_TEMP/demoz-smoke" ./dist/demoz-"$TARGET" list --json

- name: Stage canary binary
shell: bash
Expand Down Expand Up @@ -199,7 +199,11 @@ jobs:
set -euo pipefail

target/release/cs.exe --help >/dev/null
CONDA_SHIP_ALLOW_UNSTAMPED_TEMPLATE=1 target/release/cs-template.exe --version
if target/release/cs-template.exe 2>template-error.txt; then
echo "Expected the unstamped template to refuse execution" >&2
exit 1
fi
grep -q "runtime template, not a runnable conda runtime" template-error.txt

package-wheels:
name: Package PyPI wheel (${{ matrix.target }})
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ jobs:
else
BIN="./dist/demo-${TARGET}"
fi
"$BIN" --path "$RUNNER_TEMP/demo-smoke" bootstrap
"$BIN" --path "$RUNNER_TEMP/demo-smoke" status
DEMO_PREFIX="$RUNNER_TEMP/demo-smoke" "$BIN" info --json
DEMO_PREFIX="$RUNNER_TEMP/demo-smoke" "$BIN" list --json

- name: Build embedded bundle
shell: bash
Expand Down Expand Up @@ -146,8 +146,8 @@ jobs:
else
BIN="./dist/demoz-${TARGET}"
fi
"$BIN" --path "$RUNNER_TEMP/demoz-smoke" bootstrap
"$BIN" --path "$RUNNER_TEMP/demoz-smoke" status
DEMO_PREFIX="$RUNNER_TEMP/demoz-smoke" "$BIN" info --json
DEMO_PREFIX="$RUNNER_TEMP/demoz-smoke" "$BIN" list --json

coverage:
name: Coverage
Expand Down
21 changes: 9 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,10 @@ conda workspace lock
cs inspect
cs build --dry-run
cs build
./dist/demo --version
./dist/demo info
```

![Quickstart: inspect, preview, build, and run a stamped runtime](demos/quickstart.gif)

For a guided walkthrough with bootstrap, status, uninstall, and embedded runtime
For a guided walkthrough with automatic first-run bootstrap and embedded runtime
examples, see the
[first runtime tutorial](https://jezdez.github.io/conda-ship/tutorials/first-runtime/).

Expand All @@ -74,9 +72,10 @@ conda-ship stages a runtime binary plus release metadata:
- `.sha256`: checksums for staged files
- optional `.bundle.tar.zst`: compressed package archives for offline builds

The runtime itself has a small management surface: `bootstrap`, `status`,
`shell`, and `uninstall`. Other commands pass through to the configured
delegate executable after bootstrap, usually `conda`.
On first invocation, the runtime automatically bootstraps its managed prefix.
It then passes every argument to the configured delegate executable, usually
`conda`. The delegate and its plugins handle `--help`, `--version`, and every
subcommand. conda-ship does not reserve those arguments.

During bootstrap, generated runtimes also write constructor-compatible conda
prefix metadata. The managed prefix gets `conda-meta/history` and
Expand Down Expand Up @@ -140,7 +139,7 @@ cs inspect
cs build --dry-run
cs build
cs build --artifact-layout embedded
cs run -- --path /tmp/demo-smoke bootstrap
cs run --install-path /tmp/demo-smoke -- info
```

`cs inspect` is the preflight command. It derives the runtime lock, validates the
Expand All @@ -159,10 +158,8 @@ before handing them to downstream packaging or signing.

![Verify staged conda-ship artifacts](demos/verify.gif)

The staged runtime is a stamped copy of the generic runtime template with its
own command surface before pass-through to the configured delegate.

![Run a generated conda-ship runtime](demos/runtime-cli.gif)
The staged runtime is a stamped copy of the generic runtime template. It
bootstraps the managed prefix if needed, then runs the configured delegate.

## GitHub Actions

Expand Down
2 changes: 1 addition & 1 deletion demos/quickstart.tape
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ Type@80ms "cs build --out-dir dist"
Enter
Sleep 3s

Type@80ms "./dist/demo --version"
Type@80ms `DEMO_PREFIX="$DEMO_HOME/quickstart-prefix" ./dist/demo info --base`
Enter
Sleep 3s
6 changes: 3 additions & 3 deletions demos/runtime-cli.tape
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ Type "# Run the generated runtime binary"
Enter
Sleep 500ms

Type@80ms `"$DEMO_HOME/runtime/demo" --version`
Type@80ms `DEMO_PREFIX="$DEMO_HOME/runtime-prefix" "$DEMO_HOME/runtime/demo" --version`
Enter
Wait /\$/
Sleep 1s

Type "# conda activation gets runtime-specific guidance"
Type "# Later invocations go directly to the configured delegate"
Enter
Sleep 500ms

Type@80ms `"$DEMO_HOME/runtime/demo" activate`
Type@80ms `DEMO_PREFIX="$DEMO_HOME/runtime-prefix" "$DEMO_HOME/runtime/demo" info --base`
Enter
Wait /\$/
Sleep 5s
46 changes: 27 additions & 19 deletions docs/explanation/install-locations-and-ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,29 @@ install-name = "express"

With the `conda-home` scheme, that runtime installs below `~/.conda/express`.

## Runtime `--path`
## Runtime Prefix Override

Users can override the resolved install path at runtime:
Users can override the resolved install path with the prefix environment
variable derived from the runtime name:

```bash
RUNTIME --path /tmp/demo bootstrap
RUNTIME --path /tmp/demo status
RUNTIME --path /tmp/demo uninstall --yes
DEMO_PREFIX=/tmp/demo demo info
```

This is intentionally a runtime option, not a build-time path. Build artifacts
should remain cross-platform. A path that makes sense on one build machine may
not make sense for users on another operating system.
For a runtime named `demo`, the variable is `DEMO_PREFIX`. Non-alphanumeric
characters in the runtime name become underscores and letters are uppercased.
The override remains a runtime choice so build artifacts stay cross-platform.

For a local `cs run` smoke test, use the builder-side option instead:

```bash
cs run --install-path /tmp/demo -- info
```

## Ownership Metadata

After bootstrap, the runtime writes a metadata file inside the managed prefix.
After automatic bootstrap, the runtime writes a metadata file inside the
managed prefix.
It records:

- schema version
Expand All @@ -61,7 +67,7 @@ It records:
- channels
- package names

Later operations check that metadata before using or removing a prefix.
Later runtime invocations check that metadata before reusing a prefix.

This ownership file is conda-ship-specific. The runtime also writes standard
conda prefix metadata:
Expand All @@ -87,16 +93,18 @@ be:
- an unrelated directory

conda-ship-generated runtimes refuse to operate on non-empty unmanaged prefixes.
This protects existing conda installations from accidental mutation or deletion.
This protects existing conda installations from accidental mutation.

`bootstrap --force`, pass-through commands, `status`, and `uninstall` all use
ownership checks before touching an existing prefix.
Automatic bootstrap and later delegate invocations use ownership checks before
reusing an existing prefix.

## Uninstall
## Lifecycle Commands

`RUNTIME uninstall` removes the managed install path. It does not remove the
runtime binary itself because that binary may be owned by Homebrew, a conda
package, a constructor installer, Docker, or another channel.
The generated runtime does not own `status`, `repair`, or `uninstall` commands.
Those names are passed to the configured delegate like every other argument.

If `installer` was stamped into the runtime, uninstall prints it as a hint
for removing the runtime binary after the managed prefix is gone.
For conda delegates, use `conda info` for status. Use `conda doctor` and its
supported fixes to diagnose and repair an installed prefix. Installer snapshot
and self-management commands can come from conda-self when a distribution
includes it. Removal of the runtime binary remains the responsibility of the
package manager or installer that placed it.
2 changes: 1 addition & 1 deletion docs/explanation/manifests-and-conda-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Package and channel intent belongs in the
{external+conda-workspaces:doc}`conda workspace sections <reference/conda-toml-spec>`
when that manifest is available. conda-ship reads the selected lockfile
environment and stamps the resolved package names and channel URLs into runtime
metadata for status output.
metadata.

For conda-workspaces projects that keep conda config in `pyproject.toml`, use
`[tool.conda.*]` table names, such as `[tool.conda.workspace]` and
Expand Down
14 changes: 8 additions & 6 deletions docs/explanation/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Executive Summary

conda-ship turns a solved conda environment into a ready-to-run runtime.
It owns generic build and bootstrap mechanics. It is not a distribution, an
It contains generic build and bootstrap code. It is not a distribution, an
environment manager, or an installer generator.

At a glance:
Expand All @@ -13,8 +13,8 @@ At a glance:
- The builder selects one solved environment, derives a runtime lock, stamps
the generic runtime template, and stages online, external, or embedded
artifacts.
- The generated runtime bootstraps a managed prefix and passes user commands to
its configured delegate.
- The generated runtime automatically bootstraps a managed prefix when absent
and passes every argument to its configured delegate unchanged.
- The downstream project owns package sets, runtime names, user-facing policy,
installers, documentation, and release channels.

Expand Down Expand Up @@ -82,7 +82,8 @@ Runtime
: The executable conda-ship produces.

Delegate
: The executable inside the managed prefix that receives pass-through commands.
: The executable inside the managed prefix that receives every runtime
argument.

Artifact
: A release file staged by the build.
Expand Down Expand Up @@ -124,8 +125,9 @@ artifact carries the compressed bundle inside the runtime. See
[artifact layouts](../how-to/choose-artifact-layout.md) for the exact files and
configuration choices.

An embedded runtime automatically uses its bundled archives during bootstrap.
Its bundle can be overridden when needed.
An embedded runtime automatically uses its bundled archives during first-run
bootstrap. Its bundle can be overridden with the bundle environment variable
derived from the runtime name when needed.

The bundle format is intentionally narrow. conda-ship writes top-level `.conda`
and `.tar.bz2` files, then verifies them against the lockfile at install time.
Expand Down
6 changes: 3 additions & 3 deletions docs/explanation/project-boundaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ conda-ship owns the reusable build and runtime machinery:
and `.sha256`
- exposing the composite GitHub Action and local builder CLI

The generated runtime behavior also lives here: `bootstrap`, `status`, `shell`,
`uninstall`, pass-through to the configured delegate, offline bundle handling, embedded bundle
handling, and optional conda-spawn based activation.
The generated runtime behavior also lives here: automatic first-run bootstrap,
execution of the configured delegate, offline bundle handling, and embedded
bundle handling. conda-ship does not define the delegate's commands or plugins.

## What Downstream Distributions Own

Expand Down
31 changes: 16 additions & 15 deletions docs/explanation/runtime-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ binary:
- optional compressed package bundle
- documentation URL
- metadata filename
- bundle and offline environment variable names
- bundle, offline, and prefix environment variable names

That is what turns the same generic bootstrap code into a specific runtime
with its own runtime name, delegate, package set, help links, and install
location.
with its own runtime name, delegate, package set, and install location.

## Where The Template Comes From

Expand Down Expand Up @@ -56,15 +55,17 @@ or an explicit `--template PATH`.

## What Users See

The finished runtime has a small command surface:
The finished runtime does not expose conda-ship commands. On first invocation it
installs the selected package set into its managed prefix, then executes the
configured delegate with the original arguments. Later invocations execute the
same delegate directly through the existing prefix.

- `bootstrap`: install the selected package set into the runtime's install path
- `status`: report runtime and install details
- `shell`: start a conda-spawn subshell when conda-spawn is included
- `uninstall`: remove the install path

All other commands are passed through to the configured delegate executable
after bootstrap.
This means `--help`, `--version`, `status`, `shell`, `uninstall`, and every
other argument belong to the delegate. For a conda delegate, `conda info`
reports conda and prefix status. A distribution that includes conda-spawn with
the alias from
[conda-spawn PR #59](https://github.com/conda/conda-spawn/pull/59) can expose
`RUNTIME shell` as a command provided by conda-spawn.

The base prefix is protected with a CEP 22 frozen marker. Users create named
environments for regular package work.
Expand All @@ -73,10 +74,10 @@ environments for regular package work.

Some runtime behavior is visible to users:

- optional conda-spawn based activation through `RUNTIME shell`
- disabled `activate`, `deactivate`, and `init` commands with guidance when the delegate is `conda`
- automatic bootstrap before pass-through delegate commands
- uninstall that removes the install path and prints a runtime-removal hint
- automatic bootstrap before the first delegate invocation
- unchanged delegate arguments, process streams, signals, and exit status
- optional commands provided by packages such as conda-spawn and conda-self
- bundle, offline, and prefix environment variables derived from the runtime name

The package set, runtime name, delegate, documentation URL, and release channel belong to
the project using conda-ship.
5 changes: 2 additions & 3 deletions docs/explanation/source-locks-and-runtime-locks.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The runtime lock answers:

- What will this runtime install into its managed prefix?
- Which package records should be verified during bootstrap?
- Which channels and packages should status output report?
- Which channels and packages were selected for the runtime artifact?

Keeping them separate lets a downstream project maintain normal workspace input
while shipping only the selected runtime environment.
Expand Down Expand Up @@ -87,6 +87,5 @@ dist/demo.runtime.lock runtime lock
|
| stamped into runtime
v
demo bootstrap installs from that lock
first demo invocation installs from that lock, then runs the delegate
```

7 changes: 5 additions & 2 deletions docs/how-to/build-locally.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,13 @@ Use `cs run` to build and immediately execute the staged runtime:

```bash
cs run \
-- --path /tmp/demo-smoke bootstrap
--install-path /tmp/demo-smoke \
-- info
```

Everything after `--` is passed to the generated runtime.
`--install-path` controls the managed prefix used by this smoke test. Everything
after `--` is passed unchanged to the configured delegate after automatic
bootstrap.

## Build For Another Target

Expand Down
Loading
Loading