Files
cypress/scripts/binary/util/upload.coffee
Gleb Bahmutov ebaa7a375c Copy test runner binaries before releasing new version (#4082)
* adding S3 sdk

* test binary folder

* linting

* before searching for binary

* linting

* grab folders in the given S3 prefix

* grab folders in the given S3 prefix

* find the last build

* found last builds for commit

* refactoring

* add tests for upload dir name

* create destination zip filename

* copying S3 files

* move s3 helpers into own object, prepare for testing

* add realistic test

* linting

* chore: add documentation to DEPLOY.md file
2019-05-01 10:14:25 -04:00

175 lines
5.7 KiB
CoffeeScript

_ = require("lodash")
path = require("path")
awspublish = require('gulp-awspublish')
human = require("human-interval")
la = require("lazy-ass")
check = require("check-more-types")
cp = require("child_process")
fs = require("fs")
os = require("os")
Promise = require("bluebird")
{configFromEnvOrJsonFile, filenameToShellVariable} = require('@cypress/env-or-json-file')
konfig = require('../../binary/get-config')()
formHashFromEnvironment = () ->
env = process.env
if env.BUILDKITE
return "buildkite-#{env.BUILDKITE_BRANCH}-#{env.BUILDKITE_COMMIT}-#{env.BUILDKITE_BUILD_NUMBER}"
if env.CIRCLECI
return "circle-#{env.CIRCLE_BRANCH}-#{env.CIRCLE_SHA1}-#{env.CIRCLE_BUILD_NUM}"
if env.APPVEYOR
return "appveyor-#{env.APPVEYOR_REPO_BRANCH}-#{env.APPVEYOR_REPO_COMMIT}-#{env.APPVEYOR_BUILD_ID}"
throw new Error("Do not know how to form unique build hash on this CI")
getS3Credentials = () ->
key = path.join('scripts', 'support', 'aws-credentials.json')
config = configFromEnvOrJsonFile(key)
if !config
console.error('⛔️ Cannot find AWS credentials')
console.error('Using @cypress/env-or-json-file module')
console.error('and filename', key)
console.error('which is environment variable', filenameToShellVariable(key))
console.error('available environment variable keys')
console.error(Object.keys(process.env))
throw new Error('AWS config not found')
la(check.unemptyString(config.bucket), 'missing AWS config bucket')
la(check.unemptyString(config.folder), 'missing AWS config folder')
la(check.unemptyString(config.key), 'missing AWS key')
la(check.unemptyString(config.secret), 'missing AWS secret key')
config
getPublisher = (getAwsObj = getS3Credentials) ->
aws = getAwsObj()
# console.log("aws.bucket", aws.bucket)
awspublish.create {
httpOptions: {
timeout: human("10 minutes")
}
params: {
Bucket: aws.bucket
}
accessKeyId: aws.key
secretAccessKey: aws.secret
}
hasCloudflareEnvironmentVars = () ->
check.unemptyString(process.env.CF_TOKEN) &&
check.unemptyString(process.env.CF_EMAIL) &&
check.unemptyString(process.env.CF_DOMAIN)
# depends on the credentials file or environment variables
makeCloudflarePurgeCommand = (url) ->
configFile = path.resolve(__dirname, "..", "support", ".cfcli.yml")
if fs.existsSync(configFile)
console.log("using CF credentials file")
return "cfcli purgefile -c #{configFile} #{url}"
else if hasCloudflareEnvironmentVars()
console.log("using CF environment variables")
token = process.env.CF_TOKEN
email = process.env.CF_EMAIL
domain = process.env.CF_DOMAIN
return "cfcli purgefile -e #{email} -k #{token} -d #{domain} #{url}"
else
throw new Error("Cannot form Cloudflare purge command without credentials")
# purges a given url from Cloudflare
purgeCache = (url) ->
la(check.url(url), "missing url to purge", url)
new Promise (resolve, reject) =>
console.log("purging url", url)
purgeCommand = makeCloudflarePurgeCommand(url)
cp.exec purgeCommand, (err, stdout, stderr) ->
if err
console.error("Could not purge #{url}")
console.error(err.message)
return reject(err)
console.log("#purgeCache: #{url}")
resolve()
getDestktopUrl = (version, osName, zipName) ->
url = [konfig("cdn_url"), "desktop", version, osName, zipName].join("/")
url
# purges desktop application url from Cloudflare cache
purgeDesktopAppFromCache = ({version, platform, zipName}) ->
la(check.unemptyString(version), "missing desktop version", version)
la(check.unemptyString(platform), "missing platform", platform)
la(check.unemptyString(zipName), "missing zip filename")
la(check.extension("zip", zipName),
"zip filename should end with .zip", zipName)
osName = getUploadNameByOsAndArch(platform)
la(check.unemptyString(osName), "missing osName", osName)
url = getDestktopUrl(version, osName, zipName)
purgeCache(url)
# purges links to desktop app for all platforms
# for a given version
purgeDesktopAppAllPlatforms = (version, zipName) ->
la(check.unemptyString(version), "missing desktop version", version)
la(check.unemptyString(zipName), "missing zipName", zipName)
platforms = ["darwin", "linux", "win32"]
console.log("purging all desktop links for version #{version} from Cloudflare")
Promise.mapSeries platforms, (platform) ->
purgeDesktopAppFromCache({version, platform, zipName})
# all architectures we are building test runner for
validPlatformArchs = ["darwin-x64", "linux-x64", "win32-ia32", "win32-x64"]
# simple check for platform-arch string
# example: isValidPlatformArch("darwin") // FALSE
isValidPlatformArch = check.oneOf(validPlatformArchs)
getValidPlatformArchs = () -> validPlatformArchs
getUploadNameByOsAndArch = (platform) ->
## just hard code for now...
arch = os.arch()
uploadNames = {
darwin: {
"x64": "darwin-x64"
},
linux: {
"x64": "linux-x64"
},
win32: {
"x64": "win32-x64",
"ia32": "win32-ia32"
}
}
name = _.get(uploadNames[platform], arch)
if not name
throw new Error("Cannot find upload name for OS: '#{platform}' with arch: '#{arch}'")
la(isValidPlatformArch(name), "formed invalid platform", name, "from", platform, arch)
name
saveUrl = (filename) -> (url) ->
la(check.unemptyString(filename), "missing filename", filename)
la(check.url(url), "invalid url to save", url)
s = JSON.stringify({url})
fs.writeFileSync(filename, s)
console.log("saved url", url)
console.log("into file", filename)
module.exports = {
getS3Credentials,
getPublisher,
purgeCache,
purgeDesktopAppFromCache,
purgeDesktopAppAllPlatforms,
getUploadNameByOsAndArch,
validPlatformArchs,
getValidPlatformArchs,
isValidPlatformArch,
saveUrl,
formHashFromEnvironment
}