Only package Windows builds of ffmpeg with Windows, build for win32 and win64 (#3877)

* appveyor build for this branch

* don't force install ffmpeg on windows

don't force install ffmpeg on windows

* derp

* fix

* build in appveyor

* oops

* delete using del

* use RMDIR instead of DEL

* only build 32-bit

* build for x64 and x86 windows

* separate win32 and win64

* require lodash

* make electron arch configurable

* cross-compile 32, only run in 64-bit

* force install ffmpeg if necessary

* it's all win10 x64, but we can force it to build for ia32 in x32 mode

* add windows util

* who's idea was it to make whitespace meaningful?

* pass arch to npm install, pass arch to uploader

* add TARGET_PLATFORM

* fun fact: appveyor titlecases env var names

fun fact: appveyor titlecases env var names

* fix: pass args

* use process

* cli: use arch package to send arch to server

* pass TARGET_ARCH to all npm installs

* run-all

* always call getUploadNameByOs

* use the precise version of node, enable both x64 and ia32 arch

* quotes

* uh wat

* move console logs to script because windows

* add yet another env var to install the right node arch

* use x86, not x32

* give ia32 a try, why not

* use platform env again

* and also try x86 again

* remove notion of target_arch since we're using the right node version with arch set correctly

* more comprehensive checks to ensure the arch is correct

* simplify building the binary, do not accept arch as options

* build the binary and test it on this branch

* remove arch, ensure that process.env.Platform is set to x86

* do build the binary unless this is a forked PR

* attempt to verify that this is a 32bit or 64bit windows binary

* remove unused dep

* consolidate commands

* don't install packages in windows - just build the binary

- this avoids needing to reinstall all node_modules and build-js twice

* build the binary on more branches

* cd up appveyor

* ugh

* right logic for whether or not this is a forked PR

* remove unused deps

* fix undefined var

* platformArch

* set in options

* turns out we do have to npm install before building the binary

* options.platformArch

* comment out appveyor build 32bit/64bit verification temporarily


Co-authored-by: Brian Mann <brian.mann86@gmail.com>
This commit is contained in:
Zach Bloomquist
2019-04-08 11:48:14 -04:00
committed by Brian Mann
parent ae97c7ceb4
commit db752f5f93
15 changed files with 172 additions and 65 deletions
+11 -3
View File
@@ -3,11 +3,12 @@ branches:
- master
- develop
- /win*/
- issue-716-ffmpeg-packaging
# https://www.appveyor.com/docs/lang/nodejs-iojs/
environment:
# use latest version of Node 8 with NPM 6
nodejs_version: "8"
nodejs_version: "8.2.1"
# encode secure variables which will NOT be used
# in pull requests
# https://www.appveyor.com/docs/build-configuration/#secure-variables
@@ -23,6 +24,10 @@ environment:
CF_TOKEN:
secure: d8SQfJ2r6qrKDjYWoFg3AzgY7aL6hTuE5OIlRr0TXkcXkZzdmYCujfzIYcCQfpZg
platform:
- x64
- x86
# https://www.appveyor.com/docs/build-cache/
# hmm, seems there is NPM on windows problem
# with installing over cached folder
@@ -33,12 +38,14 @@ environment:
# Install scripts. (runs after repo cloning)
install:
- ps: Install-Product node $env:nodejs_version
- npm run check-node-version
- ps: Install-Product node $env:nodejs_version $env:platform
- npm install -g @bahmutov/print-env
# Output useful info for debugging.
- node --version
- node --print process.arch
- npm --version
- print-env Platform
- npm run check-node-version
- print-env APPVEYOR
# clean cache to prevent install permission issues
- npm cache clean --force
@@ -72,6 +79,7 @@ test_script:
- echo Building Windows NPM package %NEXT_DEV_VERSION%
- npm --no-git-tag-version version %NEXT_DEV_VERSION%
- cd cli
- npm install
- npm run build
- cd build
- npm pack
+6 -1
View File
@@ -773,6 +773,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-716-ffmpeg-packaging
requires:
- build
- test-kitchensink-against-staging:
@@ -787,6 +788,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-716-ffmpeg-packaging
requires:
- build
- build-binary:
@@ -794,6 +796,7 @@ linux-workflow: &linux-workflow
branches:
only:
- develop
- issue-716-ffmpeg-packaging
requires:
- build
- test-next-version:
@@ -849,6 +852,7 @@ mac-workflow: &mac-workflow
branches:
only:
- develop
- issue-716-ffmpeg-packaging
requires:
- Mac build
@@ -860,7 +864,7 @@ mac-workflow: &mac-workflow
branches:
only:
- develop
- fix-typescript-binary-building
- issue-716-ffmpeg-packaging
requires:
- Mac build
@@ -882,6 +886,7 @@ mac-workflow: &mac-workflow
branches:
only:
- develop
- issue-716-ffmpeg-packaging
requires:
- Mac NPM package
- Mac binary
+16 -1
View File
@@ -1,3 +1,4 @@
const arch = require('arch')
const la = require('lazy-ass')
const is = require('check-more-types')
const os = require('os')
@@ -15,6 +16,20 @@ const util = require('../util')
const defaultBaseUrl = 'https://download.cypress.io/'
const getRealOsArch = () => {
// os.arch() returns the arch for which this node was compiled
// we want the operating system's arch instead: x64 or x86
const osArch = arch()
if (osArch === 'x86') {
// match process.platform output
return 'ia32'
}
return osArch
}
const getBaseUrl = () => {
if (util.getEnv('CYPRESS_DOWNLOAD_MIRROR')) {
let baseUrl = util.getEnv('CYPRESS_DOWNLOAD_MIRROR')
@@ -32,7 +47,7 @@ const getBaseUrl = () => {
const prepend = (urlPath) => {
const endpoint = url.resolve(getBaseUrl(), urlPath)
const platform = os.platform()
const arch = os.arch()
const arch = getRealOsArch()
return `${endpoint}?platform=${platform}&arch=${arch}`
}
+1
View File
@@ -41,6 +41,7 @@
"dependencies": {
"@cypress/listr-verbose-renderer": "0.4.1",
"@cypress/xvfb": "1.2.4",
"arch": "2.1.1",
"bluebird": "3.5.0",
"cachedir": "1.3.0",
"chalk": "2.4.2",
+1 -1
View File
@@ -64,7 +64,7 @@ module.exports = {
out: "tmp"
name: "Cypress"
platform: os.platform()
arch: "x64"
arch: os.arch()
asar: false
prune: true
overwrite: true
@@ -1,7 +1,5 @@
path = require("path")
fs = require("fs-extra")
Promise = require("bluebird")
request = require("request-promise")
path = require("path")
root = path.join(__dirname, "..", "..", "..")
projects = path.join(root, "test", "support", "fixtures", "projects")
+1 -11
View File
@@ -116,17 +116,7 @@ buildCypressApp = (platform, version, options = {}) ->
npmInstallPackages = ->
log("#npmInstallPackages")
packages.npmInstallAll(distDir("packages", "*"))
.then () ->
if os.platform() != "win32"
return
# on windows include both versions of FFMPEG
console.log("installing FFMPEG win32-x64")
serverFolder = distDir("packages", "server")
packages.forceNpmInstall(serverFolder, "@ffmpeg-installer/win32-x64")
.then () ->
console.log("installing FFMPEG win32-ia32")
packages.forceNpmInstall(serverFolder, "@ffmpeg-installer/win32-ia32")
packages.npmInstallAll(distDir("packages", "*"), options)
createRootPackage = ->
log("#createRootPackage #{platform} #{version}")
+5 -2
View File
@@ -165,7 +165,10 @@ deploy = {
# upload Cypress binary ZIP file
upload: (options) ->
console.log('#upload')
if !options then options = @parseOptions(process.argv)
if not options
options = @parseOptions(process.argv)
askMissingOptions(['version', 'platform', 'zip'])(options)
.then (options) ->
la(check.unemptyString(options.zip),
@@ -180,7 +183,7 @@ deploy = {
upload.toS3({
zipFile: options.zip,
version: options.version,
platform: options.platform
platform: options.platform,
})
# purge all platforms of a desktop app for specific version
+6 -6
View File
@@ -32,9 +32,9 @@ getCDN = ({version, hash, filename, platform}) ->
getUploadDirName = (options) ->
la(check.unemptyString(options.version), 'missing version', options)
la(check.unemptyString(options.hash), 'missing hash', options)
la(check.unemptyString(options.platform), 'missing platform', options)
la(check.unemptyString(options.platformArch), 'missing platformArch', options)
dir = [rootFolder, folder, options.version, options.platform, options.hash, null].join("/")
dir = [rootFolder, folder, options.version, options.platformArch, options.hash, null].join("/")
dir
uploadFile = (options) ->
@@ -42,7 +42,6 @@ uploadFile = (options) ->
publisher = uploadUtils.getPublisher()
headers = {}
# TODO: should cache it!
headers["Cache-Control"] = "no-cache"
gulp.src(options.file)
@@ -84,8 +83,9 @@ uploadUniqueBinary = (args = []) ->
la(fs.existsSync(options.file), "cannot find file", options.file)
if not options.platform
options.platform = uploadUtils.getUploadNameByOs()
platform = options.platform ? process.platform
options.platformArch = uploadUtils.getUploadNameByOsAndArch(platform)
uploadFile(options)
.then () ->
@@ -93,7 +93,7 @@ uploadUniqueBinary = (args = []) ->
version: options.version,
hash: options.hash,
filename: uploadFileName
platform: options.platform
platform: options.platformArch
})
console.log("Binary can be downloaded using URL")
console.log(cdnUrl)
+6 -3
View File
@@ -33,8 +33,8 @@ module.exports = {
# something like desktop/0.20.1/osx64/
getUploadDirName: ({version, platform}) ->
aws = @getAwsObj()
osName = uploadUtils.getUploadNameByOs(platform)
dirName = [aws.folder, version, osName, null].join("/")
platformArch = uploadUtils.getUploadNameByOsAndArch(platform)
dirName = [aws.folder, version, platformArch, null].join("/")
console.log("target directory %s", dirName)
dirName
@@ -57,7 +57,8 @@ module.exports = {
## start adding the new ones
## using node's platform
darwin: getUrl("osx64")
win32: getUrl("win64")
win32: getUrl("win32")
win64: getUrl("win64")
linux: getUrl("linux64")
}
}
@@ -94,6 +95,7 @@ module.exports = {
toS3: ({zipFile, version, platform}) ->
console.log("#uploadToS3 ⏳")
la(check.unemptyString(version), "expected version string", version)
la(check.unemptyString(zipFile), "expected zip filename", zipFile)
la(check.extension("zip", zipFile),
@@ -101,6 +103,7 @@ module.exports = {
la(meta.isValidPlatform(platform), "invalid platform", platform)
console.log("zip filename #{zipFile}")
if !fs.existsSync(zipFile)
throw new Error("Cannot find zip file #{zipFile}")
+1
View File
@@ -130,6 +130,7 @@ npmInstallAll = (pathToPackages) ->
# force installing only PRODUCTION dependencies
# https://docs.npmjs.com/cli/install
npmInstall = _.partial(npmRun, ["install", "--only=production", "--quiet"])
npmInstall(pkg, {NODE_ENV: "production"})
.catch {code: "EMFILE"}, ->
Promise
+19 -8
View File
@@ -1,3 +1,4 @@
_ = require("lodash")
path = require("path")
awspublish = require('gulp-awspublish')
human = require("human-interval")
@@ -100,7 +101,7 @@ purgeDesktopAppFromCache = ({version, platform, zipName}) ->
la(check.extension("zip", zipName),
"zip filename should end with .zip", zipName)
osName = getUploadNameByOs(platform)
osName = getUploadNameByOsAndArch(platform)
la(check.unemptyString(osName), "missing osName", osName)
url = getDestktopUrl(version, osName, zipName)
purgeCache(url)
@@ -116,15 +117,25 @@ purgeDesktopAppAllPlatforms = (version, zipName) ->
Promise.mapSeries platforms, (platform) ->
purgeDesktopAppFromCache({version, platform, zipName})
getUploadNameByOs = (osName = os.platform()) ->
getUploadNameByOsAndArch = (platform) ->
## just hard code for now...
arch = os.arch()
uploadNames = {
darwin: "osx64"
linux: "linux64"
win32: "win64"
darwin: {
"x64": "osx64"
},
linux: {
"x64": "linux64"
},
win32: {
"x64": "win64",
"ia32": "win32"
}
}
name = uploadNames[osName]
name = _.get(uploadNames[platform], arch)
if not name
throw new Error("Cannot find upload name for OS #{osName}")
throw new Error("Cannot find upload name for OS: '#{platform}' with arch: '#{arch}'")
name
saveUrl = (filename) -> (url) ->
@@ -141,7 +152,7 @@ module.exports = {
purgeCache,
purgeDesktopAppFromCache,
purgeDesktopAppAllPlatforms,
getUploadNameByOs,
getUploadNameByOsAndArch,
saveUrl,
formHashFromEnvironment
}
+62 -21
View File
@@ -1,34 +1,75 @@
const os = require('os')
const assert = require('assert')
// TODO make this check a 3rd party little tool
// on CircleCI Mac machine, we need to use on of the laer executors
// that already has Node 10 / 11
const isMac = () => {
return process.platform === 'darwin'
return os.platform() === 'darwin'
}
if (isMac()) {
const isWindows = () => {
return os.platform() === 'win32'
}
if (isMac() && process.env.CIRCLECI) {
// eslint-disable-next-line no-console
console.log('Skipping Node version check on Mac')
} else {
// we want to ensure we are building using the same major version
// as the one specified in ../.node-version file
const read = require('fs').readFileSync
const join = require('path').join
console.log('Skipping Node version check on CircleCI Mac')
const nodeVersionNeededString = read(
join(__dirname, '..', '.node-version'),
'utf8'
)
const nodeVersionNeeded = nodeVersionNeededString.split('.')
return
}
const nodeVersion = process.versions.node.split('.')
// if we're windows + in appveyor...
if (isWindows() && process.env.APPVEYOR) {
// check to ensure that the cpuArch + nodeArch are in sync
const cpuArch = process.env.Platform
const nodeArch = os.arch()
// check just major version for now
if (nodeVersionNeeded[0] !== nodeVersion[0]) {
/* eslint-disable no-console */
console.error('🛑 .node-version specified %s', nodeVersionNeededString)
console.error('but current Node is %s', process.versions.node)
/* eslint-enable no-console */
process.exit(1)
const getErrMsg = (expectedArch) => {
return `Appveyor CPU arch is set to: '${cpuArch}' but the node version that is being used is running: '${nodeArch}'. Expected it to equal: '${expectedArch}'`
}
// if we're in the x86 CPU architecture check
// to ensure that os.arch() is ia32
// eslint-disable-next-line default-case
switch (cpuArch) {
case 'x86':
assert.equal(
os.arch(),
'ia32',
getErrMsg('ia32')
)
break
case 'x64':
assert.equal(
os.arch(),
'x64',
getErrMsg('x64')
)
break
}
}
// we want to ensure we are building using the same major version
// as the one specified in ../.node-version file
const read = require('fs').readFileSync
const join = require('path').join
const nodeVersionNeededString = read(
join(__dirname, '..', '.node-version'),
'utf8'
)
const nodeVersionNeeded = nodeVersionNeededString.split('.')
const nodeVersion = process.versions.node.split('.')
// check just major version for now
if (nodeVersionNeeded[0] !== nodeVersion[0]) {
/* eslint-disable no-console */
console.error('🛑 .node-version specified %s', nodeVersionNeededString)
console.error('but current Node is %s', process.versions.node)
/* eslint-enable no-console */
process.exit(1)
}
+7 -1
View File
@@ -92,7 +92,9 @@ const mapTasks = (cmd, packages) => {
let runCommand
switch (cmd) {
const command = cmd.split(' ', 2)[0]
switch (command) {
case 'install':
case 'i':
case 'test':
@@ -189,6 +191,10 @@ module.exports = (cmd, options) => {
return checkDirsLength(dirs, errMessage)
})
.then((dirs) => {
if (options.args) {
cmd += ` ${options.args}`
}
return mapTasks(cmd, dirs)
})
.then((tasks) => {
+29 -4
View File
@@ -6,8 +6,10 @@
// but only on the right branch
const shell = require('shelljs')
const os = require('os')
const la = require('lazy-ass')
const is = require('check-more-types')
// const assert = require('assert')
shell.set('-v') // verbose
shell.set('-e') // any error is fatal
@@ -18,15 +20,17 @@ shell.set('-e') // any error is fatal
const isRightBranch = () => {
const branch = process.env.APPVEYOR_REPO_BRANCH
return branch === 'develop'
return branch === 'develop' || branch === 'issue-716-ffmpeg-packaging'
}
const isPullRequest = () => {
return Boolean(process.env.APPVEYOR_PULL_REQUEST_NUMBER)
const isForkedPullRequest = () => {
const repoName = process.env.APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME
return repoName && repoName !== 'cypress-io/cypress'
}
const shouldBuildBinary = () => {
return isRightBranch() && !isPullRequest()
return isRightBranch() && !isForkedPullRequest()
}
if (!shouldBuildBinary()) {
@@ -44,6 +48,11 @@ la(is.unemptyString(version), 'missing NEXT_DEV_VERSION')
console.log('building version', version)
shell.exec(`node scripts/binary.js upload-npm-package --file cli/build/${filename} --version ${version}`)
const arch = os.arch()
shell.echo(`Building for win32 [${arch}]...`)
shell.cat('npm-package-url.json')
shell.exec(`npm run binary-build -- --platform windows --version ${version}`)
@@ -62,6 +71,22 @@ if (result.stdout.includes('nodemon')) {
process.exit(1)
}
// const pathToExe = 'C:/projects/cypress/build/win32/Cypress/Cypress.exe'
// // verify that Cypress.exe is either 32bit or 64bit based on node's arch
// const dumpbin = shell.exec(`dumpbin /headers ${pathToExe}`)
// // eslint-disable-next-line default-case
// switch (arch) {
// case 'ia32':
// assert.ok(dumpbin.stdout.includes('machine (x86)'))
// break
// case 'x64':
// assert.ok(dumpbin.stdout.includes('machine (x64)'))
// break
// }
shell.exec('npm run binary-zip')
shell.ls('-l', '*.zip')
shell.exec(`node scripts/binary.js upload-unique-binary --file cypress.zip --version ${version}`)