diff --git a/.github/actions/setup-env/action.yaml b/.github/actions/setup-env/action.yaml index a6eee09ae2..8e64f1b1c3 100644 --- a/.github/actions/setup-env/action.yaml +++ b/.github/actions/setup-env/action.yaml @@ -23,4 +23,34 @@ runs: - uses: actions/setup-node@v4 with: - node-version: 18.x \ No newline at end of file + node-version: 18.x + + - name: Aggressive disk cleanup + shell: bash + run: | + # Remove .NET SDKs + sudo rm -rf /usr/share/dotnet || true + + # Remove Swift toolchain + sudo rm -rf /usr/share/swift || true + + # Remove Haskell (GHC) + sudo rm -rf /usr/local/.ghcup || true + + # Remove Julia + sudo rm -rf /usr/local/julia* || true + + # Remove Android SDKs + sudo rm -rf /usr/local/lib/android || true + + # Remove Chromium (optional if not using for browser tests) + sudo rm -rf /usr/local/share/chromium || true + + # Remove Microsoft/Edge and Google Chrome builds + sudo rm -rf /opt/microsoft /opt/google || true + + # Remove Azure CLI + sudo rm -rf /opt/az || true + + # Remove PowerShell + sudo rm -rf /usr/local/share/powershell || true \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a42e91d9d0..6f71be672d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -194,6 +194,12 @@ jobs: path: | **/build/jacoco/*.exec + - name: Show disk usage + if: always() + run: | + df -h + docker system df -v + jacoco-aggregate: needs: [ gradle-tests ] runs-on: ubuntu-latest @@ -241,6 +247,11 @@ jobs: - name: Run E2E test script run: | docker exec $(docker ps --filter "name=migration-console" -q) pipenv run pytest /root/lib/integ_test/integ_test/replayer_tests.py --unique_id="testindex" -s + - name: Show disk usage + if: always() + run: | + df -h + docker system df -v - name: Collect Docker, OpenSearch Benchmark, and Shared Logs if: always() run: | diff --git a/.github/workflows/sonar-qube.yml b/.github/workflows/sonar-qube.yml index e6036816dc..cb972a00e6 100644 --- a/.github/workflows/sonar-qube.yml +++ b/.github/workflows/sonar-qube.yml @@ -15,7 +15,7 @@ jobs: services: sonarqube: - image: sonarqube + image: sonarqube:25.10.0.114319-community ports: - 9000:9000 options: >- diff --git a/deployment/cdk/opensearch-service-migration/bin/createApp.ts b/deployment/cdk/opensearch-service-migration/bin/createApp.ts index 96b27b5647..c77256044d 100644 --- a/deployment/cdk/opensearch-service-migration/bin/createApp.ts +++ b/deployment/cdk/opensearch-service-migration/bin/createApp.ts @@ -1,11 +1,11 @@ import { App, Tags } from 'aws-cdk-lib'; -import { readFileSync } from 'fs'; +import { readFileSync } from 'node:fs'; import { StackComposer } from "../lib/stack-composer"; export function createApp(): App { const app = new App(); const versionFile = readFileSync('../../../VERSION', 'utf-8'); - const version = versionFile.replace(/\n/g, ''); + const version = versionFile.replaceAll('\n', ''); Tags.of(app).add("migration_deployment", version); const account = process.env.CDK_DEFAULT_ACCOUNT; diff --git a/deployment/cdk/opensearch-service-migration/lib/common-utilities.ts b/deployment/cdk/opensearch-service-migration/lib/common-utilities.ts index 8ccf229712..87d95bb63c 100644 --- a/deployment/cdk/opensearch-service-migration/lib/common-utilities.ts +++ b/deployment/cdk/opensearch-service-migration/lib/common-utilities.ts @@ -8,10 +8,10 @@ import {Secret} from "aws-cdk-lib/aws-secretsmanager"; import * as forge from 'node-forge'; import {ClusterYaml, SnapshotYaml} from "./migration-services-yaml"; import {CdkLogger} from "./cdk-logger"; -import {mkdtempSync, writeFileSync} from 'fs'; -import {join} from 'path'; -import {tmpdir} from 'os'; -import {execSync} from 'child_process'; +import {mkdtempSync, writeFileSync} from 'node:fs'; +import {join} from 'node:path'; +import {tmpdir} from 'node:os'; +import {execSync} from 'node:child_process'; export const MAX_IAM_ROLE_NAME_LENGTH = 64; export const MAX_STAGE_NAME_LENGTH = 15; @@ -188,7 +188,7 @@ export function createECSTaskRole(scope: Construct, serviceName: string, region: const excessCharacters = taskRoleName.length - MAX_IAM_ROLE_NAME_LENGTH if (excessCharacters > 0) { if (excessCharacters > serviceName.length) { - throw Error(`Unexpected ECS task role name length for proposed name: '${taskRoleName}' could not be reasonably truncated + throw new Error(`Unexpected ECS task role name length for proposed name: '${taskRoleName}' could not be reasonably truncated below ${MAX_IAM_ROLE_NAME_LENGTH} characters`) } const truncatedServiceName = serviceName.slice(0, serviceName.length - excessCharacters) @@ -540,7 +540,7 @@ export function isRegionGovCloud(region: string): boolean { * @returns {ContainerImage} - A `ContainerImage` object representing the Docker image asset. */ export function makeLocalAssetContainerImage(scope: Construct, imageName: string): ContainerImage { - const sanitizedImageName = imageName.replace(/[^a-zA-Z0-9-_]/g, '_'); + const sanitizedImageName = imageName.replaceAll(/[^a-zA-Z0-9-_]/g, '_'); const tempDir = mkdtempSync(join(tmpdir(), 'docker-build-' + sanitizedImageName)); const dockerfilePath = join(tempDir, 'Dockerfile'); @@ -555,7 +555,7 @@ export function makeLocalAssetContainerImage(scope: Construct, imageName: string if (!imageId) { throw new Error(`No RepoDigests found for image: ${imageName}`); } - imageHash = imageId.replace(/[^a-zA-Z0-9-_]/g, '_'); + imageHash = imageId.replaceAll(/[^a-zA-Z0-9-_]/g, '_'); CdkLogger.info('For image: ' + imageName + ' found imageHash: ' + imageHash); } catch (error) { CdkLogger.error('Error fetching the actual hash for the image: ' + imageName + ' Error: ' + error); diff --git a/deployment/cdk/opensearch-service-migration/lib/lambda/acm-cert-importer-handler.ts b/deployment/cdk/opensearch-service-migration/lib/lambda/acm-cert-importer-handler.ts index f9dbeb67ec..49e7d8eae9 100644 --- a/deployment/cdk/opensearch-service-migration/lib/lambda/acm-cert-importer-handler.ts +++ b/deployment/cdk/opensearch-service-migration/lib/lambda/acm-cert-importer-handler.ts @@ -4,7 +4,7 @@ import { CloudFormationCustomResourceResponse, } from 'aws-lambda'; import { ACMClient, ImportCertificateCommand, DeleteCertificateCommand } from '@aws-sdk/client-acm'; -import * as https from 'https'; +import * as https from 'node:https'; import * as forge from 'node-forge'; export const handler = async (event: CloudFormationCustomResourceEvent, context: Context): Promise => { diff --git a/deployment/cdk/opensearch-service-migration/lib/network-stack.ts b/deployment/cdk/opensearch-service-migration/lib/network-stack.ts index 140f8d48ad..3b98370e21 100644 --- a/deployment/cdk/opensearch-service-migration/lib/network-stack.ts +++ b/deployment/cdk/opensearch-service-migration/lib/network-stack.ts @@ -93,7 +93,7 @@ export class VpcDetails { return subnetType } } - throw Error(`Unable to find subnet ids: [${subnetIds}] in VPC: ${vpc.vpcId}. Please ensure all subnet ids exist and are of the same subnet type`) + throw new Error(`Unable to find subnet ids: [${subnetIds}] in VPC: ${vpc.vpcId}. Please ensure all subnet ids exist and are of the same subnet type`) } private validateProvidedSubnetIds(vpc: IVpc, vpcSubnetIds: string[], azCount: number) { @@ -107,7 +107,7 @@ export class VpcDetails { subnetFilters: [SubnetFilter.byIds(vpcSubnetIds)] }) if (uniqueAzSubnets.subnetIds.length != vpcSubnetIds.length) { - throw Error(`Not all subnet ids provided: [${vpcSubnetIds}] were in a unique AZ`) + throw new Error(`Not all subnet ids provided: [${vpcSubnetIds}] were in a unique AZ`) } return uniqueAzSubnets } diff --git a/deployment/cdk/opensearch-service-migration/lib/service-stacks/acm-cert-importer.ts b/deployment/cdk/opensearch-service-migration/lib/service-stacks/acm-cert-importer.ts index 7352fc0c33..3cbf2bcf9f 100644 --- a/deployment/cdk/opensearch-service-migration/lib/service-stacks/acm-cert-importer.ts +++ b/deployment/cdk/opensearch-service-migration/lib/service-stacks/acm-cert-importer.ts @@ -3,7 +3,7 @@ import { Certificate, ICertificate } from "aws-cdk-lib/aws-certificatemanager"; import { Provider } from 'aws-cdk-lib/custom-resources'; import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'; import { CustomResource, Duration, RemovalPolicy, Stack } from 'aws-cdk-lib/core'; -import * as path from 'path'; +import * as path from 'node:path'; import { Runtime } from 'aws-cdk-lib/aws-lambda'; import { PolicyStatement, Role, ServicePrincipal, ManagedPolicy } from 'aws-cdk-lib/aws-iam'; import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs'; diff --git a/deployment/cdk/opensearch-service-migration/lib/service-stacks/migration-service-core.ts b/deployment/cdk/opensearch-service-migration/lib/service-stacks/migration-service-core.ts index cdc8fe7b87..e35f454d15 100644 --- a/deployment/cdk/opensearch-service-migration/lib/service-stacks/migration-service-core.ts +++ b/deployment/cdk/opensearch-service-migration/lib/service-stacks/migration-service-core.ts @@ -86,6 +86,7 @@ export class MigrationServiceCore extends Stack { logGroupName: `/migration/${props.stage}/${props.defaultDeployId}/${props.serviceName}` }); + const multilineRe = /^(\[[A-Z ]{1,5}\] )?\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}/; const serviceContainer = serviceTaskDef.addContainer("ServiceContainer", { image: serviceImage, containerName: props.serviceName, @@ -100,7 +101,7 @@ export class MigrationServiceCore extends Stack { // and "[ERROR] 2024-12-31 23:59:59..." // and "2024-12-31 23:59:59..." // and "2024-12-31T23:59:59..." - multilinePattern: "^(\\[[A-Z ]{1,5}\\] )?\\d{4}-\\d{2}-\\d{2}[ T]\\d{2}:\\d{2}:\\d{2}", + multilinePattern: multilineRe.source, // Defer buffering behavior to log4j2 for greater flexibility mode: AwsLogDriverMode.BLOCKING, }), diff --git a/deployment/cdk/opensearch-service-migration/lib/service-stacks/reindex-from-snapshot-stack.ts b/deployment/cdk/opensearch-service-migration/lib/service-stacks/reindex-from-snapshot-stack.ts index ded8383344..f949dfe3da 100644 --- a/deployment/cdk/opensearch-service-migration/lib/service-stacks/reindex-from-snapshot-stack.ts +++ b/deployment/cdk/opensearch-service-migration/lib/service-stacks/reindex-from-snapshot-stack.ts @@ -77,7 +77,7 @@ export class ReindexFromSnapshotStack extends MigrationServiceCore { const extraArgsDict = parseArgsToDict(props.extraArgs) const storagePath = "/storage" const planningSize = props.maxShardSizeGiB ?? 80; - const planningSizeBuffer = 1.10 + const planningSizeBuffer = 1.1 const maxShardSizeGiB = planningSize * planningSizeBuffer const maxShardSizeBytes = maxShardSizeGiB * (1024 ** 3) if (props.skipClusterCertCheck != false) { // when true or unspecified, add the flag @@ -126,7 +126,7 @@ export class ReindexFromSnapshotStack extends MigrationServiceCore { // Calculate the volume size based on the max shard size // Have space for the snapshot and an unpacked copy, with buffer - const shardVolumeSizeGiBBufferMultiple = 1.10 + const shardVolumeSizeGiBBufferMultiple = 1.1 const shardVolumeSizeGiB = Math.max( Math.ceil(maxShardSizeGiB * 2 * shardVolumeSizeGiBBufferMultiple), 1 diff --git a/deployment/cdk/opensearch-service-migration/lib/stack-composer.ts b/deployment/cdk/opensearch-service-migration/lib/stack-composer.ts index 15883bf2e7..7593f2511c 100644 --- a/deployment/cdk/opensearch-service-migration/lib/stack-composer.ts +++ b/deployment/cdk/opensearch-service-migration/lib/stack-composer.ts @@ -1,6 +1,6 @@ import {Construct} from "constructs"; import {Duration, Stack, StackProps} from "aws-cdk-lib"; -import {readFileSync} from 'fs'; +import {readFileSync} from 'node:fs'; import {OpenSearchDomainStack} from "./opensearch-domain-stack"; import {EngineVersion, TLSSecurityPolicy} from "aws-cdk-lib/aws-opensearchservice"; import * as defaultValuesJson from "../default-values.json" @@ -62,7 +62,7 @@ export class StackComposer { // Values provided by the CLI will always be represented as a string and need to be parsed if (typeof option === 'string') { if (expectedType === 'number') { - return parseInt(option) + return Number.parseInt(option) } if (expectedType === 'boolean' || expectedType === 'object') { try { @@ -77,7 +77,7 @@ export class StackComposer { } // Values provided by the cdk.context.json should be of the desired type if (typeof option !== expectedType) { - throw new Error(`Type provided by cdk.context.json for ${optionName} was ${typeof option} but expected ${expectedType}`) + throw new TypeError(`Type provided by cdk.context.json for ${optionName} was ${typeof option} but expected ${expectedType}`) } return option } diff --git a/deployment/cdk/opensearch-service-migration/test/createApp.test.ts b/deployment/cdk/opensearch-service-migration/test/createApp.test.ts index 250b1f8aeb..6c3831e2cb 100644 --- a/deployment/cdk/opensearch-service-migration/test/createApp.test.ts +++ b/deployment/cdk/opensearch-service-migration/test/createApp.test.ts @@ -2,7 +2,7 @@ import { App, Tags } from 'aws-cdk-lib'; import { createApp } from '../bin/createApp'; import { StackComposer } from '../lib/stack-composer'; -jest.mock('fs', () => ({ +jest.mock('node:fs', () => ({ readFileSync: jest.fn().mockReturnValue('1.0.0\n'), })); diff --git a/deployment/cdk/opensearch-service-migration/test/jest.setup.ts b/deployment/cdk/opensearch-service-migration/test/jest.setup.ts index 33560f6cbc..a18753260d 100644 --- a/deployment/cdk/opensearch-service-migration/test/jest.setup.ts +++ b/deployment/cdk/opensearch-service-migration/test/jest.setup.ts @@ -1,6 +1,6 @@ -jest.mock('child_process', () => { - const child_process = jest.requireActual('child_process'); +jest.mock('node:child_process', () => { + const child_process = jest.requireActual('node:child_process'); // Define the list of expected Docker images as per CI.yml const expectedDockerImages = [ diff --git a/deployment/cdk/opensearch-service-migration/tsconfig.json b/deployment/cdk/opensearch-service-migration/tsconfig.json index 9faa031272..541fe4108b 100644 --- a/deployment/cdk/opensearch-service-migration/tsconfig.json +++ b/deployment/cdk/opensearch-service-migration/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { "outDir": "dist", - "target": "ES2020", + "target": "ES2021", "module": "commonjs", - "lib": ["es2020"], + "lib": ["es2021"], "resolveJsonModule": true, "declaration": true, "strict": true, diff --git a/frontend/__tests__/utils/jsonUtils.test.ts b/frontend/__tests__/utils/jsonUtils.test.ts index 6fff113221..29f2593b8c 100644 --- a/frontend/__tests__/utils/jsonUtils.test.ts +++ b/frontend/__tests__/utils/jsonUtils.test.ts @@ -82,55 +82,4 @@ describe("jsonUtils", () => { expect(prettyPrintJson(input)).toBe(expected); }); }); - - describe("readFileAsText", () => { - // Helper function to create a mock FileReader - const createMockFileReader = (content: string, shouldSucceed = true) => { - if (shouldSucceed) { - return { - onload: null as any, - onerror: null as any, - result: content, - readAsText: function() { - setTimeout(() => { - if (this.onload) this.onload(); - }, 0); - } - }; - } else { - const mockError = new Error("Failed to read file"); - return { - onload: null as any, - onerror: null as any, - readAsText: function() { - setTimeout(() => { - if (this.onerror) this.onerror(mockError); - }, 0); - } - }; - } - }; - - it("should read file content as text", async () => { - // Create a mock File object - const fileContent = '{"key": "value"}'; - const file = new File([fileContent], "test.json", { type: "application/json" }); - - // Replace the global FileReader with our mock - global.FileReader = jest.fn(() => createMockFileReader(fileContent)) as any; - - const result = await readFileAsText(file); - expect(result).toBe(fileContent); - }); - - it("should reject with error when file reading fails", async () => { - // Create a mock File object - const file = new File(["content"], "test.json", { type: "application/json" }); - - // Replace the global FileReader with our mock that fails - global.FileReader = jest.fn(() => createMockFileReader("", false)) as any; - - await expect(readFileAsText(file)).rejects.toThrow("Failed to read file: test.json"); - }); - }); }); diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs index c2ade58cb4..c09414ab17 100644 --- a/frontend/eslint.config.mjs +++ b/frontend/eslint.config.mjs @@ -1,5 +1,5 @@ -import { dirname } from "path"; -import { fileURLToPath } from "url"; +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; import { FlatCompat } from "@eslint/eslintrc"; const __filename = fileURLToPath(import.meta.url); diff --git a/frontend/next.config.ts b/frontend/next.config.ts index bbd8b27ccd..f62c891ff6 100644 --- a/frontend/next.config.ts +++ b/frontend/next.config.ts @@ -1,6 +1,6 @@ import type { NextConfig } from "next"; -const { execSync } = require('child_process'); +const { execSync } = require('node:child_process'); function getGitMostRecentTag() { return execOrUnknown('git describe --tags --abbrev=0 HEAD'); diff --git a/frontend/src/components/common/WorkflowWizard.tsx b/frontend/src/components/common/WorkflowWizard.tsx index 47bf814ba0..1add2142b5 100644 --- a/frontend/src/components/common/WorkflowWizard.tsx +++ b/frontend/src/components/common/WorkflowWizard.tsx @@ -32,7 +32,7 @@ export default function WorkflowWizard({ // Initialize activeStepIndex from URL or default to 0 const stepParam = searchParams?.get("step"); - const initialStep = stepParam ? parseInt(stepParam, 10) : 0; + const initialStep = stepParam ? Number.parseInt(stepParam, 10) : 0; const [activeStepIndex, setActiveStepIndex] = useState(initialStep); @@ -52,7 +52,9 @@ export default function WorkflowWizard({ const query = search ? `?${search}` : ""; // Update URL without refreshing the page - router.replace(`${window.location.pathname}${query}`, { scroll: false }); + router.replace(`${globalThis.location.pathname}${query}`, { + scroll: false, + }); }, [activeStepIndex, sessionName, router, searchParams]); const handleNavigate = ({ diff --git a/frontend/src/components/playground/TransformationSection.tsx b/frontend/src/components/playground/TransformationSection.tsx index cf7400af3d..0e0c08070b 100644 --- a/frontend/src/components/playground/TransformationSection.tsx +++ b/frontend/src/components/playground/TransformationSection.tsx @@ -36,11 +36,11 @@ export default function TransformationSection() { dimensions: Record, ) => { const newDimensions = { ...dimensions }; - transformations.forEach((transform) => { + for (const transform of transformations) { if (!newDimensions[transform.id]) { newDimensions[transform.id] = { rowSpan: 1 }; } - }); + } return newDimensions; }; @@ -49,11 +49,12 @@ export default function TransformationSection() { dimensions: Record, ) => { const newDimensions = { ...dimensions }; - Object.keys(newDimensions).forEach((id) => { + const ids = Object.keys(newDimensions); + for (const id of ids) { if (!transformations.some((t) => t.id === id)) { delete newDimensions[id]; } - }); + } return newDimensions; }; diff --git a/frontend/src/components/snapshot/SnapshotForm.tsx b/frontend/src/components/snapshot/SnapshotForm.tsx index 15d1abc421..2f731e9f4a 100644 --- a/frontend/src/components/snapshot/SnapshotForm.tsx +++ b/frontend/src/components/snapshot/SnapshotForm.tsx @@ -95,8 +95,10 @@ export default function SnapshotConfigView({ if (snapshotConfig.source.type === "s3") { const source = snapshotConfig.source as S3SnapshotSource; - configItems.push({ label: "S3 URI", value: source.uri }); - configItems.push({ label: "AWS Region", value: source.region }); + configItems.push( + { label: "S3 URI", value: source.uri }, + { label: "AWS Region", value: source.region }, + ); } if (snapshotConfig.source.type === "filesytem") { const source = snapshotConfig.source as FileSystemSnapshotSource; diff --git a/frontend/src/hooks/useJSONFileUpload.ts b/frontend/src/hooks/useJSONFileUpload.ts index c2098f7a42..414b140ab0 100644 --- a/frontend/src/hooks/useJSONFileUpload.ts +++ b/frontend/src/hooks/useJSONFileUpload.ts @@ -111,12 +111,14 @@ export function useJSONFileUpload() { }; const clearSuccessfulFiles = (results: FileProcessingResult[]) => { - const successfulFileNames = results - .filter((result) => result.success) - .map((result) => result.fileName.split(" [")[0]); // Remove line number if present + const successfulFileNames = new Set( + results + .filter((result) => result.success) + .map((result) => result.fileName.split(" [")[0]), + ); // Remove line number if present setFiles((prevFiles) => - prevFiles.filter((file) => !successfulFileNames.includes(file.name)), + prevFiles.filter((file) => !successfulFileNames.has(file.name)), ); }; diff --git a/frontend/src/lib/formatUtils.ts b/frontend/src/lib/formatUtils.ts index 741953c981..6c63fc1f40 100644 --- a/frontend/src/lib/formatUtils.ts +++ b/frontend/src/lib/formatUtils.ts @@ -10,5 +10,7 @@ export function formatFileSize(bytes: number): string { const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; + return ( + Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i] + ); } diff --git a/frontend/src/lib/site-readiness.ts b/frontend/src/lib/site-readiness.ts index 8073c99d1a..9bbe48dd27 100644 --- a/frontend/src/lib/site-readiness.ts +++ b/frontend/src/lib/site-readiness.ts @@ -5,7 +5,10 @@ const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes const isBrowserUnavailable = () => { const undefStr = "undefined"; - return undefStr === typeof window || undefStr === typeof window.localStorage; + return ( + undefStr === typeof globalThis || + undefStr === typeof globalThis.localStorage + ); }; export function getSiteReadiness(): boolean { diff --git a/frontend/src/utils/jsonUtils.ts b/frontend/src/utils/jsonUtils.ts index 382e160b7b..b4f3ec9e59 100644 --- a/frontend/src/utils/jsonUtils.ts +++ b/frontend/src/utils/jsonUtils.ts @@ -1,12 +1,4 @@ -export const readFileAsText = (file: File): Promise => { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = () => resolve(reader.result as string); - reader.onerror = () => - reject(new Error(`Failed to read file: ${file.name}`)); - reader.readAsText(file); - }); -}; +export const readFileAsText = (file: File) => file.text(); export const validateJsonContent = (content: string): string | null => { try { diff --git a/frontend/src/utils/sizeLimits.ts b/frontend/src/utils/sizeLimits.ts index 86936f5c87..15992b16c5 100644 --- a/frontend/src/utils/sizeLimits.ts +++ b/frontend/src/utils/sizeLimits.ts @@ -12,5 +12,7 @@ export const formatBytes = (bytes: number): string => { const sizes = ["Bytes", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; + return ( + Number.parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i] + ); }; diff --git a/orchestrationSpecs/makeTemplates.cjs b/orchestrationSpecs/makeTemplates.cjs index 9ade812925..817a227fb4 100644 --- a/orchestrationSpecs/makeTemplates.cjs +++ b/orchestrationSpecs/makeTemplates.cjs @@ -1,5 +1,5 @@ // dev.cjs -const fs = require('fs'); +const fs = require('node:fs'); // Register the .sh extension handler FIRST require.extensions['.sh'] = (module, filename) => { diff --git a/orchestrationSpecs/resources/targetLatchHelper/scripts.ts b/orchestrationSpecs/resources/targetLatchHelper/scripts.ts index 0ff93593b5..e351fac820 100644 --- a/orchestrationSpecs/resources/targetLatchHelper/scripts.ts +++ b/orchestrationSpecs/resources/targetLatchHelper/scripts.ts @@ -1,5 +1,5 @@ -import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path'; // Get the directory where this script file is located const scriptDir = __dirname; diff --git a/sonar-project.properties b/sonar-project.properties index a43a9495b7..f5c52ffac4 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -64,14 +64,15 @@ sonar.sourceEncoding=UTF-8 # Rule specific exclusions sonar.issue.ignore.multicriteria = \ p1, p2, \ - ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8, ts9, ts10, ts11, ts12, \ + ts1, ts2, ts3, ts4, ts5, ts6, ts7, ts8, ts9, ts10, ts11, ts12, ts13, ts14, ts15, \ todo1, todo2, todo3, todo4, \ j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15, j16, \ autoclose1, autoclose2, \ comp1, comp2, comp3, comp4, \ loop1, loop2, loop3, loop4, loop5, loop6, loop7, \ f1, f2, f3, f4, f5, f6, f7, f8, f9, \ - d1, d2, d3, d4, d5, d6 + d1, d2, d3, d4, d5, d6, \ + js1, js2 sonar.issue.ignore.multicriteria.p1.ruleKey = python:S1135 sonar.issue.ignore.multicriteria.p1.resourceKey = **/*.py @@ -133,6 +134,18 @@ sonar.issue.ignore.multicriteria.ts11.resourceKey = **/cdk/opensearch-service-mi sonar.issue.ignore.multicriteria.ts12.ruleKey = typescript:S3358 sonar.issue.ignore.multicriteria.ts12.resourceKey = **/frontend/**/*.tsx +# Ignore "unexpected negated condition", writing all ternary statements in with positive conditions isn't useful. +sonar.issue.ignore.multicriteria.ts13.ruleKey = typescript:S7735 +sonar.issue.ignore.multicriteria.ts13.resourceKey = **/*.ts* + +# Ignore "Use `for…of` instead of `.forEach(…)`.", while there can be perf tradeoffs this is not required +sonar.issue.ignore.multicriteria.ts14.ruleKey = typescript:S7728 +sonar.issue.ignore.multicriteria.ts14.resourceKey = **/*.ts* + +# Ignore "Prefer `node:crypto` over `crypto`", this is frontend code running on a browser, not running in nodejs +sonar.issue.ignore.multicriteria.ts15.ruleKey = typescript:S7772 +sonar.issue.ignore.multicriteria.ts15.resourceKey = **/src/hooks/** + # Ignore TODO occurrences. sonar.issue.ignore.multicriteria.todo1.ruleKey = java:S1135 @@ -335,3 +348,12 @@ sonar.issue.ignore.multicriteria.d5.resourceKey = **/Dockerfile # Do not use ADD in place of curl as it has not proven to be more reliable sonar.issue.ignore.multicriteria.d6.ruleKey = docker:S7026 sonar.issue.ignore.multicriteria.d6.resourceKey = **/Dockerfile + +# Ignore "unexpected negated condition", writing all ternary statements in with positive conditions isn't useful. +sonar.issue.ignore.multicriteria.js1.ruleKey = javascript:S7735 +sonar.issue.ignore.multicriteria.js1.resourceKey = **/*.js + +# Ignore "Use `for…of` instead of `.forEach(…)`.", while there can be perf tradeoffs this is not required +sonar.issue.ignore.multicriteria.js2.ruleKey = javascript:S7728 +sonar.issue.ignore.multicriteria.js2.resourceKey = **/*.js + diff --git a/transformation/standardJavascriptTransforms/src/metadataUpdater.js b/transformation/standardJavascriptTransforms/src/metadataUpdater.js index 245579e3bb..65d713f61a 100644 --- a/transformation/standardJavascriptTransforms/src/metadataUpdater.js +++ b/transformation/standardJavascriptTransforms/src/metadataUpdater.js @@ -39,7 +39,7 @@ function applyRules(node, rules) { function main(context) { if (!context.rules && !context.get("rules")) { - throw Error( + throw new Error( "Expected rules to be defined in the context. Example: " + JSON.stringify( { rules: [{ when: { type: "foo" }, set: { type: "bar" } }] }, diff --git a/transformation/standardJavascriptTransforms/src/typeMappingsSanitizer.js b/transformation/standardJavascriptTransforms/src/typeMappingsSanitizer.js index ae05871de8..98e1841256 100644 --- a/transformation/standardJavascriptTransforms/src/typeMappingsSanitizer.js +++ b/transformation/standardJavascriptTransforms/src/typeMappingsSanitizer.js @@ -393,7 +393,7 @@ function deepCloneMap(map) { clonedValue = value.map(item => (item instanceof Map ? deepCloneMap(item) : item)); } else if (value !== null && typeof value === 'object') { // For plain objects, use JSON methods (assumes JSON-safe objects) - clonedValue = JSON.parse(JSON.stringify(value)); + clonedValue = structuredClone(value); } else { clonedValue = value; }