akua / examples / 12-vendor-offline

example 12 — vendor-offline (render without network or auth)

A Package whose dep is materialized into `.akua/vendor//` so render works without re-fetching from the canonical source. This example takes the offline guarantee literally — the canonical `upstream-ch

Renders end-to-end off the local vendor tree. No registry, no network, no credentials needed at render time. The same Package renders identically inside an air-gapped environment or behind a firewall once akua vendor add has staged the bytes.

A Package whose dep is materialized into .akua/vendor/<name>/ so render works without re-fetching from the canonical source. This example takes the offline guarantee literally — the canonical upstream-chart/ source is not present in the checkout. Render succeeds because the resolver finds the bytes under .akua/vendor/upstream/.

Why vendor

The resolver prefers .akua/vendor/<name>/ when it exists for every dep kind — path, OCI, and git alike (see chart_resolver::resolve_with_options). akua vendor add is the public CLI verb that populates that path from a declared dep and pins the digest in akua.lock. The contract:

/ git). It records what the dep is.

Always preferred when present — across all dep kinds.

workspace produces a byte-identical render.

This is the same story Go's vendor/ directory tells: "commit the deps so your build is reproducible without a network round-trip."

What's here

filepurpose
package.kKCL Package; renders the chart at .akua/vendor/upstream.
akua.tomlManifest — declares upstream as a path dep pointing at ./upstream-chart.
akua.lockPins the vendor tree's digest. Committed.
inputs.example.yamlAuto-discovered when --inputs is omitted.
.akua/vendor/upstream/The vendored chart bytes. Committed — this is the offline-render guarantee.
rendered/Golden-rendered output the integration test diffs against.
~~upstream-chart/~~Intentionally absent. In a production install pipeline this would be the OCI ref / private git repo / inaccessible-at-render-time canonical source. The point of this example is that render works without it.

Try it

# 1. Confirm the canonical source is gone:
ls upstream-chart/  # → No such file or directory

# 2. Confirm the vendor tree is committed:
ls .akua/vendor/upstream/  # → Chart.yaml  templates/

# 3. Render — succeeds without network, auth, or canonical source:
akua render --out ./rendered

# 4. Verify integrity — `akua vendor check` re-hashes the vendor tree
#    and compares against akua.lock:
akua vendor check
# → ok

# 5. List what's vendored, including any orphan trees that no longer
#    correspond to a dep in akua.toml:
akua vendor list

To regenerate the vendor tree from a canonical source (e.g., during development before committing), restore upstream-chart/ and run akua vendor add upstream.

When vendoring matters

For interactive Package authoring, vendoring is overkill — let the resolver fetch from OCI or git on every render.

It earns its keep when:

registry. Vendor at bootstrap from a host that does; commit; render reproducibly later.

auth. If render runs in a least-privilege context that shouldn't hold those credentials, vendor at a one-shot privileged step upstream.

hosts can disappear, garbage-collect old tags, or rewrite history. Vendoring pins the bytes locally; the digest in akua.lock keeps the post-checkout render deterministic.

case). The install pipeline mints a per-install token, vendors the composed Package's bytes once at bootstrap, and commits the result. Subsequent renders need neither the token nor network access.

Out of scope (for now)

vendors upstream only. If upstream itself depends on a chart that needs network at render time, vendor that too — track CI drift with akua vendor check.

exactly one dep name. Looping is the caller's job.

Path-escape safety

akua vendor add rejects:

"../sibling"E_PATH_ESCAPE`.

Same workspace-local invariant the resolver enforces for path deps — vendor cannot be used as a side-channel to copy arbitrary host bytes into an install repo.

package.k

# Renders a chart vendored into `.akua/vendor/upstream/` via
# `akua vendor add upstream`. The dep declaration in `akua.toml`
# stays canonical (`path = "./upstream-chart"`); the resolver
# prefers the vendored copy when present, so render is offline-
# safe once the vendor tree is committed alongside the Package.

import akua.ctx
import akua.helm

schema Input:
    """Public inputs for the vendored upstream."""

    message: str = "rendered from .akua/vendor/upstream"
    """Embedded into the rendered ConfigMap so you can spot which copy
    of the chart was used."""

input: Input = ctx.input()

_manifests = helm.template(helm.Template {
    chart     = ".akua/vendor/upstream"
    values    = {
        message = input.message
    }
    release   = "vendored"
    namespace = "default"
})

resources = _manifests

Rendered output

000-configmap-vendored-vendored.yaml

apiVersion: v1
data:
  message: rendered from .akua/vendor/upstream
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/name: vendored
    vendored: 'true'
  name: vendored-vendored
  namespace: default

Source: examples/12-vendor-offline/