Skip to content

snapshot-review: scale review time with the change, not the repo (baseline cache, prebuilt images, changed-file render subsetting) #74

Description

@max06

Motivation

snapshot-review renders the full deployment tree twice (baseline + PR). On a consumer repo with ~115 deployments the workflow takes ~4:20 today; opened up to application developers adding their own deployments, both the tree size and the PR rate grow — full-twice rendering scales as O(repo) per PR, so total CI load grows roughly quadratically. Target: feedback time proportional to the change, not the repo.

This is a design issue for later implementation. Three building blocks, ordered by risk (the first two are correctness-free and should land first).

1. Baseline snapshot cache (flat ~2× win, zero risk)

Baseline renders are deterministic per (target-branch sha, toolchain/action version). Cache the rendered baseline as a workflow artifact keyed on those and replay it in PR runs instead of re-rendering.

  • Store snapshots redacted: markers are deterministic (REDACTED:sha256:<12hex> of the value), so diffs against a redacted PR-side render align exactly — and the cached artifact contains no secret material at rest.
  • First run after a target-branch push (or a toolchain change) renders and populates; subsequent PRs replay.
  • Invalidation key must include the atlas-render image identity, not just the ref.

2. Prebuilt action images (flat 30–60s+ win, zero risk)

atlas-render / atlas-diff are Dockerfile actions built on every job. Publish them per release/main-sha and reference the image directly (docker://), removing the per-run build.

3. Changed-file render subsetting (the big win, needs care)

The directory convention is the dependency graph, so changed paths classify mechanically:

Changed path Affected render set
deployments/<scope>/apps/<name>/** deployment <name> at that scope's fan-out (cluster → 1, group → group's clusters, global → all clusters)
deployments/<...>/cluster.values.* all deployments of that cluster
deployments/<group>/group.values.* all deployments in that group
deployments/global.values.* full render
templates/<t>/** all deployments instantiating template <t> (deployment→template map = cheap yq pass over all deployment.yaml files, no render needed)
entry helmfile / atlas version ref full render
anything unclassifiable full render (default-deny)

Classifier requirements:

  • Evaluate against both revisions (deletions/moves invalidate their old scope; a cluster-level deployment.yaml added/removed flips most-specific-wins shadowing — mapping by deployment name on both sides catches this). Input is git diff --name-status base...head.
  • Union of per-file sets; any single "full" wins.
  • Both sides render the same subset.

Execution: ATLAS_FILTER_CLUSTER / ATLAS_FILTER_DEPLOYMENT_NAME are the stage-1 short-circuit this needs, but they are single-valued (eq) today → prerequisite: multi-value filter support (comma-separated list) so one invocation renders a set of (cluster, deployment) pairs without repeated state builds.

Known failure mode: false negatives

A change affecting a render the classifier did not select produces a silent green PR. The only conventional-layout escape is readFile/tpl reaching outside the owning directory (shared snippets). Mitigations, in trust order:

  1. Shadow mode first: compute the subset, still render full, assert subset-diff ≡ full-diff on every PR for an extended period; log discrepancies. Switch over only on empirical evidence.
  2. Escape hatches, permanent: a PR label forcing full render + a scheduled full render of the target branch (bounds any classifier bug to one day).
  3. Optional lint: constrain readFile targets to the template's own directory, turning the convention the classifier depends on into an enforced contract.

The review comment should state the subset transparently ("rendered N of M deployments; rules: ...") so a surprising green sheet is auditable.

Long-term: atlas emits the dependency map

The path→(cluster, deployment) mapping is the same knowledge consumer-side render-optimization annotations (Argo CD manifest-generate-paths-style) encode by hand. Atlas should emit this map itself (it already knows deployment→template and hierarchy scopes at discovery time) as a machine-readable artifact, consumed by both the review subsetter and consumer annotations — one source of truth instead of two drifting approximations.

Expected outcome (measured baseline: ~4:20 full-twice)

  • Blocks 1+2 alone: well under 2 minutes, no correctness risk.
  • With subsetting — typical single-deployment PR (the dominant case once developers self-serve): ~15–30s; template-touching PR: ~1–2 min; framework/global PR: unchanged full render (rare, intentionally).

Rollout order

  1. Prebuilt images → 2. baseline cache → 3. multi-value ATLAS_FILTER_* → 4. classifier in shadow mode → 5. cutover with escape hatches → 6. atlas-emitted dependency map.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions