Clone a package version
Publish a new package version behind the same aliases at a handoff hour.
Goal
Publish a new version of the growth package that takes over the alias at 1 January 2027, 00:00 UTC, and switch its usage statements to the contract anniversary. Contracts created from that hour get the new version. Existing contracts keep the version they were created from.
Packages can't be edited, so a new version is a fresh package create whose alias entry starts at the handoff. From that hour, alias resolution moves to the new version. See Packages.
Preview
metro package list --search=growth --sandbox --json
metro package clone-version preflight --aliases=growth --handoff-at=2027-01-01T00:00:00.000Z \
--usage-day=CONTRACT_START --sandbox --out=plans/clone.json--aliases takes a comma-separated list, so one plan can roll several packages at once. For each alias, preflight:
- reads the version live now and copies it into a new create body;
- sets the alias on the new version to start at
--handoff-at, which must be a future UTC hour; - changes
usage_statement_schedule.dayonly if you pass--usage-day(CONTRACT_STARTorFIRST_OF_MONTH); - bumps the
uniqueness_key, and skips an alias whose new key already exists, so a re-run creates nothing twice.
It blocks with alias_not_live when no version is live, and with alias_already_has_a_future_version when a handoff is already scheduled. The diff shows, per alias:
growth.usage_statement_schedule.day: "FIRST_OF_MONTH" -> "CONTRACT_START"
growth.resolves_to: "00000000-0000-4000-8000-000000000104" -> "(new version) from 2027-01-01T00:00:00.000Z"
Steps: POST /v1/packages/create
Payload hash: sha256:...To change prices or terms in the new version, write a full spec instead and run metro package create preflight --file=package.yaml --allow-alias-takeover --sandbox, with a future starting_at on the alias. Preflight warns MTR-PKG-004 that the alias moves.
Confirm
Show the human each alias, the handoff hour, what changes, and the hash. Check who's on the old version with metro package customers --alias=growth --sandbox. Then dry-run:
metro package clone-version apply --file plans/clone.json --sandbox --confirm-hash sha256:...Apply
metro package clone-version apply --file plans/clone.json --sandbox --confirm-hash sha256:... \
--apply --confirm-live-apply=I_UNDERSTAND_THIS_WILL_WRITE_LIVE_METRONOME_SANDBOXNothing is archived. When you later retire the old version, check it offline first: metro package archive preview --file handoff.json --sandbox refuses an archive until the replacement alias is live and read back. Archiving before then makes contract creation fail with 400.
Readback
metro reads the new package back, compares it with the plan, and proves both sides of the handoff:
Applied (sandbox).
Read-back (expected vs actual):
ok growth.name: expected "Acme Growth" actual "Acme Growth"
ok growth.rate_card_id: expected "00000000-0000-4000-8000-000000000103" actual "00000000-0000-4000-8000-000000000103"
ok growth.usage_day: expected "CONTRACT_START" actual "CONTRACT_START"
ok growth.alias_starting_at: expected "2027-01-01T00:00:00.000Z" actual "2027-01-01T00:00:00.000Z"
...
ok growth resolves to predecessor before handoff: expected "00000000-0000-4000-8000-000000000104" actual "00000000-0000-4000-8000-000000000104"
ok growth resolves to new version at handoff: expected "00000000-0000-4000-8000-000000000204" actual "00000000-0000-4000-8000-000000000204"The full list also covers the uniqueness key, duration, usage frequency, billing provider, and subscription, credit and commit counts. Illustrative IDs; the check names are exact. Any FAIL exits 3.