Skip to content

feat(sync): clone_project composite — clone + parameterize + push from a reference snapshot #426

Description

@padak

Context

A downstream SDK/CLI consumer (the FIIA Scaffold Kit) builds new customer projects by cloning a golden reference project snapshot and parameterizing it. Today this is hand-rolled in ~35 KB of untested Python (clone_reference.py):

  • copy the pulled config tree,
  • rename per-instance directories,
  • rewrite bucket IDs,
  • override variable row values,
  • reset every _config.yml._keboola.config_id to placeholders so push CREATEs fresh configs,
  • swap in per-source SQL,
  • rebuild .keboola/manifest.json,
  • kbagent sync push,
  • a second pass to remap orchestrator task configIds (golden → new).

Problem

This is exactly the mechanical, side-effecting, idempotency-sensitive logic that belongs in the tested SDK, not re-implemented per consumer. In that consumer it is the single highest-risk untested surface (regex rewrites of SQL casts + shutil.rmtree of "cruft" dirs + manifest surgery), and every consumer that wants "clone a known-good project into a new one" will re-invent it.

Request

A first-class composite in the service layer, e.g.:

SyncService.clone_project(
    source,            # reference dir or source alias
    target_alias,
    overrides={        # declarative parameterization
        "bucket_map": {...},
        "variable_values": {...},
        "instance_rename": {...},
    },
)

and/or a kbagent sync clone command, that: clones a reference tree, applies declarative overrides, resets/rebuilds the manifest for fresh CREATE, pushes, and remaps orchestrator task configIds — idempotently (re-running is a no-op).

Acceptance sketch

  • Clone a golden project into a fresh target in one call.
  • Manifest ends with fresh ULIDs; orchestrator tasks point at the new configs.
  • Re-running the same clone reports no_changes / created: 0.

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions