From aed2a88f38fc6210251971365e71ca03d8c16d3e Mon Sep 17 00:00:00 2001 From: Rebecca Hum Date: Thu, 18 Jun 2026 13:46:43 -0600 Subject: [PATCH 1/5] vip app deploy - Flag large archive files included in BYOR deploy --- __tests__/bin/vip-app-deploy.js | 15 ++++ __tests__/lib/custom-deploy/custom-deploy.js | 83 ++++++++++++++++++ src/bin/vip-app-deploy.ts | 20 ++++- src/lib/custom-deploy/custom-deploy.ts | 70 ++++++++++++++- src/lib/validations/custom-deploy.ts | 92 ++++++++++++++++++-- 5 files changed, 273 insertions(+), 7 deletions(-) create mode 100644 __tests__/lib/custom-deploy/custom-deploy.js diff --git a/__tests__/bin/vip-app-deploy.js b/__tests__/bin/vip-app-deploy.js index e769d6f2d..723f4f390 100644 --- a/__tests__/bin/vip-app-deploy.js +++ b/__tests__/bin/vip-app-deploy.js @@ -3,6 +3,7 @@ import * as exit from '../../src/lib/cli/exit'; import { uploadImportFileToS3 } from '../../src/lib/client-file-uploader'; import { validateFile, + validateLargeArchiveFiles, promptToContinue, validateCustomDeployKey, } from '../../src/lib/custom-deploy/custom-deploy'; @@ -18,6 +19,7 @@ jest.mock( '../../src/lib/client-file-uploader', () => ( { jest.mock( '../../src/lib/custom-deploy/custom-deploy', () => ( { validateFile: jest.fn(), + validateLargeArchiveFiles: jest.fn(), renameFile: jest.fn(), promptToContinue: jest.fn().mockResolvedValue( true ), validateCustomDeployKey: jest.fn().mockResolvedValue( { @@ -96,6 +98,10 @@ describe( 'vip-app-deploy', () => { } ); describe( 'appDeployCmd', () => { + beforeEach( () => { + jest.clearAllMocks(); + } ); + it( 'should call expected functions', async () => { await appDeployCmd( args, opts ); @@ -103,9 +109,18 @@ describe( 'vip-app-deploy', () => { expect( validateFile ).toHaveBeenCalledTimes( 1 ); + expect( validateLargeArchiveFiles ).toHaveBeenCalledTimes( 1 ); + expect( promptToContinue ).not.toHaveBeenCalled(); expect( uploadImportFileToS3 ).toHaveBeenCalledTimes( 1 ); } ); + + it( 'skips large file verification when requested', async () => { + await appDeployCmd( args, { ...opts, skipLargeFileVerify: true } ); + + expect( validateFile ).toHaveBeenCalledTimes( 1 ); + expect( validateLargeArchiveFiles ).not.toHaveBeenCalled(); + } ); } ); } ); diff --git a/__tests__/lib/custom-deploy/custom-deploy.js b/__tests__/lib/custom-deploy/custom-deploy.js new file mode 100644 index 000000000..89140a27d --- /dev/null +++ b/__tests__/lib/custom-deploy/custom-deploy.js @@ -0,0 +1,83 @@ +import * as exit from '../../../src/lib/cli/exit'; +import { validateLargeArchiveFiles } from '../../../src/lib/custom-deploy/custom-deploy'; +import { trackEventWithEnv } from '../../../src/lib/tracker'; +import { findLargeArchiveFilesInDeployArchive } from '../../../src/lib/validations/custom-deploy'; + +jest.mock( '../../../src/lib/validations/custom-deploy', () => ( { + ...jest.requireActual( '../../../src/lib/validations/custom-deploy' ), + findLargeArchiveFilesInDeployArchive: jest.fn(), +} ) ); + +jest.mock( '../../../src/lib/tracker', () => ( { + trackEventWithEnv: jest.fn().mockResolvedValue( [] ), +} ) ); + +const exitSpy = jest.spyOn( exit, 'withError' ); +jest.spyOn( process, 'exit' ).mockImplementation( () => {} ); +jest.spyOn( console, 'error' ).mockImplementation( () => {} ); +jest.spyOn( console, 'log' ).mockImplementation( () => {} ); +const consoleWarnSpy = jest.spyOn( console, 'warn' ).mockImplementation( () => {} ); + +describe( 'custom deploy large archive file validation', () => { + beforeEach( () => { + jest.clearAllMocks(); + } ); + + it( 'passes when the deploy archive has no large archive files', async () => { + findLargeArchiveFilesInDeployArchive.mockResolvedValue( [] ); + + await validateLargeArchiveFiles( 123, 456, { + fileName: '/vip/skeleton.zip', + basename: 'skeleton.zip', + } ); + + expect( consoleWarnSpy ).not.toHaveBeenCalled(); + expect( exitSpy ).not.toHaveBeenCalled(); + expect( trackEventWithEnv ).not.toHaveBeenCalled(); + } ); + + it( 'warns and exits when the deploy archive has archive files over 50 MB', async () => { + findLargeArchiveFilesInDeployArchive.mockResolvedValue( [ + { + path: 'mysite/plugins/big-plugin.tar.gz', + size: 51 * 1024 * 1024, + }, + ] ); + + await validateLargeArchiveFiles( 123, 456, { + fileName: '/vip/skeleton.zip', + basename: 'skeleton.zip', + } ); + + expect( trackEventWithEnv ).toHaveBeenCalledWith( 123, 456, 'deploy_app_command_error', { + error_type: 'large-archive-files', + large_archive_files: [ 'mysite/plugins/big-plugin.tar.gz' ], + } ); + expect( consoleWarnSpy.mock.calls[ 0 ][ 0 ] ).toContain( + 'Found archive file(s) larger than 50.0 MB in the deploy archive' + ); + expect( consoleWarnSpy.mock.calls[ 0 ][ 0 ] ).toContain( + 'mysite/plugins/big-plugin.tar.gz (51.0 MB)' + ); + expect( consoleWarnSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-verify' ); + expect( exitSpy ).toHaveBeenCalledWith( 'Large archive file verification failed.' ); + } ); + + it( 'exits with skip instructions when large file verification fails', async () => { + findLargeArchiveFilesInDeployArchive.mockRejectedValue( new Error( 'invalid archive' ) ); + + await validateLargeArchiveFiles( 123, 456, { + fileName: '/vip/skeleton.zip', + basename: 'skeleton.zip', + } ); + + expect( trackEventWithEnv ).toHaveBeenCalledWith( 123, 456, 'deploy_app_command_error', { + error_type: 'large-archive-file-verify-failed', + verify_error: 'invalid archive', + } ); + expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( + 'Unable to verify large archive files in the deploy archive: invalid archive' + ); + expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-verify' ); + } ); +} ); diff --git a/src/bin/vip-app-deploy.ts b/src/bin/vip-app-deploy.ts index b333056c4..316ee0d91 100755 --- a/src/bin/vip-app-deploy.ts +++ b/src/bin/vip-app-deploy.ts @@ -23,7 +23,11 @@ import { WithId, UploadArguments, } from '../lib/client-file-uploader'; -import { validateCustomDeployKey, validateFile } from '../lib/custom-deploy/custom-deploy'; +import { + validateCustomDeployKey, + validateFile, + validateLargeArchiveFiles, +} from '../lib/custom-deploy/custom-deploy'; import { trackEventWithEnv } from '../lib/tracker'; const START_DEPLOY_MUTATION = gql` @@ -95,6 +99,10 @@ export async function appDeployCmd( arg: string[] = [], opts: Record< string, un debug( 'Validating file...' ); await validateFile( appId, envId, fileMeta ); + if ( ! opts.skipLargeFileVerify ) { + await validateLargeArchiveFiles( appId, envId, fileMeta ); + } + await track( 'deploy_app_command_execute' ); // Upload file as different name to avoid overwriting existing same named files @@ -269,6 +277,11 @@ const examples = [ description: 'Skip the confirmation prompt for the Custom Deployment of the archived file named "file.tar.gz" to the environment.', }, + { + usage: + 'WPVIP_DEPLOY_TOKEN=1234 vip @example-app.develop app deploy file.zip --skip-large-file-verify', + description: 'Skip checking the deploy archive for repository archive files larger than 50 MB.', + }, ]; void command( { @@ -279,6 +292,11 @@ void command( { .examples( examples ) .option( 'message', 'Add a description of a deployment.' ) .option( 'skip-confirmation', 'Skip the confirmation prompt.' ) + .option( + 'skip-large-file-verify', + 'Skip checking for repository archive files over 50 MB.', + false + ) .option( 'force', 'Skip confirmation prompt (deprecated)' ) .option( 'app', diff --git a/src/lib/custom-deploy/custom-deploy.ts b/src/lib/custom-deploy/custom-deploy.ts index 0911df15e..eb4886b33 100644 --- a/src/lib/custom-deploy/custom-deploy.ts +++ b/src/lib/custom-deploy/custom-deploy.ts @@ -1,3 +1,4 @@ +import chalk from 'chalk'; import fs from 'fs'; import gql from 'graphql-tag'; @@ -6,10 +7,18 @@ import * as exit from '../../lib/cli/exit'; import { checkFileAccess, getFileSize, isFile, FileMeta } from '../../lib/client-file-uploader'; import { GB_IN_BYTES } from '../../lib/constants/file-size'; import { trackEventWithEnv } from '../../lib/tracker'; -import { validateDeployFileExt, validateFilename } from '../../lib/validations/custom-deploy'; +import { + findLargeArchiveFilesInDeployArchive, + LARGE_ARCHIVE_FILE_SIZE_LIMIT, + validateDeployFileExt, + validateFilename, +} from '../../lib/validations/custom-deploy'; + +import type { LargeArchiveFile } from '../../lib/validations/custom-deploy'; const DEPLOY_MAX_FILE_SIZE = 4 * GB_IN_BYTES; const WPVIP_DEPLOY_TOKEN = process.env.WPVIP_DEPLOY_TOKEN; +const SKIP_LARGE_FILE_VERIFY_FLAG = '--skip-large-file-verify'; type CustomDeployInfo = { success: boolean; @@ -25,6 +34,22 @@ type ValidateMutationPayload = { validateCustomDeployAccess: CustomDeployInfo; }; +function formatFileSize( bytes: number ): string { + return `${ ( bytes / ( 1024 * 1024 ) ).toFixed( 1 ) } MB`; +} + +function getLargeArchiveFilesMessage( largeArchiveFiles: LargeArchiveFile[] ): string { + const fileList = largeArchiveFiles + .map( file => `- ${ file.path } (${ formatFileSize( file.size ) })` ) + .join( '\n' ); + + return `Found archive file(s) larger than ${ formatFileSize( + LARGE_ARCHIVE_FILE_SIZE_LIMIT + ) } in the deploy archive:\n${ fileList }\nRemove these files from the repository, or rerun with ${ chalk.bold( + SKIP_LARGE_FILE_VERIFY_FLAG + ) } to skip this check.`; +} + export async function validateCustomDeployKey( app: string | number, env: string | number @@ -127,3 +152,46 @@ export async function validateFile( appId: number, envId: number, fileMeta: File ); } } + +/** + * @param {number} appId + * @param {number} envId + * @param {FileMeta} fileMeta + */ +export async function validateLargeArchiveFiles( + appId: number, + envId: number, + fileMeta: FileMeta +) { + const track = trackEventWithEnv.bind( null, appId, envId ); + let largeArchiveFiles: LargeArchiveFile[]; + + try { + largeArchiveFiles = await findLargeArchiveFilesInDeployArchive( fileMeta.fileName ); + } catch ( error ) { + await track( 'deploy_app_command_error', { + error_type: 'large-archive-file-verify-failed', + verify_error: ( error as Error ).message, + } ); + + return exit.withError( + `Unable to verify large archive files in the deploy archive: ${ + ( error as Error ).message + }. Rerun with ${ SKIP_LARGE_FILE_VERIFY_FLAG } to skip this check.` + ); + } + + if ( ! largeArchiveFiles.length ) { + return; + } + + await track( 'deploy_app_command_error', { + error_type: 'large-archive-files', + large_archive_files: largeArchiveFiles.map( file => file.path ), + } ); + + console.warn( + `${ chalk.yellow( 'Warning:' ) } ${ getLargeArchiveFilesMessage( largeArchiveFiles ) }` + ); + return exit.withError( 'Large archive file verification failed.' ); +} diff --git a/src/lib/validations/custom-deploy.ts b/src/lib/validations/custom-deploy.ts index b65a64cc1..88bb34912 100644 --- a/src/lib/validations/custom-deploy.ts +++ b/src/lib/validations/custom-deploy.ts @@ -4,11 +4,18 @@ import path from 'path'; import * as tar from 'tar'; import * as exit from '../../lib/cli/exit'; +import { MB_IN_BYTES } from '../../lib/constants/file-size'; interface TarEntry { path: string; type: string; mode: number | undefined; + size?: number; +} + +export interface LargeArchiveFile { + path: string; + size: number; } const errorMessages = { @@ -21,6 +28,85 @@ const errorMessages = { }; const symlinkIgnorePattern = /\/node_modules\/[^/]+\/\.bin\//; const macosxDir = '__MACOSX'; +export const LARGE_ARCHIVE_FILE_SIZE_LIMIT = 50 * MB_IN_BYTES; + +function getDeployFileExt( filename: string ): string { + let ext = path.extname( filename ).toLowerCase(); + + if ( ext === '.gz' && path.extname( path.basename( filename, ext ) ) === '.tar' ) { + ext = '.tar.gz'; + } + + return ext; +} + +function isDeployArchiveFile( filename: string ): boolean { + return [ '.zip', '.tar.gz', '.tgz' ].includes( getDeployFileExt( filename ) ); +} + +async function findLargeArchiveFilesInZipArchive( + filePath: string +): Promise< LargeArchiveFile[] > { + const zipFile = new StreamZip.async( { file: filePath } ); + + try { + const zipEntries = await zipFile.entries(); + + return Object.values( zipEntries ) + .filter( + entry => + ! entry.isDirectory && + isDeployArchiveFile( entry.name ) && + entry.size > LARGE_ARCHIVE_FILE_SIZE_LIMIT + ) + .map( entry => ( { + path: entry.name, + size: entry.size, + } ) ); + } finally { + await zipFile.close(); + } +} + +async function findLargeArchiveFilesInTarArchive( + filePath: string +): Promise< LargeArchiveFile[] > { + const largeArchiveFiles: LargeArchiveFile[] = []; + + await tar.list( { + file: filePath, + onReadEntry: entry => { + if ( + entry.type === 'File' && + isDeployArchiveFile( entry.path ) && + entry.size > LARGE_ARCHIVE_FILE_SIZE_LIMIT + ) { + largeArchiveFiles.push( { + path: entry.path, + size: entry.size, + } ); + } + }, + } ); + + return largeArchiveFiles; +} + +export async function findLargeArchiveFilesInDeployArchive( + filePath: string +): Promise< LargeArchiveFile[] > { + const ext = getDeployFileExt( filePath ); + + if ( ext === '.zip' ) { + return findLargeArchiveFilesInZipArchive( filePath ); + } + + if ( ext === '.tar.gz' || ext === '.tgz' ) { + return findLargeArchiveFilesInTarArchive( filePath ); + } + + return []; +} /** * Check if a file has a valid extension @@ -29,11 +115,7 @@ const macosxDir = '__MACOSX'; * @returns {boolean} True if the extension is valid */ export function validateDeployFileExt( filename: string ): void { - let ext = path.extname( filename ).toLowerCase(); - - if ( ext === '.gz' && path.extname( path.basename( filename, ext ) ) === '.tar' ) { - ext = '.tar.gz'; - } + const ext = getDeployFileExt( filename ); if ( ! [ '.zip', '.tar.gz', '.tgz' ].includes( ext ) ) { exit.withError( errorMessages.invalidExt ); From b5c3ac03397fae4a21cefee34b87fafb57214bad Mon Sep 17 00:00:00 2001 From: Rebecca Hum Date: Thu, 18 Jun 2026 13:55:07 -0600 Subject: [PATCH 2/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/lib/validations/custom-deploy.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lib/validations/custom-deploy.ts b/src/lib/validations/custom-deploy.ts index 88bb34912..dfc9be537 100644 --- a/src/lib/validations/custom-deploy.ts +++ b/src/lib/validations/custom-deploy.ts @@ -31,13 +31,21 @@ const macosxDir = '__MACOSX'; export const LARGE_ARCHIVE_FILE_SIZE_LIMIT = 50 * MB_IN_BYTES; function getDeployFileExt( filename: string ): string { - let ext = path.extname( filename ).toLowerCase(); + const lower = filename.toLowerCase(); - if ( ext === '.gz' && path.extname( path.basename( filename, ext ) ) === '.tar' ) { - ext = '.tar.gz'; + if ( lower.endsWith( '.tar.gz' ) ) { + return '.tar.gz'; } - return ext; + if ( lower.endsWith( '.tgz' ) ) { + return '.tgz'; + } + + if ( lower.endsWith( '.zip' ) ) { + return '.zip'; + } + + return path.extname( lower ); } function isDeployArchiveFile( filename: string ): boolean { From 273d1b9d57339f37126fe297e420244eeae7aaa1 Mon Sep 17 00:00:00 2001 From: Rebecca Hum Date: Thu, 18 Jun 2026 13:58:23 -0600 Subject: [PATCH 3/5] Feedback --- __tests__/lib/custom-deploy/custom-deploy.js | 13 +++++-------- src/lib/custom-deploy/custom-deploy.ts | 7 ++----- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/__tests__/lib/custom-deploy/custom-deploy.js b/__tests__/lib/custom-deploy/custom-deploy.js index 89140a27d..6c019125c 100644 --- a/__tests__/lib/custom-deploy/custom-deploy.js +++ b/__tests__/lib/custom-deploy/custom-deploy.js @@ -16,7 +16,6 @@ const exitSpy = jest.spyOn( exit, 'withError' ); jest.spyOn( process, 'exit' ).mockImplementation( () => {} ); jest.spyOn( console, 'error' ).mockImplementation( () => {} ); jest.spyOn( console, 'log' ).mockImplementation( () => {} ); -const consoleWarnSpy = jest.spyOn( console, 'warn' ).mockImplementation( () => {} ); describe( 'custom deploy large archive file validation', () => { beforeEach( () => { @@ -31,12 +30,11 @@ describe( 'custom deploy large archive file validation', () => { basename: 'skeleton.zip', } ); - expect( consoleWarnSpy ).not.toHaveBeenCalled(); expect( exitSpy ).not.toHaveBeenCalled(); expect( trackEventWithEnv ).not.toHaveBeenCalled(); } ); - it( 'warns and exits when the deploy archive has archive files over 50 MB', async () => { + it( 'exits when the deploy archive has archive files over 50 MB', async () => { findLargeArchiveFilesInDeployArchive.mockResolvedValue( [ { path: 'mysite/plugins/big-plugin.tar.gz', @@ -53,14 +51,13 @@ describe( 'custom deploy large archive file validation', () => { error_type: 'large-archive-files', large_archive_files: [ 'mysite/plugins/big-plugin.tar.gz' ], } ); - expect( consoleWarnSpy.mock.calls[ 0 ][ 0 ] ).toContain( - 'Found archive file(s) larger than 50.0 MB in the deploy archive' + expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( + 'Deploy archive contains archive file(s) larger than 50.0 MB in the deploy archive' ); - expect( consoleWarnSpy.mock.calls[ 0 ][ 0 ] ).toContain( + expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( 'mysite/plugins/big-plugin.tar.gz (51.0 MB)' ); - expect( consoleWarnSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-verify' ); - expect( exitSpy ).toHaveBeenCalledWith( 'Large archive file verification failed.' ); + expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-verify' ); } ); it( 'exits with skip instructions when large file verification fails', async () => { diff --git a/src/lib/custom-deploy/custom-deploy.ts b/src/lib/custom-deploy/custom-deploy.ts index eb4886b33..7f6f66825 100644 --- a/src/lib/custom-deploy/custom-deploy.ts +++ b/src/lib/custom-deploy/custom-deploy.ts @@ -43,7 +43,7 @@ function getLargeArchiveFilesMessage( largeArchiveFiles: LargeArchiveFile[] ): s .map( file => `- ${ file.path } (${ formatFileSize( file.size ) })` ) .join( '\n' ); - return `Found archive file(s) larger than ${ formatFileSize( + return `Deploy archive contains archive file(s) larger than ${ formatFileSize( LARGE_ARCHIVE_FILE_SIZE_LIMIT ) } in the deploy archive:\n${ fileList }\nRemove these files from the repository, or rerun with ${ chalk.bold( SKIP_LARGE_FILE_VERIFY_FLAG @@ -190,8 +190,5 @@ export async function validateLargeArchiveFiles( large_archive_files: largeArchiveFiles.map( file => file.path ), } ); - console.warn( - `${ chalk.yellow( 'Warning:' ) } ${ getLargeArchiveFilesMessage( largeArchiveFiles ) }` - ); - return exit.withError( 'Large archive file verification failed.' ); + return exit.withError( getLargeArchiveFilesMessage( largeArchiveFiles ) ); } From 1b542fd96a8dbeab54ce134c08c9a5d3c5ac2989 Mon Sep 17 00:00:00 2001 From: Rebecca Hum Date: Thu, 18 Jun 2026 15:15:44 -0600 Subject: [PATCH 4/5] Change to 20MB --- __tests__/lib/custom-deploy/custom-deploy.js | 8 ++++---- src/bin/vip-app-deploy.ts | 4 ++-- src/lib/validations/custom-deploy.ts | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/__tests__/lib/custom-deploy/custom-deploy.js b/__tests__/lib/custom-deploy/custom-deploy.js index 6c019125c..9cf93b7c6 100644 --- a/__tests__/lib/custom-deploy/custom-deploy.js +++ b/__tests__/lib/custom-deploy/custom-deploy.js @@ -34,11 +34,11 @@ describe( 'custom deploy large archive file validation', () => { expect( trackEventWithEnv ).not.toHaveBeenCalled(); } ); - it( 'exits when the deploy archive has archive files over 50 MB', async () => { + it( 'exits when the deploy archive has archive files over 20 MB', async () => { findLargeArchiveFilesInDeployArchive.mockResolvedValue( [ { path: 'mysite/plugins/big-plugin.tar.gz', - size: 51 * 1024 * 1024, + size: 21 * 1024 * 1024, }, ] ); @@ -52,10 +52,10 @@ describe( 'custom deploy large archive file validation', () => { large_archive_files: [ 'mysite/plugins/big-plugin.tar.gz' ], } ); expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( - 'Deploy archive contains archive file(s) larger than 50.0 MB in the deploy archive' + 'Deploy archive contains archive file(s) larger than 20.0 MB in the deploy archive' ); expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( - 'mysite/plugins/big-plugin.tar.gz (51.0 MB)' + 'mysite/plugins/big-plugin.tar.gz (21.0 MB)' ); expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-verify' ); } ); diff --git a/src/bin/vip-app-deploy.ts b/src/bin/vip-app-deploy.ts index 316ee0d91..f3d58be1d 100755 --- a/src/bin/vip-app-deploy.ts +++ b/src/bin/vip-app-deploy.ts @@ -280,7 +280,7 @@ const examples = [ { usage: 'WPVIP_DEPLOY_TOKEN=1234 vip @example-app.develop app deploy file.zip --skip-large-file-verify', - description: 'Skip checking the deploy archive for repository archive files larger than 50 MB.', + description: 'Skip checking the deploy archive for repository archive files larger than 20 MB.', }, ]; @@ -294,7 +294,7 @@ void command( { .option( 'skip-confirmation', 'Skip the confirmation prompt.' ) .option( 'skip-large-file-verify', - 'Skip checking for repository archive files over 50 MB.', + 'Skip checking for repository archive files over 20 MB.', false ) .option( 'force', 'Skip confirmation prompt (deprecated)' ) diff --git a/src/lib/validations/custom-deploy.ts b/src/lib/validations/custom-deploy.ts index dfc9be537..e532a1e0f 100644 --- a/src/lib/validations/custom-deploy.ts +++ b/src/lib/validations/custom-deploy.ts @@ -28,7 +28,7 @@ const errorMessages = { }; const symlinkIgnorePattern = /\/node_modules\/[^/]+\/\.bin\//; const macosxDir = '__MACOSX'; -export const LARGE_ARCHIVE_FILE_SIZE_LIMIT = 50 * MB_IN_BYTES; +export const LARGE_ARCHIVE_FILE_SIZE_LIMIT = 20 * MB_IN_BYTES; function getDeployFileExt( filename: string ): string { const lower = filename.toLowerCase(); From 375147c8e108f2922b6ff7bb22f9ad89bb7c9d9e Mon Sep 17 00:00:00 2001 From: Rebecca Hum Date: Thu, 18 Jun 2026 15:50:52 -0600 Subject: [PATCH 5/5] Update per feedback --- __tests__/bin/vip-app-deploy.js | 2 +- __tests__/lib/custom-deploy/custom-deploy.js | 4 ++-- src/bin/vip-app-deploy.ts | 6 +++--- src/lib/custom-deploy/custom-deploy.ts | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/__tests__/bin/vip-app-deploy.js b/__tests__/bin/vip-app-deploy.js index 723f4f390..fdd81b661 100644 --- a/__tests__/bin/vip-app-deploy.js +++ b/__tests__/bin/vip-app-deploy.js @@ -117,7 +117,7 @@ describe( 'vip-app-deploy', () => { } ); it( 'skips large file verification when requested', async () => { - await appDeployCmd( args, { ...opts, skipLargeFileVerify: true } ); + await appDeployCmd( args, { ...opts, skipLargeFileValidation: true } ); expect( validateFile ).toHaveBeenCalledTimes( 1 ); expect( validateLargeArchiveFiles ).not.toHaveBeenCalled(); diff --git a/__tests__/lib/custom-deploy/custom-deploy.js b/__tests__/lib/custom-deploy/custom-deploy.js index 9cf93b7c6..83d4337e9 100644 --- a/__tests__/lib/custom-deploy/custom-deploy.js +++ b/__tests__/lib/custom-deploy/custom-deploy.js @@ -57,7 +57,7 @@ describe( 'custom deploy large archive file validation', () => { expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( 'mysite/plugins/big-plugin.tar.gz (21.0 MB)' ); - expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-verify' ); + expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-validation' ); } ); it( 'exits with skip instructions when large file verification fails', async () => { @@ -75,6 +75,6 @@ describe( 'custom deploy large archive file validation', () => { expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( 'Unable to verify large archive files in the deploy archive: invalid archive' ); - expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-verify' ); + expect( exitSpy.mock.calls[ 0 ][ 0 ] ).toContain( '--skip-large-file-validation' ); } ); } ); diff --git a/src/bin/vip-app-deploy.ts b/src/bin/vip-app-deploy.ts index f3d58be1d..93f3ea512 100755 --- a/src/bin/vip-app-deploy.ts +++ b/src/bin/vip-app-deploy.ts @@ -99,7 +99,7 @@ export async function appDeployCmd( arg: string[] = [], opts: Record< string, un debug( 'Validating file...' ); await validateFile( appId, envId, fileMeta ); - if ( ! opts.skipLargeFileVerify ) { + if ( ! opts.skipLargeFileValidation ) { await validateLargeArchiveFiles( appId, envId, fileMeta ); } @@ -279,7 +279,7 @@ const examples = [ }, { usage: - 'WPVIP_DEPLOY_TOKEN=1234 vip @example-app.develop app deploy file.zip --skip-large-file-verify', + 'WPVIP_DEPLOY_TOKEN=1234 vip @example-app.develop app deploy file.zip --skip-large-file-validation', description: 'Skip checking the deploy archive for repository archive files larger than 20 MB.', }, ]; @@ -293,7 +293,7 @@ void command( { .option( 'message', 'Add a description of a deployment.' ) .option( 'skip-confirmation', 'Skip the confirmation prompt.' ) .option( - 'skip-large-file-verify', + 'skip-large-file-validation', 'Skip checking for repository archive files over 20 MB.', false ) diff --git a/src/lib/custom-deploy/custom-deploy.ts b/src/lib/custom-deploy/custom-deploy.ts index 7f6f66825..b15cc1dbc 100644 --- a/src/lib/custom-deploy/custom-deploy.ts +++ b/src/lib/custom-deploy/custom-deploy.ts @@ -18,7 +18,7 @@ import type { LargeArchiveFile } from '../../lib/validations/custom-deploy'; const DEPLOY_MAX_FILE_SIZE = 4 * GB_IN_BYTES; const WPVIP_DEPLOY_TOKEN = process.env.WPVIP_DEPLOY_TOKEN; -const SKIP_LARGE_FILE_VERIFY_FLAG = '--skip-large-file-verify'; +const SKIP_LARGE_FILE_VALIDATION_FLAG = '--skip-large-file-validation'; type CustomDeployInfo = { success: boolean; @@ -46,7 +46,7 @@ function getLargeArchiveFilesMessage( largeArchiveFiles: LargeArchiveFile[] ): s return `Deploy archive contains archive file(s) larger than ${ formatFileSize( LARGE_ARCHIVE_FILE_SIZE_LIMIT ) } in the deploy archive:\n${ fileList }\nRemove these files from the repository, or rerun with ${ chalk.bold( - SKIP_LARGE_FILE_VERIFY_FLAG + SKIP_LARGE_FILE_VALIDATION_FLAG ) } to skip this check.`; } @@ -177,7 +177,7 @@ export async function validateLargeArchiveFiles( return exit.withError( `Unable to verify large archive files in the deploy archive: ${ ( error as Error ).message - }. Rerun with ${ SKIP_LARGE_FILE_VERIFY_FLAG } to skip this check.` + }. Rerun with ${ SKIP_LARGE_FILE_VALIDATION_FLAG } to skip this check.` ); }