Skip to content

Commit bb81fee

Browse files
committed
Merge pull request #28 from contentstack/CL-1571
feat:Allow specifying environment using flag for redeploying existing project
2 parents 8f2f002 + 3d83e86 commit bb81fee

File tree

11 files changed

+560
-45
lines changed

11 files changed

+560
-45
lines changed

package-lock.json

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

package.json

Lines changed: 1 addition & 1 deletion
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": {

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/commands/launch/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ export default class Launch extends BaseCommand<typeof Launch> {
1818
'<%= config.bin %> <%= command.id %> --type <options: GitHub|FileUpload>',
1919
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --type <options: GitHub|FileUpload>',
2020
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --redeploy-latest',
21-
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --redeploy-latest --redeploy-last-upload',
21+
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --redeploy-last-upload',
2222
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload>',
23+
'<%= config.bin %> <%= command.id %> --environment=<value> --redeploy-latest',
2324
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload> --name=<value> --environment=<value> --branch=<value> --build-command=<value> --framework=<option> --org=<value> --out-dir=<value>',
2425
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload> --name=<value> --environment=<value> --branch=<value> --build-command=<value> --framework=<option> --org=<value> --out-dir=<value> --server-command=<value>',
2526
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload> --name=<value> --environment=<value> --branch=<value> --build-command=<value> --framework=<option> --org=<value> --out-dir=<value> --variable-type="Import variables from a stack" --alias=<value>',

src/types/launch.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,23 @@ type SignedUploadUrlData = {
8282
uploadUid: string;
8383
};
8484

85+
export type Environment = {
86+
uid: string;
87+
name: string;
88+
frameworkPreset: string;
89+
};
90+
91+
export enum DeploymentStatus {
92+
QUEUED = 'QUEUED',
93+
LIVE = 'LIVE',
94+
DEPLOYED = 'DEPLOYED',
95+
ARCHIVED = 'ARCHIVED',
96+
DEPLOYING = 'DEPLOYING',
97+
SKIPPED = 'SKIPPED',
98+
FAILED = 'FAILED',
99+
CANCELLED = 'CANCELLED',
100+
}
101+
85102
export {
86103
LogFn,
87104
ExitFn,

src/util/logs-polling-utilities.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ApolloClient, ObservableQuery } from '@apollo/client/core';
44

55
import { LogPollingInput, ConfigType } from '../types';
66
import { deploymentQuery, deploymentLogsQuery, serverlessLogsQuery } from '../graphql';
7+
import { setTimeout as sleep } from "timers/promises";
78

89
export default class LogPolling {
910
private config: ConfigType;
@@ -79,6 +80,7 @@ export default class LogPolling {
7980
}
8081
this.deploymentStatus = data?.Deployment?.status;
8182
if (this.config.deploymentStatus.includes(this.deploymentStatus)) {
83+
this.config.currentDeploymentStatus = this.deploymentStatus;
8284
statusWatchQuery.stopPolling();
8385
}
8486
});
@@ -109,7 +111,7 @@ export default class LogPolling {
109111
>,
110112
): void {
111113
let timestamp: number = 0;
112-
logsWatchQuery.subscribe(({ data, errors, error }) => {
114+
logsWatchQuery.subscribe(async({ data, errors, error }) => {
113115
ux.action.start('Loading deployment logs...');
114116

115117
if (error) {
@@ -152,6 +154,7 @@ export default class LogPolling {
152154
}
153155

154156
if (this.config.deploymentStatus.includes(this.deploymentStatus)) {
157+
await sleep(1_000);
155158
logsWatchQuery.stopPolling();
156159
this.$event.emit('deployment-logs', {
157160
message: 'DONE',

0 commit comments

Comments
 (0)