Documentation
Source Acquisition
drydock renders from local files and explicit source caches. It may fetch
declared Git, HTTP Helm, OCI Helm, and remote Kustomize inputs unless
--offline is set. It does not read ambient Git credential helpers, ambient
Helm registry config, or live Argo CD repository state.
Resolution Order
For repository sources, drydock resolves deterministically:
- Explicit
--repo-map URL=PATH. - Existing local source path under the selected repository tree.
- A source naming the local checkout — a configured remote of the selected
repository — at
""/HEAD, a diffed ref name (during diffs), or the repository’s default-branch name resolves to the local tree (during diffs, the active side tree). Full-commit-SHA revisions still acquire remotely. - Declared Git cache or fetch behavior for unmapped external repositories.
- Clear failure.
--repo-map wins over local fallback and network fetching. Use it for adjacent
local checkouts or CI jobs that prepare dependencies explicitly:
drydock test apps --path . \
--repo-map https://github.com/example/platform-config=../platform-config
For mapped pull-request repositories, --path and --path-orig are
authoritative source roots and override declared revisions.
Self-references — sources naming the checkout’s own repository at HEAD or
its default-branch name — resolve to the local tree automatically on all
surfaces, so they need no --repo-map entry. Keep --repo-map for forks,
commit-SHA pins, and runs from a subdirectory of the checkout.
Ref-only sources are allowed and render no manifests. $ref/... Helm value
files and file parameters resolve from the referenced source root, not from its
path.
Self-Repository Sources
On every render surface — get, build, test, diag, and both sides of
diff — drydock detects when a source repoURL matches one of the configured
remotes of the local checkout. At ""/HEAD, at the literal
--ref/--ref-orig names (diffs only), or at the repository’s default-branch
name, such sources resolve to the local tree — the active side tree during
diffs — with no Git cache read or network fetch, including under --offline.
Full-commit-SHA revisions, tags, and branches not named by the diff or a
remote HEAD symref still acquire remotely.
Default-branch names come from remote HEAD symrefs only
(refs/remotes/<remote>/HEAD — set by git clone; recreate it with
git remote set-head origin -a after a bare git init/fetch checkout; the
pr-action records the pull request’s base branch there whenever a base ref is
known — pull-request events or an explicit base-ref input). There is
no fallback guessing: without a symref, a source pinned to the default-branch
name acquires remotely, because init.defaultBranch or the checked-out HEAD
could wrongly treat a feature branch as the default.
Because self-repository sources read the local tree, uncommitted working-tree
edits flow into self-$repo value files on render surfaces, exactly as they do
for the primary source path. The converse also holds: a self-repository source
whose path was deleted locally but still exists on the remote tip fails with
path-not-found instead of silently rendering stale remote content — the tree
drydock is pointed at is the desired state.
Detection opens the Git repository at the selected --path/--repo exactly;
it does not walk up to a parent .git. Running test apps --path <subdir>
from inside a checkout gets no self-resolution — run from the checkout root,
or add --repo-map.
A --repo-map entry whose path is the checkout under diff
is rewritten per side for ref diffs, so a single mapped path never serves one
worktree to both sides. For path diffs of exported trees (no .git anywhere),
detection finds no remotes; provide per-invocation side-correct maps rather
than one static self-map. When a source merely resembles the local checkout
(same host and repository name, different owner — a fork layout), drydock
emits a source.self-repo-near-miss warning and keeps remote acquisition; add
--repo-map URL=PATH if they are the same repository. The warning is advisory
only: --strict neither escalates it nor fails the run on it.
Helm Sources
Chart-only HTTP(S) and OCI Helm sources may be fetched into the chart cache
unless --offline is set. Local Helm chart sources render from the repository
tree.
Drydock resolves missing HTTP(S) and OCI chart dependencies declared in
Chart.yaml through its native chart cache. With --offline, cache hits are
allowed but network fetches are disabled. The source checkout is not mutated,
and drydock does not run helm dependency build.
Local file://, repository-alias, or otherwise unresolved dependencies must
already be available under charts/. Missing local dependencies fail with a
clear vendored-chart requirement.
Helm valueFiles support local paths, $ref/... paths, glob expansion,
HTTP(S) remote value files, and discovered helm.valuesFileSchemes. Remote
value files use the remote-resource cache and --remote-* credentials, not the
chart cache. Explicitly empty helm.valuesFileSchemes disables remote
value-file URLs.
source.helm.passCredentials affects only HTTP chart repositories with
explicit --helm-* credentials. By default, drydock sends those credentials to
the repository index and to chart archive URLs on the same host. When
passCredentials is true, drydock also forwards them to cross-host chart
archive URLs returned by the repository index. It does not enable ambient
credential discovery.
Kustomize Sources
For local Kustomize sources, drydock applies the supported subset of Argo CD
kustomize.buildOptions discovered from argocd-cm or Argo CD Helm values:
| Build option | Behavior |
|---|---|
--enable-helm |
Enables native Kustomize helmCharts rendering through drydock’s Helm library path. |
--helm-api-versions |
Passes declared API versions to Helm chart inflation. |
--load-restrictor=LoadRestrictionsRootOnly |
Keeps Kustomize’s root-only load restriction. |
--load-restrictor=LoadRestrictionsNone |
Allows Kustomize to load files outside the Kustomization root. |
Unsupported build options fail explicitly instead of being ignored.
Version-specific kustomize.buildOptions.<version> and
kustomize.path.<version> settings produce warnings because drydock uses
embedded Go libraries instead of selecting external Kustomize binaries.
Kustomize helmCharts render natively through the same Helm library path used
for Argo CD chart sources. No external Kustomize CLI is required for chart
inflation.
Supported Kustomize Git remote forms include:
| Form | Remote root |
|---|---|
https://github.com/org/repo?ref=v1 |
Repository root at ref. |
https://github.com/org/repo.git?ref=v1 |
Repository root at ref. |
https://github.com/org/repo//path?ref=v1 |
path inside the repository at ref. |
git::https://github.com/org/repo.git?ref=v1 |
Repository root at ref with explicit Git syntax. |
git::https://github.com/org/repo.git//path?ref=v1 |
path inside the repository at ref with explicit Git syntax. |
ssh://git@github.com/org/repo.git?ref=v1 |
Repository root over SSH at ref. |
ssh://git@github.com/org/repo.git//path?ref=v1 |
path inside the repository over SSH at ref. |
git@github.com:org/repo.git?ref=v1 |
Repository root over SCP-style SSH at ref. |
git@github.com:org/repo.git//path?ref=v1 |
path inside the repository over SCP-style SSH at ref. |
Git refs may omit ref; omitted or empty ref values resolve to HEAD. Root
Git refs copy the repository root as the remote Kustomization root.
Remote Kustomize refs are supported in these fields:
| Field group | Supported fields |
|---|---|
| Kustomization directories | resources, bases, components |
| Patch files | patches.path, patchesJson6902.path, non-inline patchesStrategicMerge |
| Support files | generators, transformers, validators, configurations, crds, openapi.path, replacements.path |
| Generator inputs | ConfigMap and Secret generator files, envs, and env entries |
HTTP(S) refs are treated as single YAML or JSON files. Directory-shaped fields, including remote bases and components, must use Git refs that resolve to Kustomization directories.
Ambiguous non-file HTTP(S) URLs are rejected unless they use known Git host
shorthand, a .git repository path, or explicit Git syntax such as git::,
ssh://, or SCP-style git@host:org/repo.git.
The renderer copies acquired content into a temporary workspace under generated
.drydock paths. It does not write generated manifests into the source tree.
Caches And Offline Runs
Offline render, build, and diff commands require cache hits, repo maps, local
files, or local chart availability. Populate caches with a non-offline run,
then use --offline for cache-only validation:
drydock test apps --path .
drydock test apps --path . --offline
| Flag | Behavior |
|---|---|
--offline |
Disable Git, Helm chart, and remote Kustomize network fetching. |
--repo-map URL=PATH |
Map a source repository URL to a local checkout. |
--refresh-git |
Fetch cached Git repositories and bypass persisted render outputs for those inputs. |
--git-cache-dir PATH |
Override the default Git repository cache root. |
--refresh-charts |
Refresh cached immutable chart entries and bypass persisted render outputs for those inputs. |
--chart-cache-dir PATH |
Override the default chart cache root. |
--refresh-remotes |
Refresh cached remote Kustomize resources and bypass persisted render outputs for those inputs. |
--remote-cache-dir PATH |
Override the default remote-resource cache root. |
--render-cache |
Reuse persisted Application render outputs across runs (default on). |
--render-cache-dir PATH |
Override the default render-output cache root. |
--render-cache-max-size QUANTITY |
Size cap before LRU eviction (default 512Mi). |
--refresh-renders |
Ignore persisted render outputs and overwrite them after rendering. |
--plugin-cache-dir PATH |
Runtime override for policy-managed container plugin cache mounts. |
--registry-config PATH |
Supply the only Helm OCI registry credentials. |
Render-time Git, chart, and remote-resource caches must stay outside the current repository tree, compared repository trees, repo-map roots, and their symlink-resolved equivalents. Drydock validates these roots before cache reads, fetches, or writes so a repository cannot double as its own mutable source cache. A render-cache directory that cannot be opened fails the run at validation time, consistent with Git and chart cache validation. Dev builds without release version stamping never persist renders, so they do not require access to the render-cache directory.
Cache entries include hidden .drydock-cache/metadata.json sidecars with
redacted target metadata. Older hash-only entries are listed as legacy entries
when their filesystem layout is recognized.
--plugin-cache-dir is separate: it is a render-time override for
policy-managed container plugin cache mounts. Plugin cache mount roots remain
excluded from cache lifecycle commands (policy-managed).
Cache lifecycle commands also list, prune, and delete persisted render
output entries via --source render and --render-cache-dir. During prune,
when render entries are in scope (either because --source render is set or
because no --source filter is used), cache prune additionally enforces the
render cache size cap and removes stale orphaned temp files. A --source git, --source chart, or --source remote prune scopes only to that source
and skips the render sweep entirely.
Warning: The render cache size cap is a runtime flag (
--render-cache-max-size) thatcache prunecannot discover automatically. If your builds use a custom--render-cache-max-size, pass the same value tocache prune— otherwise the sweep enforces the 512Mi default and may evict entries your runtime cap would keep.
Render Output Cache
Successful Application render outputs persist across processes under
<user cache dir>/drydock/render, keyed by the Application spec, Argo
settings signature, drydock build that produced them, and provable source
inputs. A warm run returns cached manifests without invoking render engines.
For clean local repositories, drydock hashes committed per-Application input
paths instead of the whole repository commit. A commit that changes one
Application’s Helm values, Kustomize graph, directory or Jsonnet source, or
generated Application input invalidates that Application while unchanged
Applications can still hit the render cache. Generated inputs include static
Application YAML, ApplicationSet generator files, and rendered bootstrap
Application parents when discovery records those paths. Local source override
files (.argocd-source.yaml and .argocd-source-<app>.yaml) are also part
of every Application’s input digest; adding, editing, or deleting an override
file invalidates that Application’s cached entry.
Local dirty worktrees can also use the render output cache for Applications
whose proven render inputs are unchanged. In dirty Git-backed roots, drydock
enumerates the complete set of changed files once per run and decides the cache
strategy per Application input path set. Applications whose proven input paths
are untouched by any dirty file keep their clean-worktree cache keys — entries
persisted from clean runs are served directly across the mode transition, so
editing one Application re-renders only that Application. Applications whose
input paths overlap any dirty file are hashed from the working tree, including
modified, deleted, untracked, and ignored files under those paths. Helm sources
with glob value-file patterns always re-render and skip persistence in dirty
mode, because a new untracked file matching the glob would be invisible to the
path-set intersection. Untouched Applications that skip the working-tree hash
share clean mode’s run-stability contract: the dirty-path enumeration is
computed once at the start of a run, and any mid-run edits are caught by the
existing store-time verification rather than by a second scan. A worktree that
is clean except for nested .git directories is classified dirty (the nested
.git content is treated conservatively, consistent with the store guard’s
fail-closed treatment of git links).
This behavior is automatic, including in the PR action; no new action input is
required. The PR action stores persisted render outputs under
${cache-path}/renders when action caching is enabled.
Renders are persisted only when every input is provably pinned. Floating remote Kustomize bases, remote URL Helm value files, plugin sources, repo-mapped sources, and unsupported local input graphs always re-render.
Clean Git roots use committed input digests. Dirty Git roots use per-Application
committed or working-tree input digests, as described above. Symlinks,
unsupported file types, unreadable files, unbounded input graphs, and non-Git
roots render normally but skip persistence for the affected Application. Dev
builds without release version stamping disable persistence automatically.
Release binaries are always stamped; when building from source, ensure Go’s VCS
stamping is active (the default in a git checkout — go build -buildvcs=true
forces it) or persistence silently stays off. --cache-events with diag
shows a disabled event with reason dev-build when this applies.
Use --cache-events when diagnosing render-cache behavior. For build and
test, cache events are written to stderr so that stdout stays
machine-parseable (manifests for build, status lines for test). For diag,
cache events are included in structured output alongside diagnostics. Render
cache events report hit, miss, store, skipped, and error actions.
skipped reasons include input-graph-unsupported (the source’s input graph
is unsupported or cannot be fully enumerated), helm-glob-inputs (a dirty
worktree where Helm value-file globs make the input set unprovable from
committed content), duplicate-application (two discovered Applications share
the same namespace and name, so neither input set is authoritative),
input-digest-error, ineligible-source, and inputs-changed. All of these
mean drydock rendered normally without persisting the result. inputs-changed indicates drydock
could not prove the render inputs still match the cache key at store time —
usually because source files changed between cache-key computation and the end
of rendering (a TOCTOU guard), and always for sources whose inputs cannot be
re-verified, such as symlinks. When verification failed with an error, the
event carries the error text. One inherent limit: an edit that is reverted to
its original content before the render completes is indistinguishable from no
edit, so the verification cannot catch it.
Chart-backed renders key on the exact chart name and version. If a registry
republishes an existing version, for example a mutable OCI chart version, use
--refresh-charts (or --refresh-renders) to re-render and overwrite the
cached entries.
Credentials
Credentials are explicit and non-interactive. Drydock does not read ambient Git credential helpers, ambient Helm registry config, credential fields from discovered repository Secrets, or live Argo CD repository state.
| Source | Auth form | Flags |
|---|---|---|
| Git HTTPS | Bearer token | --git-bearer-token TOKEN |
| Git HTTPS | Basic auth | --git-username USER, --git-password PASS |
| Git SSH | SSH key | --git-ssh-key-file PATH, --git-known-hosts-file PATH, --git-ssh-passphrase PASSPHRASE |
| HTTP(S) Helm | Bearer token | --helm-bearer-token TOKEN |
| HTTP(S) Helm | Basic auth | --helm-username USER, --helm-password PASS |
| OCI Helm | Registry config | --registry-config PATH |
| HTTP(S) remote Kustomize | Bearer token | --remote-bearer-token TOKEN |
| HTTP(S) remote Kustomize | Basic auth | --remote-username USER, --remote-password PASS |
For Git HTTPS, HTTP(S) Helm, and HTTP(S) remote Kustomize, bearer auth wins
when both bearer and basic credentials are provided. Kustomize Git remote refs
reuse the explicit --git-* credentials, but use the remote Kustomize cache
and --offline or --refresh-remotes behavior.
Supported SSH URL forms are:
| Form | Username behavior |
|---|---|
ssh://git@host/org/repo.git |
Uses the explicit git username. |
git@host:org/repo.git |
Uses the explicit git username. |
ssh://host/org/repo.git |
Defaults the missing username to git. |
Passwords, bearer tokens, SSH private keys, SSH passphrases, registry credential values, and credential-bearing URLs are never printed in diagnostics or formatted errors.
Cache Lifecycle Boundary
Cache lifecycle commands are local filesystem operations only:
drydock cache path
drydock cache list -o json
drydock cache prune --older-than 720h --dry-run
drydock cache prune --max-size 4Gi --yes
They do not:
- render Applications
- clone or fetch Git repositories
- fetch Helm charts
- fetch remote Kustomize resources
- read credential flags
- retry failed network or authentication acquisitions
cache prune and cache delete operate only on recognized drydock Git,
chart, remote-resource, and render output cache entry roots. They do not
manage plugin cache mount roots selected with --plugin-cache-dir.
Cache lifecycle commands reject cache roots that resolve inside the current
working directory, selected repository roots, Git repository trees, or
symlink-resolved equivalents. Non-dry-run deletion requires --yes; dry-runs
never require confirmation.
Pruning by age
--older-than DURATION removes cache entries whose last-used timestamp
(Metadata.UpdatedAt, refreshed on every cache hit and fetch) predates the
given duration. Legacy entries without metadata fall back to filesystem mtime.
Pruning by size (--max-size)
--max-size QUANTITY evicts the least-recently-used entries from the selected
sources until their total size is at or below the cap. Recency is measured by
Metadata.UpdatedAt, which is refreshed on every cache use — not just the
initial fetch. This means the oldest (least-recently-used) entries are evicted
first. Eviction proceeds to at or below the cap exactly, not to a hysteresis
target.
--max-size composes with --source and --older-than. When both flags are
set, age-based entries are removed first; the size cap is then applied to the
survivors. The cap applies to the sum of SizeBytes across entries matching
the selected source and kind filters — the same per-entry sizes cache list
reports.
Warning: Evicted source cache entries hard-fail subsequent runs that use
--offline, because offline mode cannot re-fetch missing entries ("offline cache miss for ..."). Do not use--max-sizebefore an offline run unless you are confident the remaining entries cover all sources that offline run will need.
Automation
The Cache Lifecycle Boundary is defined by explicit invocation with explicit
caps — not by whether a human issued the command. Automation such as the
pr-action’s local-mode post-run prune step may invoke cache prune on the
operator’s behalf; the same boundary and --offline warning apply.
Deferred design
A shared content-addressed store with ref tables, leases, and mark-sweep collection is intentionally deferred. It would be useful only after drydock has multiple cache surfaces sharing immutable blobs.