Skip to content

Commit

Permalink
feat: add cloud recommendation message to CI output (#24680)
Browse files Browse the repository at this point in the history
  • Loading branch information
astone123 authored Nov 18, 2022
1 parent e3435b6 commit bf6a52a
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cli/types/cypress-npm-api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ declare namespace CypressCommandLine {
startedAt: dateTimeISO
endedAt: dateTimeISO
duration: ms
wallClockDuration?: number
}
/**
* Reporter name like "spec"
Expand Down Expand Up @@ -259,8 +260,10 @@ declare namespace CypressCommandLine {
* resolved filename of the spec
*/
absolute: string
relativeToCommonRoot: string
}
shouldUploadVideo: boolean
skippedSpec: boolean
}

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/config/test/project/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import path from 'node:path'
const debug = Debug('test')

describe('config/src/project/utils', () => {
beforeEach(function () {
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS
})

before(function () {
this.env = process.env;

Expand Down
4 changes: 4 additions & 0 deletions packages/config/test/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import {
} from '../src/project/utils'

describe('config/src/utils', () => {
beforeEach(function () {
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS
})

describe('hideKeys', () => {
it('removes middle part of the string', () => {
const hidden = hideKeys('12345-xxxx-abcde')
Expand Down
56 changes: 56 additions & 0 deletions packages/server/__snapshots__/cypress_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,59 @@ exports['Long Cypress Cloud URL'] = `
Recorded Run: http://cloud.cypress.io/this-is-a-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-long-url
`

exports['CLOUD_RECOMMENDATION_MESSAGE'] = `
====================================================================================================
(Run Starting)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Cypress: 1.2.3 │
│ Browser: FooBrowser 88 │
│ Specs: 1 found (test1.js) │
│ Searched: tests/test1.js │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
────────────────────────────────────────────────────────────────────────────────────────────────────
Running: test1.js (1 of 1)
(Results)
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Tests: undefined │
│ Passing: undefined │
│ Failing: 1 │
│ Pending: undefined │
│ Skipped: undefined │
│ Screenshots: 0 │
│ Video: false │
│ Duration: undefined seconds │
│ Spec Ran: test1.js │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
====================================================================================================
(Run Finished)
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✖ test1.js XX:XX - - 1 - - │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
✖ 1 of 1 failed (100%) XX:XX - - 1 - -
----------------------------------------------------------------------------------------------------
Having trouble debugging your CI failures?
Record your runs to Cypress Cloud to watch video recordings for each test,
debug failing and flaky tests, and integrate with your favorite tools.
>> https://on.cypress.io/cloud-get-started
----------------------------------------------------------------------------------------------------
`
1 change: 1 addition & 0 deletions packages/server/lib/modes/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,7 @@ async function ready (options: { projectRoot: string, record: boolean, key: stri

if (!options.quiet) {
printResults.renderSummaryTable(runUrl, results)
printResults.maybeLogCloudRecommendationMessage(results.runs || [], record)
}

return results
Expand Down
5 changes: 5 additions & 0 deletions packages/server/lib/util/ci_provider.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const _ = require('lodash')
const isCi = require('is-ci')
const debug = require('debug')('cypress:server')

const getIsCi = () => isCi

const join = (char, ...pieces) => {
return _.chain(pieces).compact().join(char).value()
}
Expand Down Expand Up @@ -668,6 +671,8 @@ const detectableCiBuildIdProviders = () => {
}

module.exports = {
getIsCi,

list,

provider,
Expand Down
26 changes: 24 additions & 2 deletions packages/server/lib/util/print-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import duration from './duration'
import newlines from './newlines'
import env from './env'
import terminal from './terminal'
import { getIsCi } from './ci_provider'
import * as experiments from '../experiments'
import type { SpecFile } from '@packages/types'
import type { Cfg } from '../project-base'
Expand All @@ -22,11 +23,18 @@ type Screenshot = {
specName: string
}

export const cloudRecommendationMessage = `
Having trouble debugging your CI failures?
Record your runs to Cypress Cloud to watch video recordings for each test,
debug failing and flaky tests, and integrate with your favorite tools.
`

function color (val: any, c: string) {
return chalk[c](val)
}

function gray (val: any) {
export function gray (val: any) {
return color(val, 'gray')
}

Expand Down Expand Up @@ -274,7 +282,21 @@ export function displaySpecHeader (name: string, curr: number, total: number, es
}
}

export function renderSummaryTable (runUrl: string | undefined, results: any) {
export function maybeLogCloudRecommendationMessage (runs: CypressCommandLine.RunResult[], record: boolean) {
if (!getIsCi() || env.get('CYPRESS_COMMERCIAL_RECOMMENDATIONS') === '0' || record) {
return
}

if (runs.some((run) => run.stats.failures > 0)) {
terminal.divider('-')
console.log(cloudRecommendationMessage)
console.log(` >>`, color('https://on.cypress.io/cloud-get-started', 'cyan'))
console.log('')
terminal.divider('-')
}
}

export function renderSummaryTable (runUrl: string | undefined, results: CypressCommandLine.CypressRunResult) {
const { runs } = results

console.log('')
Expand Down
1 change: 1 addition & 0 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"http-proxy": "https://github.com/cypress-io/node-http-proxy.git#9322b4b69b34f13a6f3874e660a35df3305179c6",
"human-interval": "1.0.0",
"image-size": "0.8.3",
"is-ci": "^3.0.0",
"is-fork-pr": "2.5.0",
"is-html": "2.0.0",
"jimp": "0.14.0",
Expand Down
77 changes: 77 additions & 0 deletions packages/server/test/integration/cypress_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const electronApp = require('../../lib/util/electron-app')
const savedState = require(`../../lib/saved_state`)
const { getCtx, clearCtx, setCtx, makeDataContext } = require(`../../lib/makeDataContext`)
const { BrowserCriClient } = require(`../../lib/browsers/browser-cri-client`)
const { cloudRecommendationMessage } = require('../../lib/util/print-run')

const TYPICAL_BROWSERS = [
{
Expand Down Expand Up @@ -349,6 +350,58 @@ describe('lib/cypress', () => {
sinon.stub(commitInfo, 'getRemoteOrigin').resolves('remoteOrigin')
})

describe('cloud recommendation message', () => {
it('gets logged when in CI and there is a failure', function () {
const relativePath = path.relative(cwd(), this.todosPath)

sinon.stub(ciProvider, 'getIsCi').returns(true)
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS
globalThis.CY_TEST_MOCK.listenForProjectEnd = { stats: { failures: 1 } }

return cypress.start([`--run-project=${this.todosPath}`, `--spec=${relativePath}/tests/test1.js`]).then(() => {
expect(console.log).to.be.calledWith(cloudRecommendationMessage)

snapshotConsoleLogs('CLOUD_RECOMMENDATION_MESSAGE')
})
})

it('does not get logged if CYPRESS_COMMERCIAL_RECOMMENDATIONS is set to 0', function () {
const relativePath = path.relative(cwd(), this.todosPath)

sinon.stub(ciProvider, 'getIsCi').returns(true)
process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS = '0'
globalThis.CY_TEST_MOCK.listenForProjectEnd = { stats: { failures: 1 } }

return cypress.start([`--run-project=${this.todosPath}`, `--spec=${relativePath}/tests/test1.js`]).then(() => {
expect(console.log).not.to.be.calledWith(cloudRecommendationMessage)
})
})

it('does not get logged if all tests pass', function () {
const relativePath = path.relative(cwd(), this.todosPath)

sinon.stub(ciProvider, 'getIsCi').returns(true)
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS
globalThis.CY_TEST_MOCK.listenForProjectEnd = { stats: { failures: 0 } }

return cypress.start([`--run-project=${this.todosPath}`, `--spec=${relativePath}/tests/test1.js`]).then(() => {
expect(console.log).not.to.be.calledWith(cloudRecommendationMessage)
})
})

it('does not get logged if not running in CI', function () {
const relativePath = path.relative(cwd(), this.todosPath)

sinon.stub(ciProvider, 'getIsCi').returns(undefined)
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS
globalThis.CY_TEST_MOCK.listenForProjectEnd = { stats: { failures: 1 } }

return cypress.start([`--run-project=${this.todosPath}`, `--spec=${relativePath}/tests/test1.js`]).then(() => {
expect(console.log).not.to.be.calledWith(cloudRecommendationMessage)
})
})
})

it('runs project headlessly and exits with exit code 0', function () {
return cypress.start([`--run-project=${this.todosPath}`])
.then(() => {
Expand Down Expand Up @@ -881,6 +934,10 @@ describe('lib/cypress', () => {
})

describe('config overrides', () => {
beforeEach(function () {
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS
})

it('can override default values', function () {
return cypress.start([`--run-project=${this.todosPath}`, '--config=requestTimeout=1234,videoCompression=false'])
.then(() => {
Expand Down Expand Up @@ -1069,6 +1126,7 @@ describe('lib/cypress', () => {
describe('--env', () => {
beforeEach(() => {
process.env = _.omit(process.env, 'CYPRESS_DEBUG')
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS

globalThis.CY_TEST_MOCK.listenForProjectEnd = { stats: { failures: 0 } }
})
Expand Down Expand Up @@ -1566,6 +1624,25 @@ describe('lib/cypress', () => {
return snapshotConsoleLogs('CLOUD_STALE_RUN 1')
})
})

describe('cloud recommendation message', () => {
it('does not display if --record is passed', function () {
sinon.stub(ciProvider, 'getIsCi').returns(true)
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS
globalThis.CY_TEST_MOCK.listenForProjectEnd = { stats: { failures: 1 } }

return cypress.start([
`--run-project=${this.recordPath}`,
'--record',
'--key=token-123',
'--group=electron-smoke-tests',
'--ciBuildId=ciBuildId123',
])
.then(() => {
expect(console.log).not.to.be.calledWith(cloudRecommendationMessage)
})
})
})
})

context('--return-pkg', () => {
Expand Down
2 changes: 2 additions & 0 deletions packages/server/test/unit/config_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ describe('lib/config', () => {

context('.get', () => {
beforeEach(async function () {
delete process.env.CYPRESS_COMMERCIAL_RECOMMENDATIONS

this.ctx = getCtx()

this.projectRoot = '/_test-output/path/to/project'
Expand Down
2 changes: 2 additions & 0 deletions tooling/v8-snapshot/src/setup/force-no-rewrite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ export default [
'node_modules/prettier/parser-meriyah.js',
'node_modules/prettier/parser-typescript.js',
'node_modules/prettier/third-party.js',
'packages/server/node_modules/is-ci/index.js',
'packages/server/node_modules/ci-info/index.js',
]

5 comments on commit bf6a52a

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on bf6a52a Nov 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/11.2.0/linux-arm64/develop-bf6a52ab3d6b674985042c2871be4f36ade7652a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on bf6a52a Nov 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/11.2.0/linux-x64/develop-bf6a52ab3d6b674985042c2871be4f36ade7652a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on bf6a52a Nov 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/11.2.0/darwin-x64/develop-bf6a52ab3d6b674985042c2871be4f36ade7652a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on bf6a52a Nov 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/11.2.0/win32-x64/develop-bf6a52ab3d6b674985042c2871be4f36ade7652a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on bf6a52a Nov 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/11.2.0/darwin-arm64/develop-bf6a52ab3d6b674985042c2871be4f36ade7652a/cypress.tgz

Please sign in to comment.