Skip to content

Commit 411f2be

Browse files
Merge pull request #29 from contentstack/development
Allow specifying environment when trying to redeploy, allow specifying PORT when running cloud functions and bug fixes
2 parents e81ceec + 26f5bc2 commit 411f2be

File tree

16 files changed

+4150
-3663
lines changed

16 files changed

+4150
-3663
lines changed

.github/workflows/release.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
id: release-plugin
5353
uses: JS-DevTools/npm-publish@v2.2.0
5454
with:
55-
token: ${{ secrets.NPM_TOKEN }}
55+
token: "${{ secrets.NPM_TOKEN }}"
5656
access: public
5757
- name: get-npm-version
5858
id: package-version
@@ -61,4 +61,5 @@ jobs:
6161
id: github-release
6262
env:
6363
GITHUB_TOKEN: ${{ secrets.PKG_TOKEN }}
64-
run: gh release create v${{ steps.release-plugin.outputs.version }} --title "Release ${{ steps.release-plugin.outputs.version }}" --generate-notes
64+
VERSION: ${{ steps.release-plugin.outputs.version }}
65+
run: gh release create v"$VERSION" --title "Release $VERSION" --generate-notes

.github/workflows/sca-scan.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ jobs:
1212
env:
1313
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
1414
with:
15-
args: --all-projects --fail-on=all
15+
args: --all-projects --fail-on=all --strict-out-of-sync=false

package-lock.json

