Skip to content

Crane Migration: Python to Go -- Full APM CLI Rewrite #78

@mrjf

Description

@mrjf

schedule: every 20m
strategy: greenfield
source-language: python
target-languages: [go]
target-metric: 1.0
metric_direction: higher

APM CLI: Python to Go -- Full Rewrite

Complete rewrite of the APM CLI from Python to Go. The Python implementation
stays in place for benchmarking and parity verification throughout the
migration. The Go version is built incrementally module-by-module, but the
end state is 100% Go with no Python in the shipping binary.

Source

  • Language: Python 3.10+ (CPython)
  • Runtime: CPython with Click CLI framework, Rich output, PyInstaller packaging
  • Paths:
    • src/apm_cli/ -- all application code (302 files, ~25 modules)
    • tests/ -- unit, integration, acceptance, benchmark suites
  • Key dependencies: click, rich, requests, pyyaml, gitpython, ruamel.yaml, watchdog

Target

  • Languages: Go (latest stable)
  • Runtime: Native binary (replaces PyInstaller onedir packaging)
  • Paths:
    • cmd/apm/ -- CLI entry point
    • internal/ -- all internal packages (mirroring src/apm_cli modules)
    • pkg/ -- any public library APIs
  • Bridge: None. Go binary fully replaces Python. Python kept only for
    benchmark parity during migration.

Strategy

Greenfield -- the Go implementation is built in parallel alongside the existing
Python codebase. This is the right choice because:

  1. The Python version must stay runnable for benchmark parity testing throughout.
  2. No external consumers depend on Python internals (only CLI surface matters).
  3. The end state is a clean Go codebase, not a Python/Go hybrid.

Milestone ordering

Milestone 0 -- Go test/benchmark harness (MUST complete before any code migration):
Build a Go-based test and benchmark harness that exercises the existing Python
CLI binary. This harness must achieve 100% behavioral coverage of the Python
implementation. It becomes the parity oracle for all subsequent milestones.

  • Acceptance tests calling the Python binary via subprocess
  • Benchmark suite capturing latency and resource baselines for every command
  • Parity check framework: run identical inputs against Python and Go, diff outputs

Milestone 1 -- Build scaffolding:

  • go.mod, go.sum, toolchain setup
  • CI integration (go test, go build in existing workflows)
  • Binary packaging parity with PyInstaller output

Milestone 2+ -- Module-by-module migration (suggested order):

  1. utils/, constants, config -- foundational, no external deps
  2. models/, primitives/ -- data structures
  3. deps/ -- dependency resolution
  4. cache/ -- HTTP/git caching
  5. core/ -- auth, target detection, orchestration
  6. install/ -- install pipeline and phases
  7. commands/ -- CLI command handlers (cobra replacing click)
  8. integration/ -- file integrators
  9. compilation/ -- compilation pipeline
  10. runtime/ -- runtime adapters
  11. policy/, security/ -- policy engine
  12. marketplace/, registry/ -- marketplace and registry
  13. bundle/, output/ -- packing and output
  14. cli.py entry point -- final wiring

Each milestone: port module, pass parity tests, pass benchmarks >= Python baseline.

Verification

cd cmd/apm && go test -json ./... | go run .crane/scripts/score.go

The scoring script will output JSON:

{
  "migration_score": 0.0,
  "progress": 0.0,
  "parity_passing": 0,
  "parity_total": 302,
  "source_tests_passing": 247,
  "target_tests_passing": 0,
  "perf_ratio": 1.0
}

migration_score = (parity_passing / parity_total) * correctness_gate
where correctness_gate is 1.0 if all target tests pass, 0.0 otherwise.

Out of scope

  • src/apm_cli/ -- Crane must NOT modify the Python source (kept for benchmarking)
  • tests/ -- existing Python test suite (kept as-is for parity reference)
  • docs/ -- documentation updates happen after migration completes
  • build/apm.spec -- PyInstaller spec (kept for Python benchmark builds)
  • .apm/ -- APM primitives (language-agnostic, no migration needed)
  • packages/ -- downstream packages
  • templates/ -- project templates

Metadata

Metadata

Assignees

No one assigned

    Labels

    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