mirror of
https://github.com/cypress-io/cypress.git
synced 2026-01-07 06:59:49 -06:00
deploy: rename deploy -> binary folder
This commit is contained in:
162
scripts/binary/ask.coffee
Normal file
162
scripts/binary/ask.coffee
Normal file
@@ -0,0 +1,162 @@
|
||||
_ = require("lodash")
|
||||
fs = require("fs-extra")
|
||||
glob = require("glob")
|
||||
Promise = require("bluebird")
|
||||
inquirer = require("inquirer")
|
||||
|
||||
glob = Promise.promisify(glob)
|
||||
|
||||
prompt = (questions) ->
|
||||
Promise.resolve(inquirer.prompt(questions))
|
||||
|
||||
fs = Promise.promisifyAll(fs)
|
||||
|
||||
getZipFile = ->
|
||||
[{
|
||||
name: "zipFile"
|
||||
type: "string"
|
||||
message: "Which zip file should we upload?"
|
||||
}]
|
||||
|
||||
getPlatformQuestion = ->
|
||||
[{
|
||||
name: "platform"
|
||||
type: "list"
|
||||
message: "Which OS should we deploy?"
|
||||
choices: [{
|
||||
name: "Mac"
|
||||
value: "darwin"
|
||||
},{
|
||||
name: "Linux"
|
||||
value: "linux"
|
||||
}]
|
||||
}]
|
||||
|
||||
getQuestions = (version) ->
|
||||
[{
|
||||
name: "publish"
|
||||
type: "list"
|
||||
message: "Publish a new version? (currently: #{version})"
|
||||
choices: [{
|
||||
name: "Yes: set a new version and deploy new version."
|
||||
value: true
|
||||
},{
|
||||
name: "No: just override the current deploy’ed version."
|
||||
value: false
|
||||
}]
|
||||
},{
|
||||
name: "version"
|
||||
type: "input"
|
||||
message: "Bump version to...? (currently: #{version})"
|
||||
default: ->
|
||||
a = version.split(".")
|
||||
v = a[a.length - 1]
|
||||
v = Number(v) + 1
|
||||
a.splice(a.length - 1, 1, v)
|
||||
a.join(".")
|
||||
when: (answers) ->
|
||||
answers.publish
|
||||
}]
|
||||
|
||||
getReleases = (releases) ->
|
||||
[{
|
||||
name: "release"
|
||||
type: "list"
|
||||
message: "Release which version?"
|
||||
choices: _.map releases, (r) ->
|
||||
{
|
||||
name: r
|
||||
value: r
|
||||
}
|
||||
}]
|
||||
|
||||
getVersions = (releases) ->
|
||||
[{
|
||||
name: "version"
|
||||
type: "list"
|
||||
message: "Bump to which version?"
|
||||
choices: _.map releases, (r) ->
|
||||
{
|
||||
name: r
|
||||
value: r
|
||||
}
|
||||
}]
|
||||
|
||||
getBumpTasks = ->
|
||||
[{
|
||||
name: "task"
|
||||
type: "list"
|
||||
message: "Which bump task?"
|
||||
choices: [{
|
||||
name: "Bump Cypress Version for all CI providers"
|
||||
value: "version"
|
||||
},{
|
||||
name: "Run All Projects for all CI providers"
|
||||
value: "run"
|
||||
}]
|
||||
}]
|
||||
|
||||
deployNewVersion = ->
|
||||
fs.readJsonAsync("./package.json")
|
||||
.then (json) =>
|
||||
prompt(getQuestions(json.version))
|
||||
.then (answers) ->
|
||||
## set the new version if we're publishing!
|
||||
## update our own local package.json as well
|
||||
if answers.publish
|
||||
# @updateLocalPackageJson(answers.version, json).then ->
|
||||
answers.version
|
||||
else
|
||||
json.version
|
||||
|
||||
whichZipFile = ->
|
||||
prompt(getZipFile())
|
||||
.get("zipFile")
|
||||
|
||||
whichVersion = (distDir) ->
|
||||
## realpath returns the absolute full path
|
||||
glob("*/package.json", {cwd: distDir, realpath: true})
|
||||
.map (pkg) =>
|
||||
fs.readJsonAsync(pkg)
|
||||
.get("version")
|
||||
.then (versions) =>
|
||||
versions = _.uniq(versions)
|
||||
|
||||
prompt(getVersions(versions))
|
||||
.get("version")
|
||||
|
||||
whichRelease = (distDir) ->
|
||||
## realpath returns the absolute full path
|
||||
glob("*/package.json", {cwd: distDir, realpath: true})
|
||||
.map (pkg) =>
|
||||
fs.readJsonAsync(pkg)
|
||||
.get("version")
|
||||
.then (versions) =>
|
||||
versions = _.uniq(versions)
|
||||
|
||||
prompt(getReleases(versions))
|
||||
.get("release")
|
||||
|
||||
whichPlatform = ->
|
||||
prompt(getPlatformQuestion())
|
||||
.get("platform")
|
||||
|
||||
whichBumpTask = ->
|
||||
prompt(getBumpTasks())
|
||||
.get("task")
|
||||
|
||||
module.exports = {
|
||||
getZipFile
|
||||
getPlatformQuestion
|
||||
getQuestions
|
||||
getReleases
|
||||
getVersions
|
||||
getBumpTasks
|
||||
deployNewVersion
|
||||
whichZipFile
|
||||
whichVersion
|
||||
whichRelease
|
||||
whichPlatform
|
||||
whichBumpTask
|
||||
|
||||
}
|
||||
452
scripts/binary/base.coffee
Normal file
452
scripts/binary/base.coffee
Normal file
@@ -0,0 +1,452 @@
|
||||
_ = require("lodash")
|
||||
gulpCoffee = require("gulp-coffee")
|
||||
fs = require("fs-extra")
|
||||
cp = require("child_process")
|
||||
path = require("path")
|
||||
gulp = require("gulp")
|
||||
glob = require("glob")
|
||||
chalk = require("chalk")
|
||||
expect = require("chai").expect
|
||||
Promise = require("bluebird")
|
||||
obfuscator = require("obfuscator")
|
||||
# runSequence = require("run-sequence")
|
||||
cypressElectron = require("@packages/electron")
|
||||
log = require("./log")
|
||||
meta = require("./meta")
|
||||
pkg = require("../../package.json")
|
||||
konfig = require("@packages/server/lib/konfig")
|
||||
appData = require("@packages/server/lib/util/app_data")
|
||||
Fixtures = require("@packages/server/test/support/helpers/fixtures")
|
||||
|
||||
# pkgr = Promise.promisify(pkgr)
|
||||
fs = Promise.promisifyAll(fs)
|
||||
glob = Promise.promisify(glob)
|
||||
zipName = "cypress.zip"
|
||||
|
||||
DEFAULT_PATHS = "node_modules package.json".split(" ")
|
||||
|
||||
pathToPackageJson = (pkg) ->
|
||||
path.join(pkg, "package.json")
|
||||
|
||||
class Base
|
||||
constructor: (os, @options = {}) ->
|
||||
_.defaults @options, {
|
||||
version: null
|
||||
}
|
||||
|
||||
@zipName = zipName
|
||||
@osName = os
|
||||
@uploadOsName = @getUploadNameByOs(os)
|
||||
|
||||
buildPathToAppFolder: ->
|
||||
meta.buildDir(@osName)
|
||||
|
||||
buildPathToZip: ->
|
||||
path.join @buildPathToAppFolder(), @zipName
|
||||
|
||||
getUploadNameByOs: (os) ->
|
||||
{
|
||||
darwin: "osx64"
|
||||
linux: "linux64"
|
||||
win32: "win64"
|
||||
}[os]
|
||||
|
||||
getVersion: ->
|
||||
@options.version ? fs.readJsonSync(@distDir("package.json")).version
|
||||
|
||||
copyPackages: ->
|
||||
@log("#copyPackages")
|
||||
|
||||
dist = @distDir()
|
||||
|
||||
copy = (src, dest) =>
|
||||
dest ?= src
|
||||
dest = @distDir(dest.slice(1))
|
||||
|
||||
fs.copyAsync(src, dest)
|
||||
|
||||
copyRelativePathToDist = (relative) ->
|
||||
dest = path.join(dist, relative)
|
||||
|
||||
console.log(relative, "->", dest)
|
||||
|
||||
# copy = ->
|
||||
# new Promise (resolve, reject) ->
|
||||
# cp.spawn("cp", ["-R", relative, dest], {stdio: "inherit"})
|
||||
# .on "error", reject
|
||||
# .on "exit", resolve
|
||||
|
||||
# if relative.includes(".")
|
||||
# copy()
|
||||
# else
|
||||
# fs.ensureDirAsync(dest)
|
||||
# .then(copy)
|
||||
|
||||
fs.copyAsync(relative, dest)
|
||||
|
||||
copyPackage = (pkg) ->
|
||||
## copies the package to dist
|
||||
## including the default paths
|
||||
## and any specified in package.json files
|
||||
fs.readJsonAsync(pathToPackageJson(pkg))
|
||||
.then (json) ->
|
||||
## grab all the files
|
||||
## and default included paths
|
||||
## and convert to relative paths
|
||||
DEFAULT_PATHS
|
||||
.concat(json.files or [])
|
||||
.map (file) ->
|
||||
path.join(pkg, file)
|
||||
.map(copyRelativePathToDist, {concurrency: 1})
|
||||
|
||||
## fs-extra concurrency tests (copyPackage / copyRelativePathToDist)
|
||||
## 1/1 41688
|
||||
## 1/5 42218
|
||||
## 1/10 42566
|
||||
## 2/1 45041
|
||||
## 2/2 43589
|
||||
## 3/3 51399
|
||||
|
||||
## cp -R concurrency tests
|
||||
## 1/1 65811
|
||||
|
||||
started = new Date()
|
||||
|
||||
fs
|
||||
.removeAsync(dist)
|
||||
.bind(@)
|
||||
.then ->
|
||||
fs.ensureDirAsync(dist)
|
||||
.then ->
|
||||
glob("./packages/*")
|
||||
.map(copyPackage, {concurrency: 1})
|
||||
.then ->
|
||||
console.log("Finished Copying", new Date() - started)
|
||||
|
||||
prunePackages: ->
|
||||
pathToDistPackages = @distDir("packages", "*")
|
||||
|
||||
## 1,060,495,784 bytes (1.54 GB on disk) for 179,156 items
|
||||
## 313,416,512 bytes (376.6 MB on disk) for 23,576 items
|
||||
|
||||
prune = (pkg) ->
|
||||
console.log("prune", pkg)
|
||||
|
||||
new Promise (resolve, reject) ->
|
||||
cp.spawn("npm", ["prune", "--production"], {
|
||||
cwd: pkg
|
||||
stdio: "inherit"
|
||||
})
|
||||
.on("error", reject)
|
||||
.on("exit", (code) ->
|
||||
if code is 0
|
||||
resolve()
|
||||
else
|
||||
reject(new Error("'npm prune --production' on #{pkg} failed with exit code: #{code}"))
|
||||
)
|
||||
|
||||
## prunes out all of the devDependencies
|
||||
## from what was copied
|
||||
glob(pathToDistPackages)
|
||||
.map(prune)
|
||||
|
||||
convertCoffeeToJs: ->
|
||||
@log("#convertCoffeeToJs")
|
||||
|
||||
## grab everything in src
|
||||
## convert to js
|
||||
new Promise (resolve, reject) =>
|
||||
gulp.src(@distDir("lib", "**", "*.coffee"))
|
||||
.pipe gulpCoffee()
|
||||
.pipe gulp.dest(@distDir("lib"))
|
||||
.on("end", resolve)
|
||||
.on("error", reject)
|
||||
|
||||
distDir: (args...) ->
|
||||
args = _.compact [meta.distDir, @osName, args...]
|
||||
path.join args...
|
||||
|
||||
obfuscate: ->
|
||||
@log("#obfuscate")
|
||||
|
||||
## obfuscate all the js files
|
||||
new Promise (resolve, reject) =>
|
||||
## grab all of the js files
|
||||
files = glob.sync @distDir("src/**/*.js")
|
||||
|
||||
## root is src
|
||||
## entry is cypress.js
|
||||
## files are all the js files
|
||||
opts = {root: @distDir("src"), entry: @distDir("src/index.js"), files: files}
|
||||
|
||||
obfuscator.concatenate opts, (err, obfuscated) =>
|
||||
return reject(err) if err
|
||||
|
||||
## move to lib
|
||||
fs.writeFileSync(@distDir("index.js"), obfuscated)
|
||||
|
||||
resolve(obfuscated)
|
||||
|
||||
cleanupSrc: ->
|
||||
@log("#cleanupSrc")
|
||||
|
||||
fs.removeAsync @distDir("/src")
|
||||
|
||||
cleanupPlatform: ->
|
||||
@log("#cleanupPlatform")
|
||||
|
||||
cleanup = =>
|
||||
Promise.all([
|
||||
fs.removeAsync path.join(meta.distDir, @osName)
|
||||
fs.removeAsync path.join(meta.buildDir, @osName)
|
||||
])
|
||||
|
||||
cleanup().catch(cleanup)
|
||||
|
||||
symlinkPackages: ->
|
||||
@log("#symlinkPackages")
|
||||
|
||||
dist = @distDir()
|
||||
pathToPackages = path.join('node_modules', '@')
|
||||
pathToDistPackages = @distDir("packages", "*")
|
||||
|
||||
symlink = (pkg) ->
|
||||
# console.log(pkg, dist)
|
||||
## strip off the initial './'
|
||||
## ./packages/foo -> node_modules/@packages/foo
|
||||
dest = path.join(dist, "node_modules", "@packages", path.basename(pkg))
|
||||
|
||||
fs.ensureSymlinkAsync(pkg, dest)
|
||||
|
||||
glob(pathToDistPackages)
|
||||
.map(symlink)
|
||||
|
||||
# // glob all of the names of packages
|
||||
# glob('./packages/*')
|
||||
# .map((folder) => {
|
||||
# // strip off the initial './'
|
||||
# // ./packages/foo -> node_modules/@packages/foo
|
||||
# const dest = pathToPackages + folder.slice(2)
|
||||
#
|
||||
# console.log('symlinking', folder, '->', dest)
|
||||
#
|
||||
# return fs.ensureSymlinkAsync(folder, dest)
|
||||
# })
|
||||
|
||||
## add tests around this method
|
||||
createRootPackage: ->
|
||||
version = @options.version
|
||||
|
||||
@log("#createRootPackage #{version}")
|
||||
|
||||
fs.outputJsonAsync(@distDir("package.json"), {
|
||||
name: "cypress"
|
||||
productName: "Cypress",
|
||||
version: version
|
||||
main: "index.js"
|
||||
scripts: {}
|
||||
env: "production"
|
||||
})
|
||||
.then =>
|
||||
str = "require('./packages/server')"
|
||||
|
||||
fs.outputFileAsync(@distDir("index.js"), str)
|
||||
|
||||
npmInstall: ->
|
||||
@log("#npmInstall")
|
||||
|
||||
new Promise (resolve, reject) =>
|
||||
attempts = 0
|
||||
|
||||
npmInstall = =>
|
||||
attempts += 1
|
||||
|
||||
cp.exec "npm install --production", {cwd: @distDir()}, (err, stdout, stderr) ->
|
||||
if err
|
||||
if attempts is 3
|
||||
fs.writeFileSync("./npm-install.log", stderr)
|
||||
return reject(err)
|
||||
|
||||
console.log chalk.red("'npm install' failed, retrying")
|
||||
return npmInstall()
|
||||
|
||||
resolve()
|
||||
|
||||
npmInstall()
|
||||
|
||||
elBuilder: ->
|
||||
@log("#elBuilder")
|
||||
|
||||
fs.readJsonAsync(@distDir("package.json"))
|
||||
.then (json) =>
|
||||
cypressElectron.install({
|
||||
dir: @distDir()
|
||||
dist: @buildPathForElectron()
|
||||
platform: @osName
|
||||
"app-version": json.version
|
||||
})
|
||||
|
||||
uploadFixtureToS3: ->
|
||||
@log("#uploadFixtureToS3")
|
||||
|
||||
@uploadToS3("osx64", "fixture")
|
||||
|
||||
getManifest: ->
|
||||
requestPromise(konfig("desktop_manifest_url")).then (resp) ->
|
||||
console.log resp
|
||||
|
||||
fixture: (cb) ->
|
||||
@dist()
|
||||
.then(@uploadFixtureToS3)
|
||||
.then(@cleanupPlatform)
|
||||
.then ->
|
||||
@log("Fixture Complete!", "green")
|
||||
cb?()
|
||||
.catch (err) ->
|
||||
@log("Fixture Failed!", "red")
|
||||
console.log err
|
||||
|
||||
log: ->
|
||||
log.apply(@, arguments)
|
||||
|
||||
buildPackages: ->
|
||||
@log("#buildPackages")
|
||||
|
||||
new Promise (resolve, reject) ->
|
||||
console.log(process.cwd())
|
||||
|
||||
## build all the packages except for
|
||||
## cli and docs
|
||||
cp.spawn("npm", ["run", "all", "build", "--", "--skip-packages", "cli,docs"], { stdio: "inherit" })
|
||||
.on "error", reject
|
||||
.on "exit", (code) ->
|
||||
if code is 0
|
||||
resolve()
|
||||
else
|
||||
reject(new Error("'npm run build' failed with exit code: #{code}"))
|
||||
|
||||
_runProjectTest: ->
|
||||
@log("#runProjectTest")
|
||||
|
||||
Fixtures.scaffold()
|
||||
|
||||
e2e = Fixtures.projectPath("e2e")
|
||||
|
||||
runProjectTest = =>
|
||||
new Promise (resolve, reject) =>
|
||||
env = _.omit(process.env, "CYPRESS_ENV")
|
||||
|
||||
sp = cp.spawn @buildPathToAppExecutable(), ["--run-project=#{e2e}", "--spec=cypress/integration/simple_passing_spec.coffee"], {stdio: "inherit", env: env}
|
||||
sp.on "exit", (code) ->
|
||||
if code is 0
|
||||
resolve()
|
||||
else
|
||||
reject(new Error("running project tests failed with: '#{code}' errors."))
|
||||
|
||||
runProjectTest()
|
||||
.then ->
|
||||
Fixtures.remove()
|
||||
|
||||
_runFailingProjectTest: ->
|
||||
@log("#runFailingProjectTest")
|
||||
|
||||
Fixtures.scaffold()
|
||||
|
||||
e2e = Fixtures.projectPath("e2e")
|
||||
|
||||
verifyScreenshots = =>
|
||||
screenshot1 = path.join(e2e, "cypress", "screenshots", "simple failing spec -- fails1.png")
|
||||
screenshot2 = path.join(e2e, "cypress", "screenshots", "simple failing spec -- fails2.png")
|
||||
|
||||
Promise.all([
|
||||
fs.statAsync(screenshot1)
|
||||
fs.statAsync(screenshot2)
|
||||
])
|
||||
|
||||
runProjectTest = =>
|
||||
new Promise (resolve, reject) =>
|
||||
env = _.omit(process.env, "CYPRESS_ENV")
|
||||
|
||||
sp = cp.spawn @buildPathToAppExecutable(), ["--run-project=#{e2e}", "--spec=cypress/integration/simple_failing_spec.coffee"], {stdio: "inherit", env: env}
|
||||
sp.on "exit", (code) ->
|
||||
if code is 2
|
||||
resolve()
|
||||
else
|
||||
reject(new Error("running project tests failed with: '#{code}' errors."))
|
||||
|
||||
runProjectTest()
|
||||
.then(verifyScreenshots)
|
||||
.then ->
|
||||
Fixtures.remove()
|
||||
|
||||
_runSmokeTest: ->
|
||||
@log("#runSmokeTest")
|
||||
|
||||
smokeTest = =>
|
||||
new Promise (resolve, reject) =>
|
||||
rand = "" + Math.random()
|
||||
executable = @buildPathToAppExecutable()
|
||||
console.log("executable path #{executable}")
|
||||
|
||||
cp.exec "#{executable} --smoke-test --ping=#{rand}", (err, stdout, stderr) ->
|
||||
stdout = stdout.replace(/\s/, "")
|
||||
|
||||
if err
|
||||
console.error("smoke test failed with error %s", err.message)
|
||||
return reject(err)
|
||||
|
||||
if stdout isnt rand
|
||||
throw new Error("Stdout: '#{stdout}' did not match the random number: '#{rand}'")
|
||||
else
|
||||
console.log("smokeTest passes")
|
||||
resolve()
|
||||
|
||||
verifyAppPackage = =>
|
||||
new Promise (resolve, reject) =>
|
||||
console.log("verifyAppPackage")
|
||||
cp.exec "#{@buildPathToAppExecutable()} --return-pkg", (err, stdout, stderr) ->
|
||||
return reject(err) if err
|
||||
|
||||
stdout = JSON.parse(stdout)
|
||||
|
||||
try
|
||||
expect(stdout.env).to.eq("production")
|
||||
catch err
|
||||
console.error("failed to verify app via --return-pkg")
|
||||
console.log(stdout)
|
||||
return reject(err)
|
||||
|
||||
console.log("app verified")
|
||||
resolve()
|
||||
|
||||
smokeTest()
|
||||
# TODO refactor verifying app package
|
||||
# .then(verifyAppPackage)
|
||||
|
||||
cleanupCy: ->
|
||||
appData.removeSymlink()
|
||||
|
||||
build: ->
|
||||
Promise
|
||||
.bind(@)
|
||||
# .then(@cleanupPlatform)
|
||||
# .then(@buildPackages)
|
||||
# .then(@copyPackages)
|
||||
# .then(@prunePackages)
|
||||
.then(@createRootPackage)
|
||||
.then(@symlinkPackages)
|
||||
# .then(@convertCoffeeToJs)
|
||||
# .then(@obfuscate)
|
||||
# .then(@cleanupSrc)
|
||||
# .then(@npmInstall)
|
||||
# .then(@npmInstall)
|
||||
# .then(@elBuilder)
|
||||
# .then(@runSmokeTest)
|
||||
# .then(@runProjectTest)
|
||||
# .then(@runFailingProjectTest)
|
||||
# .then(@cleanupCy)
|
||||
# .then(@codeSign) ## codesign after running smoke tests due to changing .cy
|
||||
# .then(@verifyAppCanOpen)
|
||||
.return(@)
|
||||
|
||||
module.exports = Base
|
||||
200
scripts/binary/build.coffee
Normal file
200
scripts/binary/build.coffee
Normal file
@@ -0,0 +1,200 @@
|
||||
_ = require("lodash")
|
||||
fs = require("fs-extra")
|
||||
del = require("del")
|
||||
path = require("path")
|
||||
gulp = require("gulp")
|
||||
chalk = require("chalk")
|
||||
Promise = require("bluebird")
|
||||
gulpDebug = require("gulp-debug")
|
||||
gulpCoffee = require("gulp-coffee")
|
||||
gulpTypeScript = require("gulp-typescript")
|
||||
pluralize = require("pluralize")
|
||||
vinylPaths = require("vinyl-paths")
|
||||
coffee = require("@packages/coffee")
|
||||
electron = require("@packages/electron")
|
||||
|
||||
meta = require("./meta")
|
||||
packages = require("./util/packages")
|
||||
Darwin = require("./darwin")
|
||||
Linux = require("./linux")
|
||||
|
||||
fs = Promise.promisifyAll(fs)
|
||||
|
||||
logger = (msg) ->
|
||||
console.log(chalk.yellow(msg), chalk.bgWhite(chalk.black(platform)))
|
||||
|
||||
runDarwinSmokeTest = ->
|
||||
darwin = new Darwin("darwin")
|
||||
darwin.runSmokeTest()
|
||||
|
||||
runLinuxSmokeTest = ->
|
||||
linux = new Linux("linux")
|
||||
linux.runSmokeTest()
|
||||
|
||||
smokeTests = {
|
||||
darwin: runDarwinSmokeTest,
|
||||
linux: runLinuxSmokeTest
|
||||
}
|
||||
|
||||
module.exports = (platform, version) ->
|
||||
distDir = _.partial(meta.distDir, platform)
|
||||
buildDir = _.partial(meta.buildDir, platform)
|
||||
buildAppDir = _.partial(meta.buildAppDir, platform)
|
||||
|
||||
log = _.partialRight(logger, platform)
|
||||
|
||||
cleanupPlatform = ->
|
||||
log("#cleanupPlatform")
|
||||
|
||||
cleanup = =>
|
||||
fs.removeAsync(distDir())
|
||||
|
||||
cleanup()
|
||||
.catch(cleanup)
|
||||
|
||||
buildPackages = ->
|
||||
log("#buildPackages")
|
||||
|
||||
packages.runAllBuild()
|
||||
.then(packages.runAllBuildJs)
|
||||
|
||||
copyPackages = ->
|
||||
log("#copyPackages")
|
||||
|
||||
packages.copyAllToDist(distDir())
|
||||
|
||||
npmInstallPackages = ->
|
||||
log("#npmInstallPackages")
|
||||
|
||||
packages.npmInstallAll(distDir("packages", "*"))
|
||||
|
||||
createRootPackage = ->
|
||||
log("#createRootPackage", platform, version)
|
||||
|
||||
fs.outputJsonAsync(distDir("package.json"), {
|
||||
name: "cypress"
|
||||
productName: "Cypress",
|
||||
version: version
|
||||
main: "index.js"
|
||||
scripts: {}
|
||||
env: "production"
|
||||
})
|
||||
.then =>
|
||||
str = """
|
||||
process.env.CYPRESS_ENV = 'production'
|
||||
require('./packages/server')
|
||||
"""
|
||||
|
||||
fs.outputFileAsync(distDir("index.js"), str)
|
||||
|
||||
symlinkPackages = ->
|
||||
log("#symlinkPackages")
|
||||
|
||||
packages.symlinkAll(distDir("packages", "*", "package.json"), distDir)
|
||||
|
||||
removeTypeScript = ->
|
||||
## remove the .ts files in our packages
|
||||
log("#removeTypeScript")
|
||||
del([
|
||||
## include coffee files of packages
|
||||
distDir("**", "*.ts")
|
||||
|
||||
## except those in node_modules
|
||||
"!" + distDir("**", "node_modules", "**", "*.ts")
|
||||
])
|
||||
.then (paths) ->
|
||||
console.log(
|
||||
"deleted %d TS %s",
|
||||
paths.length,
|
||||
pluralize("file", paths.length)
|
||||
)
|
||||
console.log(paths)
|
||||
|
||||
symlinkBuildPackages = ->
|
||||
log("#symlinkBuildPackages")
|
||||
wildCard = buildAppDir("packages", "*", "package.json")
|
||||
console.log("packages", wildCard)
|
||||
packages.symlinkAll(
|
||||
wildCard,
|
||||
buildAppDir
|
||||
)
|
||||
|
||||
symlinkDistPackages = ->
|
||||
log("#symlinkDistPackages")
|
||||
|
||||
packages.symlinkAll(
|
||||
distDir("packages", "*", "package.json"),
|
||||
distDir
|
||||
)
|
||||
|
||||
cleanJs = ->
|
||||
log("#cleanJs")
|
||||
|
||||
packages.runAllCleanJs()
|
||||
|
||||
convertCoffeeToJs = ->
|
||||
log("#convertCoffeeToJs")
|
||||
|
||||
## grab everything in src
|
||||
## convert to js
|
||||
new Promise (resolve, reject) =>
|
||||
gulp.src([
|
||||
## include coffee files of packages
|
||||
distDir("**", "*.coffee")
|
||||
|
||||
## except those in node_modules
|
||||
"!" + distDir("**", "node_modules", "**", "*.coffee")
|
||||
])
|
||||
.pipe vinylPaths(del)
|
||||
.pipe(gulpDebug())
|
||||
.pipe gulpCoffee({
|
||||
coffee: coffee
|
||||
})
|
||||
.pipe gulp.dest(distDir())
|
||||
.on("end", resolve)
|
||||
.on("error", reject)
|
||||
|
||||
elBuilder = ->
|
||||
log("#elBuilder")
|
||||
dir = distDir()
|
||||
dist = buildDir()
|
||||
console.log("from #{dir}")
|
||||
console.log("into #{dist}")
|
||||
|
||||
electron.install({
|
||||
dir
|
||||
dist
|
||||
platform
|
||||
"app-version": version
|
||||
})
|
||||
|
||||
runSmokeTest = ->
|
||||
log("#runSmokeTest")
|
||||
# console.log("skipping smoke test for now")
|
||||
smokeTest = smokeTests[platform]
|
||||
smokeTest()
|
||||
|
||||
Promise.resolve()
|
||||
.then(cleanupPlatform)
|
||||
.then(buildPackages)
|
||||
.then(copyPackages)
|
||||
.then(npmInstallPackages)
|
||||
.then(createRootPackage)
|
||||
.then(symlinkPackages)
|
||||
.then(convertCoffeeToJs)
|
||||
.then(removeTypeScript)
|
||||
.then(cleanJs)
|
||||
.then(symlinkDistPackages)
|
||||
.then(elBuilder)
|
||||
.then(symlinkBuildPackages)
|
||||
.then(runSmokeTest)
|
||||
|
||||
# older build steps
|
||||
# .then(@runProjectTest)
|
||||
# .then(@runFailingProjectTest)
|
||||
# .then(@cleanupCy)
|
||||
# .then(@codeSign) ## codesign after running smoke tests due to changing .cy
|
||||
# .then(@verifyAppCanOpen)
|
||||
.return({
|
||||
buildDir: buildDir()
|
||||
})
|
||||
67
scripts/binary/bump.coffee
Normal file
67
scripts/binary/bump.coffee
Normal file
@@ -0,0 +1,67 @@
|
||||
_ = require("lodash")
|
||||
fs = require("fs-extra")
|
||||
Promise = require("bluebird")
|
||||
bumpercar = require("@cypress/bumpercar")
|
||||
path = require("path")
|
||||
|
||||
fs = Promise.promisifyAll(fs)
|
||||
|
||||
PROVIDERS = {
|
||||
circle: [
|
||||
"cypress-io/cypress-dashboard"
|
||||
"cypress-io/cypress-core-example"
|
||||
"cypress-io/cypress-core-desktop-gui"
|
||||
"cypress-io/cypress-example-kitchensink"
|
||||
"cypress-io/cypress-example-todomvc"
|
||||
"cypress-io/cypress-example-piechopper"
|
||||
"cypress-io/cypress-example-recipes"
|
||||
"cypress-io/cypress-example-node-versions"
|
||||
"cypress-io/cypress-example-module-api"
|
||||
"cypress-io/cypress-test-ci-environments"
|
||||
]
|
||||
|
||||
travis: [
|
||||
# "cypress-io/cypress-dashboard"
|
||||
"cypress-io/cypress-core-example"
|
||||
"cypress-io/cypress-core-desktop-gui"
|
||||
"cypress-io/cypress-example-kitchensink"
|
||||
"cypress-io/cypress-example-todomvc"
|
||||
"cypress-io/cypress-example-piechopper"
|
||||
"cypress-io/cypress-example-recipes"
|
||||
]
|
||||
}
|
||||
|
||||
awaitEachProjectAndProvider = (fn) ->
|
||||
ciJson = path.join(__dirname, "support/ci.json")
|
||||
creds = fs.readJsonSync(ciJson, "utf8")
|
||||
|
||||
fs.readJsonAsync(ciJson)
|
||||
.then (creds) ->
|
||||
## configure a new Bumpercar
|
||||
car = bumpercar.create({
|
||||
providers: {
|
||||
travis: {
|
||||
githubToken: creds.githubToken
|
||||
}
|
||||
circle: {
|
||||
circleToken: creds.circleToken
|
||||
}
|
||||
}
|
||||
})
|
||||
.then ->
|
||||
_.map PROVIDERS, (projects, provider) ->
|
||||
Promise.map projects, (project) ->
|
||||
fn(project, provider)
|
||||
.all()
|
||||
|
||||
module.exports = {
|
||||
version: (version) ->
|
||||
awaitEachProjectAndProvider (project, provider) ->
|
||||
car.updateProjectEnv(project, provider, {
|
||||
CYPRESS_VERSION: version
|
||||
})
|
||||
|
||||
run: ->
|
||||
awaitEachProjectAndProvider (project, provider) ->
|
||||
car.runProject(project, provider)
|
||||
}
|
||||
59
scripts/binary/darwin.coffee
Normal file
59
scripts/binary/darwin.coffee
Normal file
@@ -0,0 +1,59 @@
|
||||
fs = require("fs-extra")
|
||||
cp = require("child_process")
|
||||
path = require("path")
|
||||
sign = require("electron-osx-sign")
|
||||
plist = require("plist")
|
||||
Promise = require("bluebird")
|
||||
meta = require("./meta")
|
||||
Base = require("./base")
|
||||
|
||||
sign = Promise.promisify(sign)
|
||||
fs = Promise.promisifyAll(fs)
|
||||
|
||||
class Darwin extends Base
|
||||
buildPathForElectron: ->
|
||||
@buildPathToAppFolder()
|
||||
|
||||
buildPathToApp: ->
|
||||
path.join @buildPathToAppFolder(), "Cypress.app"
|
||||
|
||||
buildPathToAppExecutable: ->
|
||||
path.join @buildPathToApp(), "Contents", "MacOS", "Cypress"
|
||||
|
||||
buildPathToAppResources: ->
|
||||
path.join @buildPathToApp(), "Contents", "Resources", "app"
|
||||
|
||||
runSmokeTest: ->
|
||||
@_runSmokeTest()
|
||||
|
||||
runProjectTest: ->
|
||||
@_runProjectTest()
|
||||
|
||||
runFailingProjectTest: ->
|
||||
@_runFailingProjectTest()
|
||||
|
||||
codeSign: ->
|
||||
@log("#codeSign")
|
||||
|
||||
sign({
|
||||
app: @buildPathToApp()
|
||||
platform: "darwin"
|
||||
verbose: true
|
||||
})
|
||||
|
||||
verifyAppCanOpen: ->
|
||||
@log("#verifyAppCanOpen")
|
||||
|
||||
new Promise (resolve, reject) =>
|
||||
sp = cp.spawn "spctl", ["-a", "-vvvv", @buildPathToApp()], {stdio: "inherit"}
|
||||
sp.on "exit", (code) ->
|
||||
if code is 0
|
||||
resolve()
|
||||
else
|
||||
reject new Error("Verifying App via GateKeeper failed")
|
||||
|
||||
deploy: ->
|
||||
@build()
|
||||
.return(@)
|
||||
|
||||
module.exports = Darwin
|
||||
162
scripts/binary/index.coffee
Normal file
162
scripts/binary/index.coffee
Normal file
@@ -0,0 +1,162 @@
|
||||
## store the cwd
|
||||
cwd = process.cwd()
|
||||
|
||||
path = require("path")
|
||||
_ = require("lodash")
|
||||
os = require("os")
|
||||
chalk = require("chalk")
|
||||
Promise = require("bluebird")
|
||||
minimist = require("minimist")
|
||||
la = require("lazy-ass")
|
||||
check = require("check-more-types")
|
||||
|
||||
zip = require("./zip")
|
||||
ask = require("./ask")
|
||||
bump = require("./bump")
|
||||
meta = require("./meta")
|
||||
build = require("./build")
|
||||
upload = require("./upload")
|
||||
Base = require("./base")
|
||||
Linux = require("./linux")
|
||||
Darwin = require("./darwin")
|
||||
|
||||
success = (str) ->
|
||||
console.log chalk.bgGreen(" " + chalk.black(str) + " ")
|
||||
|
||||
fail = (str) ->
|
||||
console.log chalk.bgRed(" " + chalk.black(str) + " ")
|
||||
|
||||
zippedFilename = (platform) ->
|
||||
# TODO use .tar.gz for linux archive. For now to preserve
|
||||
# same file format as before use .zip
|
||||
if platform is "linux" then "cypress.zip" else "cypress.zip"
|
||||
|
||||
# goes through the list of properties and asks relevant question
|
||||
# resolves with all relevant options set
|
||||
# if the property already exists, skips the question
|
||||
askMissingOptions = (properties = []) ->
|
||||
return (options = {}) ->
|
||||
questions = {
|
||||
platform: ask.whichPlatform,
|
||||
version: ask.deployNewVersion,
|
||||
# note: zip file might not be absolute
|
||||
zip: ask.whichZipFile
|
||||
}
|
||||
|
||||
reducer = (memo, property) ->
|
||||
if (check.has(memo, property)) then return memo
|
||||
question = questions[property]
|
||||
if (!check.fn(question)) then return memo
|
||||
la(check.fn(question), "cannot find question for property", property)
|
||||
|
||||
question(memo[property])
|
||||
.then (answer) ->
|
||||
memo[property] = answer
|
||||
memo
|
||||
|
||||
Promise.reduce(properties, reducer, options)
|
||||
|
||||
## hack for @packages/server modifying cwd
|
||||
process.chdir(cwd)
|
||||
|
||||
deploy = {
|
||||
meta: meta
|
||||
Base: Base
|
||||
Darwin: Darwin
|
||||
Linux: Linux
|
||||
|
||||
# getPlatform: (platform, options) ->
|
||||
# platform ?= os.platform()
|
||||
#
|
||||
# Platform = @[platform.slice(0, 1).toUpperCase() + platform.slice(1)]
|
||||
#
|
||||
# throw new Error("Platform: '#{platform}' not found") if not Platform
|
||||
#
|
||||
# options ?= @parseOptions(process.argv.slice(2))
|
||||
#
|
||||
# (new Platform(platform, options))
|
||||
|
||||
parseOptions: (argv) ->
|
||||
opts = minimist(argv)
|
||||
opts.runTests = false if opts["skip-tests"]
|
||||
opts
|
||||
|
||||
bump: ->
|
||||
ask.whichBumpTask()
|
||||
.then (task) ->
|
||||
switch task
|
||||
when "run"
|
||||
bump.run()
|
||||
when "version"
|
||||
ask.whichVersion(meta.distDir)
|
||||
.then (v) ->
|
||||
bump.version(v)
|
||||
|
||||
release: ->
|
||||
## read off the argv
|
||||
options = @parseOptions(process.argv)
|
||||
|
||||
release = (version) =>
|
||||
upload.s3Manifest(version)
|
||||
.then ->
|
||||
success("Release Complete")
|
||||
.catch (err) ->
|
||||
fail("Release Failed")
|
||||
reject(err)
|
||||
|
||||
if v = options.version
|
||||
release(v)
|
||||
else
|
||||
ask.whichRelease(meta.distDir)
|
||||
.then(release)
|
||||
|
||||
build: (options) ->
|
||||
console.log('#build')
|
||||
if !options then options = @parseOptions(process.argv)
|
||||
askMissingOptions(['version', 'platform'])(options)
|
||||
.then () ->
|
||||
build(options.platform, options.version)
|
||||
|
||||
zip: (options) ->
|
||||
console.log('#zip')
|
||||
if !options then options = @parseOptions(process.argv)
|
||||
askMissingOptions(['platform'])(options)
|
||||
.then (options) ->
|
||||
zipDir = meta.zipDir(options.platform)
|
||||
options.zip = path.resolve(zippedFilename(options.platform))
|
||||
zip.ditto(zipDir, options.zip)
|
||||
|
||||
upload: (options) ->
|
||||
console.log('#upload')
|
||||
if !options then options = @parseOptions(process.argv)
|
||||
askMissingOptions(['version', 'platform', 'zip'])(options)
|
||||
.then (options) ->
|
||||
la(check.unemptyString(options.zip),
|
||||
"missing zipped filename", options)
|
||||
options.zip = path.resolve(options.zip)
|
||||
options
|
||||
.then (options) ->
|
||||
console.log("Need to upload file %s", options.zip)
|
||||
console.log("for platform %s version %s",
|
||||
options.platform, options.version)
|
||||
|
||||
upload.toS3({
|
||||
zipFile: options.zip,
|
||||
version: options.version,
|
||||
platform: options.platform
|
||||
})
|
||||
|
||||
# goes through the entire pipeline:
|
||||
# - build
|
||||
# - zip
|
||||
# - upload
|
||||
deploy: ->
|
||||
options = @parseOptions(process.argv)
|
||||
askMissingOptions(['version', 'platform'])(options)
|
||||
.then(build)
|
||||
.then(() => @zip(options))
|
||||
# assumes options.zip contains the zipped filename
|
||||
.then(upload)
|
||||
}
|
||||
|
||||
module.exports = _.bindAll(deploy, _.functions(deploy))
|
||||
118
scripts/binary/linux.coffee
Normal file
118
scripts/binary/linux.coffee
Normal file
@@ -0,0 +1,118 @@
|
||||
fs = require("fs")
|
||||
cp = require("child_process")
|
||||
path = require("path")
|
||||
Xvfb = require("xvfb")
|
||||
chalk = require("chalk")
|
||||
vagrant = require("vagrant")
|
||||
Promise = require("bluebird")
|
||||
Base = require("./base")
|
||||
|
||||
fs = Promise.promisifyAll(fs)
|
||||
|
||||
vagrant.debug = true
|
||||
["rsync", "rsync-auto", "rsync-back"].forEach (cmd) ->
|
||||
vagrant[cmd] = vagrant._runWithArgs(cmd)
|
||||
|
||||
class Linux extends Base
|
||||
buildPathForElectron: ->
|
||||
@buildPathToApp()
|
||||
|
||||
buildPathToApp: ->
|
||||
path.join @buildPathToAppFolder() #, "Cypress"
|
||||
|
||||
buildPathToAppExecutable: ->
|
||||
path.join @buildPathToApp(), "Cypress"
|
||||
|
||||
buildPathToAppResources: ->
|
||||
path.join @buildPathToApp(), "resources", "app"
|
||||
|
||||
codeSign: ->
|
||||
Promise.resolve()
|
||||
|
||||
runProjectTest: ->
|
||||
@_runProjectTest()
|
||||
.catch (err) =>
|
||||
@tryXvfb(@_runProjectTest)
|
||||
|
||||
runFailingProjectTest: ->
|
||||
@_runFailingProjectTest()
|
||||
.catch (err) =>
|
||||
@tryXvfb(@_runFailingProjectTest)
|
||||
|
||||
tryXvfb: (p) ->
|
||||
console.log("tryXvfb")
|
||||
xvfb = new Xvfb()
|
||||
xvfb = Promise.promisifyAll(xvfb)
|
||||
xvfb.startAsync()
|
||||
.then (xvfbProcess) =>
|
||||
console.log("executing in xvfb process %j", xvfbProcess)
|
||||
Promise.try(p.bind(@))
|
||||
.finally ->
|
||||
console.log("stopping xvfb")
|
||||
xvfb.stopAsync()
|
||||
|
||||
runSmokeTest: ->
|
||||
## if we fail assume perhaps
|
||||
## its due to not starting xvfb
|
||||
@_runSmokeTest()
|
||||
.catch =>
|
||||
@tryXvfb(@_runSmokeTest)
|
||||
|
||||
npm: ->
|
||||
new Promise (resolve, reject) ->
|
||||
vagrant.ssh ["-c", "cd /cypress-app && npm install"], (code) ->
|
||||
if code isnt 0
|
||||
reject("vagrant.rsync failed!")
|
||||
else
|
||||
resolve()
|
||||
|
||||
rsync: ->
|
||||
new Promise (resolve, reject) ->
|
||||
vagrant.rsync (code) ->
|
||||
if code isnt 0
|
||||
reject("vagrant.rsync failed!")
|
||||
else
|
||||
resolve()
|
||||
|
||||
rsyncBack: ->
|
||||
new Promise (resolve, reject) ->
|
||||
vagrant["rsync-back"] (code) ->
|
||||
if code isnt 0
|
||||
reject("vagrant.rsync-back failed!")
|
||||
else
|
||||
resolve()
|
||||
|
||||
deploy: ->
|
||||
version = @options.version
|
||||
|
||||
getOpts = =>
|
||||
if @options.runTests is false
|
||||
"--skip-tests"
|
||||
else
|
||||
""
|
||||
|
||||
deploy = =>
|
||||
new Promise (resolve, reject) =>
|
||||
ssh = ->
|
||||
vagrant.ssh ["-c", "cd /cypress-app && ./node_modules/.bin/gulp build --version #{version} #{getOpts()}"], (code) ->
|
||||
if code isnt 0
|
||||
reject("vagrant.ssh gulp build failed!")
|
||||
else
|
||||
resolve()
|
||||
|
||||
vagrant.status (code) ->
|
||||
if code isnt 0
|
||||
vagrant.up (code) ->
|
||||
reject("vagrant.up failed!") if code isnt 0
|
||||
ssh()
|
||||
else
|
||||
ssh()
|
||||
|
||||
@npm()
|
||||
.bind(@)
|
||||
.then(@rsync)
|
||||
.then(deploy)
|
||||
.then(@rsyncBack)
|
||||
.return(@)
|
||||
|
||||
module.exports = Linux
|
||||
6
scripts/binary/log.coffee
Normal file
6
scripts/binary/log.coffee
Normal file
@@ -0,0 +1,6 @@
|
||||
chalk = require("chalk")
|
||||
|
||||
module.exports = (msg, color = "yellow") ->
|
||||
return if process.env["NODE_ENV"] is "test"
|
||||
|
||||
console.log chalk[color](msg), chalk.bgWhite(chalk.black(@osName))
|
||||
48
scripts/binary/meta.coffee
Normal file
48
scripts/binary/meta.coffee
Normal file
@@ -0,0 +1,48 @@
|
||||
path = require("path")
|
||||
la = require("lazy-ass")
|
||||
check = require("check-more-types")
|
||||
|
||||
isValidPlatform = check.oneOf(["darwin", "linux"])
|
||||
|
||||
## returns a path into the /build directory
|
||||
## the output folder should look something like this
|
||||
## build/
|
||||
## <platform>/ = linux or darwin
|
||||
## ... platform-specific files
|
||||
buildDir = (platform, args...) ->
|
||||
la(isValidPlatform(platform), "invalid platform", platform)
|
||||
switch platform
|
||||
when "darwin"
|
||||
path.resolve("build", platform, args...)
|
||||
when "linux"
|
||||
path.resolve("build", platform, "Cypress", args...)
|
||||
|
||||
## returns a path into the /dist directory
|
||||
distDir = (platform, args...) ->
|
||||
path.resolve("dist", platform, args...)
|
||||
|
||||
## returns folder to zip before uploading
|
||||
zipDir = (platform) ->
|
||||
switch platform
|
||||
when "darwin"
|
||||
buildDir(platform, "Cypress.app")
|
||||
when "linux"
|
||||
buildDir(platform)
|
||||
|
||||
## returns a path into the /build/*/app directory
|
||||
## specific to each platform
|
||||
buildAppDir = (platform, args...) ->
|
||||
switch platform
|
||||
when "darwin"
|
||||
buildDir(platform, "Cypress.app", "Contents", "resources", "app", args...)
|
||||
when "linux"
|
||||
buildDir(platform, "resources", "app", args...)
|
||||
|
||||
module.exports = {
|
||||
isValidPlatform
|
||||
buildDir
|
||||
distDir
|
||||
zipDir
|
||||
buildAppDir
|
||||
cacheDir: path.join(process.cwd(), "cache")
|
||||
}
|
||||
140
scripts/binary/upload.coffee
Normal file
140
scripts/binary/upload.coffee
Normal file
@@ -0,0 +1,140 @@
|
||||
awspublish = require('gulp-awspublish')
|
||||
rename = require('gulp-rename')
|
||||
debug = require('gulp-debug')
|
||||
fs = require("fs-extra")
|
||||
cp = require("child_process")
|
||||
path = require("path")
|
||||
gulp = require("gulp")
|
||||
human = require("human-interval")
|
||||
konfig = require("@packages/server/lib/konfig")
|
||||
Promise = require("bluebird")
|
||||
meta = require("./meta")
|
||||
la = require("lazy-ass")
|
||||
check = require("check-more-types")
|
||||
|
||||
fs = Promise.promisifyAll(fs)
|
||||
|
||||
uploadNames = {
|
||||
darwin: "osx64"
|
||||
linux: "linux64"
|
||||
win32: "win64"
|
||||
}
|
||||
|
||||
getUploadNameByOs = (os) ->
|
||||
name = uploadNames[os]
|
||||
if not name
|
||||
throw new Error("Cannot find upload name for OS #{os}")
|
||||
name
|
||||
|
||||
module.exports = {
|
||||
getPublisher: ->
|
||||
aws = @getAwsObj()
|
||||
|
||||
awspublish.create {
|
||||
httpOptions: {
|
||||
timeout: human("10 minutes")
|
||||
}
|
||||
params: {
|
||||
Bucket: aws.bucket
|
||||
}
|
||||
accessKeyId: aws.key
|
||||
secretAccessKey: aws.secret
|
||||
}
|
||||
|
||||
getAwsObj: ->
|
||||
fs.readJsonSync("./support/aws-credentials.json")
|
||||
|
||||
# store uploaded application in subfolders by platform and version
|
||||
# something like desktop/0.20.1/osx64/
|
||||
getUploadDirName: ({version, platform}) ->
|
||||
aws = @getAwsObj()
|
||||
osName = getUploadNameByOs(platform)
|
||||
dirName = [aws.folder, version, osName, null].join("/")
|
||||
console.log("target directory %s", dirName)
|
||||
dirName
|
||||
|
||||
purgeCache: ({zipFile, version, platform}) ->
|
||||
la(check.unemptyString(platform), "missing platform", platform)
|
||||
new Promise (resolve, reject) =>
|
||||
zipName = path.basename(zipFile)
|
||||
|
||||
url = [konfig('cdn_url'), "desktop", version, platform, zipName].join("/")
|
||||
console.log("purging url", url)
|
||||
configFile = path.resolve("support", ".cfcli.yml")
|
||||
cp.exec "cfcli purgefile -c #{configFile} #{url}", (err, stdout, stderr) ->
|
||||
if err
|
||||
console.error("Could not purge #{url}")
|
||||
console.error(err.message)
|
||||
return reject(err)
|
||||
console.log("#purgeCache: #{url}")
|
||||
resolve()
|
||||
|
||||
createRemoteManifest: (folder, version) ->
|
||||
## TODO: refactor this
|
||||
zipName = "cypress.zip"
|
||||
|
||||
getUrl = (uploadOsName) ->
|
||||
{
|
||||
url: [konfig('cdn_url'), folder, version, uploadOsName, zipName].join("/")
|
||||
}
|
||||
|
||||
obj = {
|
||||
name: "Cypress"
|
||||
version: version
|
||||
packages: {
|
||||
mac: getUrl("osx64")
|
||||
win: getUrl("win64")
|
||||
linux64: getUrl("linux64")
|
||||
}
|
||||
}
|
||||
|
||||
src = path.join(meta.buildDir, "manifest.json")
|
||||
fs.outputJsonAsync(src, obj).return(src)
|
||||
|
||||
s3Manifest: (version) ->
|
||||
publisher = @getPublisher()
|
||||
|
||||
aws = @getAwsObj()
|
||||
|
||||
headers = {}
|
||||
headers["Cache-Control"] = "no-cache"
|
||||
|
||||
new Promise (resolve, reject) =>
|
||||
@createRemoteManifest(aws.folder, version).then (src) ->
|
||||
gulp.src(src)
|
||||
.pipe rename (p) ->
|
||||
p.dirname = aws.folder + "/" + p.dirname
|
||||
p
|
||||
.pipe debug()
|
||||
.pipe publisher.publish(headers)
|
||||
.pipe awspublish.reporter()
|
||||
.on "error", reject
|
||||
.on "end", resolve
|
||||
|
||||
toS3: ({zipFile, version, platform}) ->
|
||||
console.log("#uploadToS3 ⏳")
|
||||
la(check.unemptyString(version), "expected version string", version)
|
||||
la(check.unemptyString(zipFile), "expected zip filename", zipFile)
|
||||
la(meta.isValidPlatform(platform), "invalid platform", platform)
|
||||
|
||||
upload = =>
|
||||
new Promise (resolve, reject) =>
|
||||
publisher = @getPublisher()
|
||||
|
||||
headers = {}
|
||||
headers["Cache-Control"] = "no-cache"
|
||||
|
||||
gulp.src(zipFile)
|
||||
.pipe rename (p) =>
|
||||
p.dirname = @getUploadDirName({version, platform})
|
||||
p
|
||||
.pipe debug()
|
||||
.pipe publisher.publish(headers)
|
||||
.pipe awspublish.reporter()
|
||||
.on "error", reject
|
||||
.on "end", resolve
|
||||
|
||||
upload()
|
||||
.then =>
|
||||
@purgeCache({zipFile, version, platform})
|
||||
}
|
||||
167
scripts/binary/util/packages.coffee
Normal file
167
scripts/binary/util/packages.coffee
Normal file
@@ -0,0 +1,167 @@
|
||||
_ = require("lodash")
|
||||
fs = require("fs-extra")
|
||||
cp = require("child_process")
|
||||
path = require("path")
|
||||
glob = require("glob")
|
||||
Promise = require("bluebird")
|
||||
la = require("lazy-ass")
|
||||
check = require("check-more-types")
|
||||
|
||||
fs = Promise.promisifyAll(fs)
|
||||
glob = Promise.promisify(glob)
|
||||
|
||||
DEFAULT_PATHS = "package.json".split(" ")
|
||||
|
||||
pathToPackageJson = (pkg) ->
|
||||
path.join(pkg, "package.json")
|
||||
|
||||
npmRun = (args, cwd) ->
|
||||
new Promise (resolve, reject) ->
|
||||
reject = _.once(reject)
|
||||
|
||||
cp.spawn("npm", args, { stdio: "inherit", cwd })
|
||||
.on "error", reject
|
||||
.on "exit", (code) ->
|
||||
if code is 0
|
||||
resolve()
|
||||
else
|
||||
msg = "npm " + args.join(" ") + " failed with exit code: #{code}"
|
||||
reject(new Error(msg))
|
||||
|
||||
|
||||
runAllBuildJs = _.partial(npmRun, ["run", "all", "build-js"])
|
||||
|
||||
# removes transpiled JS files in the original package folders
|
||||
runAllCleanJs = _.partial(npmRun, ["run", "all", "clean-js"])
|
||||
|
||||
# builds all the packages except for cli and docs
|
||||
runAllBuild = _.partial(npmRun,
|
||||
["run", "all", "build", "--", "--serial", "--skip-packages", "cli,docs"])
|
||||
|
||||
copyAllToDist = (distDir) ->
|
||||
copyRelativePathToDist = (relative) ->
|
||||
dest = path.join(distDir, relative)
|
||||
|
||||
console.log(relative, "->", dest)
|
||||
|
||||
fs.copyAsync(relative, dest)
|
||||
|
||||
copyPackage = (pkg) ->
|
||||
## copies the package to dist
|
||||
## including the default paths
|
||||
## and any specified in package.json files
|
||||
fs.readJsonAsync(pathToPackageJson(pkg))
|
||||
.then (json) ->
|
||||
## grab all the files
|
||||
## and default included paths
|
||||
## and convert to relative paths
|
||||
DEFAULT_PATHS
|
||||
.concat(json.files or [])
|
||||
.concat(json.main or [])
|
||||
.map (file) ->
|
||||
path.join(pkg, file)
|
||||
.map(copyRelativePathToDist, {concurrency: 1})
|
||||
|
||||
## fs-extra concurrency tests (copyPackage / copyRelativePathToDist)
|
||||
## 1/1 41688
|
||||
## 1/5 42218
|
||||
## 1/10 42566
|
||||
## 2/1 45041
|
||||
## 2/2 43589
|
||||
## 3/3 51399
|
||||
|
||||
## cp -R concurrency tests
|
||||
## 1/1 65811
|
||||
|
||||
started = new Date()
|
||||
|
||||
fs.ensureDirAsync(distDir)
|
||||
.then ->
|
||||
glob("./packages/*")
|
||||
.map(copyPackage, {concurrency: 1})
|
||||
.then ->
|
||||
console.log("Finished Copying", new Date() - started)
|
||||
|
||||
npmInstallAll = (pathToPackages) ->
|
||||
## 1,060,495,784 bytes (1.54 GB on disk) for 179,156 items
|
||||
## 313,416,512 bytes (376.6 MB on disk) for 23,576 items
|
||||
|
||||
console.log("npmInstallAll packages in #{pathToPackages}")
|
||||
|
||||
started = new Date()
|
||||
|
||||
retryGlobbing = ->
|
||||
glob(pathToPackages)
|
||||
.catch {code: "EMFILE"}, ->
|
||||
## wait 1 second then retry
|
||||
Promise
|
||||
.delay(1000)
|
||||
.then(retryGlobbing)
|
||||
|
||||
|
||||
retryNpmInstall = (pkg) ->
|
||||
npmInstall = _.partial(npmRun, ["install", "--production"])
|
||||
npmInstall(pkg)
|
||||
.catch {code: "EMFILE"}, ->
|
||||
Promise
|
||||
.delay(1000)
|
||||
.then ->
|
||||
retryNpmInstall(pkg)
|
||||
.catch (err) ->
|
||||
console.log(err, err.code)
|
||||
throw err
|
||||
|
||||
## prunes out all of the devDependencies
|
||||
## from what was copied
|
||||
retryGlobbing()
|
||||
.map(retryNpmInstall)
|
||||
.then ->
|
||||
console.log("Finished NPM Installing", new Date() - started)
|
||||
|
||||
removePackageJson = (filename) ->
|
||||
if filename.endsWith("/package.json") then path.dirname(filename) else filename
|
||||
|
||||
ensureFoundSomething = (files) ->
|
||||
if files.length == 0
|
||||
throw new Error("Could not find any files")
|
||||
files
|
||||
|
||||
symlinkAll = (pathToDistPackages, pathTo) ->
|
||||
console.log("symlink these packages", pathToDistPackages)
|
||||
la(check.unemptyString(pathToDistPackages),
|
||||
"missing paths to dist packages", pathToDistPackages)
|
||||
|
||||
baseDir = path.dirname(pathTo())
|
||||
toBase = path.relative.bind(null, baseDir)
|
||||
|
||||
symlink = (pkg) ->
|
||||
# console.log(pkg, dist)
|
||||
## strip off the initial './'
|
||||
## ./packages/foo -> node_modules/@packages/foo
|
||||
pkg = removePackageJson(pkg)
|
||||
dest = pathTo("node_modules", "@packages", path.basename(pkg))
|
||||
|
||||
console.log(toBase(pkg), "link ->", toBase(dest))
|
||||
fs.ensureSymlinkAsync(pkg, dest)
|
||||
.catch((err) ->
|
||||
if not err.message.includes "EEXIST"
|
||||
throw err
|
||||
)
|
||||
|
||||
glob(pathToDistPackages)
|
||||
.then(ensureFoundSomething)
|
||||
.map(symlink)
|
||||
|
||||
module.exports = {
|
||||
runAllBuild
|
||||
|
||||
runAllBuildJs
|
||||
|
||||
copyAllToDist
|
||||
|
||||
npmInstallAll
|
||||
|
||||
symlinkAll
|
||||
|
||||
runAllCleanJs
|
||||
}
|
||||
61
scripts/binary/zip.coffee
Normal file
61
scripts/binary/zip.coffee
Normal file
@@ -0,0 +1,61 @@
|
||||
cp = require("child_process")
|
||||
Promise = require("bluebird")
|
||||
os = require("os")
|
||||
execa = require("execa")
|
||||
|
||||
# resolves with zipped filename
|
||||
macZip = (src, dest) ->
|
||||
new Promise (resolve, reject) =>
|
||||
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}"
|
||||
console.log(zip)
|
||||
cp.exec zip, {}, (err, stdout, stderr) ->
|
||||
return reject(err) if err
|
||||
|
||||
console.log("✅ ditto zip finished")
|
||||
resolve(dest)
|
||||
|
||||
# resolves with zipped filename
|
||||
linuxZip = (src, dest) ->
|
||||
cmd = "tar -zcvf #{dest} #{src}"
|
||||
console.log("linux zip: #{cmd}")
|
||||
execa.shell(cmd)
|
||||
.then((result) ->
|
||||
console.log("✅ tar finished")
|
||||
dest
|
||||
)
|
||||
.catch((err) ->
|
||||
console.error("⛔️ could not zip #{src} into #{dest}")
|
||||
console.error(err.message)
|
||||
throw err
|
||||
)
|
||||
|
||||
zippers = {
|
||||
# until the CLI tool can unzip both ".zip" and ".tar.gz" files,
|
||||
# must use Mac platform to build the .zip file
|
||||
linux: macZip,
|
||||
darwin: macZip
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user