Skip to content

feat(migrate): X9 — devstack import (devdock → two-file schema, spec 14) - #76

Merged
gustavobertoi merged 1 commit into
mainfrom
nightly/X9-import
Jun 29, 2026
Merged

feat(migrate): X9 — devstack import (devdock → two-file schema, spec 14)#76
gustavobertoi merged 1 commit into
mainfrom
nightly/X9-import

Conversation

@gustavobertoi

Copy link
Copy Markdown
Contributor

What

Implements the spec-14 devstack import: converts a legacy devdock single-file project.yaml into the clean-slate split — workspace.yaml (shared layer) + a per-repo devstack.yaml — plus a lossless-or-loud conversion report. Replaces the M1 stub; completes X9.

Converter (internal/migrate.Convert)

Tolerant (the exact devdock dialect isn't pinned, so parse leniently + report rather than guess):

  • services with a repo → projects (git shorthand expanded via internal/git)
  • recognized stateful engines (postgres/redis/minio, by template or image) with no repo → shared:
  • per-service params/uses/env carry into each devstack.yaml
  • usesworkspace.shared.<name>; devdock ${svc.var} → typed ${ref:workspace.shared.svc.var}
  • every field it can't confidently convert (non-shared uses/refs, image-only services, unplaceable services) goes in the report — nothing dropped silently (spec 14 §lossless-or-loud)

Output is ordered (yaml.MapSlice) with an apiVersion: devstack/v1 header pointing at docs/MIGRATION.md.

CLI

devstack import <project.yaml> [--dry-run] [--out <dir>] [--force] — no-clobber by default (refuses to overwrite workspace.yaml/a target devstack.yaml), --force backs up originals first, --dry-run previews + writes nothing, --json for scripts.

Tests

Converter: shared/project split, uses + env-ref rewrite, git expansion, report for an unconvertible ref, valid Project/Workspace YAML, no-services-is-loud. CLI: registration, dry-run writes nothing, real run writes split + report, no-clobber refuses without --force and backs up with it. make ci + make determinism green.

Spec acceptance (spec 14 §import)

  • import --dry-run emits the workspace + per-repo split and a conversion report, writing nothing.
  • refuses to overwrite an existing workspace.yaml without --force; with --force backs up originals first.
  • lossless-or-loud: every unconvertible field is reported.

If a real devdock file uses different field names than the spec describes, only the tolerant accessors need a tweak — and the report already surfaces anything unmapped.

🤖 Generated with Claude Code

… 14)

Implements the spec-14 importer: reads a legacy devdock single-file project.yaml
and emits the clean-slate split — workspace.yaml (shared layer) + a per-repo
devstack.yaml — plus a lossless-or-loud conversion report.

`internal/migrate.Convert` is a TOLERANT converter (the exact devdock dialect
isn't pinned, so parse leniently and report rather than guess): services with a
`repo` become projects (git shorthand expanded via internal/git); recognized
stateful engines (postgres/redis/minio, by template or image) with no repo become
`shared:`; per-service params/uses/env carry into each devstack.yaml; `uses`
rewrites to `workspace.shared.<name>`; devdock `${svc.var}` interpolation rewrites
to the typed `${ref:workspace.shared.svc.var}` grammar. Every field it can't
confidently convert (non-shared uses/refs, image-only services, unplaceable
services) is recorded in the report — nothing is dropped silently (spec 14
§lossless-or-loud). Output is ordered (yaml.MapSlice) and carries an
apiVersion/v1 header pointing at docs/MIGRATION.md.

CLI `devstack import <project.yaml> [--dry-run] [--out <dir>] [--force]`:
no-clobber by default (refuses to overwrite workspace.yaml / a target
devstack.yaml), `--force` backs up originals first, `--dry-run` previews + writes
nothing, `--json` for scripted use. Replaces the M1 stub.

Tested: shared/project split + uses/env-ref rewrite + git expansion + report for
an unconvertible ref; every emitted file is valid Project/Workspace YAML;
no-services input is loud; CLI dry-run writes nothing, real run writes the split +
report, no-clobber refuses without --force and backs up with it. `make ci` +
`make determinism` green.

Note: the converter follows spec 14's described mapping; if a real devdock file
uses different field names, only the tolerant accessors in migrate.go need a
tweak, and the conversion report already surfaces anything unmapped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gustavobertoi
gustavobertoi merged commit 272f27a into main Jun 29, 2026
3 checks passed
@gustavobertoi
gustavobertoi deleted the nightly/X9-import branch June 29, 2026 22:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant