diff --git a/package-lock.json b/package-lock.json index 3c23b308..359679e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,14 +15,14 @@ "@dfinity/ic-management": "^6.1.1", "@dfinity/identity": "^2.3.0", "@dfinity/principal": "^2.3.0", - "@junobuild/admin": "^0.5.0-next-2025-06-04.1", - "@junobuild/cdn": "^0.1.0-next-2025-06-04.1", - "@junobuild/cli-tools": "^0.2.0-next-2025-06-04.1", + "@junobuild/admin": "^0.5.0-next-2025-06-04.3", + "@junobuild/cdn": "^0.1.0-next-2025-06-04.3", + "@junobuild/cli-tools": "^0.2.0-next-2025-06-04.3", "@junobuild/config": "^0.1.8", "@junobuild/config-loader": "^0.2.1", - "@junobuild/core": "^0.1.15-next-2025-06-04.1", + "@junobuild/core": "^0.1.15-next-2025-06-04.3", "@junobuild/did-tools": "^0.2.1", - "@junobuild/storage": "^0.2.0-next-2025-06-04.1", + "@junobuild/storage": "^0.2.0-next-2025-06-04.3", "@junobuild/utils": "^0.1.3", "chokidar": "^4.0.3", "conf": "^13.1.0", @@ -1464,9 +1464,9 @@ } }, "node_modules/@junobuild/admin": { - "version": "0.5.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/admin/-/admin-0.5.0-next-2025-06-04.1.tgz", - "integrity": "sha512-XzhQGSjJYvBz+C0JHPMr3e3zFwG8FjgGYm+kFaIUmaTRRsCUnpXbI1Nf6suA59GpcqXyILfxgzBuCEE9LP7Xzg==", + "version": "0.5.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/admin/-/admin-0.5.0-next-2025-06-04.3.tgz", + "integrity": "sha512-WT25gbMfM53PEk72dHw71q6eCA5rFKMRY93tMSjcYx8z40vB9h/g6CyuOha+8ZZDhUqWTgTDYFWWe0Am2XPHNw==", "license": "MIT", "peerDependencies": { "@dfinity/agent": "*", @@ -1481,9 +1481,9 @@ } }, "node_modules/@junobuild/cdn": { - "version": "0.1.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/cdn/-/cdn-0.1.0-next-2025-06-04.1.tgz", - "integrity": "sha512-o1rDVG+KucjZaD2MsVSpIrQNNMrl1a2sCJXbUhg8ZjAtXrVDE+Ew543OkIX0m7dQUXJ/7mJWxzrnbAQO5B4b8A==", + "version": "0.1.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/cdn/-/cdn-0.1.0-next-2025-06-04.3.tgz", + "integrity": "sha512-2JTNnHd3XUSTVD7NiOB9ptbKb1onrct7ffJ4pKGBwjZJQp1GWeCWh9jFLkPU/oKsqyz2DYxNCuylOS8H8hwxAA==", "license": "MIT", "peerDependencies": { "@dfinity/agent": "*", @@ -1497,9 +1497,9 @@ } }, "node_modules/@junobuild/cli-tools": { - "version": "0.2.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.2.0-next-2025-06-04.1.tgz", - "integrity": "sha512-zM16Ugqe4JaTbroceEa4BP4g+1PaP9CrCF+5yQO1wTFRxPDzPI/h7uKsT/h1JRTKHr4IO7HP0iTg85oi836u6A==", + "version": "0.2.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.2.0-next-2025-06-04.3.tgz", + "integrity": "sha512-IfOnvE9Awxtf7VVrB7m/Q4pb0kQgsuXNfw1IuUmWQxawiuab7Vhe6UYPpgs4wjyPOD2II4QST+elqv9twX73DA==", "license": "MIT", "dependencies": { "file-type": "^21.0.0", @@ -1536,9 +1536,9 @@ } }, "node_modules/@junobuild/core": { - "version": "0.1.15-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-0.1.15-next-2025-06-04.1.tgz", - "integrity": "sha512-0UaD9H0asneLLLCPz2SUbZgk+C3YL8/pJiJv4AHavzpQWjEbQjoCB1vq4IFv2SKEeNuGW/DrRZ6SPCmtl4HiLA==", + "version": "0.1.15-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-0.1.15-next-2025-06-04.3.tgz", + "integrity": "sha512-YBFfb8GPrgIfcmXQB7MqDIPMfrladDiKNtysYGXSke0jRBy9XqD/69lF95zE8SWivPfQL4d8LpOgNOcwDaKYWg==", "license": "MIT", "dependencies": { "@junobuild/errors": "*", @@ -1591,9 +1591,9 @@ } }, "node_modules/@junobuild/storage": { - "version": "0.2.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/storage/-/storage-0.2.0-next-2025-06-04.1.tgz", - "integrity": "sha512-PNd2uB6VDICyILauTp80MAiEfSHWR23sjJqFhryqdZVTnoaWBNHWu9jUQiOb7f5yDcblM/uixVHzseI/Xwlolg==", + "version": "0.2.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/storage/-/storage-0.2.0-next-2025-06-04.3.tgz", + "integrity": "sha512-VScyEeZ4f4WBUwtegsBei+x/Q77xVdJ0T4IkKNh3u6SLmMBfTMHL6uMMS4aOg2jcZaKWwJQV8wZRJRrJe4kXtA==", "license": "MIT", "peerDependencies": { "@dfinity/agent": "*", @@ -8011,21 +8011,21 @@ } }, "@junobuild/admin": { - "version": "0.5.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/admin/-/admin-0.5.0-next-2025-06-04.1.tgz", - "integrity": "sha512-XzhQGSjJYvBz+C0JHPMr3e3zFwG8FjgGYm+kFaIUmaTRRsCUnpXbI1Nf6suA59GpcqXyILfxgzBuCEE9LP7Xzg==", + "version": "0.5.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/admin/-/admin-0.5.0-next-2025-06-04.3.tgz", + "integrity": "sha512-WT25gbMfM53PEk72dHw71q6eCA5rFKMRY93tMSjcYx8z40vB9h/g6CyuOha+8ZZDhUqWTgTDYFWWe0Am2XPHNw==", "requires": {} }, "@junobuild/cdn": { - "version": "0.1.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/cdn/-/cdn-0.1.0-next-2025-06-04.1.tgz", - "integrity": "sha512-o1rDVG+KucjZaD2MsVSpIrQNNMrl1a2sCJXbUhg8ZjAtXrVDE+Ew543OkIX0m7dQUXJ/7mJWxzrnbAQO5B4b8A==", + "version": "0.1.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/cdn/-/cdn-0.1.0-next-2025-06-04.3.tgz", + "integrity": "sha512-2JTNnHd3XUSTVD7NiOB9ptbKb1onrct7ffJ4pKGBwjZJQp1GWeCWh9jFLkPU/oKsqyz2DYxNCuylOS8H8hwxAA==", "requires": {} }, "@junobuild/cli-tools": { - "version": "0.2.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.2.0-next-2025-06-04.1.tgz", - "integrity": "sha512-zM16Ugqe4JaTbroceEa4BP4g+1PaP9CrCF+5yQO1wTFRxPDzPI/h7uKsT/h1JRTKHr4IO7HP0iTg85oi836u6A==", + "version": "0.2.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/cli-tools/-/cli-tools-0.2.0-next-2025-06-04.3.tgz", + "integrity": "sha512-IfOnvE9Awxtf7VVrB7m/Q4pb0kQgsuXNfw1IuUmWQxawiuab7Vhe6UYPpgs4wjyPOD2II4QST+elqv9twX73DA==", "requires": { "file-type": "^21.0.0", "listr": "^0.14.3", @@ -8046,9 +8046,9 @@ "requires": {} }, "@junobuild/core": { - "version": "0.1.15-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-0.1.15-next-2025-06-04.1.tgz", - "integrity": "sha512-0UaD9H0asneLLLCPz2SUbZgk+C3YL8/pJiJv4AHavzpQWjEbQjoCB1vq4IFv2SKEeNuGW/DrRZ6SPCmtl4HiLA==", + "version": "0.1.15-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/core/-/core-0.1.15-next-2025-06-04.3.tgz", + "integrity": "sha512-YBFfb8GPrgIfcmXQB7MqDIPMfrladDiKNtysYGXSke0jRBy9XqD/69lF95zE8SWivPfQL4d8LpOgNOcwDaKYWg==", "requires": { "@junobuild/errors": "*", "@junobuild/storage": "*", @@ -8074,9 +8074,9 @@ "requires": {} }, "@junobuild/storage": { - "version": "0.2.0-next-2025-06-04.1", - "resolved": "https://registry.npmjs.org/@junobuild/storage/-/storage-0.2.0-next-2025-06-04.1.tgz", - "integrity": "sha512-PNd2uB6VDICyILauTp80MAiEfSHWR23sjJqFhryqdZVTnoaWBNHWu9jUQiOb7f5yDcblM/uixVHzseI/Xwlolg==", + "version": "0.2.0-next-2025-06-04.3", + "resolved": "https://registry.npmjs.org/@junobuild/storage/-/storage-0.2.0-next-2025-06-04.3.tgz", + "integrity": "sha512-VScyEeZ4f4WBUwtegsBei+x/Q77xVdJ0T4IkKNh3u6SLmMBfTMHL6uMMS4aOg2jcZaKWwJQV8wZRJRrJe4kXtA==", "requires": {} }, "@junobuild/utils": { diff --git a/package.json b/package.json index eed0b14b..c90c8edf 100644 --- a/package.json +++ b/package.json @@ -30,14 +30,14 @@ "@dfinity/ic-management": "^6.1.1", "@dfinity/identity": "^2.3.0", "@dfinity/principal": "^2.3.0", - "@junobuild/admin": "^0.5.0-next-2025-06-04.1", - "@junobuild/cdn": "^0.1.0-next-2025-06-04.1", - "@junobuild/cli-tools": "^0.2.0-next-2025-06-04.1", + "@junobuild/admin": "^0.5.0-next-2025-06-04.3", + "@junobuild/cdn": "^0.1.0-next-2025-06-04.3", + "@junobuild/cli-tools": "^0.2.0-next-2025-06-04.3", "@junobuild/config": "^0.1.8", "@junobuild/config-loader": "^0.2.1", - "@junobuild/core": "^0.1.15-next-2025-06-04.1", + "@junobuild/core": "^0.1.15-next-2025-06-04.3", "@junobuild/did-tools": "^0.2.1", - "@junobuild/storage": "^0.2.0-next-2025-06-04.1", + "@junobuild/storage": "^0.2.0-next-2025-06-04.3", "@junobuild/utils": "^0.1.3", "chokidar": "^4.0.3", "conf": "^13.1.0", diff --git a/src/commands/functions.ts b/src/commands/functions.ts index b55c6cb5..3f9fbdfc 100644 --- a/src/commands/functions.ts +++ b/src/commands/functions.ts @@ -7,7 +7,7 @@ import {logHelpFunctionsUpgrade} from '../help/functions.upgrade.help'; import {build} from '../services/functions/build/build.services'; import {eject} from '../services/functions/eject/eject.services'; import {publish} from '../services/functions/publish.services'; -import {upgradeFunctions} from '../services/functions/upgrade.services'; +import {upgradeFunctions} from '../services/functions/upgrade/upgrade.services'; export const functions = async (args?: string[]) => { const [subCommand] = args ?? []; diff --git a/src/constants/help.constants.ts b/src/constants/help.constants.ts index b1fbaf95..9b679a21 100644 --- a/src/constants/help.constants.ts +++ b/src/constants/help.constants.ts @@ -44,8 +44,8 @@ export const OPTION_KEEP_STAGED = `${yellow('-k, --keep-staged')} Keep stage export const OPTION_HASH = `${yellow('--hash')} The expected hash of all included changes (for verification).`; export const OPTION_HELP = `${yellow('-h, --help')} Output usage information.`; export const OPTION_SRC = `${yellow('-s, --src')} A path to a specific local gzipped WASM file to publish.`; -export const OPTIONS_UPGRADE = `${yellow('-r, --reset')} Reset to the initial state. - ${yellow('--clear-chunks')} Clear any previously uploaded WASM chunks (applies if the WASM size is greater than 2MB). - ${yellow('--no-snapshot')} Skip creating a snapshot before upgrading.`; +export const OPTIONS_UPGRADE = `${yellow('--clear-chunks')} Clear any previously uploaded WASM chunks (applies if the WASM size is greater than 2MB). + ${yellow('--no-snapshot')} Skip creating a snapshot before upgrading. + ${yellow('-r, --reset')} Reset to the initial state.`; export const NOTE_KEEP_STAGED = `The option ${yellow('--keep-staged')} only applies when ${yellow('--no-apply')} is NOT used (i.e. the change is applied immediately).`; diff --git a/src/help/functions.upgrade.help.ts b/src/help/functions.upgrade.help.ts index 1aafe8a7..bdf3a7ab 100644 --- a/src/help/functions.upgrade.help.ts +++ b/src/help/functions.upgrade.help.ts @@ -11,9 +11,17 @@ import {TITLE} from './help'; const usage = `Usage: ${green('juno')} ${cyan('functions')} ${magenta('upgrade')} ${yellow('[options]')} Options: - ${OPTION_SRC} + ${yellow('--cdn')} Select a previously published WASM file from the CDN (interactive). + ${yellow('--cdn-path')} Use a specific published WASM file from the CDN. ${OPTIONS_UPGRADE} - ${OPTION_HELP}`; + ${OPTION_SRC} + ${OPTION_HELP} + +Notes: + +- If no option is provided, the default local build output will be used. +- If ${yellow('--src')} is specified, it takes precedence over any CDN options. +- Use ${yellow('--cdn')} to interactively select from recent published releases.`; const doc = `${FUNCTIONS_UPGRADE_DESCRIPTION} diff --git a/src/services/functions/upgrade.services.ts b/src/services/functions/upgrade.services.ts deleted file mode 100644 index 217950a2..00000000 --- a/src/services/functions/upgrade.services.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {nextArg} from '@junobuild/cli-tools'; -import {SATELLITE_OUTPUT} from '../../constants/dev.constants'; -import {assertConfigAndLoadSatelliteContext} from '../../utils/satellite.utils'; -import {upgradeSatelliteWithSrc} from '../modules/upgrade/upgrade.satellite.services'; - -export const upgradeFunctions = async (args?: string[]) => { - const {satellite} = await assertConfigAndLoadSatelliteContext(args); - - const srcArgs = nextArg({args, option: '-s'}) ?? nextArg({args, option: '--src'}); - const src = srcArgs ?? `${SATELLITE_OUTPUT}.gz`; - - await upgradeSatelliteWithSrc({ - args, - src, - satellite - }); -}; diff --git a/src/services/functions/upgrade/upgrade.cdn.list.services.ts b/src/services/functions/upgrade/upgrade.cdn.list.services.ts new file mode 100644 index 00000000..21370773 --- /dev/null +++ b/src/services/functions/upgrade/upgrade.cdn.list.services.ts @@ -0,0 +1,41 @@ +import {COLLECTION_CDN_RELEASES} from '@junobuild/cli-tools'; +import {type Asset, listAssets} from '@junobuild/core'; +import {DEPLOY_LIST_ASSETS_PAGINATION} from '../../../constants/deploy.constants'; +import type {SatelliteParametersWithId} from '../../../types/satellite'; +import {last} from '../../../utils/array.utils'; + +export const listCdnAssets = async ({ + startAfter, + satellite, + traverseAll = false +}: { + startAfter?: string; + satellite: SatelliteParametersWithId; + traverseAll?: boolean; +}): Promise => { + const {items, items_length, matches_length} = await listAssets({ + collection: COLLECTION_CDN_RELEASES, + satellite, + filter: { + order: { + desc: true, + field: 'created_at' + }, + paginate: { + startAfter, + limit: DEPLOY_LIST_ASSETS_PAGINATION + } + } + }); + + if (items_length > matches_length && traverseAll) { + const nextItems = await listCdnAssets({ + startAfter: last(items)?.fullPath, + satellite, + traverseAll + }); + return [...items, ...nextItems]; + } + + return items; +}; diff --git a/src/services/functions/upgrade/upgrade.cdn.services.ts b/src/services/functions/upgrade/upgrade.cdn.services.ts new file mode 100644 index 00000000..8772c9b3 --- /dev/null +++ b/src/services/functions/upgrade/upgrade.cdn.services.ts @@ -0,0 +1,95 @@ +import {isNullish, nonNullish, notEmptyString} from '@dfinity/utils'; +import {assertAnswerCtrlC, hasArgs, nextArg} from '@junobuild/cli-tools'; +import {yellow} from 'kleur'; +import prompts from 'prompts'; +import {CDN_RELEASES_FULL_PATH} from '../../../constants/functions.constants'; +import {type SatelliteParametersWithId} from '../../../types/satellite'; +import {defaultSatelliteDomain} from '../../../utils/domain.utils'; +import {logUpgradeResult} from '../../../utils/upgrade.utils'; +import {upgradeSatelliteWithCdn} from '../../modules/upgrade/upgrade.satellite.services'; +import {listCdnAssets} from './upgrade.cdn.list.services'; + +export const upgradeWithCdn = async ({ + args, + satellite +}: { + args?: string[]; + satellite: SatelliteParametersWithId; +}) => { + const cdnPath = hasArgs({args, options: ['--cdn-path']}) + ? nextArg({args, option: '--cdn-path'}) + : undefined; + + const fullPath = cdnPath ?? (await selectCdnFullPath({satellite})); + + if (isNullish(fullPath)) { + return; + } + + const customHost = URL.parse(defaultSatelliteDomain(satellite.satelliteId))?.hostname; + + const cdn = { + url: process.env.CONTAINER_URL ?? defaultSatelliteDomain(satellite.satelliteId), + path: fullPath, + ...(nonNullish(customHost) && {customHost}) + }; + + const result = await upgradeSatelliteWithCdn({ + args, + cdn, + satellite + }); + + logUpgradeResult({ + ...result, + successMessage: 'Satellite successfully upgraded with serverless functions.' + }); +}; + +const selectCdnFullPath = async (params: { + satellite: SatelliteParametersWithId; +}): Promise => { + const assets = await collectCdnAssets(params); + + if (assets.length === 0) { + console.log(yellow('No published WASM files found in the CDN.')); + return undefined; + } + + return await promptCdnFullPath({assets}); +}; + +type AssetFullPathToken = string; + +interface AssetForPrompt { + title: string; + value: AssetFullPathToken; +} + +const collectCdnAssets = async (params: { + satellite: SatelliteParametersWithId; +}): Promise => { + const assets = await listCdnAssets(params); + + return assets.map(({fullPath, description, token}) => ({ + title: `${fullPath.replace(`${CDN_RELEASES_FULL_PATH}/`, '')}${notEmptyString(description) ? ` (${description})` : ''}`, + value: `${fullPath}${notEmptyString(token) ? `?token=${token}` : ''}` + })); +}; + +const promptCdnFullPath = async ({ + assets +}: { + assets: AssetForPrompt[]; +}): Promise => { + const {fullPath}: {fullPath: AssetFullPathToken} = await prompts({ + type: 'select', + name: 'fullPath', + message: 'Which published WASM would you like to use?', + choices: assets + }); + + assertAnswerCtrlC(fullPath); + + return fullPath; +}; diff --git a/src/services/functions/upgrade/upgrade.services.ts b/src/services/functions/upgrade/upgrade.services.ts new file mode 100644 index 00000000..35fd0c0f --- /dev/null +++ b/src/services/functions/upgrade/upgrade.services.ts @@ -0,0 +1,36 @@ +import {hasArgs, nextArg} from '@junobuild/cli-tools'; +import {SATELLITE_OUTPUT} from '../../../constants/dev.constants'; +import {type SatelliteParametersWithId} from '../../../types/satellite'; +import {assertConfigAndLoadSatelliteContext} from '../../../utils/satellite.utils'; +import {upgradeSatelliteWithSrc} from '../../modules/upgrade/upgrade.satellite.services'; +import {upgradeWithCdn} from './upgrade.cdn.services'; + +export const upgradeFunctions = async (args?: string[]) => { + const {satellite} = await assertConfigAndLoadSatelliteContext(args); + + const cdnOption = hasArgs({args, options: ['--cdn', '--cdn-path']}); + + const fn = cdnOption ? upgradeWithCdn : upgradeWithSrc; + + await fn({ + args, + satellite + }); +}; + +const upgradeWithSrc = async ({ + args, + satellite +}: { + args?: string[]; + satellite: SatelliteParametersWithId; +}) => { + const srcArgs = nextArg({args, option: '-s'}) ?? nextArg({args, option: '--src'}); + const src = srcArgs ?? `${SATELLITE_OUTPUT}.gz`; + + await upgradeSatelliteWithSrc({ + args, + src, + satellite + }); +}; diff --git a/src/services/modules/upgrade/upgrade.mission-control.services.ts b/src/services/modules/upgrade/upgrade.mission-control.services.ts index d8b0686a..0d2d2564 100644 --- a/src/services/modules/upgrade/upgrade.mission-control.services.ts +++ b/src/services/modules/upgrade/upgrade.mission-control.services.ts @@ -11,13 +11,8 @@ import {getCliMissionControl} from '../../../configs/cli.config'; import {MISSION_CONTROL_WASM_NAME} from '../../../constants/constants'; import type {UpgradeWasmModule} from '../../../types/upgrade'; import {NEW_CMD_LINE} from '../../../utils/prompt.utils'; -import {readUpgradeOptions} from '../../../utils/upgrade.utils'; -import { - consoleUpgradeResult, - selectVersion, - upgradeWasmCdn, - upgradeWasmLocal -} from './upgrade.services'; +import {logUpgradeResult, readUpgradeOptions} from '../../../utils/upgrade.utils'; +import {selectVersion, upgradeWasmJunoCdn, upgradeWasmLocal} from './upgrade.services'; export const upgradeMissionControl = async (args?: string[]) => { const missionControl = await getCliMissionControl(); @@ -40,20 +35,20 @@ export const upgradeMissionControl = async (args?: string[]) => { ...(await actorParameters()) }; - const consoleResult = (result: {success: boolean; err?: unknown}) => { - consoleUpgradeResult({...result, successMessage: 'Mission control successfully upgraded.'}); + const logResult = (result: {success: boolean; err?: unknown}) => { + logUpgradeResult({...result, successMessage: 'Mission control successfully upgraded.'}); }; if (hasArgs({args, options: ['-s', '--src']})) { const result = await upgradeMissionControlCustom({args, missionControlParameters}); - consoleResult(result); + logResult(result); return; } const result = await updateMissionControlRelease({args, missionControlParameters}); - consoleResult(result); + logResult(result); }; const updateMissionControlRelease = async ({ @@ -89,7 +84,7 @@ const updateMissionControlRelease = async ({ }); }; - return await upgradeWasmCdn({ + return await upgradeWasmJunoCdn({ version, assetKey: 'mission_control', upgrade: upgradeMissionControlWasm diff --git a/src/services/modules/upgrade/upgrade.orbiter.services.ts b/src/services/modules/upgrade/upgrade.orbiter.services.ts index c9f29138..449d3c9b 100644 --- a/src/services/modules/upgrade/upgrade.orbiter.services.ts +++ b/src/services/modules/upgrade/upgrade.orbiter.services.ts @@ -11,12 +11,11 @@ import {ORBITER_WASM_NAME} from '../../../constants/constants'; import type {UpgradeWasmModule} from '../../../types/upgrade'; import {NEW_CMD_LINE} from '../../../utils/prompt.utils'; import {orbiterKey} from '../../../utils/satellite.utils'; -import {readUpgradeOptions} from '../../../utils/upgrade.utils'; +import {logUpgradeResult, readUpgradeOptions} from '../../../utils/upgrade.utils'; import { confirmReset, - consoleUpgradeResult, selectVersion, - upgradeWasmCdn, + upgradeWasmJunoCdn, upgradeWasmLocal } from './upgrade.services'; @@ -35,20 +34,20 @@ export const upgradeOrbiters = async (args?: string[]) => { ...(await actorParameters()) }; - const consoleResult = (result: {success: boolean; err?: unknown}) => { - consoleUpgradeResult({...result, successMessage: 'Orbiter successfully upgraded.'}); + const logResult = (result: {success: boolean; err?: unknown}) => { + logUpgradeResult({...result, successMessage: 'Orbiter successfully upgraded.'}); }; if (hasArgs({args, options: ['-s', '--src']})) { const result = await upgradeOrbiterCustom({args, orbiterParameters}); - consoleResult(result); + logResult(result); return; } const result = await updateOrbiterRelease(orbiterParameters); - consoleResult(result); + logResult(result); }; for (const orbiter of authOrbiters) { @@ -129,7 +128,7 @@ const updateOrbiterRelease = async ({ }); }; - return await upgradeWasmCdn({ + return await upgradeWasmJunoCdn({ version, assetKey: 'orbiter', upgrade: upgradeOrbiterWasm, diff --git a/src/services/modules/upgrade/upgrade.satellite.services.ts b/src/services/modules/upgrade/upgrade.satellite.services.ts index 98251e45..ed9776b7 100644 --- a/src/services/modules/upgrade/upgrade.satellite.services.ts +++ b/src/services/modules/upgrade/upgrade.satellite.services.ts @@ -9,17 +9,22 @@ import {hasArgs, nextArg} from '@junobuild/cli-tools'; import {cyan, red} from 'kleur'; import {compare} from 'semver'; import {SATELLITE_WASM_NAME} from '../../../constants/constants'; -import type {AssertWasmModule, UpgradeWasm, UpgradeWasmModule} from '../../../types/upgrade'; +import { + type AssertWasmModule, + type UpgradeCdn, + type UpgradeWasmModule, + type UpgradeWasmParams +} from '../../../types/upgrade'; import {NEW_CMD_LINE} from '../../../utils/prompt.utils'; import {assertConfigAndLoadSatelliteContext, satelliteKey} from '../../../utils/satellite.utils'; -import {readUpgradeOptions} from '../../../utils/upgrade.utils'; +import {logUpgradeResult, readUpgradeOptions} from '../../../utils/upgrade.utils'; import {assertSatelliteBuildType} from './upgrade-assert.services'; import { confirmReset, - consoleUpgradeResult, redoCustomDomains, selectVersion, upgradeWasmCdn, + upgradeWasmJunoCdn, upgradeWasmLocal } from './upgrade.services'; @@ -31,20 +36,20 @@ export const upgradeSatellite = async (args?: string[]) => { `${NEW_CMD_LINE}Initiating upgrade for satellite ${cyan(satelliteId)}.${NEW_CMD_LINE}` ); - const consoleResult = (result: {success: boolean; err?: unknown}) => { - consoleUpgradeResult({...result, successMessage: 'Satellite successfully upgraded.'}); + const logResult = (result: {success: boolean; err?: unknown}) => { + logUpgradeResult({...result, successMessage: 'Satellite successfully upgraded.'}); }; if (hasArgs({args, options: ['-s', '--src']})) { const result = await upgradeSatelliteCustom({satellite, args}); - consoleResult(result); + logResult(result); return; } const result = await upgradeSatelliteRelease({satellite, args}); - consoleResult(result); + logResult(result); }; const upgradeSatelliteCustom = async ({ @@ -68,13 +73,49 @@ const upgradeSatelliteCustom = async ({ }; export const upgradeSatelliteWithSrc = async ({ - satellite, src, - args + ...rest }: { satellite: SatelliteParameters; src: string; args?: string[]; +}): Promise<{success: boolean; err?: unknown}> => { + const upgrade = async (params: UpgradeWasmParams): Promise<{success: boolean; err?: unknown}> => { + return await upgradeWasmLocal({src, assetKey: 'satellite', ...params}); + }; + + return await upgradeSatelliteWithUpgradeFn({ + ...rest, + upgradeFn: upgrade + }); +}; + +export const upgradeSatelliteWithCdn = async ({ + cdn, + ...rest +}: { + satellite: SatelliteParameters; + cdn: UpgradeCdn; + args?: string[]; +}): Promise<{success: boolean; err?: unknown}> => { + const upgrade = async (params: UpgradeWasmParams): Promise<{success: boolean; err?: unknown}> => { + return await upgradeWasmCdn({cdn, assetKey: 'satellite', ...params}); + }; + + return await upgradeSatelliteWithUpgradeFn({ + ...rest, + upgradeFn: upgrade + }); +}; + +const upgradeSatelliteWithUpgradeFn = async ({ + satellite, + args, + upgradeFn +}: { + satellite: SatelliteParameters; + args?: string[]; + upgradeFn: (params: UpgradeWasmParams) => Promise<{success: boolean; err?: unknown}>; }): Promise<{success: boolean; err?: unknown}> => { // TODO: option to be removed const currentVersion = await satelliteVersion({ @@ -83,19 +124,13 @@ export const upgradeSatelliteWithSrc = async ({ const {noSnapshot, preClearChunks} = readUpgradeOptions(args); - const upgrade = async ( - params: Pick - ): Promise<{success: boolean; err?: unknown}> => { - return await upgradeWasmLocal({src, assetKey: 'satellite', ...params}); - }; - return await executeUpgradeSatellite({ satellite, args, currentVersion, preClearChunks, noSnapshot, - upgrade + upgrade: upgradeFn }); }; @@ -119,10 +154,8 @@ const upgradeSatelliteRelease = async ({ const {noSnapshot, preClearChunks} = readUpgradeOptions(args); - const upgrade = async ( - params: Pick - ): Promise<{success: boolean; err?: unknown}> => { - return await upgradeWasmCdn({version, assetKey: 'satellite', ...params}); + const upgrade = async (params: UpgradeWasmParams): Promise<{success: boolean; err?: unknown}> => { + return await upgradeWasmJunoCdn({version, assetKey: 'satellite', ...params}); }; return await executeUpgradeSatellite({ @@ -148,9 +181,7 @@ const executeUpgradeSatellite = async ({ currentVersion: string; preClearChunks: boolean; noSnapshot: boolean; - upgrade: ( - params: Pick - ) => Promise<{success: boolean; err?: unknown}>; + upgrade: (params: UpgradeWasmParams) => Promise<{success: boolean; err?: unknown}>; }): Promise<{success: boolean; err?: unknown}> => { const reset = await confirmReset({args, assetKey: 'satellite'}); diff --git a/src/services/modules/upgrade/upgrade.services.ts b/src/services/modules/upgrade/upgrade.services.ts index 3bad0602..b0481e43 100644 --- a/src/services/modules/upgrade/upgrade.services.ts +++ b/src/services/modules/upgrade/upgrade.services.ts @@ -1,4 +1,4 @@ -import {isNullish} from '@dfinity/utils'; +import {nonNullish, notEmptyString} from '@dfinity/utils'; import { checkUpgradeVersion, setCustomDomains, @@ -16,7 +16,7 @@ import ora from 'ora'; import prompts from 'prompts'; import {JUNO_CDN_URL} from '../../../constants/constants'; import type {AssetKey} from '../../../types/asset-key'; -import type {UpgradeWasm} from '../../../types/upgrade'; +import {type UpgradeCdn, type UpgradeWasm, type UpgradeWasmParams} from '../../../types/upgrade'; import {toAssetKeys} from '../../../utils/asset-key.utils'; import {isNotHeadless} from '../../../utils/process.utils'; import {confirmAndExit} from '../../../utils/prompt.utils'; @@ -90,7 +90,7 @@ export const upgradeWasmLocal = async ({ }: { src: string; assetKey: AssetKey; -} & Pick): Promise<{ +} & UpgradeWasmParams): Promise<{ success: boolean; err?: unknown; }> => { @@ -120,27 +120,56 @@ export const upgradeWasmLocal = async ({ } }; -export const upgradeWasmCdn = async ({ +export const upgradeWasmJunoCdn = async ({ version, + assetKey, + ...rest +}: { + version: string; + assetKey: AssetKey; + cdn?: UpgradeCdn; +} & UpgradeWasmParams): Promise<{ + success: boolean; + err?: unknown; +}> => { + const cdn = { + url: JUNO_CDN_URL, + path: `/releases/${assetKey}-v${version}.wasm.gz` + }; + + return await upgradeWasmCdn({ + ...rest, + assetKey, + cdn + }); +}; + +export const upgradeWasmCdn = async ({ assetKey, upgrade, assert, - reset + reset, + cdn }: { - version: string; assetKey: AssetKey; -} & Pick): Promise<{ + cdn: UpgradeCdn; +} & UpgradeWasmParams): Promise<{ success: boolean; err?: unknown; }> => { const downloadWasm = async (): Promise<{hash: string; wasm: Buffer}> => { - const {hostname} = new URL(JUNO_CDN_URL); + const {url, path, customHost} = cdn; + + const {hostname, port, protocol} = new URL(url); const wasm = await downloadFromURL({ hostname, - path: `/releases/${assetKey}-v${version}.wasm.gz`, + protocol, + ...(notEmptyString(port) && {port}), + path, headers: { - 'Accept-Encoding': 'gzip, deflate, br' + 'Accept-Encoding': 'gzip, deflate, br', + ...(nonNullish(customHost) && {Host: customHost}) } }); @@ -283,29 +312,3 @@ export const confirmReset = async ({ return true; }; - -export const consoleUpgradeResult = ({ - success, - err, - successMessage -}: { - successMessage: string; - success: boolean; - err?: unknown; -}) => { - if (success) { - console.log(`✅ ${successMessage}`); - return; - } - - if (isNullish(err)) { - return; - } - - if (err instanceof UpgradeCodeUnchangedError) { - console.log(`🙅‍♂️ ${err.message}`); - return; - } - - throw err; -}; diff --git a/src/types/upgrade.ts b/src/types/upgrade.ts index c72acdb5..51ca6db5 100644 --- a/src/types/upgrade.ts +++ b/src/types/upgrade.ts @@ -12,3 +12,11 @@ export interface UpgradeWasm { assert?: (params: AssertWasmModule) => Promise; reset?: boolean; } + +export interface UpgradeCdn { + url: string; + path: string; + customHost?: string; +} + +export type UpgradeWasmParams = Pick; diff --git a/src/utils/domain.utils.ts b/src/utils/domain.utils.ts index 2b2a4555..558780e7 100644 --- a/src/utils/domain.utils.ts +++ b/src/utils/domain.utils.ts @@ -1,6 +1,12 @@ +import {nonNullish} from '@dfinity/utils'; import {CONSOLE_SATELLITE_URL} from '../constants/constants'; -export const defaultSatelliteDomain = (satelliteId: string): string => - `https://${satelliteId}.icp0.io`; +export const defaultSatelliteDomain = (satelliteId: string): string => { + if (nonNullish(process.env.CONTAINER_URL)) { + return `http://${satelliteId}.${process.env.CONTAINER_URL.replace('http://127.0.0.1', 'localhost')}`; + } + + return `https://${satelliteId}.icp0.io`; +}; export const consoleUrl = (satelliteId: string): string => `${CONSOLE_SATELLITE_URL}${satelliteId}`; diff --git a/src/utils/upgrade.utils.ts b/src/utils/upgrade.utils.ts index 84273e52..8ccf2e31 100644 --- a/src/utils/upgrade.utils.ts +++ b/src/utils/upgrade.utils.ts @@ -1,3 +1,5 @@ +import {isNullish} from '@dfinity/utils'; +import {UpgradeCodeUnchangedError} from '@junobuild/admin'; import {hasArgs} from '@junobuild/cli-tools'; import {compare} from 'semver'; import {getReleasesMetadata} from '../rest/cdn.rest'; @@ -45,3 +47,29 @@ export const readUpgradeOptions = ( return {noSnapshot, preClearChunks}; }; + +export const logUpgradeResult = ({ + success, + err, + successMessage +}: { + successMessage: string; + success: boolean; + err?: unknown; +}) => { + if (success) { + console.log(`✅ ${successMessage}`); + return; + } + + if (isNullish(err)) { + return; + } + + if (err instanceof UpgradeCodeUnchangedError) { + console.log(`🙅‍♂️ ${err.message}`); + return; + } + + throw err; +};