Skip to content

Commit

Permalink
add mondaycoderc check (#103)
Browse files Browse the repository at this point in the history
* add mondaycoderc check
  • Loading branch information
danielva-monday authored Sep 29, 2024
1 parent d56cef6 commit b8652e3
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 18 deletions.
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', () => {
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 @@ -5,8 +5,10 @@ import path from 'node:path';
import archiver from 'archiver';
import glob from 'glob';
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 createGitignoreAndAppendConfigFileIfNeeded = (directoryPath: string
**/
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
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
.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

0 comments on commit b8652e3

Please sign in to comment.