mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-13 02:40:22 -05:00
Merge remote-tracking branch 'origin/develop' into merge-develop-2-28-22
This commit is contained in:
@@ -1,268 +0,0 @@
|
||||
const _ = require('lodash')
|
||||
const Promise = require('bluebird')
|
||||
const bumpercar = require('@cypress/bumpercar')
|
||||
const path = require('path')
|
||||
const la = require('lazy-ass')
|
||||
const check = require('check-more-types')
|
||||
const { configFromEnvOrJsonFile, filenameToShellVariable } = require('@cypress/env-or-json-file')
|
||||
const makeEmptyGithubCommit = require('make-empty-github-commit')
|
||||
const parse = require('parse-github-repo-url')
|
||||
const { setCommitStatus } = require('@cypress/github-commit-status-check')
|
||||
|
||||
let car = null
|
||||
|
||||
// all the projects to trigger / run / change environment variables for
|
||||
const _PROVIDERS = {
|
||||
circle: {
|
||||
main: 'cypress-io/cypress',
|
||||
linux: [
|
||||
'cypress-io/cypress-test-module-api',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const remapProjects = function (projectsByProvider) {
|
||||
const list = []
|
||||
|
||||
_.mapValues(projectsByProvider, (provider, name) => {
|
||||
const remapPlatform = (platform, repos) => {
|
||||
return repos.forEach((repo) => {
|
||||
return list.push({
|
||||
repo,
|
||||
provider: name,
|
||||
platform,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (provider.win32) {
|
||||
remapPlatform('win32', provider.win32)
|
||||
}
|
||||
|
||||
if (provider.linux) {
|
||||
remapPlatform('linux', provider.linux)
|
||||
}
|
||||
|
||||
if (provider.darwin) {
|
||||
return remapPlatform('darwin', provider.darwin)
|
||||
}
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
// make flat list of objects
|
||||
// {repo, provider, platform}
|
||||
const PROJECTS = remapProjects(_PROVIDERS)
|
||||
|
||||
const getCiConfig = function () {
|
||||
const key = path.join('scripts', 'support', 'ci.json')
|
||||
const config = configFromEnvOrJsonFile(key)
|
||||
|
||||
if (!config) {
|
||||
console.error('⛔️ Cannot find CI credentials')
|
||||
console.error('Using @cypress/env-or-json-file module')
|
||||
console.error('and filename', key)
|
||||
console.error('which is environment variable', filenameToShellVariable(key))
|
||||
throw new Error('CI config not found')
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
const awaitEachProjectAndProvider = function (projects, fn, filter = (val) => val) {
|
||||
const creds = getCiConfig()
|
||||
|
||||
// configure a new Bumpercar
|
||||
const providers = {}
|
||||
|
||||
if (check.unemptyString(creds.githubToken)) {
|
||||
providers.travis = {
|
||||
githubToken: process.env.GH_TOKEN,
|
||||
}
|
||||
}
|
||||
|
||||
if (check.unemptyString(creds.circleToken)) {
|
||||
providers.circle = {
|
||||
circleToken: creds.circleToken,
|
||||
}
|
||||
}
|
||||
|
||||
const providerNames = Object.keys(providers)
|
||||
|
||||
console.log('configured providers', providerNames)
|
||||
la(check.not.empty(providerNames), 'empty list of providers')
|
||||
|
||||
car = bumpercar.create({ providers })
|
||||
|
||||
const filteredProjects = projects.filter(filter)
|
||||
|
||||
if (check.empty(filteredProjects)) {
|
||||
console.log('⚠️ zero filtered projects left after filtering')
|
||||
}
|
||||
|
||||
console.log('filtered projects:')
|
||||
console.table(filteredProjects)
|
||||
|
||||
return Promise.mapSeries(filteredProjects, (project) => {
|
||||
return fn(project.repo, project.provider, creds)
|
||||
})
|
||||
}
|
||||
|
||||
// do not trigger all projects if there is specific provider
|
||||
const getFilterByProvider = function (providerName, platformName) {
|
||||
return (val) => {
|
||||
if (providerName && val.provider !== providerName) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (platformName && val.platform !== platformName) {
|
||||
return false
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
_PROVIDERS,
|
||||
|
||||
remapProjects,
|
||||
|
||||
getFilterByProvider,
|
||||
|
||||
// in each project, set a couple of environment variables
|
||||
version (nameOrUrl, binaryVersionOrUrl, platform, providerName) {
|
||||
console.log('All possible projects:')
|
||||
console.table(PROJECTS)
|
||||
|
||||
la(check.unemptyString(nameOrUrl),
|
||||
'missing cypress name or url to set', nameOrUrl)
|
||||
|
||||
if (check.semver(nameOrUrl)) {
|
||||
console.log('for version', nameOrUrl)
|
||||
nameOrUrl = `cypress@${nameOrUrl}`
|
||||
console.log('full NPM install name is', nameOrUrl)
|
||||
}
|
||||
|
||||
la(check.unemptyString(binaryVersionOrUrl),
|
||||
'missing binary version or url', binaryVersionOrUrl)
|
||||
|
||||
const result = {
|
||||
versionName: nameOrUrl,
|
||||
binary: binaryVersionOrUrl,
|
||||
}
|
||||
|
||||
const projectFilter = getFilterByProvider(providerName)
|
||||
|
||||
const updateProject = function (project, provider) {
|
||||
console.log('setting environment variables in', project)
|
||||
|
||||
return car.updateProjectEnv(project, provider, {
|
||||
CYPRESS_NPM_PACKAGE_NAME: nameOrUrl,
|
||||
CYPRESS_INSTALL_BINARY: binaryVersionOrUrl,
|
||||
})
|
||||
}
|
||||
|
||||
return awaitEachProjectAndProvider(PROJECTS, updateProject, projectFilter)
|
||||
.then(() => result)
|
||||
},
|
||||
|
||||
// triggers test projects on multiple CIs
|
||||
// the test projects will exercise the new version of
|
||||
// the Cypress test runner we just built
|
||||
runTestProjects (getStatusAndMessage, providerName, version, platform) {
|
||||
const projectFilter = getFilterByProvider(providerName, platform)
|
||||
|
||||
const makeCommit = function (project, provider, creds) {
|
||||
// make empty commit to trigger CIs
|
||||
// project is owner/repo string like cypress-io/cypress-test-tiny
|
||||
console.log('making commit to project', project)
|
||||
|
||||
// print if we have a few github variables present
|
||||
console.log('do we have GH_APP_ID?', Boolean(process.env.GH_APP_ID))
|
||||
console.log('do we have GH_INSTALLATION_ID?', Boolean(process.env.GH_INSTALLATION_ID))
|
||||
console.log('do we have GH_PRIVATE_KEY?', Boolean(process.env.GH_PRIVATE_KEY))
|
||||
console.log('do we have GH_TOKEN?', Boolean(process.env.GH_TOKEN))
|
||||
|
||||
const parsedRepo = parse(project)
|
||||
const owner = parsedRepo[0]
|
||||
const repo = parsedRepo[1]
|
||||
|
||||
let { status, message } = getStatusAndMessage(repo)
|
||||
|
||||
if (!message) {
|
||||
message =
|
||||
`\
|
||||
Testing new Cypress version ${version}
|
||||
\
|
||||
`
|
||||
|
||||
if (process.env.CIRCLE_BUILD_URL) {
|
||||
message += '\n'
|
||||
message += `Circle CI build url ${process.env.CIRCLE_BUILD_URL}`
|
||||
}
|
||||
}
|
||||
|
||||
const defaultOptions = {
|
||||
owner,
|
||||
repo,
|
||||
message,
|
||||
token: process.env.GH_TOKEN,
|
||||
}
|
||||
|
||||
const createGithubCommitStatusCheck = function ({ sha }) {
|
||||
if (!status) {
|
||||
return
|
||||
}
|
||||
|
||||
// status is {owner, repo, sha} and maybe a few other properties
|
||||
const isStatus = check.schema({
|
||||
owner: check.unemptyString,
|
||||
repo: check.unemptyString,
|
||||
sha: check.commitId,
|
||||
context: check.unemptyString,
|
||||
platform: check.unemptyString,
|
||||
arch: check.unemptyString,
|
||||
})
|
||||
|
||||
if (!isStatus(status)) {
|
||||
console.error('Invalid status object %o', status)
|
||||
}
|
||||
|
||||
const targetUrl = `https://github.com/${owner}/${repo}/commit/${sha}`
|
||||
const commitStatusOptions = {
|
||||
targetUrl,
|
||||
owner: status.owner,
|
||||
repo: status.repo,
|
||||
sha: status.sha,
|
||||
context: status.context,
|
||||
state: 'pending',
|
||||
description: `${owner}/${repo}`,
|
||||
}
|
||||
|
||||
console.log(
|
||||
'creating commit status check',
|
||||
commitStatusOptions.description,
|
||||
commitStatusOptions.context,
|
||||
)
|
||||
|
||||
return setCommitStatus(commitStatusOptions)
|
||||
}
|
||||
|
||||
if (!version) {
|
||||
return makeEmptyGithubCommit(defaultOptions).then(createGithubCommitStatusCheck)
|
||||
}
|
||||
|
||||
// first try to commit to branch for next upcoming version
|
||||
return makeEmptyGithubCommit({ ...defaultOptions, branch: version })
|
||||
.catch(() => {
|
||||
// maybe there is no branch for next version
|
||||
// try default branch
|
||||
return makeEmptyGithubCommit(defaultOptions)
|
||||
}).then(createGithubCommitStatusCheck)
|
||||
}
|
||||
|
||||
return awaitEachProjectAndProvider(PROJECTS, makeCommit, projectFilter)
|
||||
},
|
||||
}
|
||||
@@ -16,7 +16,6 @@ const rp = require('@cypress/request-promise')
|
||||
|
||||
const zip = require('./zip')
|
||||
const ask = require('./ask')
|
||||
const bump = require('./bump')
|
||||
const meta = require('./meta')
|
||||
const build = require('./build')
|
||||
const upload = require('./upload')
|
||||
@@ -104,23 +103,6 @@ const deploy = {
|
||||
return opts
|
||||
},
|
||||
|
||||
bump () {
|
||||
return ask.whichBumpTask()
|
||||
.then((task) => {
|
||||
switch (task) {
|
||||
case 'run':
|
||||
return bump.runTestProjects()
|
||||
case 'version':
|
||||
return ask.whichVersion(meta.distDir(''))
|
||||
.then((v) => {
|
||||
return bump.version(v)
|
||||
})
|
||||
default:
|
||||
throw new Error('unknown task')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
release () {
|
||||
// read off the argv
|
||||
const options = this.parseOptions(process.argv)
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
// See ../guides/next-version.md for documentation.
|
||||
|
||||
const path = require('path')
|
||||
const semver = require('semver')
|
||||
const Bluebird = require('bluebird')
|
||||
const bumpCb = require('conventional-recommended-bump')
|
||||
const { promisify } = require('util')
|
||||
|
||||
const currentVersion = require('../package.json').version
|
||||
|
||||
const bump = Bluebird.promisify(bumpCb)
|
||||
const bump = promisify(bumpCb)
|
||||
const paths = ['packages', 'cli']
|
||||
|
||||
let nextVersion
|
||||
@@ -30,14 +31,17 @@ if (require.main !== module) {
|
||||
return
|
||||
}
|
||||
|
||||
Bluebird.mapSeries(paths, async (path) => {
|
||||
const pathNextVersion = await getNextVersionForPath(path)
|
||||
(async () => {
|
||||
process.chdir(path.join(__dirname, '..'))
|
||||
|
||||
if (!nextVersion || semver.gt(pathNextVersion, nextVersion)) {
|
||||
nextVersion = pathNextVersion
|
||||
for (const path of paths) {
|
||||
const pathNextVersion = await getNextVersionForPath(path)
|
||||
|
||||
if (!nextVersion || semver.gt(pathNextVersion, nextVersion)) {
|
||||
nextVersion = pathNextVersion
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
if (!nextVersion) {
|
||||
throw new Error('Unable to determine next version.')
|
||||
}
|
||||
@@ -51,4 +55,4 @@ Bluebird.mapSeries(paths, async (path) => {
|
||||
}
|
||||
|
||||
console.log(nextVersion)
|
||||
})
|
||||
})()
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
const la = require('lazy-ass')
|
||||
const is = require('check-more-types')
|
||||
const { getNameAndBinary, getJustVersion, getShortCommit } = require('./utils')
|
||||
const bump = require('./binary/bump')
|
||||
const { stripIndent } = require('common-tags')
|
||||
const os = require('os')
|
||||
const minimist = require('minimist')
|
||||
const { getInstallJson } = require('@cypress/commit-message-install')
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
// See ../guides/testing-other-projects.md for documentation.
|
||||
|
||||
const { npm, binary } = getNameAndBinary(process.argv)
|
||||
|
||||
la(is.unemptyString(npm), 'missing npm url')
|
||||
la(is.unemptyString(binary), 'missing binary url')
|
||||
const platform = os.platform()
|
||||
const arch = os.arch()
|
||||
|
||||
console.log('bumping versions for other projects')
|
||||
console.log(' npm:', npm)
|
||||
console.log(' binary:', binary)
|
||||
console.log(' platform:', platform)
|
||||
console.log(' arch:', arch)
|
||||
|
||||
const cliOptions = minimist(process.argv, {
|
||||
string: 'provider',
|
||||
alias: {
|
||||
provider: 'p',
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Returns given string surrounded by ```json + ``` quotes
|
||||
* @param {string} s
|
||||
*/
|
||||
const toJsonCodeBlock = (s) => {
|
||||
const start = '```json'
|
||||
const finish = '```'
|
||||
|
||||
return `${start}\n${s}\n${finish}\n`
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts given JSON object into markdown text block
|
||||
* @param {object} object
|
||||
*/
|
||||
const toMarkdownJsonBlock = (object) => {
|
||||
la(object, 'expected an object to convert to JSON', object)
|
||||
const str = JSON.stringify(object, null, 2)
|
||||
|
||||
return toJsonCodeBlock(str)
|
||||
}
|
||||
|
||||
console.log('starting each test projects')
|
||||
|
||||
const shortNpmVersion = getJustVersion(npm)
|
||||
|
||||
console.log('short NPM version', shortNpmVersion)
|
||||
|
||||
let subject = `Testing new ${platform} ${arch} Cypress version ${shortNpmVersion}`
|
||||
const commitInfo = getShortCommit()
|
||||
|
||||
if (commitInfo) {
|
||||
subject += ` ${commitInfo.short}`
|
||||
}
|
||||
|
||||
// instructions for installing this binary,
|
||||
// see "@cypress/commit-message-install"
|
||||
const env = {
|
||||
CYPRESS_INSTALL_BINARY: binary,
|
||||
}
|
||||
|
||||
const getStatusAndMessage = (projectRepoName) => {
|
||||
// also pass "status" object that points back at this repo and this commit
|
||||
// so that other projects can report their test success as GitHub commit status check
|
||||
let status = null
|
||||
const commit = commitInfo && commitInfo.sha
|
||||
|
||||
if (commit && is.commitId(commit)) {
|
||||
// commit is full 40 character hex string
|
||||
const platform = os.platform()
|
||||
const arch = os.arch()
|
||||
|
||||
status = {
|
||||
owner: 'cypress-io',
|
||||
repo: 'cypress',
|
||||
sha: commit,
|
||||
platform,
|
||||
arch,
|
||||
context: `[${platform}-${arch}] ${projectRepoName}`,
|
||||
}
|
||||
}
|
||||
|
||||
const commitMessageInstructions = getInstallJson({
|
||||
packages: npm,
|
||||
env,
|
||||
platform,
|
||||
arch,
|
||||
branch: shortNpmVersion, // use as version as branch name on test projects
|
||||
commit,
|
||||
status,
|
||||
})
|
||||
const jsonBlock = toMarkdownJsonBlock(commitMessageInstructions)
|
||||
const footer =
|
||||
'Use tool `@cypress/commit-message-install` to install from above block'
|
||||
let message = `${subject}\n\n${jsonBlock}\n${footer}\n`
|
||||
|
||||
if (process.env.CIRCLE_BUILD_URL) {
|
||||
message += '\n'
|
||||
message += stripIndent`
|
||||
CircleCI job url: ${process.env.CIRCLE_BUILD_URL}
|
||||
`
|
||||
}
|
||||
|
||||
console.log('commit message:')
|
||||
console.log(message)
|
||||
|
||||
return {
|
||||
status,
|
||||
message,
|
||||
}
|
||||
}
|
||||
|
||||
const onError = (e) => {
|
||||
console.error('could not bump test projects')
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
bump
|
||||
.runTestProjects(
|
||||
getStatusAndMessage,
|
||||
cliOptions.provider,
|
||||
shortNpmVersion,
|
||||
platform,
|
||||
)
|
||||
.catch(onError)
|
||||
@@ -1,48 +0,0 @@
|
||||
const la = require('lazy-ass')
|
||||
const snapshot = require('snap-shot-it')
|
||||
const _ = require('lodash')
|
||||
|
||||
const bump = require('../../binary/bump')
|
||||
|
||||
/* eslint-env mocha */
|
||||
describe('bump', () => {
|
||||
context('remapProjects', () => {
|
||||
it('returns flat list of projects', () => {
|
||||
la(bump._PROVIDERS, 'has _PROVIDERS', bump)
|
||||
const list = bump.remapProjects(bump._PROVIDERS)
|
||||
|
||||
snapshot('list of all projects', list)
|
||||
})
|
||||
})
|
||||
|
||||
context('getFilterByProvider', () => {
|
||||
it('returns a filter function without provider name', () => {
|
||||
const projects = bump.remapProjects(bump._PROVIDERS)
|
||||
const filter = bump.getFilterByProvider()
|
||||
// should return ALL projects
|
||||
const filtered = projects.filter(filter)
|
||||
|
||||
la(
|
||||
_.isEqual(filtered, projects),
|
||||
'should have kept all projects',
|
||||
filtered,
|
||||
)
|
||||
})
|
||||
|
||||
it('returns a filter function for circle and linux', () => {
|
||||
const projects = bump.remapProjects(bump._PROVIDERS)
|
||||
|
||||
la(
|
||||
projects.length,
|
||||
'there should be at least a few projects in the list of projects',
|
||||
projects,
|
||||
)
|
||||
|
||||
const filter = bump.getFilterByProvider('circle', 'linux')
|
||||
const filtered = projects.filter(filter)
|
||||
|
||||
la(filtered.length, 'there should be at least a few projects', filtered)
|
||||
snapshot('should have just circle and linux projects', filtered)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user