Files
cypress/scripts/binary/zip.js
renovate[bot] 8db1b236e2 chore(deps): update dependency filesize to v10 (#29379)
* chore(deps): update dependency filesize to v10

* empty commit

* update filesize require

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jennifer Shehane <jennifer@cypress.io>
2024-04-23 12:22:34 -04:00

224 lines
5.8 KiB
JavaScript

const Promise = require('bluebird')
const os = require('os')
const execa = require('execa')
const path = require('path')
const la = require('lazy-ass')
const fs = require('fs')
const { filesize } = require('filesize')
// prints disk usage numbers using "du" utility
// available on Linux and Mac
const printFileSizes = function (folder) {
console.log(`File sizes in ${folder}`)
const paths = path.join(folder, '*')
const options = {
stdio: 'inherit',
shell: true,
}
return execa(`du -hs ${paths}`, options)
}
// resolves with zipped filename
const macZip = (src, dest) => {
return printFileSizes(src)
.then(() => {
if (os.platform() !== 'darwin') {
throw new Error('Can only zip on Mac platform')
}
// Ditto (Mac) options
// http://www.unix.com/man-page/OSX/1/ditto/
// -c create archive
// -k set archive format to PKZip
// --sequesterRsrc When creating a PKZip archive, preserve resource
// forks and HFS meta-data in the subdirectory __MACOSX
// --keepParent when zipping folder "foo", makes the folder
// the top level in the archive
// foo.zip
// foo/
// ...
const zip = `ditto -c -k --sequesterRsrc --keepParent ${src} ${dest}`
const options = {
stdio: 'inherit',
shell: true,
}
console.log(zip)
const onZipFinished = () => {
return console.log('✅ ditto finished')
}
const onError = function (err) {
console.error(`⛔️ could not zip ${src} into ${dest}`)
console.error(err.message)
throw err
}
return execa(zip, options)
.then(onZipFinished)
.then(() => dest)
.catch(onError)
})
}
const megaBytes = (bytes) => {
return 1024 * 1024 * bytes
}
const checkZipSize = function (zipPath) {
const stats = fs.statSync(zipPath)
const zipSize = filesize(stats.size, { round: 0 })
console.log(`zip file size ${zipSize}`)
// Before you modify these max sizes, check and see what you did that might have
// done to increase the size of the binary, and if you do need to change it,
// call it out in the PR description / comments
const MAX_ALLOWED_SIZE_MB = os.platform() === 'win32' ? 295 : 200
const MAX_ZIP_FILE_SIZE = megaBytes(MAX_ALLOWED_SIZE_MB)
if (stats.size > MAX_ZIP_FILE_SIZE) {
throw new Error(`Zip file is too large: ${zipSize} (${stats.size} bytes) exceeds ${MAX_ZIP_FILE_SIZE} bytes`)
}
}
const linuxZipAction = function (parentFolder, dest, relativeSource) {
console.log(`zipping ${parentFolder}`)
const cmd = `cd ${parentFolder} && zip -r9 ${dest} ${relativeSource}`
console.log(`linux zip: ${cmd}`)
const onZipFinished = () => {
return console.log('✅ zip finished')
}
const onError = function (err) {
console.error(`⛔️ could not zip ${relativeSource} in folder ${parentFolder}`)
console.error(`to produce ${dest}`)
console.error(err.message)
throw err
}
return execa(cmd, { shell: true })
.then(onZipFinished)
.then(() => dest)
.then((val) => {
checkZipSize(val)
return val
})
.catch(onError)
}
// src is built folder with packed Cypress application
// like /root/app/build/linux-unpacked or build/win-unpacked
// and we want to always have /root/app/build/Cypress
const renameFolder = function (src) {
const parentFolder = path.dirname(src)
const folderName = path.basename(src)
if (folderName === 'Cypress') {
console.log('nothing to rename, folder "%s" ends with Cypress', src)
return Promise.resolve(src)
}
const renamed = path.join(parentFolder, 'Cypress')
console.log(`renaming ${src} to ${renamed}`)
return fs.promises.rename(src, renamed)
.then(() => renamed)
}
// resolves with zipped filename
const linuxZip = function (src, dest) {
// in Linux switch to the folder containing source folder
la(path.isAbsolute(src), 'source path should be absolute', src)
la(path.isAbsolute(dest), 'destination path should be absolute', dest)
// on Linux, make sure the folder name is "Cypress" first
return renameFolder(src)
.then((renamedSource) => {
return printFileSizes(renamedSource)
.then(() => renamedSource)
}).then((renamedSource) => {
console.log(`will zip folder ${renamedSource}`)
const parentFolder = path.dirname(renamedSource)
const relativeSource = path.basename(renamedSource)
return linuxZipAction(parentFolder, dest, relativeSource)
})
}
// resolves with zipped filename
const windowsZipAction = function (src, dest) {
// use 7Zip to zip
// http://www.7-zip.org/
// zips entire source directory including top level folder name
// Cypress/
// foo.txt
// creates cypress.zip for example
// unzip cypress.zip to get back the folder
// Cypress/
// foo.txt
const cmd = `7z a ${dest} ${src}`
console.log(`windows zip: ${cmd}`)
const onZipFinished = () => {
return console.log('✅ 7z finished')
}
const onError = function (err) {
console.error(`⛔️ could not zip ${src} into ${dest}`)
console.error(err.message)
throw err
}
return execa(cmd, { shell: true })
.then(onZipFinished)
.then(() => dest)
.then((val) => {
checkZipSize(val)
return val
})
.catch(onError)
}
const windowsZip = (src, dest) => {
return renameFolder(src)
.then((renamedSource) => {
return windowsZipAction(renamedSource, dest)
})
}
const zippers = {
linux: linuxZip,
darwin: macZip,
win32: windowsZip,
}
module.exports = {
// zip Cypress folder to create destination zip file
// uses tool depending on the platform
ditto (src, dest) {
const platform = os.platform()
console.log('#zip', platform)
console.log('Zipping %s into %s', src, dest)
const zipper = zippers[platform]
if (!zipper) {
throw new Error(`Missing zip function for platform ${platform}`)
}
return zipper(src, dest)
},
checkZipSize,
}