Skip to content

orbital migrate apply

orbital migrate apply is the second step in a migration. It consumes the JSON plan envelope produced by orbital migrate plan, provisions an OrbitalReg project + repositories that mirror the source registry, and writes a migration_runs row so a crashed apply can be resumed where it left off.

The CLI is a thin layer over POST /api/admin/migrate/apply. The strategy you supplied to plan (or the recommendation it picked) becomes the default; override with --strategy if you've decided differently.

Strategy semantics

StrategyWhat apply does
big-bangCreates the OrbitalReg project and local-mode repos. Artifact ingest follows in Phase E (importer-plugin glue).
blue-greenSame as big-bang for the apply step — repos are local-mode placeholders. The cutover dance lives outside the CLI.
lazy-proxyCreates remote-mode repos with the source registry as the upstream. No bulk copy; consumer pulls fill the cache. Run orbital migrate finalize once the hit rate is steady.

big-bang and blue-green are identical at the apply layer — the difference shows up at cutover time, not provisioning time.

Quick start

bash
# 1. Generate a plan (Phase A)
orbital migrate plan \
  --source jfrog \
  --endpoint https://jfrog.example.com \
  --token "$JFROG_TOKEN" \
  --output-file migration-plan.json

# 2. Preview what apply would do (no writes)
orbital migrate apply --plan migration-plan.json --dry-run

# 3. Run it for real
orbital migrate apply --plan migration-plan.json

Sample output (pretty-printed):

text
Migration apply — strategy=big-bang project=jfrog-import
  Run ID:        7f4a2d1c-9b1e-4e1c-95d8-2a4d05fe1c33
  Status:        complete
  Provisioned:   42 repositor(y|ies)
  Skipped:       3
    - oddball-format-1 — unsupported format: oddballfmt
    - existing-collision — repository jfrog-import/existing-collision already exists
    - bad/key — repo key normalises to empty slug
  Repositories:
    - jfrog-import/maven-prod [maven, local]
    - jfrog-import/npm-mirror [npm, local]
    ...

Next steps:
  - Repos are local-mode placeholders; artifact ingest lands in Phase E.

Flags

FlagDefaultNotes
--plan(required)Path to the JSON envelope migrate plan --output-file wrote.
--strategyplan's recommendationOverride: big-bang, blue-green, lazy-proxy.
--project-slug<source>-importOrbitalReg project the new repos land under.
--dry-runfalsePreview — no projects / repositories rows written.
--resumefalseContinue a previously-failed apply for the same source/endpoint/project tuple.
--jsonfalseEmit the full apply-result JSON instead of the pretty summary.

Resuming a failed apply

If the server, your laptop, or the network blinks mid-apply, re-run with --resume. The server looks up the previous migration_runs row by (source, endpoint, project_slug, status='applying'), re-uses its progress_json, and skips repositories already provisioned in the prior attempt. Idempotency holds at the (project, slug) level — a re-creation of the same slug surfaces as a Skipped row with reason "repository … already exists".

bash
orbital migrate apply --plan migration-plan.json --resume

--resume and --dry-run are mutually compatible; combining them re-reads the plan and reports what work the resume would perform without writing.

What gets skipped

Apply is conservative. It records, but does not fail on:

  • Unsupported format — a source repo whose package_type doesn't map to a registered OrbitalReg format. The row appears under Skipped with reason unsupported format: ….
  • Empty slug — a source key that normalises to an empty OrbitalReg slug (e.g. :::: or all-symbol keys).
  • Existing collision — an OrbitalReg repository at the target slug already exists. Apply doesn't overwrite. Drop / rename and re-run with --resume to retry.

Provisioned counts repos that landed; Skipped counts the above. The two together cover every plan repo.

Output formats

ModeFlagUse case
Pretty(default)Operator review in a terminal
JSON--jsonMachine-readable for CI scripting + dashboards

Exit codes

CodeMeaning
0Apply completed successfully (provisioned + skipped accounted for)
1User error (bad flag, missing --plan, OrbitalReg returned 400)
2Auth error (no OrbitalReg token, OrbitalReg returned 401 / 403)
3Server error (OrbitalReg returned 5xx; the run row is left at failed so --resume works)

Inspecting runs

GET /api/admin/migrate/runs returns the most recent runs (limit 50). GET /api/admin/migrate/runs/{id} returns one row including the full plan envelope and progress map. Useful for an admin UI that surfaces apply history; the CLI presents the same shape via --json.

What apply does not do

  • Artifact ingest. Phase B leaves big-bang / blue-green repos empty. The per-source artifact walk lives in Phase E (importer plugins).
  • Cutover automation. Pointing your CI at the new registry, port flips on a load balancer, or DNS changes — those are operator steps documented in the per-source playbooks.
  • Verification. orbital migrate verify (Phase C) compares artifact digests post-apply.

See also

Released under the Apache-2.0 License.