Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
1e6a91c
Skip logging in, init and sdk initialization for 'functions' command …
dhruvparekh12 Mar 11, 2025
7927f0f
Merge pull request #25 from contentstack/CL-1573
dhruvparekh12 Mar 11, 2025
89e5ce0
fix: support for dynamic paths on launch cloud functions by restoring…
dhruvparekh12 Mar 11, 2025
6411c2c
Merge pull request #26 from contentstack/CL-1573
dhruvparekh12 Mar 11, 2025
5420443
feat: Enable setting port using PORT environment variable when runnin…
dhruvparekh12 Mar 11, 2025
8f2f002
Merge pull request #27 from contentstack/CL-1573
dhruvparekh12 Mar 11, 2025
655f7e3
feat:Allow specifying environment using flag for redeploying existing…
Chhavi-Mandowara Mar 18, 2025
8434092
docs:add static example of command usage
Chhavi-Mandowara Mar 19, 2025
fce1db2
refactor:refactor method to simplify conditional logic
Chhavi-Mandowara Mar 19, 2025
116b506
fix: types in BaseClass -> getEnvironment method
dhruvparekh12 Mar 19, 2025
3d83e86
fix: Exit with non zero status code when the deployment fails and pol…
dhruvparekh12 Mar 20, 2025
bb81fee
Merge pull request #28 from contentstack/CL-1571
dhruvparekh12 Mar 20, 2025
9224f27
chore: upgrade cross-fetch package version
Chhavi-Mandowara Mar 25, 2025
84e5dfa
Merge pull request #30 from contentstack/CL-1621
Chhavi-Mandowara Mar 25, 2025
ce86e1e
Update sca-scan.yml
aravindbuilt Mar 26, 2025
e6e6a34
fix: semgrep finding in github workflow
dhruvparekh12 Mar 26, 2025
b7adf1f
fix:fix HPE_INVALID_HEADER_TOKEN error on creating new GitHub project
Chhavi-Mandowara Mar 26, 2025
26f5bc2
Merge pull request #31 from contentstack/CL-1627
Chhavi-Mandowara Mar 26, 2025
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
5 changes: 3 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
id: release-plugin
uses: JS-DevTools/npm-publish@v2.2.0
with:
token: ${{ secrets.NPM_TOKEN }}
token: "${{ secrets.NPM_TOKEN }}"
access: public
- name: get-npm-version
id: package-version
Expand All @@ -61,4 +61,5 @@ jobs:
id: github-release
env:
GITHUB_TOKEN: ${{ secrets.PKG_TOKEN }}
run: gh release create v${{ steps.release-plugin.outputs.version }} --title "Release ${{ steps.release-plugin.outputs.version }}" --generate-notes
VERSION: ${{ steps.release-plugin.outputs.version }}
run: gh release create v"$VERSION" --title "Release $VERSION" --generate-notes
2 changes: 1 addition & 1 deletion .github/workflows/sca-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ jobs:
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --all-projects --fail-on=all
args: --all-projects --fail-on=all --strict-out-of-sync=false
7,143 changes: 3,554 additions & 3,589 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/cli-launch",
"version": "1.6.0",
"version": "1.7.0",
"description": "Launch related operations",
"author": "Contentstack CLI",
"bin": {
Expand Down Expand Up @@ -34,7 +34,7 @@
"@types/express-serve-static-core": "^4.17.34",
"adm-zip": "^0.5.16",
"chalk": "^4.1.2",
"cross-fetch": "^3.1.8",
"cross-fetch": "^4.1.0",
"dotenv": "^16.4.7",
"express": "^4.21.1",
"form-data": "^4.0.0",
Expand Down
50 changes: 44 additions & 6 deletions src/adapters/base-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
fileFrameworkQuery,
createDeploymentMutation,
cmsEnvironmentVariablesQuery,
environmentsQuery
} from '../graphql';
import {
LogFn,
Expand All @@ -36,6 +37,7 @@ import {
EmitMessage,
DeploymentLogResp,
ServerLogResp,
Environment,
} from '../types';

export default class BaseClass {
Expand Down Expand Up @@ -85,14 +87,14 @@ export default class BaseClass {
* @return {*} {Promise<void>}
* @memberof GitHub
*/
async createNewDeployment(skipGitData = false, uploadUid?: string): Promise<void> {
async createNewDeployment(skipGitData = false, environmentUid:string, uploadUid?: string): Promise<void> {
const deployment: Record<string, any> = {
environment: (first(this.config.currentConfig.environments) as Record<string, any>)?.uid,
environment: environmentUid
};

if (uploadUid) {
deployment.uploadUid = uploadUid;
}
}

await this.apolloClient
.mutate({
Expand Down Expand Up @@ -394,7 +396,7 @@ export default class BaseClass {
data.project = this.config.currentConfig;
}

writeFileSync(this.config.config, JSON.stringify(data), {
writeFileSync(this.config.config, JSON.stringify(data, null, 2), {
encoding: 'utf8',
flag: 'w',
});
Expand Down Expand Up @@ -675,7 +677,7 @@ export default class BaseClass {
},
baseUrl: this.config.manageApiBaseUrl,
}).apolloClient;
this.config.environment = (last(this.config.currentConfig.environments) as Record<string, any>)?.uid;
this.config.environment = (await this.getEnvironment()).uid;
this.config.deployment = (last(this.config.currentConfig.deployments) as Record<string, any>)?.uid;
const logs = new LogPolling({
config: this.config,
Expand Down Expand Up @@ -744,6 +746,42 @@ export default class BaseClass {
this.exit(1);
}

async getEnvironment(): Promise<Environment> | never {
const environmentFlagInput = this.config['environment'];

if (!environmentFlagInput) {
const defaultEnvironment = (first(this.config.currentConfig.environments) as Environment);
this.setEnvironmentOnConfig(defaultEnvironment as Environment);
return defaultEnvironment;
}
const environmentList = await this.fetchEnvironments();
let environment = environmentList.find((env: Environment) => env.name === environmentFlagInput || env.uid === environmentFlagInput);

if (!environment) {
this.log(`Environment "${environmentFlagInput}" not found in this project. Please provide a valid environment name or UID.`, 'error');
this.exit(1);
}

environment = environment as Environment;
this.setEnvironmentOnConfig(environment);
return environment;
}

async setEnvironmentOnConfig(environment: Environment): Promise<void> {
this.config.environment = environment.uid;
}

async fetchEnvironments(): Promise<Environment[]> | never {
try {
const { data } = await this.apolloClient.query({ query: environmentsQuery });
const environments = map(data.Environments.edges, 'node');
return environments;
} catch (error: unknown) {
this.log(error instanceof Error ? error.message : String(error), 'error');
process.exit(1);
}
}

/**
* @method showDeploymentUrl - show deployment URL and open it on browser
*
Expand Down Expand Up @@ -791,4 +829,4 @@ export default class BaseClass {
});
}
}
}
}
12 changes: 8 additions & 4 deletions src/adapters/file-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { print } from '../util';
import BaseClass from './base-class';
import { getFileList } from '../util/fs';
import { createSignedUploadUrlMutation, importProjectMutation } from '../graphql';
import { SignedUploadUrlData, FileUploadMethod } from '../types/launch';
import { SignedUploadUrlData, FileUploadMethod, DeploymentStatus } from '../types/launch';
import config from '../config';

export default class FileUpload extends BaseClass {
Expand All @@ -26,18 +26,22 @@ export default class FileUpload extends BaseClass {
*/
async run(): Promise<void> {
if (this.config.isExistingProject) {
await this.handleExistingProject();
const environment = await this.getEnvironment();
await this.handleExistingProject(environment.uid);
} else {
await this.handleNewProject();
}

this.prepareLaunchConfig();
await this.showLogs();
if(this.config.currentDeploymentStatus === DeploymentStatus.FAILED) {
this.exit(1);
}
this.showDeploymentUrl();
this.showSuggestion();
}

private async handleExistingProject(): Promise<void> {
private async handleExistingProject(environment: string): Promise<void> {
await this.initApolloClient();

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

await this.createNewDeployment(true, uploadUid);
await this.createNewDeployment(true, environment, uploadUid);
}

private async confirmRedeployment(): Promise<void> {
Expand Down
11 changes: 8 additions & 3 deletions src/adapters/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { print } from '../util';
import BaseClass from './base-class';
import { getRemoteUrls } from '../util/create-git-meta';
import { repositoriesQuery, userConnectionsQuery, importProjectMutation } from '../graphql';
import { DeploymentStatus } from '../types';

export default class GitHub extends BaseClass {
/**
Expand All @@ -22,18 +23,22 @@ export default class GitHub extends BaseClass {
*/
async run(): Promise<void> {
if (this.config.isExistingProject) {
await this.handleExistingProject();
const environment = await this.getEnvironment();
await this.handleExistingProject(environment.uid);
} else {
await this.handleNewProject();
}

this.prepareLaunchConfig();
await this.showLogs();
if(this.config.currentDeploymentStatus === DeploymentStatus.FAILED) {
this.exit(1);
}
this.showDeploymentUrl();
this.showSuggestion();
}

private async handleExistingProject(): Promise<void> {
private async handleExistingProject(environmentUid:string): Promise<void> {
await this.initApolloClient();

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

await this.createNewDeployment();
await this.createNewDeployment(false, environmentUid);
}

private async confirmLatestRedeployment(): Promise<void> {
Expand Down
2 changes: 1 addition & 1 deletion src/adapters/pre-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default class PreCheck extends BaseClass {
this.log('Current Project details:', { bold: true, color: 'green' });
this.log(''); // Empty line
const { name, projectType, repository, environments } = this.config.currentConfig;
const [environment] = environments;
const environment = await this.getEnvironment();

const detail: Record<string, any> = {
'Project Name': name,
Expand Down
29 changes: 18 additions & 11 deletions src/base-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import config from './config';
import { GraphqlApiClient, Logger } from './util';
import { getLaunchHubUrl } from './util/common-utility';
import { ConfigType, LogFn, Providers } from './types';
import { ConfigType, LogFn, Providers, GraphqlHeaders } from './types';

export type Flags<T extends typeof Command> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
Expand Down Expand Up @@ -198,20 +198,27 @@ export abstract class BaseCommand<T extends typeof Command> extends Command {
* @memberof BaseCommand
*/
async prepareApiClients(): Promise<void> {
let headers: GraphqlHeaders = {
'X-CS-CLI': this.context.analyticsInfo
}

const { uid, organizationUid } = this.sharedConfig.currentConfig;

if (uid) {
headers['x-project-uid'] = uid;
}

if (organizationUid) {
headers['organization_uid'] = organizationUid;
}

this.apolloClient = await new GraphqlApiClient({
headers: {
'X-CS-CLI': this.context.analyticsInfo,
'x-project-uid': this.sharedConfig.currentConfig.uid,
organization_uid: this.sharedConfig.currentConfig.organizationUid,
},
headers,
baseUrl: this.sharedConfig.manageApiBaseUrl,
}).apolloClient;

this.apolloLogsClient = await new GraphqlApiClient({
headers: {
'X-CS-CLI': this.context.analyticsInfo,
'x-project-uid': this.sharedConfig.currentConfig.uid,
organization_uid: this.sharedConfig.currentConfig.organizationUid,
},
headers,
baseUrl: this.sharedConfig.logsApiBaseUrl,
}).apolloClient;
}
Expand Down
25 changes: 14 additions & 11 deletions src/commands/launch/functions.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { FlagInput, Flags } from '@contentstack/cli-utilities';

import { BaseCommand } from '../../base-command';
import { FlagInput } from '@contentstack/cli-utilities';
import Contentfly from '../../util/cloud-function';
import { Flags, Command } from '@oclif/core';

export default class Functions extends BaseCommand<typeof Functions> {
export default class Functions extends Command {
static description = 'Serve cloud functions';

static examples = [
'$ csdx launch:functions',
'$ csdx launch:functions --port=port',
'$ csdx launch:functions --data-dir <path/of/current/working/dir>',
'$ csdx launch:functions --config <path/to/launch/config/file>',
'$ csdx launch:functions --data-dir <path/of/current/working/dir> -p "port number"',
'$ csdx launch:functions --config <path/to/launch/config/file> --port=port',
];

static flags: FlagInput = {
Expand All @@ -21,13 +18,19 @@ export default class Functions extends BaseCommand<typeof Functions> {
default: '3000',
description: 'Port number',
}),
'data-dir': Flags.string({
char: 'd',
description: 'Current working directory',
}),
};

async run(): Promise<void> {
this.sharedConfig.config =
this.flags['data-dir'] || this.flags.config
? this.flags.config?.split(`${this.sharedConfig.configName}`)[0] || this.flags['data-dir']
: process.cwd();
await new Contentfly(this.sharedConfig.config as string).serveCloudFunctions(+this.flags.port);
const { flags } = await this.parse(Functions);
const currentWorkingDirectory = process.cwd();
const projectBasePath = flags['data-dir'] || currentWorkingDirectory;

const port = process.env.PORT || flags.port;

await new Contentfly(projectBasePath).serveCloudFunctions(port);
}
}
3 changes: 2 additions & 1 deletion src/commands/launch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ export default class Launch extends BaseCommand<typeof Launch> {
'<%= config.bin %> <%= command.id %> --type <options: GitHub|FileUpload>',
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --type <options: GitHub|FileUpload>',
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --redeploy-latest',
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --redeploy-latest --redeploy-last-upload',
'<%= config.bin %> <%= command.id %> --data-dir <path/of/current/working/dir> --redeploy-last-upload',
'<%= config.bin %> <%= command.id %> --config <path/to/launch/config/file> --type <options: GitHub|FileUpload>',
'<%= config.bin %> <%= command.id %> --environment=<value> --redeploy-latest',
'<%= 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>',
'<%= 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>',
'<%= 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>',
Expand Down
17 changes: 17 additions & 0 deletions src/types/launch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ type SignedUploadUrlData = {
uploadUid: string;
};

export type Environment = {
uid: string;
name: string;
frameworkPreset: string;
};

export enum DeploymentStatus {
QUEUED = 'QUEUED',
LIVE = 'LIVE',
DEPLOYED = 'DEPLOYED',
ARCHIVED = 'ARCHIVED',
DEPLOYING = 'DEPLOYING',
SKIPPED = 'SKIPPED',
FAILED = 'FAILED',
CANCELLED = 'CANCELLED',
}

export {
LogFn,
ExitFn,
Expand Down
6 changes: 1 addition & 5 deletions src/util/cloud-function/cloud-functions-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,7 @@ export class CloudFunctionsValidator {
}

private hasInvalidFilepathNaming(filepath: string): boolean {
const validFilePathRegex = new RegExp(
'^(\\/[-a-z\\d%_.~+]*)*' + // path
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
'(\\#[-a-z\\d_]*)?$',
);
const validFilePathRegex = /^(\[[\w-]+\]|[\w-]+|\/)+$/;

const matchResult = filepath.match(validFilePathRegex);
return matchResult === null;
Expand Down
Loading