Files
cypress/scripts/binary/zip.coffee
Gleb Bahmutov abf4d85869 switch to electron-builder to code sign and notarize Cypress ap… (#6013)
* electron@7.x

* node12.8.1-chrome78-ff70

* Revert "node12.8.1-chrome78-ff70" for now

This reverts commit db2d521994.

* update sendCommand to log on all sendcommands

* promisification in 6.x

* Revert "Revert "node12.8.1-chrome78-ff70" for now"

This reverts commit 57fe764098.

* fix sendcommand

* fix cdp in electron

* fix desktop-gui test

* skip tests that will be fixed by #4973

* bump MAX_ALLOWED_FILE_SIZE :/

* update electron browser spec

* make new dialog code null-proof

* add failing e2e test for issue 5475

* bump electron packager

* add e2e snapshot

* update deprecated electron getters/setters

https://github.com/electron/electron/blob/7-1-x/docs/api/modernization/property-updates.md

* build and test on Mac

* use electron-builder 20.41.0

that adds an option to use hardened Mac OS, which is necessary
for code notarization later.

See https://github.com/electron-userland/electron-builder/releases/tag/v20.41.0
and https://github.com/electron-userland/electron-builder/pull/3858

* electron-builder and pass hardenedRuntime: true

* uncomment build

* upload built binary on mac

* back to 20.41.0, trying after sign hook without success

* use current electron-builder alias instead of build

* retry smoke test on first failure

* testing

* trying to notarize signed app (that does not have node_modules yet)

* env variable names

* copy node_modules ourselves

* build and bundle binary on mac on circle, inject new context

* enable build steps before electron build

* increase mac build timeout

* update build folder on mac

* uncomment actual electron build command

* set linux target to zip

* set zip as target for all platforms

* updated steps

* put notarization hook back

* tweaks for icons

* remove dist electron before code sign

* icons per platform

* make node_modules copy path platform-specific

* fix linux build unpacked folder

* build mac

* fix lint

* test new mac binary against kitchensink

* working on Linux build

* try building entire thing on Linux

* removing correct electron dist folder

* increase zip size limit for now

* add folder rename on Linux from linux-unpacked to Cypress

* print file sizes before zipping

* move linux-unpacked to build dir function

* try deleting second electron file, but code signing probably would not work

* test windows build [build binary]

* ignore tsc errors

* windows build path

* windows [build binary]

* update windows build folder

* increase binary build timeout on Mac

* no need to pass our dist folder

* adding explicit list of additional binaries to code sign on mac

* yarn lock

* uncomment necessary build steps

* electron dir for Linux

* yarn lock again

* back to execa v3

* use execa v4 in packages launcher

* yarn lock again and again

* updated tests that use execa

* print build folder

* add executable name on Linux

* get rid of execa.shell in build scripts

* remove old and commented out code

* need to test building binary on Windows

* throw error from after sign hook if fails

* use execa to zip

* yarn lock

* fix after merge variable

* update test

* add nohoist ffmpeg installer

* patch

* yarn types pass

* yarn lock has binary

Co-authored-by: Zach Bloomquist <github@chary.us>
Co-authored-by: Brian Mann <brian.mann86@gmail.com>
2020-03-24 21:34:52 -04:00

172 lines
4.8 KiB
CoffeeScript

Promise = require("bluebird")
os = require("os")
execa = require("execa")
path = require("path")
la = require("lazy-ass")
fs = require("fs")
R = require("ramda")
filesize = require("filesize")
# prints disk usage numbers using "du" utility
# available on Linux and Mac
printFileSizes = (folder) ->
console.log("File sizes in #{folder}")
paths = path.join(folder, "*")
options = {
stdio: "inherit",
shell: true
}
execa("du -hs #{paths}", options)
# resolves with zipped filename
macZip = (src, dest) ->
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/
# ...
zip = "ditto -c -k --sequesterRsrc --keepParent #{src} #{dest}"
options = {
stdio: "inherit",
shell: true
}
console.log(zip)
onZipFinished = () ->
console.log("✅ ditto finished")
onError = (err) ->
console.error("⛔️ could not zip #{src} into #{dest}")
console.error(err.message)
throw err
execa(zip, options)
.then onZipFinished
.then R.always(dest)
.catch onError
megaBytes = (bytes) ->
1024 * 1024 * bytes
checkZipSize = (zipPath) ->
stats = fs.statSync(zipPath)
zipSize = filesize(stats.size, {round: 0})
console.log("zip file size #{zipSize}")
MAX_ALLOWED_SIZE_MB = if os.platform() == "win32" then 245 else 170
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")
linuxZipAction = (parentFolder, dest, relativeSource) ->
console.log("zipping #{parentFolder}")
cmd = "cd #{parentFolder} && zip -r9 #{dest} #{relativeSource}"
console.log("linux zip: #{cmd}")
onZipFinished = () ->
console.log("✅ zip finished")
onError = (err) ->
console.error("⛔️ could not zip #{relativeSource} in folder #{parentFolder}")
console.error("to produce #{dest}")
console.error(err.message)
throw err
execa(cmd, {shell: true})
.then onZipFinished
.then R.always(dest)
.then R.tap(checkZipSize)
.catch onError
# src is built folder with packed Cypress application
# like /root/app/build/linux-unpacked
# and we want to always have /root/app/build/Cypress
renameFolder = (src) ->
parentFolder = path.dirname(src)
folderName = path.basename(src)
if folderName is "Cypress"
console.log("nothing to rename, folder ends with Cypress")
return Promise.resolve(src)
renamed = path.join(parentFolder, "Cypress")
console.log("renaming #{src} to #{renamed}")
fs.promises.rename(src, renamed)
.then R.always(renamed)
# resolves with zipped filename
linuxZip = (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
renameFolder(src)
.then (renamedSource) ->
printFileSizes(renamedSource)
.then R.always(renamedSource)
.then (renamedSource) ->
console.log("will zip folder #{renamedSource}")
parentFolder = path.dirname(renamedSource)
relativeSource = path.basename(renamedSource)
linuxZipAction(parentFolder, dest, relativeSource)
# resolves with zipped filename
windowsZip = (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
cmd = "7z a #{dest} #{src}"
console.log("windows zip: #{cmd}")
onZipFinished = () ->
console.log("✅ 7z finished")
onError = (err) ->
console.error("⛔️ could not zip #{src} into #{dest}")
console.error(err.message)
throw err
execa(cmd, {shell: true})
.then onZipFinished
.then R.always(dest)
.then R.tap(checkZipSize)
.catch onError
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) ->
platform = os.platform()
console.log("#zip", platform)
console.log("Zipping %s into %s", src, dest)
zipper = zippers[platform]
if !zipper
throw new Error("Missing zip function for platform #{platform}")
zipper(src, dest)
checkZipSize
}