From c2b3c7796495bceb3110a2f64419b1db6300ebd9 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 3 Oct 2025 12:24:09 +0200 Subject: [PATCH 1/2] feat: target another module when uploading snapshot --- src/help/snapshot.upload.help.ts | 9 +++- .../modules/snapshot/snapshot.services.ts | 54 ++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/help/snapshot.upload.help.ts b/src/help/snapshot.upload.help.ts index 07d0223c..1e34dbc0 100644 --- a/src/help/snapshot.upload.help.ts +++ b/src/help/snapshot.upload.help.ts @@ -2,13 +2,20 @@ import {cyan, green, magenta, yellow} from 'kleur'; import {OPTION_HELP, OPTIONS_ENV, SNAPSHOT_UPLOAD_DESCRIPTION} from '../constants/help.constants'; import {helpOutput} from './common.help'; import {TITLE} from './help'; +import {TARGET_OPTION_NOTE, targetOption} from './target.help'; const usage = `Usage: ${green('juno')} ${cyan('snapshot')} ${magenta('upload')} ${yellow('[options]')} Options: ${yellow('--dir')} Path to the snapshot directory that contains the metadata.json and chunks. + ${targetOption('snapshot')} + ${yellow('--target-id')} The module ID of a specific target to upload the snapshot to. ${OPTIONS_ENV} - ${OPTION_HELP}`; + ${OPTION_HELP} + +Notes: + +${TARGET_OPTION_NOTE}`; const doc = `${SNAPSHOT_UPLOAD_DESCRIPTION} diff --git a/src/services/modules/snapshot/snapshot.services.ts b/src/services/modules/snapshot/snapshot.services.ts index e7409184..37fd93ba 100644 --- a/src/services/modules/snapshot/snapshot.services.ts +++ b/src/services/modules/snapshot/snapshot.services.ts @@ -1,8 +1,16 @@ import type {snapshot_id} from '@dfinity/ic-management'; import {encodeSnapshotId} from '@dfinity/ic-management'; import {Principal} from '@dfinity/principal'; +import {nonNullish, notEmptyString} from '@dfinity/utils'; +import {findJunoPackageDependency, getJunoPackage} from '@junobuild/admin'; import {nextArg} from '@junobuild/cli-tools'; +import { + JUNO_PACKAGE_MISSION_CONTROL_ID, + JUNO_PACKAGE_ORBITER_ID, + JUNO_PACKAGE_SATELLITE_ID +} from '@junobuild/config'; import ora from 'ora'; +import {actorParameters} from '../../../api/actor.api'; import { deleteCanisterSnapshot, loadCanisterSnapshot, @@ -131,10 +139,54 @@ export const uploadSnapshot = async ({ const folder = nextArg({args, option: '--dir'}); assertNonNullishFolderExists(folder); + const targetCanisterId = nextArg({args, option: '--target-id'}); + + if (notEmptyString(targetCanisterId)) { + // TODO: extract into a service we can reuse for upgrade as well + const actorParams = await actorParameters(); + + const pkg = await getJunoPackage({ + moduleId: targetCanisterId, + ...actorParams + }); + + const validJunoPackage = (): {valid: boolean} => { + if (segment === 'mission_control') { + return {valid: pkg?.name === JUNO_PACKAGE_MISSION_CONTROL_ID}; + } + + if (segment === 'orbiter') { + return {valid: pkg?.name === JUNO_PACKAGE_ORBITER_ID}; + } + + // It's stock + if (pkg?.name === JUNO_PACKAGE_SATELLITE_ID) { + return {valid: true}; + } + + const {dependencies} = pkg ?? {dependencies: {}}; + + const satelliteDependency = findJunoPackageDependency({ + dependencies, + dependencyId: JUNO_PACKAGE_SATELLITE_ID + }); + + return {valid: nonNullish(satelliteDependency)}; + }; + + const {valid} = validJunoPackage(); + + if (!valid) { + await confirmAndExit( + `⚠️ The selected target is not a ${displaySegment(segment)}; this may cause issues if restored later. Are you sure you want to continue?` + ); + } + } + const {snapshotId} = await loadSnapshotAndAssertOverwrite({canisterId, segment}); await uploadExistingSnapshot({ - canisterId, + canisterId: notEmptyString(targetCanisterId) ? Principal.from(targetCanisterId) : canisterId, snapshotId, segment, folder From 2c91c6fe4b034e75831e4b4fa3c5a0819930c0f5 Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Fri, 3 Oct 2025 12:29:10 +0200 Subject: [PATCH 2/2] fix: canister id to resolve snapshot --- src/services/modules/snapshot/snapshot.services.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/modules/snapshot/snapshot.services.ts b/src/services/modules/snapshot/snapshot.services.ts index 37fd93ba..2116d69c 100644 --- a/src/services/modules/snapshot/snapshot.services.ts +++ b/src/services/modules/snapshot/snapshot.services.ts @@ -134,8 +134,6 @@ export const uploadSnapshot = async ({ segment: AssetKey; args?: string[]; }) => { - const canisterId = Principal.fromText(cId); - const folder = nextArg({args, option: '--dir'}); assertNonNullishFolderExists(folder); @@ -183,10 +181,12 @@ export const uploadSnapshot = async ({ } } + const canisterId = Principal.fromText(notEmptyString(targetCanisterId) ? targetCanisterId : cId); + const {snapshotId} = await loadSnapshotAndAssertOverwrite({canisterId, segment}); await uploadExistingSnapshot({ - canisterId: notEmptyString(targetCanisterId) ? Principal.from(targetCanisterId) : canisterId, + canisterId, snapshotId, segment, folder