Skip to content

Commit

Permalink
Variants bulk publish and unpublish (#1664)
Browse files Browse the repository at this point in the history
* Implemented variants entries bulk publish feature (#1515)

* Implemented variants entries bulk publish feature

* Fixed PR comments

* Added variant entries pagination

* Implemented error handling

* Upgraded axios package version

* Removed secrets-scan workflow file

* Implemented variants entries bulk unpublish (#1521)

* Implemented variants entries bulk unpublish

* Upgraded axios package

* Removed secrets-scan.yml workflow file

* Fixed PR comments

* Fixed PR comments

* Implemented cross publish with variant entries (#1529)

* Implemented cross publish variant entries

* Fixed PR comments

* Fixed cross publish issue and updated variant entry publish payload (#1569)

* Fixed cross publish issue and updated variant entry publish payload

* Fixed PR comments

* Fixed PR comments

* Reverted code changes

* Removed api_version from header

* Added new flag publish-without-base in entry variants publish (#1580)

* Fixed variants cross publish issue (#1603)

* Removed publish-without-base flag due to new variants publish rules

* version bump

* Removed un-necessary empty lines

* version bump (#1639)

* Fixed merge conflits (#1647)

* Fixed merge conflits

* Fixed variants publish issue when bulkPublishLimit is 1

* Merge branch 'development' into variants-bulk-publish-and-unpublish (#1657)

* Fixed merge conflits (#1659)

* Fix/merge conflits (#1662)

* Fixed merge conflits

* Fixed merge conflits

* resolved conflits

* Resolved merge conflits

* updated readme file

* Removed tsconfig file

* version bump added
  • Loading branch information
sunil-lakshman authored Nov 11, 2024
1 parent 21a8afa commit 4b0762a
Show file tree
Hide file tree
Showing 18 changed files with 435 additions and 103 deletions.
43 changes: 7 additions & 36 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/contentstack-branches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ $ npm install -g @contentstack/cli-cm-branches
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-branches/1.2.0 darwin-arm64 node-v22.8.0
@contentstack/cli-cm-branches/1.2.0 darwin-arm64 node-v22.2.0
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
64 changes: 53 additions & 11 deletions packages/contentstack-bulk-publish/README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/contentstack-bulk-publish/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@contentstack/cli-cm-bulk-publish",
"description": "Contentstack CLI plugin for bulk publish actions",
"version": "1.6.0",
"version": "1.7.0",
"author": "Contentstack",
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class CrossPublishCommand extends Command {
updatedFlags.deliveryToken = await cliux.prompt('Enter delivery token of your source environment');
}
updatedFlags.bulkPublish = updatedFlags.bulkPublish === 'false' ? false : true;

updatedFlags.includeVariants = updatedFlags.includeVariants === false ? false : true;
stack = await getStack(config);
}

Expand Down Expand Up @@ -155,6 +155,10 @@ class CrossPublishCommand extends Command {
_flags.deliveryToken = _flags['delivery-token'];
delete _flags['delivery-token'];
}
if ('include-variants' in _flags) {
_flags.includeVariants = _flags['include-variants'];
delete _flags['include-variants'];
}
return _flags;
}
}
Expand Down Expand Up @@ -257,6 +261,10 @@ CrossPublishCommand.flags = {
}),
onlyAssets: flags.boolean({ description: 'Unpublish only assets', default: false }),
onlyEntries: flags.boolean({ description: 'Unpublish only entries', default: false }),
'include-variants': flags.boolean({
description: 'Include Variants flag will publish all associated variant entries.',
default: false,
}),
};

CrossPublishCommand.examples = [
Expand All @@ -278,8 +286,11 @@ CrossPublishCommand.examples = [
'Using --stack-api-key flag',
'csdx cm:bulk-publish:cross-publish --content-type [CONTENT TYPE] --source-env [SOURCE ENV] --environments [DESTINATION ENVIRONMENT] --locales [LOCALE] --stack-api-key [STACK API KEY] --delivery-token [DELIVERY TOKEN]',
'',
'Using --include-variants flag',
'csdx cm:bulk-publish:cross-publish --content-type [CONTENT TYPE] --source-env [SOURCE ENV] --environments [DESTINATION ENVIRONMENT] --locales [LOCALE] --stack-api-key [STACK API KEY] --delivery-token [DELIVERY TOKEN] [--include-variants]',
'',
];

CrossPublishCommand.usage = `cm:bulk-publish:cross-publish [-a <value>] [--retry-failed <value>] [--bulk-publish <value>] [--content-type <value>] [--locales <value>] [--source-env <value>] [--environments <value>] [--delivery-token <value>] [-c <value>] [-y] [--branch <value>] [--onlyAssets] [--onlyEntries]`;
CrossPublishCommand.usage = `cm:bulk-publish:cross-publish [-a <value>] [--retry-failed <value>] [--bulk-publish <value>] [--content-type <value>] [--locales <value>] [--source-env <value>] [--environments <value>] [--delivery-token <value>] [-c <value>] [-y] [--branch <value>] [--onlyAssets] [--onlyEntries] [--include-variants]`;

module.exports = CrossPublishCommand;
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,19 @@ class PublishEntriesCommand extends Command {
entriesFlags.publishAllContentTypes =
entriesFlags['publish-all-content-types'] || entriesFlags.publishAllContentTypes || false;
entriesFlags.apiVersion = entriesFlags['api-version'] || '3';
entriesFlags.includeVariants = entriesFlags['include-variants'] || entriesFlags.includeVariants || false;
entriesFlags.entryUid = entriesFlags['entry-uid'] || entriesFlags.entryUid;

if (entriesFlags.entryUid === undefined) {
delete entriesFlags['entryUid'];
}
delete entriesFlags['api-version'];
delete entriesFlags['retry-failed'];
delete entriesFlags['content-types'];
delete entriesFlags['bulk-publish'];
delete entriesFlags['publish-all-content-types'];
delete entriesFlags['include-variants'];
delete entriesFlags['entry-uid'];

let updatedFlags;
try {
Expand Down Expand Up @@ -243,6 +251,11 @@ PublishEntriesCommand.flags = {
}),
'delivery-token': flags.string({ description: 'The delivery token of the source environment.' }),
'source-env': flags.string({ description: 'Source environment' }),
'entry-uid': flags.string({ description: 'Entry Uid for publish all associated variant entries.' }),
'include-variants': flags.boolean({
default: false, // set the default value to false
description: 'Include Variants flag will publish all associated variant entries with base entry.',
}),
};

PublishEntriesCommand.examples = [
Expand All @@ -266,11 +279,17 @@ PublishEntriesCommand.examples = [
'',
'Using --stack-api-key',
'csdx cm:entries:publish -e [ENVIRONMENT 1] [ENVIRONMENT 2] --locales [LOCALE 1] [LOCALE 2] --stack-api-key [STACK API KEY] --source-env [SOURCE ENVIRONMENT] --delivery-token [DELIVERY TOKEN]',
'',
'Using --include-variants',
'csdx cm:entries:publish --content-types [CONTENT TYPE 1] [CONTENT TYPE 2] -e [ENVIRONMENT 1] [ENVIRONMENT 2] --locales [LOCALE 1] [LOCALE 2] --stack-api-key [STACK API KEY] --source-env [SOURCE ENVIRONMENT] --delivery-token [DELIVERY TOKEN] [--include-variants]',
'',
'Using --entry-uid and --include-variants',
'csdx cm:entries:publish --content-types [CONTENT TYPE 1] [CONTENT TYPE 2] -e [ENVIRONMENT 1] [ENVIRONMENT 2] --locales [LOCALE 1] [LOCALE 2] --stack-api-key [STACK API KEY] --source-env [SOURCE ENVIRONMENT] --delivery-token [DELIVERY TOKEN] --entry-uid [ENTRY UID] [--include-variants]',
];

PublishEntriesCommand.aliases = ['cm:bulk-publish:entries'];

PublishEntriesCommand.usage =
'cm:entries:publish [-a <value>] [--retry-failed <value>] [--bulk-publish <value>] [--publish-all-content-types] [--content-types <value>] [--locales <value>] [-e <value>] [-c <value>] [-y] [--branch <value>] [--delivery-token <value>] [--source-env <value>]';
'cm:entries:publish [-a <value>] [--retry-failed <value>] [--bulk-publish <value>] [--publish-all-content-types] [--content-types <value>] [--locales <value>] [-e <value>] [-c <value>] [-y] [--branch <value>] [--delivery-token <value>] [--source-env <value>] [--entry-uid <value>] [--include-variants]';

module.exports = PublishEntriesCommand;
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ class UnpublishCommand extends Command {
unpublishFlags.onlyAssets = false;
unpublishFlags.onlyEntries = true;
unpublishFlags.apiVersion = unpublishFlags['api-version'] || '3';
unpublishFlags.includeVariants = unpublishFlags['include-variants'] || false;
delete unpublishFlags['api-version'];
delete unpublishFlags['retry-failed'];
delete unpublishFlags['bulk-unpublish'];
delete unpublishFlags['content-type'];
delete unpublishFlags['delivery-token'];
delete unpublishFlags['include-variants'];

let updatedFlags;
try {
Expand Down Expand Up @@ -59,7 +61,6 @@ class UnpublishCommand extends Command {
updatedFlags.deliveryToken = await cliux.prompt('Enter delivery token of your source environment');
}
updatedFlags.bulkUnpublish = updatedFlags.bulkUnpublish === 'false' ? false : true;

stack = await getStack(config);
}
if (!updatedFlags.deliveryToken && updatedFlags.deliveryToken.length === 0) {
Expand Down Expand Up @@ -136,6 +137,7 @@ UnpublishCommand.flags = {
alias: flags.string({
char: 'a',
description: 'Alias (name) for the management token. You must use either the --alias flag or the --stack-api-key flag.',
description: 'Alias (name) for the management token. You must use either the --alias flag or the --stack-api-key flag.',
}),
'stack-api-key': flags.string({
char: 'k',
Expand Down Expand Up @@ -176,6 +178,10 @@ UnpublishCommand.flags = {
'delivery-token': flags.string({
description: 'The delivery token of the source environment.',
}),
'include-variants': flags.boolean({
default: false, // set the default value to false
description: 'Include Variants flag will unpublish all associated variant entries.'
}),
};

UnpublishCommand.examples = [
Expand All @@ -195,6 +201,9 @@ UnpublishCommand.examples = [
'',
'Using --stack-api-key flag',
'csdx cm:stacks:unpublish --bulk-unpublish --content-type [CONTENT TYPE] --environment [SOURCE ENV] --locale [LOCALE] --stack-api-key [STACK API KEY] --delivery-token [DELIVERY TOKEN]',
'',
'Using --include-variants flag',
'csdx cm:stacks:unpublish --bulk-unpublish --content-type [CONTENT TYPE] --environment [SOURCE ENV] --locale [LOCALE] --stack-api-key [STACK API KEY] --delivery-token [DELIVERY TOKEN] --include-variants',
];

module.exports = UnpublishCommand;
89 changes: 84 additions & 5 deletions packages/contentstack-bulk-publish/src/producer/cross-publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const { Command } = require('@contentstack/cli-command');
const command = new Command();
const { isEmpty } = require('../util');
const { fetchBulkPublishLimit } = require('../util/common-utility');
const VARIANTS_PUBLISH_API_VERSION = '3.2';

let bulkPublishSet = [];
let bulkPublishAssetSet = [];
Expand All @@ -34,20 +35,30 @@ function getQueryParams(filter) {
return queryString;
}

async function bulkAction(stack, items, bulkPublish, filter, destEnv, apiVersion, bulkPublishLimit) {
async function bulkAction(stack, items, bulkPublish, filter, destEnv, apiVersion, bulkPublishLimit, variantsFlag = false) {
return new Promise(async (resolve) => {
for (let index = 0; index < items.length; index++) {
changedFlag = true;

if (bulkPublish) {
if (bulkPublishSet.length < bulkPublishLimit && items[index].type === 'entry_published') {
bulkPublishSet.push({
const entry = {
uid: items[index].data.uid,
content_type: items[index].content_type_uid,
locale: items[index].data.locale || 'en-us',
version: items[index].data._version,
publish_details: [items[index].data.publish_details] || [],
});
};

if (variantsFlag && Array.isArray(items[index].data.variants) && items[index].data.variants.length > 0) {
entry.variants = items[index].data.variants || [];
entry.variant_rules = {
publish_latest_base: false,
publish_latest_base_conditionally: true
};
}

bulkPublishSet.push(JSON.parse(JSON.stringify(entry)));
}

if (bulkPublishAssetSet.length < bulkPublishLimit && items[index].type === 'asset_published') {
Expand Down Expand Up @@ -145,6 +156,7 @@ async function getSyncEntries(
destEnv,
apiVersion,
bulkPublishLimit,
variantsFlag = false,
paginationToken = null,
) {
return new Promise(async (resolve, reject) => {
Expand Down Expand Up @@ -200,8 +212,19 @@ async function getSyncEntries(
);
}

if (variantsFlag) {
for (let index = 0; index < entriesResponse?.items?.length; index++) {
let variants = [];
const entries = entriesResponse.items[index];
variants = await getVariantEntries(stack, entries.content_type_uid, entriesResponse, index, queryParamsObj);
if (variants.length > 0) {
entriesResponse.items[index].data.variants = variants;
}
}
}

if (entriesResponse.items.length > 0) {
await bulkAction(stack, entriesResponse.items, bulkPublish, filter, destEnv, apiVersion, bulkPublishLimit);
await bulkAction(stack, entriesResponse.items, bulkPublish, filter, destEnv, apiVersion, bulkPublishLimit, variantsFlag);
}
if (!entriesResponse.pagination_token) {
if (!changedFlag) console.log('No Entries/Assets Found published on specified environment');
Expand Down Expand Up @@ -244,6 +267,48 @@ function setConfig(conf, bp) {
filePath = initializeLogger(logFileName);
}

async function getVariantEntries(stack, contentType, entries, index, queryParams, skip = 0) {
try {
let variantQueryParams = {
locale: queryParams.locale || 'en-us',
include_count: true,
skip: skip, // Adding skip parameter for pagination
limit: 100, // Set a limit to fetch up to 100 entries per request
};
const entryUid = entries.items[index].data.uid
const variantsEntriesResponse = await stack
.contentType(contentType)
.entry(entryUid)
.variants()
.query(variantQueryParams)
.find();

const variants = variantsEntriesResponse.items.map((entry) => ({
uid: entry.variants._variant._uid,
}));

if (variantsEntriesResponse.items.length === variantQueryParams.limit) {
const nextVariants = await getVariantEntries(
stack,
contentType,
entries,
index,
queryParams,
skip + variantQueryParams.limit,
);
return Array.isArray(nextVariants) ? variants.concat(nextVariants) : variants;
}
return variants;
} catch (error) {
const errorMessage =
error?.errorMessage ||
error?.message ||
error?.errors ||
'Falied to fetch the variant entries, Please contact the admin for support.';
throw new Error(`Error fetching variants: ${errorMessage}`);
}
}

async function start(
{
retryFailed,
Expand All @@ -258,6 +323,7 @@ async function start(
destEnv,
f_types,
apiVersion,
includeVariants,
},
stack,
config,
Expand Down Expand Up @@ -310,7 +376,20 @@ async function start(
// filter.type = (f_types) ? f_types : types // types mentioned in the config file (f_types) are given preference
const queryParams = getQueryParams(filter);
const bulkPublishLimit = fetchBulkPublishLimit(stack?.org_uid);
await getSyncEntries(stack, config, queryParams, bulkPublish, filter, deliveryToken, destEnv, apiVersion, bulkPublishLimit);
if (includeVariants) {
apiVersion = VARIANTS_PUBLISH_API_VERSION;
}
await getSyncEntries(
stack,
config,
queryParams,
bulkPublish,
filter,
deliveryToken,
destEnv,
apiVersion, bulkPublishLimit,
includeVariants,
);
}
}

Expand Down
Loading

0 comments on commit 4b0762a

Please sign in to comment.