Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add mondaycoderc check #103

Merged
merged 11 commits into from
Sep 29, 2024
Merged
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mondaycom/apps-cli",
"version": "4.1.1",
"version": "4.2.0",
"description": "A cli tool to manage apps (and monday-code projects) in monday.com",
"author": "monday.com Apps Team",
"type": "module",
Expand Down
3 changes: 3 additions & 0 deletions src/commands/code/push.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Flags } from '@oclif/core';
import { AuthenticatedCommand } from 'commands-base/authenticated-command';
import { APP_ID_TO_ENTER, APP_VERSION_ID_TO_ENTER } from 'consts/messages';
import { DynamicChoicesService } from 'services/dynamic-choices-service';
import { getCurrentWorkingDirectory } from 'services/env-service';
import { validateIfCanBuild } from 'services/files-service';
import { getTasksForServerSide } from 'services/share/deploy';
import logger from 'utils/logger';
import { addRegionToFlags, chooseRegionIfNeeded, getRegionFromString } from 'utils/region';
Expand Down Expand Up @@ -52,6 +54,7 @@ export default class Push extends AuthenticatedCommand {
const { directoryPath, region: strRegion } = flags;
const region = getRegionFromString(strRegion);
let appVersionId = flags.appVersionId;
validateIfCanBuild(directoryPath || getCurrentWorkingDirectory());

try {
if (!appVersionId) {
Expand Down
38 changes: 38 additions & 0 deletions src/services/__tests__/mondaycoderc-schema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { mondaycodercSchema } from 'services/schemas/mondaycoderc-schema';

describe('mondaycodercSchema Validation', () => {
danielva-monday marked this conversation as resolved.
Show resolved Hide resolved
it('should validate a correct Python runtime and version', () => {
const data = { RUNTIME: 'Python', RUNTIME_VERSION: '3.10.1' };
expect(() => mondaycodercSchema.parse(data)).not.toThrow();
});

it('should invalidate an incorrect Python runtime version', () => {
const data = { RUNTIME: 'Python', RUNTIME_VERSION: '2.7.0' };
expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION');
});

it('should validate a correct Java runtime and version', () => {
const data = { RUNTIME: 'Java', RUNTIME_VERSION: '17' };
expect(() => mondaycodercSchema.parse(data)).not.toThrow();
});

it('should validate a missing runtime version when runtime is specified', () => {
const data = { RUNTIME: 'Java' };
expect(() => mondaycodercSchema.parse(data)).not.toThrow();
});

it('should validate when runtime is not specified', () => {
const data = {};
expect(() => mondaycodercSchema.parse(data)).not.toThrow();
});

it('should invalidate an incorrect Go runtime version', () => {
const data = { RUNTIME: 'Go', RUNTIME_VERSION: '2.0.0' };
expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION');
});

it('should invalidate an Unsupported Runtime', () => {
const data = { RUNTIME: 'Invalid', RUNTIME_VERSION: '1.0.0' };
expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid Runtime');
});
});
37 changes: 27 additions & 10 deletions src/services/files-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import path from 'node:path';

import archiver from 'archiver';
import glob from 'glob';

Check warning on line 6 in src/services/files-service.ts

View workflow job for this annotation

GitHub Actions / Run validations

Using exported name 'glob' as identifier for default export
import parseGitIgnore from 'parse-gitignore';
import { ZodError } from 'zod';

import { CONFIG_NAME } from 'services/config-service';
import { mondaycodercSchema } from 'services/schemas/mondaycoderc-schema';

import logger from '../utils/logger.js';

Expand Down Expand Up @@ -113,18 +115,33 @@
**/
export const validateIfCanBuild = (directoryPath: string): void => {
const filePath = path.join(directoryPath, 'yarn.lock');
if (!checkIfFileExists(filePath)) {
return;
if (checkIfFileExists(filePath)) {
const packageJsonPath = path.join(directoryPath, 'package.json');
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
const packageJson = JSON.parse(packageJsonContent) as { scripts?: { build?: string } };
const hasBuildCommand = packageJson?.scripts?.build;
if (hasBuildCommand) {
throw new Error(
'monday-code does not support yarn projects with a build command. If you need a build step, use npm instead',
);
}
}

const packageJsonPath = path.join(directoryPath, 'package.json');
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
const packageJson = JSON.parse(packageJsonContent) as { scripts?: { build?: string } };
const hasBuildCommand = packageJson?.scripts?.build;
if (hasBuildCommand) {
throw new Error(
'monday-code does not support yarn projects with a build command. If you need a build step, use npm instead',
);
const rcFilePath = path.join(directoryPath, '.mondaycoderc');
if (checkIfFileExists(rcFilePath)) {
const rcFileContent = JSON.parse(fs.readFileSync(rcFilePath, 'utf8')) as {
RUNTIME: string;
RUNTIME_VERSION: string;
};
try {
mondaycodercSchema.parse(rcFileContent);
} catch (error) {
if (error instanceof ZodError) {
throw new TypeError(error.errors[0].message);
}

throw error;
}
}
};

Expand Down Expand Up @@ -156,7 +173,7 @@
ignoreSearchPattern = ignoreSearchPattern.replaceAll('\\', '/');
}

const [ignorePath] = glob.sync(ignoreSearchPattern);

Check warning on line 176 in src/services/files-service.ts

View workflow job for this annotation

GitHub Actions / Run validations

Caution: `glob` also has a named export `sync`. Check if you meant to write `import {sync} from 'glob'` instead
return ignorePath;
};

Expand All @@ -164,7 +181,7 @@
const DEBUG_TAG = 'ignore_files_for_archive';
logger.debug(`${DEBUG_TAG} - Found ${ignorePath}`);
logger.debug(`${DEBUG_TAG} - Creating exclude files list`);
const parsedIgnore = parseGitIgnore.parse(ignorePath);

Check warning on line 184 in src/services/files-service.ts

View workflow job for this annotation

GitHub Actions / Run validations

Caution: `parseGitIgnore` also has a named export `parse`. Check if you meant to write `import {parse} from 'parse-gitignore'` instead
logger.debug(`${DEBUG_TAG} - validating and aligning exclude files list`);
const filesToExclude = alignPatternsForArchive(parsedIgnore?.patterns, directoryPath);
return filesToExclude;
Expand Down
2 changes: 0 additions & 2 deletions src/services/push-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
createTarGzArchive,
readFileData,
readZipFileAsBuffer,
validateIfCanBuild,
verifyClientDirectory,
} from 'services/files-service';
import { pollPromise } from 'services/polling-service';
Expand Down Expand Up @@ -192,7 +191,6 @@ export const buildAssetToDeployTask = async (
}

task.output = `Building asset to deploy from "${ctx.directoryPath}" directory`;
validateIfCanBuild(ctx.directoryPath);
const archivePath = await createTarGzArchive(ctx.directoryPath, 'code');
ctx.archivePath = archivePath;
ctx.showPrepareEnvironmentTask = true;
Expand Down
80 changes: 80 additions & 0 deletions src/services/schemas/mondaycoderc-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { z } from 'zod';

export const mondaycodercSchema = z
danielva-monday marked this conversation as resolved.
Show resolved Hide resolved
.object({
RUNTIME: z
.enum(['Python', 'Java', 'Go', 'PHP', 'Ruby', 'Node.js', 'NETCore'], {
errorMap: () => ({
message:
'Invalid Runtime in .mondaycoderc. Supported runtimes are Python, Java, Go, PHP, Ruby, Node.js, NETCore',
}),
})
.optional(),
RUNTIME_VERSION: z.string().optional(),
})
.strict()
.refine(data => {
if (data.RUNTIME_VERSION) {
if (data.RUNTIME === 'Python') {
if (!/^3\.(10|11|12)\.\d+$/.test(data.RUNTIME_VERSION || '')) {
throw new Error(
'Invalid RUNTIME_VERSION for Python in .mondaycoderc. Allowed versions are 3.10.x, 3.11.x, 3.12.x',
);
}

return true;
}

if (data.RUNTIME === 'Java') {
if (!['11', '17', '18'].includes(data.RUNTIME_VERSION || '')) {
throw new Error('Invalid RUNTIME_VERSION for Java in .mondaycoderc. Allowed versions are 11, 17, 18');
}

return true;
}

if (data.RUNTIME === 'Go') {
if (!/^1\.\d+\.\d+$/.test(data.RUNTIME_VERSION || '')) {
throw new Error('Invalid RUNTIME_VERSION for Go in .mondaycoderc. Allowed versions are 1.x.x');
}

return true;
}

if (data.RUNTIME === 'PHP') {
if (!/^8\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || '')) {
throw new Error('Invalid RUNTIME_VERSION for PHP in .mondaycoderc. Allowed versions are 8.1.x, 8.2.x');
}

return true;
}

if (data.RUNTIME === 'Ruby') {
if (!/^3\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || '')) {
throw new Error('Invalid RUNTIME_VERSION for Ruby in .mondaycoderc. Allowed versions are 3.1.x, 3.2.x');
}

return true;
}

if (data.RUNTIME === 'Node.js') {
if (!/^(12|14|16|18|20)\.\d+\.\d+$/.test(data.RUNTIME_VERSION || '')) {
throw new Error(
'Invalid RUNTIME_VERSION for Node.js in .mondaycoderc. Allowed versions are 12.x.x, 14.x.x, 16.x.x, 18.x.x, 20.x.x',
);
}

return true;
}

if (data.RUNTIME === 'NETCore') {
if (!/^(6|7)\.\d+$/.test(data.RUNTIME_VERSION || '')) {
throw new Error('Invalid RUNTIME_VERSION for NETCore in .mondaycoderc. Allowed versions are 6.x, 7.x');
}

return true;
}
}

return true;
});
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@
}
},
"include": [
"src/**/*",
"src/**/*"
],
"exclude": [
"test",
"node_modules",
"bin",
"dist",
"dist"
]
}
31 changes: 28 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8884,7 +8884,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"

"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -8943,7 +8952,14 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down Expand Up @@ -9669,7 +9685,7 @@ wordwrap@^1.0.0:
resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz"
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -9687,6 +9703,15 @@ wrap-ansi@^6.0.1:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.0.1, wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
Expand Down
Loading