Lines changed: 3554 additions & 3589 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/cli-launch",
3-
"version": "1.6.0",
3+
"version": "1.7.0",
44
"description": "Launch related operations",
55
"author": "Contentstack CLI",
66
"bin": {
@@ -34,7 +34,7 @@
3434
"@types/express-serve-static-core": "^4.17.34",
3535
"adm-zip": "^0.5.16",
3636
"chalk": "^4.1.2",
37-
"cross-fetch": "^3.1.8",
37+
"cross-fetch": "^4.1.0",
3838
"dotenv": "^16.4.7",
3939
"express": "^4.21.1",
4040
"form-data": "^4.0.0",

src/adapters/base-class.ts

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
fileFrameworkQuery,
2727
createDeploymentMutation,
2828
cmsEnvironmentVariablesQuery,
29+
environmentsQuery
2930
} from '../graphql';
3031
import {
3132
LogFn,
@@ -36,6 +37,7 @@ import {
3637
EmitMessage,
3738
DeploymentLogResp,
3839
ServerLogResp,
40+
Environment,
3941
} from '../types';
4042

4143
export default class BaseClass {
@@ -85,14 +87,14 @@ export default class BaseClass {
8587
* @return {*} {Promise<void>}
8688
* @memberof GitHub
8789
*/
88-
async createNewDeployment(skipGitData = false, uploadUid?: string): Promise<void> {
90+
async createNewDeployment(skipGitData = false, environmentUid:string, uploadUid?: string): Promise<void> {
8991
const deployment: Record<string, any> = {
90-
environment: (first(this.config.currentConfig.environments) as Record<string, any>)?.uid,
92+
environment: environmentUid
9193
};
9294

9395
if (uploadUid) {
9496
deployment.uploadUid = uploadUid;
95-
}
97+
}
9698

9799
await this.apolloClient
98100
.mutate({
@@ -394,7 +396,7 @@ export default class BaseClass {
394396
data.project = this.config.currentConfig;
395397
}
396398

397-
writeFileSync(this.config.config, JSON.stringify(data), {
399+
writeFileSync(this.config.config, JSON.stringify(data, null, 2), {
398400
encoding: 'utf8',
399401
flag: 'w',
400402
});
@@ -675,7 +677,7 @@ export default class BaseClass {
675677
},
676678
baseUrl: this.config.manageApiBaseUrl,
677679
}).apolloClient;
678-
this.config.environment = (last(this.config.currentConfig.environments) as Record<string, any>)?.uid;
680+
this.config.environment = (await this.getEnvironment()).uid;
679681
this.config.deployment = (last(this.config.currentConfig.deployments) as Record<string, any>)?.uid;
680682
const logs = new LogPolling({
681683
config: this.config,
@@ -744,6 +746,42 @@ export default class BaseClass {
744746
this.exit(1);
745747
}
746748

749+
async getEnvironment(): Promise<Environment> | never {
750+
const environmentFlagInput = this.config['environment'];
751+
752+
if (!environmentFlagInput) {
753+
const defaultEnvironment = (first(this.config.currentConfig.environments) as Environment);
754+
this.setEnvironmentOnConfig(defaultEnvironment as Environment);
755+
return defaultEnvironment;
756+
}
757+
const environmentList = await this.fetchEnvironments();
758+
let environment = environmentList.find((env: Environment) => env.name === environmentFlagInput || env.uid === environmentFlagInput);
759+
760+
if (!environment) {
761+
this.log(`Environment "${environmentFlagInput}" not found in this project. Please provide a valid environment name or UID.`, 'error');
762+
this.exit(1);
763+
}
764+
765+
environment = environment as Environment;
766+
this.setEnvironmentOnConfig(environment);
767+
return environment;
768+
}
769+
770+
async setEnvironmentOnConfig(environment: Environment): Promise<void> {
771+
this.config.environment = environment.uid;
772+
}
773+
774+
async fetchEnvironments(): Promise<Environment[]> | never {
775+
try {
776+
const { data } = await this.apolloClient.query({ query: environmentsQuery });
777+
const environments = map(data.Environments.edges, 'node');
778+
return environments;
779+
} catch (error: unknown) {
780+
this.log(error instanceof Error ? error.message : String(error), 'error');
781+
process.exit(1);
782+
}
783+
}
784+
747785
/**
748786
* @method showDeploymentUrl - show deployment URL and open it on browser
749787
*
@@ -791,4 +829,4 @@ export default class BaseClass {
791829
});
792830
}
793831
}
794-
}
832+
}

src/adapters/file-upload.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { print } from '../util';
1414
import BaseClass from './base-class';
1515
import { getFileList } from '../util/fs';
1616
import { createSignedUploadUrlMutation, importProjectMutation } from '../graphql';
17-
import { SignedUploadUrlData, FileUploadMethod } from '../types/launch';
17+
import { SignedUploadUrlData, FileUploadMethod, DeploymentStatus } from '../types/launch';
1818
import config from '../config';
1919

2020
export default class FileUpload extends BaseClass {
@@ -26,18 +26,22 @@ export default class FileUpload extends BaseClass {
2626
*/
2727
async run(): Promise<void> {
2828
if (this.config.isExistingProject) {
29-
await this.handleExistingProject();
29+
const environment = await this.getEnvironment();
30+
await this.handleExistingProject(environment.uid);
3031
} else {
3132
await this.handleNewProject();
3233
}
3334

3435
this.prepareLaunchConfig();
3536
await this.showLogs();
37+
if(this.config.currentDeploymentStatus === DeploymentStatus.FAILED) {
38+
this.exit(1);
39+
}
3640
this.showDeploymentUrl();
3741
this.showSuggestion();
3842
}
3943

40-
private async handleExistingProject(): Promise<void> {
44+
private async handleExistingProject(environment: string): Promise<void> {
4145
await this.initApolloClient();
4246

4347
let redeployLatest = this.config['redeploy-latest'];
@@ -63,7 +67,7 @@ export default class FileUpload extends BaseClass {
6367
await this.uploadFile(zipName, zipPath, signedUploadUrlData);
6468
}
6569

66-
await this.createNewDeployment(true, uploadUid);
70+
await this.createNewDeployment(true, environment, uploadUid);
6771
}
6872

6973
private async confirmRedeployment(): Promise<void> {

src/adapters/github.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { print } from '../util';
1212
import BaseClass from './base-class';
1313
import { getRemoteUrls } from '../util/create-git-meta';
1414
import { repositoriesQuery, userConnectionsQuery, importProjectMutation } from '../graphql';
15+
import { DeploymentStatus } from '../types';
1516

1617
export default class GitHub extends BaseClass {
1718
/**
@@ -22,18 +23,22 @@ export default class GitHub extends BaseClass {
2223
*/
2324
async run(): Promise<void> {
2425
if (this.config.isExistingProject) {
25-
await this.handleExistingProject();
26+
const environment = await this.getEnvironment();
27+
await this.handleExistingProject(environment.uid);
2628
} else {
2729
await this.handleNewProject();
2830
}
2931

3032
this.prepareLaunchConfig();
3133
await this.showLogs();
34+
if(this.config.currentDeploymentStatus === DeploymentStatus.FAILED) {
35+
this.exit(1);
36+
}
3237
this.showDeploymentUrl();
3338
this.showSuggestion();
3439
}
3540

36-
private async handleExistingProject(): Promise<void> {
41+
private async handleExistingProject(environmentUid:string): Promise<void> {
3742
await this.initApolloClient();
3843

3944
const redeployLastUpload = this.config['redeploy-last-upload'];
@@ -48,7 +53,7 @@ export default class GitHub extends BaseClass {
4853
await this.confirmLatestRedeployment();
4954
}
5055

51-
await this.createNewDeployment();
56+
await this.createNewDeployment(false, environmentUid);
5257
}
5358

5459
private async confirmLatestRedeployment(): Promise<void> {

src/adapters/pre-check.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export default class PreCheck extends BaseClass {
6262
this.log('Current Project details:', { bold: true, color: 'green' });
6363
this.log(''); // Empty line
6464
const { name, projectType, repository, environments } = this.config.currentConfig;
65-
const [environment] = environments;
65+
const environment = await this.getEnvironment();
6666

6767
const detail: Record<string, any> = {
6868
'Project Name': name,

src/base-command.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
import config from './config';
2121
import { GraphqlApiClient, Logger } from './util';
2222
import { getLaunchHubUrl } from './util/common-utility';
23-
import { ConfigType, LogFn, Providers } from './types';
23+
import { ConfigType, LogFn, Providers, GraphqlHeaders } from './types';
2424

2525
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
2626
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
@@ -198,20 +198,27 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
198198
* @memberof BaseCommand
199199
*/
200200
async prepareApiClients(): Promise<void> {
201+
let headers: GraphqlHeaders = {
202+
'X-CS-CLI': this.context.analyticsInfo
203+
}
204+
205+
const { uid, organizationUid } = this.sharedConfig.currentConfig;
206+
207+
if (uid) {
208+
headers['x-project-uid'] = uid;
209+
}
210+
211+
if (organizationUid) {
212+
headers['organization_uid'] = organizationUid;
213+
}
214+
201215
this.apolloClient = await new GraphqlApiClient({
202-
headers: {
203-
'X-CS-CLI': this.context.analyticsInfo,
204-
'x-project-uid': this.sharedConfig.currentConfig.uid,
205-
organization_uid: this.sharedConfig.currentConfig.organizationUid,
206-
},
216+
headers,
207217
baseUrl: this.sharedConfig.manageApiBaseUrl,
208218
}).apolloClient;
219+
209220
this.apolloLogsClient = await new GraphqlApiClient({
210-
headers: {
211-
'X-CS-CLI': this.context.analyticsInfo,
212-
'x-project-uid': this.sharedConfig.currentConfig.uid,
213-
organization_uid: this.sharedConfig.currentConfig.organizationUid,
214-
},
221+
headers,
215222
baseUrl: this.sharedConfig.logsApiBaseUrl,
216223
}).apolloClient;
217224
}

src/commands/launch/functions.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
import { FlagInput, Flags } from '@contentstack/cli-utilities';
2-
3-
import { BaseCommand } from '../../base-command';
1+
import { FlagInput } from '@contentstack/cli-utilities';
42
import Contentfly from '../../util/cloud-function';
3+
import { Flags, Command } from '@oclif/core';
54

6-
export default class Functions extends BaseCommand<typeof Functions> {
5+
export default class Functions extends Command {
76
static description = 'Serve cloud functions';
87

98
static examples = [
109
'$ csdx launch:functions',
1110
'$ csdx launch:functions --port=port',
1211
'$ csdx launch:functions --data-dir <path/of/current/working/dir>',
13-
'$ csdx launch:functions --config <path/to/launch/config/file>',
1412
'$ csdx launch:functions --data-dir <path/of/current/working/dir> -p "port number"',
15-
'$ csdx launch:functions --config <path/to/launch/config/file> --port=port',
1613
];
1714

1815
static flags: FlagInput = {
@@ -21,13 +18,19 @@ export default class Functions extends BaseCommand<typeof Functions> {
2118
default: '3000',
2219
description: 'Port number',
2320
}),
21+
'data-dir': Flags.string({
22+
char: 'd',
23+
description: 'Current working directory',
24+
}),
2425
};
2526

2627
async run(): Promise<void> {
27-
this.sharedConfig.config =
28-
this.flags['data-dir'] || this.flags.config
29-
? this.flags.config?.split(`${this.sharedConfig.configName}`)[0] || this.flags['data-dir']
30-
: process.cwd();
31-
await new Contentfly(this.sharedConfig.config as string).serveCloudFunctions(+this.flags.port);
28+
const { flags } = await this.parse(Functions);
29+
const currentWorkingDirectory = process.cwd();
30+
const projectBasePath = flags['data-dir'] || currentWorkingDirectory;
31+
32+
const port = process.env.PORT || flags.port;
33+
34+
await new Contentfly(projectBasePath).serveCloudFunctions(port);
3235
}
3336
}

0 commit comments

Comments
 (0)