diff --git a/packages/contentstack-bulk-publish/src/commands/cm/assets/publish.js b/packages/contentstack-bulk-publish/src/commands/cm/assets/publish.js index 3aecb2c8e..b121906c9 100644 --- a/packages/contentstack-bulk-publish/src/commands/cm/assets/publish.js +++ b/packages/contentstack-bulk-publish/src/commands/cm/assets/publish.js @@ -15,12 +15,12 @@ class AssetsPublishCommand extends Command { assetsFlags.folderUid = assetsFlags['folder-uid'] || assetsFlags.folderUid; assetsFlags.bulkPublish = assetsFlags['bulk-publish'] || assetsFlags.bulkPublish; assetsFlags.apiVersion = assetsFlags['api-version'] || '3'; // setting default value for apiVersion - assetsFlags.dataDir = assetsFlags['data-dir'] || assetsFlags.dataDir; + assetsFlags.backupDir = assetsFlags['backup-dir'] || assetsFlags.backupDir; delete assetsFlags['api-version']; delete assetsFlags['retry-failed']; delete assetsFlags['folder-uid']; delete assetsFlags['bulk-publish']; - delete assetsFlags['data-dir']; + delete assetsFlags['backup-dir']; let updatedFlags; try { @@ -113,15 +113,15 @@ class AssetsPublishCommand extends Command { } } - validate({ environments, retryFailed, locales, dataDir, 'source-env': sourceEnv, 'delivery-token': deliveryToken }) { + validate({ environments, retryFailed, locales, backupDir, 'source-env': sourceEnv, 'delivery-token': deliveryToken }) { let missing = []; if (retryFailed) { return true; } - // In data-dir mode, environments and locales are derived per-asset from the + // In backup-dir mode, environments and locales are derived per-asset from the // backup publish_details, so they are not required on the command line. - if (dataDir) { + if (backupDir) { return true; } @@ -189,10 +189,10 @@ AssetsPublishCommand.flags = { '(optional) The UID of the Assets’ folder from which the assets need to be published. The default value is cs_root.', exclusive: ['source-env'], }), - 'data-dir': flags.string({ + 'backup-dir': flags.string({ description: '(optional) Path to the import backup directory. When set, each imported asset is published only to the environments and locales it was published to in the source stack (read from the backup’s publish details and asset UID mapping), with asset-scan gating applied. Intended for the post-import publish flow.', - exclusive: ['source-env', 'folder-uid'], + exclusive: ['source-env', 'folder-uid', 'environments', 'locales'], }), 'bulk-publish': flags.string({ description: 'Set this flag to use Contentstack’s Bulk Publish APIs. It is true, by default.', @@ -273,13 +273,13 @@ AssetsPublishCommand.examples = [ 'Using --stack-api-key flag', 'csdx cm:assets:publish --environments [ENVIRONMENT 1] [ENVIRONMENT 2] --locales [LOCALE] --stack-api-key [STACK API KEY]', '', - 'Using --data-dir flag (publish imported assets to their original environments after asset scanning)', - 'csdx cm:assets:publish --data-dir [PATH TO IMPORT BACKUP DIR] --stack-api-key [STACK API KEY]', + 'Using --backup-dir flag (publish imported assets to their original environments after asset scanning)', + 'csdx cm:assets:publish --backup-dir [PATH TO IMPORT BACKUP DIR] --stack-api-key [STACK API KEY]', ]; AssetsPublishCommand.aliases = ['cm:bulk-publish:assets']; AssetsPublishCommand.usage = - 'cm:assets:publish [-a ] [--retry-failed ] [-e ] [--folder-uid ] [--data-dir ] [--bulk-publish ] [-c ] [-y] [--locales ] [--branch ] [--delivery-token ] [--source-env ]'; + 'cm:assets:publish [-a ] [--retry-failed ] [-e ] [--folder-uid ] [--backup-dir ] [--bulk-publish ] [-c ] [-y] [--locales ] [--branch ] [--delivery-token ] [--source-env ]'; module.exports = AssetsPublishCommand; diff --git a/packages/contentstack-bulk-publish/src/consumer/publish.js b/packages/contentstack-bulk-publish/src/consumer/publish.js index f466b250c..cea6392fd 100644 --- a/packages/contentstack-bulk-publish/src/consumer/publish.js +++ b/packages/contentstack-bulk-publish/src/consumer/publish.js @@ -61,12 +61,12 @@ function displayEntriesDetails(sanitizedData, action, mapping = []) { function displayAssetsDetails(sanitizedData, action, mapping) { if (action === 'bulk_publish') { sanitizedData.forEach((asset) => { - asset?.publish_details.forEach((pd) => { + asset?.publish_details?.forEach((pd) => { if (Object.keys(mapping).includes(pd.environment)) { console.log( chalk.green( `Asset UID: '${asset.uid}'${pd.version ? `, Version: '${pd.version}'` : ''}${ - asset.locale ? `, Locale: '${asset.locale}'` : '' + asset.locale ? `, Locale: '${asset.locale}'` : ''} }, Environment: ${pd.environment}`, ), ); diff --git a/packages/contentstack-bulk-publish/src/producer/publish-assets.js b/packages/contentstack-bulk-publish/src/producer/publish-assets.js index df5af5da4..f35f2d751 100644 --- a/packages/contentstack-bulk-publish/src/producer/publish-assets.js +++ b/packages/contentstack-bulk-publish/src/producer/publish-assets.js @@ -256,16 +256,16 @@ async function processPendingAssets(pendingItems, stack, bulkPublish, environmen * subset). The single in-memory floor is the asset uid-mapping file itself (same * as import's publish()); for very large stacks raise Node's --max-old-space-size. */ -async function getAssetsFromBackup(stack, dataDir, bulkPublish, apiVersion, bulkPublishLimit) { - const assetsPath = path.join(dataDir, 'assets'); +async function getAssetsFromBackup(stack, backupDir, bulkPublish, apiVersion, bulkPublishLimit) { + const assetsPath = path.join(backupDir, 'assets'); const assetsIndexPath = path.join(assetsPath, 'assets.json'); - const assetUidMapperPath = path.join(dataDir, 'mapper', 'assets', 'uid-mapping.json'); - const envUidMapperPath = path.join(dataDir, 'mapper', 'environments', 'uid-mapping.json'); - const environmentsPath = path.join(dataDir, 'environments', 'environments.json'); + const assetUidMapperPath = path.join(backupDir, 'mapper', 'assets', 'uid-mapping.json'); + const envUidMapperPath = path.join(backupDir, 'mapper', 'environments', 'uid-mapping.json'); + const environmentsPath = path.join(backupDir, 'environments', 'environments.json'); // A backup with no assets is a legitimate outcome of a successful import that // had 0 assets (assets.json is never produced) — exit cleanly, not as a crash. - // A genuinely wrong --data-dir surfaces via the uid-mapping/environments guards below. + // A genuinely wrong --backup-dir surfaces via the uid-mapping/environments guards below. if (!existsSync(assetsPath) || !existsSync(assetsIndexPath)) { console.log(chalk.yellow('No assets found in backup — nothing to publish.')); return; @@ -457,7 +457,7 @@ function setConfig(conf, bp) { scanSummary = { clean: 0, quarantined: 0, inQueue: 0, noStatus: 0 }; } -async function start({ retryFailed, bulkPublish, environments, folderUid, locales, apiVersion, dataDir }, stack, config) { +async function start({ retryFailed, bulkPublish, environments, folderUid, locales, apiVersion, backupDir }, stack, config) { process.on('beforeExit', async () => { // Print the scan summary here (not inline after enqueueing): printScanSummary(scanSummary); @@ -498,12 +498,12 @@ async function start({ retryFailed, bulkPublish, environments, folderUid, locale } else { await retryFailedLogs(retryFailed, { assetQueue: queue }, 'publish'); } - } else if (dataDir) { + } else if (backupDir) { // Post-import flow: publish each imported asset only to its original // environments/locales (from backup publish_details), scan-gated. setConfig(config, bulkPublish); const bulkPublishLimit = fetchBulkPublishLimit(stack?.org_uid); - await getAssetsFromBackup(stack, dataDir, bulkPublish, apiVersion, bulkPublishLimit); + await getAssetsFromBackup(stack, backupDir, bulkPublish, apiVersion, bulkPublishLimit); } else if (folderUid) { setConfig(config, bulkPublish); const bulkPublishLimit = fetchBulkPublishLimit(stack?.org_uid); diff --git a/packages/contentstack-import/src/commands/cm/stacks/import.ts b/packages/contentstack-import/src/commands/cm/stacks/import.ts index 74217cf45..7cfc7f49a 100644 --- a/packages/contentstack-import/src/commands/cm/stacks/import.ts +++ b/packages/contentstack-import/src/commands/cm/stacks/import.ts @@ -187,6 +187,23 @@ export default class ImportCommand extends Command { log.success(`The log has been stored at: ${getLogPath()}`, importConfig.context); log.info(`The backup content has been stored at: ${backupDir}`, importConfig.context); + + // Closing reminder: when assets were imported but not published inline + // (asset scanning enabled, or --skip-assets-publish), point the user to + // cm:assets:publish with the backup dir and stack pre-filled so the note + // isn't lost in the per-module logs above. + const assetsImported = importConfig.moduleName + ? importConfig.moduleName === 'assets' + : importConfig.modules?.types?.includes('assets'); + // Mirror the publish gate in assets.ts (`!skipAssetsPublish`): assets are + // left unpublished exactly when skipAssetsPublish is set — which also + // covers the scanning case, since detecting scanning sets skipAssetsPublish. + if (!result?.noSuccessMsg && assetsImported && importConfig.skipAssetsPublish) { + log.info( + `Note: assets were imported but not published asset scanning is enabled and must complete first. To publish them, run:\n csdx cm:assets:publish --backup-dir ${backupDir} --stack-api-key ${importConfig.apiKey}`, + importConfig.context, + ); + } } catch (error) { handleAndLogError(error); log.info(`The log has been stored at '${getLogPath()}'`);