Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/contentstack-bootstrap/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@contentstack/cli-cm-bootstrap",
"description": "Bootstrap contentstack apps",
"version": "1.18.4",
"version": "1.18.5",
"author": "Contentstack",
"bugs": "https://github.com/contentstack/cli/issues",
"scripts": {
Expand All @@ -16,7 +16,7 @@
"test:report": "nyc --reporter=lcov mocha \"test/**/*.test.js\""
},
"dependencies": {
"@contentstack/cli-cm-seed": "~1.14.3",
"@contentstack/cli-cm-seed": "~1.14.4",
"@contentstack/cli-command": "~1.7.2",
"@contentstack/cli-config": "~1.19.0",
"@contentstack/cli-utilities": "~1.17.4",
Expand Down
4 changes: 2 additions & 2 deletions packages/contentstack-bootstrap/src/bootstrap/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface SeedParams {
stackAPIKey?: string;
org?: string;
stackName?: string;
yes?: string;
yes?: boolean;
managementTokenAlias?: string | undefined;
managementToken?: string | undefined;
}
Expand Down Expand Up @@ -95,7 +95,7 @@ export default class Bootstrap {
cmd.push('-n', this.options.seedParams.stackName);
}
if (this.options.seedParams.yes) {
cmd.push('-y', this.options.seedParams.yes);
cmd.push('-y');
}
if (this.options.seedParams.managementTokenAlias) {
cmd.push('--alias', this.options.seedParams.managementTokenAlias);
Expand Down
11 changes: 6 additions & 5 deletions packages/contentstack-bootstrap/src/bootstrap/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ export const setupEnvironments = async (
if (!managementToken) {
const managementBody = {
token: {
name: 'sample app',
description: 'This is a sample management token.',
name: 'Compass Starter App',
description: 'This is a compass starter app management token.',
scope: [
{
module: 'content_type',
module: '$all',
acl: {
read: true,
write: true,
Expand All @@ -58,8 +58,9 @@ export const setupEnvironments = async (
},
},
],
expires_on: '3000-01-01',
expires_on: null,
is_email_notification_enabled: false,
rate_limit_enabled: false,
},
};
managementTokenResult = await managementAPIClient
Expand Down Expand Up @@ -313,7 +314,7 @@ const envFileHandler = async (
}CONTENTSTACK_ENVIRONMENT=${environmentVariables.environment}${!isUSRegion && !customHost ? '\nCONTENTSTACK_REGION=' + region.name : ''
}\nCONTENTSTACK_LIVE_PREVIEW=${livePreviewEnabled}\nCONTENTSTACK_LIVE_EDIT_TAGS=false\nCONTENTSTACK_API_HOST=${customHost ? customHost : managementAPIHost
}${!isUSRegion && !customHost ? '\nCONTENTSTACK_REGION=' + region.name : ''
}\nCONTENTSTACK_APP_HOST=${appHost}\nCONTENTSTACK_MANAGEMENT_TOKEN=${managementTokenResult.uid
}\nCONTENTSTACK_APP_HOST=${appHost}\nCONTENTSTACK_MANAGEMENT_TOKEN=${managementTokenResult.token
}\nCONTENTSTACK_HOST=${cdnHost}`;
result = await writeEnvFile(content, filePath);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default class BootstrapCommand extends Command {
required: false,
exclusive: ['stack-api-key'],
}),
yes: flags.string({
yes: flags.boolean({
description: '[Optional] Skip stack confirmation',
char: 'y',
required: false,
Expand Down Expand Up @@ -157,7 +157,7 @@ export default class BootstrapCommand extends Command {
});
}

const yes = bootstrapCommandFlags.yes as string;
const yes = bootstrapCommandFlags.yes as boolean;

const appConfig: AppConfig = getAppLevelConfigByName(selectedAppName || selectedApp.configKey);
const master_locale = appConfig.master_locale || DEFAULT_MASTER_LOCALE;
Expand All @@ -181,7 +181,7 @@ export default class BootstrapCommand extends Command {
if (stackAPIKey) seedParams.stackAPIKey = stackAPIKey;
if (org) seedParams.org = org;
if (stackName) seedParams.stackName = stackName;
if (yes) seedParams.yes = yes;
if (yes) seedParams.yes = true;
if (managementTokenAlias) {
seedParams.managementTokenAlias = managementTokenAlias;
const listOfTokens = configHandler.get('tokens');
Expand Down
18 changes: 9 additions & 9 deletions packages/contentstack-seed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ To import content to your stack, you can choose from the following two sources:
<!-- usagestop -->
## Commands
<!-- commands -->
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y-value--s-value---locale-value)
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y-value--s-value---locale-value)
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y--s-value---locale-value)
* [`csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`](#csdx-cmstacksseed---repo-value---org-value--k-value--n-value--y--s-value---locale-value)

## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`
## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`

Create a stack from existing content types, entries, assets, etc

```
USAGE
$ csdx cm:seed cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s
<value>] [--locale <value>]
$ csdx cm:seed cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>]
[--locale <value>]

FLAGS
-a, --alias=<value> Alias of the management token
Expand All @@ -29,7 +29,7 @@ FLAGS
-o, --org=<value> Provide Organization UID to create a new stack
-r, --repo=<value> GitHub organization name or GitHub user name/repository name.
-s, --stack=<value> Provide the stack UID to seed content.
-y, --yes=<value> [Optional] Skip the stack confirmation.
-y, --yes [Optional] Skip the stack confirmation.

DESCRIPTION
Create a stack from existing content types, entries, assets, etc
Expand All @@ -49,13 +49,13 @@ EXAMPLES
$ csdx cm:stacks:seed --repo "account/repository" --org "your-org-uid" --stack-name "stack-name" //create a new stack in given org uid
```

## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]`
## `csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]`

Create a stack from existing content types, entries, assets, etc

```
USAGE
$ csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>]
$ csdx cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>]
[--locale <value>]

FLAGS
Expand All @@ -65,7 +65,7 @@ FLAGS
-o, --org=<value> Provide Organization UID to create a new stack
-r, --repo=<value> GitHub organization name or GitHub user name/repository name.
-s, --stack=<value> Provide the stack UID to seed content.
-y, --yes=<value> [Optional] Skip the stack confirmation.
-y, --yes [Optional] Skip the stack confirmation.

DESCRIPTION
Create a stack from existing content types, entries, assets, etc
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-seed/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@contentstack/cli-cm-seed",
"description": "create a Stack from existing content types, entries, assets, etc.",
"version": "1.14.3",
"version": "1.14.4",
"author": "Contentstack",
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
Expand Down
7 changes: 4 additions & 3 deletions packages/contentstack-seed/src/commands/cm/stacks/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default class SeedCommand extends Command {
'$ csdx cm:stacks:seed --repo "account/repository" --org "your-org-uid" --stack-name "stack-name" //create a new stack in given org uid',
];

static usage = 'cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y <value>] [-s <value>] [--locale <value>]';
static usage = 'cm:stacks:seed [--repo <value>] [--org <value>] [-k <value>] [-n <value>] [-y] [-s <value>] [--locale <value>]';

static flags: FlagInput = {
repo: flags.string({
Expand Down Expand Up @@ -59,7 +59,7 @@ export default class SeedCommand extends Command {
required: false,
hidden: true,
}),
yes: flags.string({
yes: flags.boolean({
char: 'y',
required: false,
description: '[Optional] Skip the stack confirmation.',
Expand All @@ -80,6 +80,7 @@ export default class SeedCommand extends Command {
}),
locale: flags.string({
description: 'Master Locale of the stack',
default: 'en-us',
hidden: true,
}),
};
Expand All @@ -106,7 +107,7 @@ export default class SeedCommand extends Command {
stackUid: seedFlags['stack-api-key'] || seedFlags.stack,
stackName: seedFlags['stack-name'],
fetchLimit: seedFlags['fetch-limit'],
skipStackConfirmation: seedFlags['yes'],
skipStackConfirmation: seedFlags.yes,
isAuthenticated: isAuthenticated(),
alias: managementTokenAlias,
master_locale: seedFlags['locale'],
Expand Down
20 changes: 20 additions & 0 deletions packages/contentstack-seed/src/seed/github/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ export default class GitHubClient {
return false;
}

async getMasterLocaleFromRepo(repo: string): Promise<string | null> {
try {
const response = await this.httpClient.get(
`https://raw.githubusercontent.com/${this.username}/${repo}/main/stack/locales/master-locale.json`,
);

if (response.data) {
const localeData = response.data;
const localeKey = Object.keys(localeData)[0];
if (localeKey && localeData[localeKey]?.code) {
return localeData[localeKey].code;
}
}
} catch (error) {
console.log('Could not fetch master locale from repository', error);
}

return null;
}

async getLatestTarballUrl(repo: string) {
try {
const response = await this.httpClient.get(`${this.gitHubRepoUrl}/${repo}/releases/latest`);
Expand Down
9 changes: 8 additions & 1 deletion packages/contentstack-seed/src/seed/importer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as fs from 'fs';
import * as process from 'process';
import * as path from 'path';
import ImportCommand from '@contentstack/cli-cm-import';
Expand All @@ -16,7 +17,13 @@ export interface ImporterOptions {
}

export async function run(options: ImporterOptions) {
const importPath = pathValidator(path.resolve(sanitizePath(options.tmpPath), STACK_FOLDER));
const tmpPathResolved = path.resolve(sanitizePath(options.tmpPath));
const stackPath = path.join(tmpPathResolved, STACK_FOLDER);

// Support both structures: repo with stack/ folder (per docs) or content at root
const importPath = fs.existsSync(stackPath)
? pathValidator(stackPath)
: pathValidator(tmpPathResolved);

const args = options.alias
? ['-k', options.api_key, '-d', importPath, '--alias', options.alias!]
Expand Down
52 changes: 12 additions & 40 deletions packages/contentstack-seed/src/seed/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface ContentModelSeederOptions {
stackUid: string | undefined;
stackName: string | undefined;
fetchLimit: string | undefined;
skipStackConfirmation: string | undefined;
skipStackConfirmation: boolean | undefined;
isAuthenticated: boolean | false;
managementToken?: string | undefined;
alias?: string | undefined;
Expand Down Expand Up @@ -181,52 +181,24 @@ export default class ContentModelSeeder {
}

async shouldProceed(api_key: string) {
let count;
const stack_details = await this.csClient.getStack(api_key);
if(this.options.master_locale != stack_details.master_locale){
cliux.print(`Compass app requires the master locale to be set to English (en).`,{
color: "yellow",
bold: true,
});
return false;
}
const managementBody = {
"name":"Checking roles for creating management token",
"description":"This is a compass app management token.",
"scope":[
{
"module":"content_type",
"acl":{
"read":true,
"write":true
}
},
{
"module":"branch",
"branches":[
"main"
],
"acl":{
"read":true
}
}
],
"expires_on": "3000-01-01",
"is_email_notification_enabled":false
}
let managementTokenResult = await this.csClient.createManagementToken(api_key, this.managementToken, managementBody);
if(managementTokenResult?.response_code == "161" || managementTokenResult?.response_code == "401"){
const repoMasterLocale = await this.ghClient.getMasterLocaleFromRepo(this.ghRepo as string);
const expectedLocale = repoMasterLocale || this.options.master_locale || ENGLISH_LOCALE;

if (stack_details.master_locale !== expectedLocale) {
cliux.print(
`Info: Failed to generate a management token.\nNote: Management token is not available in your plan. Please contact the admin for support.`,
`Repository '${this.ghRepo}' requires the master locale to be set to '${expectedLocale}', but your stack has '${stack_details.master_locale}'.`,
{
color: 'red',
color: 'yellow',
bold: true,
},
);
return false;
}
count = await this.csClient.getContentTypeCount(api_key, this.managementToken);
}

const count = await this.csClient.getContentTypeCount(api_key, this.managementToken);

if (count > 0 && this._options.skipStackConfirmation !== 'yes') {
if (count > 0 && !this._options.skipStackConfirmation) {
const proceed = await inquireProceed();

if (!proceed) {
Expand Down
19 changes: 19 additions & 0 deletions packages/contentstack-seed/tests/seeder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ describe('ContentModelSeeder', () => {
});

test('should automatically proceed when no content types', async () => {
ContentstackClient.prototype.getStack = jest.fn().mockResolvedValue({ master_locale: 'en-us' });
GitHubClient.prototype.getMasterLocaleFromRepo = jest.fn().mockResolvedValue(null);
ContentstackClient.prototype.getContentTypeCount = jest.fn().mockResolvedValue(0);

const seeder = new ContentModelSeeder(options);
Expand All @@ -76,6 +78,8 @@ describe('ContentModelSeeder', () => {
});

test('should not proceed when content types exists and user cancels', async () => {
ContentstackClient.prototype.getStack = jest.fn().mockResolvedValue({ master_locale: 'en-us' });
GitHubClient.prototype.getMasterLocaleFromRepo = jest.fn().mockResolvedValue(null);
ContentstackClient.prototype.getContentTypeCount = jest.fn().mockResolvedValue(1);

// @ts-ignore
Expand All @@ -88,6 +92,8 @@ describe('ContentModelSeeder', () => {
});

test('should proceed when content types exists and user accepts risk', async () => {
ContentstackClient.prototype.getStack = jest.fn().mockResolvedValue({ master_locale: 'en-us' });
GitHubClient.prototype.getMasterLocaleFromRepo = jest.fn().mockResolvedValue(null);
ContentstackClient.prototype.getContentTypeCount = jest.fn().mockResolvedValue(1);

// @ts-ignore
Expand All @@ -99,6 +105,19 @@ describe('ContentModelSeeder', () => {
expect(proceed).toBe(true);
});

test('should skip confirmation when skipStackConfirmation is true', async () => {
ContentstackClient.prototype.getStack = jest.fn().mockResolvedValue({ master_locale: 'en-us' });
GitHubClient.prototype.getMasterLocaleFromRepo = jest.fn().mockResolvedValue(null);
ContentstackClient.prototype.getContentTypeCount = jest.fn().mockResolvedValue(1);

const optionsWithSkip = { ...options, skipStackConfirmation: true };
const seeder = new ContentModelSeeder(optionsWithSkip);
const proceed = await seeder.shouldProceed(api_key);

expect(proceed).toBe(true);
expect(inquireProceed).not.toHaveBeenCalled();
});

test('should create stack', async () => {
ContentstackClient.prototype.createStack = jest.fn().mockResolvedValue({
api_key: api_key,
Expand Down
Loading
Loading