mirror of
https://github.com/cypress-io/cypress.git
synced 2026-04-24 07:59:12 -05:00
feat: build Cypress for linux-arm64 (#22252)
This commit is contained in:
@@ -23,6 +23,9 @@ exports['test runner manifest'] = {
|
||||
"linux-x64": {
|
||||
"url": "https://cdn.cypress.io/desktop/3.3.0/linux-x64/cypress.zip"
|
||||
},
|
||||
"linux-arm64": {
|
||||
"url": "https://cdn.cypress.io/desktop/3.3.0/linux-arm64/cypress.zip"
|
||||
},
|
||||
"win32-x64": {
|
||||
"url": "https://cdn.cypress.io/desktop/3.3.0/win32-x64/cypress.zip"
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ exports['upload util isValidPlatformArch checks given strings second 1'] = {
|
||||
"given": "linux-x64",
|
||||
"expect": true
|
||||
},
|
||||
{
|
||||
"given": "linux-arm64",
|
||||
"expect": true
|
||||
},
|
||||
{
|
||||
"given": "win32-x64",
|
||||
"expect": true
|
||||
|
||||
+66
-11
@@ -22,14 +22,13 @@ defaults: &defaults
|
||||
COLUMNS: 100
|
||||
LINES: 24
|
||||
|
||||
# filters and requires for testing binary with Firefox
|
||||
mainBuildFilters: &mainBuildFilters
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- 10.0-release
|
||||
- use-m1-runners
|
||||
- linux-arm64
|
||||
|
||||
# usually we don't build Mac app - it takes a long time
|
||||
# but sometimes we want to really confirm we are doing the right thing
|
||||
@@ -38,14 +37,23 @@ macWorkflowFilters: &darwin-workflow-filters
|
||||
when:
|
||||
or:
|
||||
- equal: [ develop, << pipeline.git.branch >> ]
|
||||
- equal: [ use-m1-runners, << pipeline.git.branch >> ]
|
||||
- equal: [ linux-arm64, << pipeline.git.branch >> ]
|
||||
- matches:
|
||||
pattern: "-release$"
|
||||
value: << pipeline.git.branch >>
|
||||
|
||||
linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
|
||||
when:
|
||||
or:
|
||||
- equal: [ develop, << pipeline.git.branch >> ]
|
||||
- equal: [ linux-arm64, << pipeline.git.branch >> ]
|
||||
- matches:
|
||||
pattern: "-release$"
|
||||
value: << pipeline.git.branch >>
|
||||
|
||||
# uncomment & add to the branch conditions below to disable the main linux
|
||||
# flow if we don't want to test it for a certain branch
|
||||
linuxWorkflowExcludeFilters: &linux-workflow-exclude-filters
|
||||
linuxWorkflowExcludeFilters: &linux-x64-workflow-exclude-filters
|
||||
unless:
|
||||
or:
|
||||
- false
|
||||
@@ -58,7 +66,7 @@ fullWindowsWorkflowFilters: &full-windows-workflow-filters
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- 'use-m1-runners'
|
||||
- 'linux-arm64'
|
||||
- '*-release'
|
||||
- 'win*'
|
||||
|
||||
@@ -108,13 +116,20 @@ executors:
|
||||
environment:
|
||||
PLATFORM: darwin
|
||||
|
||||
linux-arm64:
|
||||
machine:
|
||||
image: ubuntu-2004:2022.04.1
|
||||
resource_class: arm.medium
|
||||
environment:
|
||||
PLATFORM: linux
|
||||
|
||||
commands:
|
||||
verify_should_persist_artifacts:
|
||||
steps:
|
||||
- run:
|
||||
name: Check current branch to persist artifacts
|
||||
command: |
|
||||
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "use-m1-runners" ]]; then
|
||||
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "linux-arm64" ]]; then
|
||||
echo "Not uploading artifacts or posting install comment for this branch."
|
||||
circleci-agent step halt
|
||||
fi
|
||||
@@ -955,12 +970,24 @@ commands:
|
||||
# notarization on Mac can take a while
|
||||
no_output_timeout: "45m"
|
||||
command: |
|
||||
if [[ `node ./scripts/get-platform-key.js` == 'linux-arm64' ]]; then
|
||||
# these are missing on Circle and there is no way to pre-install them on Arm
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb
|
||||
fi
|
||||
node --version
|
||||
yarn binary-build --version $(node ./scripts/get-next-version.js)
|
||||
- run:
|
||||
name: Zip the binary
|
||||
command: |
|
||||
[[ $PLATFORM == 'linux' ]] && apt-get update && apt-get install -y zip || [[ $PLATFORM != 'linux' ]]
|
||||
if [[ $PLATFORM == 'linux' ]]; then
|
||||
# on Arm, CI runs as non-root, on x64 CI runs as root but there is no sudo binary
|
||||
if [[ `whoami` == 'root' ]]; then
|
||||
apt-get update && apt-get install -y zip
|
||||
else
|
||||
sudo apt-get update && sudo apt-get install -y zip
|
||||
fi
|
||||
fi
|
||||
yarn binary-zip
|
||||
- store-npm-logs
|
||||
- persist_to_workspace:
|
||||
@@ -2236,7 +2263,7 @@ jobs:
|
||||
command: DEBUG=cypress:cli $(yarn bin cypress) run
|
||||
- store-npm-logs
|
||||
|
||||
linux-workflow: &linux-workflow
|
||||
linux-x64-workflow: &linux-x64-workflow
|
||||
jobs:
|
||||
- node_modules_install
|
||||
- build:
|
||||
@@ -2545,6 +2572,31 @@ linux-workflow: &linux-workflow
|
||||
- create-build-artifacts
|
||||
- system-tests-node-modules-install
|
||||
|
||||
linux-arm64-workflow: &linux-arm64-workflow
|
||||
jobs:
|
||||
- node_modules_install:
|
||||
name: linux-arm64-node-modules-install
|
||||
executor: linux-arm64
|
||||
resource_class: arm.medium
|
||||
only-cache-for-root-user: true
|
||||
|
||||
- build:
|
||||
name: linux-arm64-build
|
||||
executor: linux-arm64
|
||||
resource_class: arm.medium
|
||||
requires:
|
||||
- linux-arm64-node-modules-install
|
||||
|
||||
- create-build-artifacts:
|
||||
name: linux-arm64-create-build-artifacts
|
||||
context:
|
||||
- test-runner:upload
|
||||
- test-runner:commit-status-checks
|
||||
executor: linux-arm64
|
||||
resource_class: arm.medium
|
||||
requires:
|
||||
- linux-arm64-build
|
||||
|
||||
darwin-x64-workflow: &darwin-x64-workflow
|
||||
jobs:
|
||||
- node_modules_install:
|
||||
@@ -2675,9 +2727,12 @@ windows-workflow: &windows-workflow
|
||||
- windows-create-build-artifacts
|
||||
|
||||
workflows:
|
||||
linux:
|
||||
<<: *linux-workflow
|
||||
<<: *linux-workflow-exclude-filters
|
||||
linux-x64:
|
||||
<<: *linux-x64-workflow
|
||||
<<: *linux-x64-workflow-exclude-filters
|
||||
linux-arm64:
|
||||
<<: *linux-arm64-workflow
|
||||
<<: *linux-arm64-workflow-filters
|
||||
darwin-x64:
|
||||
<<: *darwin-x64-workflow
|
||||
<<: *darwin-workflow-filters
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "../.eslintrc.js",
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "CallExpression[callee.name='arch']",
|
||||
"message": "Do not use `arch()` to detect the user's machine architecture. Use util.getRealArch() instead."
|
||||
},
|
||||
{
|
||||
"selector": "CallExpression[callee.object.name='os'][callee.property.name='arch']",
|
||||
"message": "Do not use `os.arch()` to detect the user's machine architecture. Use util.getRealArch() instead."
|
||||
},
|
||||
{
|
||||
"selector": "MemberExpression[object.name='process'][property.name='arch']",
|
||||
"message": "Do not use `process.arch` to detect the user's machine architecture. Use util.getRealArch() instead."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ const downloadAndUnzip = ({ version, installDir, downloadDir }) => {
|
||||
|
||||
const validateOS = () => {
|
||||
return util.getPlatformInfo().then((platformInfo) => {
|
||||
return platformInfo.match(/(win32-x64|linux-x64|darwin-x64|darwin-arm64)/)
|
||||
return platformInfo.match(/(win32-x64|linux-x64|linux-arm64|darwin-x64|darwin-arm64)/)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+13
-3
@@ -481,22 +481,32 @@ const util = {
|
||||
|
||||
async function _getRealArch () {
|
||||
const osPlatform = os.platform()
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const osArch = os.arch()
|
||||
|
||||
debug('detecting arch %o', { osPlatform, osArch })
|
||||
|
||||
if (osPlatform === 'darwin') {
|
||||
if (osArch === 'arm64') return 'arm64'
|
||||
if (osArch === 'arm64') return 'arm64'
|
||||
|
||||
if (osPlatform === 'darwin') {
|
||||
// could possibly be x64 node on arm64 darwin, check if we are being translated by Rosetta
|
||||
// https://stackoverflow.com/a/65347893/3474615
|
||||
const { stdout } = await execa('sysctl', ['-n', 'sysctl.proc_translated']).catch(() => '')
|
||||
|
||||
debug('rosetta check result: %o', { stdout })
|
||||
|
||||
if (stdout === '1') return 'arm64'
|
||||
}
|
||||
|
||||
if (osPlatform === 'linux') {
|
||||
// could possibly be x64 node on arm64 linux, check the "machine hardware name"
|
||||
// list of names for reference: https://stackoverflow.com/a/45125525/3474615
|
||||
const { stdout } = await execa('uname', ['-m']).catch(() => '')
|
||||
|
||||
debug('arm uname -m result: %o ', { stdout })
|
||||
if (['aarch64_be', 'aarch64', 'armv8b', 'armv8l'].includes(stdout)) return 'arm64'
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const pkgArch = arch()
|
||||
|
||||
if (pkgArch === 'x86') return 'ia32'
|
||||
|
||||
@@ -478,44 +478,91 @@ describe('lib/tasks/download', function () {
|
||||
sinon.stub(os, 'arch')
|
||||
})
|
||||
|
||||
function nockDarwinArm64 () {
|
||||
return nock('https://download.cypress.io')
|
||||
.get('/desktop/1.2.3')
|
||||
.query({ arch: 'arm64', platform: 'darwin' })
|
||||
.reply(200, undefined, {
|
||||
'x-version': '1.2.3',
|
||||
context('Apple Silicon/M1', () => {
|
||||
function nockDarwinArm64 () {
|
||||
return nock('https://download.cypress.io')
|
||||
.get('/desktop/1.2.3')
|
||||
.query({ arch: 'arm64', platform: 'darwin' })
|
||||
.reply(200, undefined, {
|
||||
'x-version': '1.2.3',
|
||||
})
|
||||
}
|
||||
|
||||
it('downloads darwin-arm64 on M1', async function () {
|
||||
os.platform.returns('darwin')
|
||||
os.arch.returns('arm64')
|
||||
nockDarwinArm64()
|
||||
|
||||
const responseVersion = await download.start(this.options)
|
||||
|
||||
expect(responseVersion).to.eq('1.2.3')
|
||||
|
||||
await fs.statAsync(downloadDestination)
|
||||
})
|
||||
}
|
||||
|
||||
it('downloads darwin-arm64 on M1', async function () {
|
||||
os.platform.returns('darwin')
|
||||
os.arch.returns('arm64')
|
||||
nockDarwinArm64()
|
||||
it('downloads darwin-arm64 on M1 translated by Rosetta', async function () {
|
||||
os.platform.returns('darwin')
|
||||
os.arch.returns('x64')
|
||||
nockDarwinArm64()
|
||||
|
||||
const responseVersion = await download.start(this.options)
|
||||
sinon.stub(cp, 'spawn').withArgs('sysctl', ['-n', 'sysctl.proc_translated'])
|
||||
.callsFake(mockSpawn(((cp) => {
|
||||
cp.stdout.write('1')
|
||||
cp.emit('exit', 0, null)
|
||||
cp.end()
|
||||
})))
|
||||
|
||||
expect(responseVersion).to.eq('1.2.3')
|
||||
const responseVersion = await download.start(this.options)
|
||||
|
||||
await fs.statAsync(downloadDestination)
|
||||
expect(responseVersion).to.eq('1.2.3')
|
||||
|
||||
await fs.statAsync(downloadDestination)
|
||||
})
|
||||
})
|
||||
|
||||
it('downloads darwin-arm64 on M1 translated by Rosetta', async function () {
|
||||
os.platform.returns('darwin')
|
||||
os.arch.returns('x64')
|
||||
nockDarwinArm64()
|
||||
context('Linux arm64/aarch64', () => {
|
||||
function nockLinuxArm64 () {
|
||||
return nock('https://download.cypress.io')
|
||||
.get('/desktop/1.2.3')
|
||||
.query({ arch: 'arm64', platform: 'linux' })
|
||||
.reply(200, undefined, {
|
||||
'x-version': '1.2.3',
|
||||
})
|
||||
}
|
||||
|
||||
sinon.stub(cp, 'spawn').withArgs('sysctl', ['-n', 'sysctl.proc_translated'])
|
||||
.callsFake(mockSpawn(((cp) => {
|
||||
cp.stdout.write('1')
|
||||
cp.emit('exit', 0, null)
|
||||
cp.end()
|
||||
})))
|
||||
it('downloads linux-arm64 on arm64 processor', async function () {
|
||||
os.platform.returns('linux')
|
||||
os.arch.returns('arm64')
|
||||
nockLinuxArm64()
|
||||
|
||||
const responseVersion = await download.start(this.options)
|
||||
const responseVersion = await download.start(this.options)
|
||||
|
||||
expect(responseVersion).to.eq('1.2.3')
|
||||
expect(responseVersion).to.eq('1.2.3')
|
||||
|
||||
await fs.statAsync(downloadDestination)
|
||||
await fs.statAsync(downloadDestination)
|
||||
})
|
||||
|
||||
it('downloads linux-arm64 on non-arm64 node running on arm machine', async function () {
|
||||
os.platform.returns('linux')
|
||||
os.arch.returns('x64')
|
||||
sinon.stub(cp, 'spawn')
|
||||
|
||||
for (const arch of ['aarch64_be', 'aarch64', 'armv8b', 'armv8l']) {
|
||||
nockLinuxArm64()
|
||||
cp.spawn.withArgs('uname', ['-m'])
|
||||
.callsFake(mockSpawn(((cp) => {
|
||||
cp.stdout.write(arch)
|
||||
cp.emit('exit', 0, null)
|
||||
cp.end()
|
||||
})))
|
||||
|
||||
const responseVersion = await download.start(this.options)
|
||||
|
||||
expect(responseVersion).to.eq('1.2.3')
|
||||
|
||||
await fs.statAsync(downloadDestination)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@
|
||||
"dedent": "^0.7.0",
|
||||
"del": "3.0.0",
|
||||
"detect-port": "^1.3.0",
|
||||
"electron": "18.0.4",
|
||||
"electron": "18.3.0",
|
||||
"electron-builder": "^22.13.1",
|
||||
"electron-notarize": "^1.1.1",
|
||||
"enzyme-adapter-react-16": "1.12.1",
|
||||
|
||||
@@ -113,6 +113,7 @@ const deploy = {
|
||||
checkDownloads ({ version }) {
|
||||
const systems = [
|
||||
{ platform: 'linux', arch: 'x64' },
|
||||
{ platform: 'linux', arch: 'arm64' },
|
||||
{ platform: 'darwin', arch: 'x64' },
|
||||
{ platform: 'darwin', arch: 'arm64' },
|
||||
{ platform: 'win32', arch: 'x64' },
|
||||
|
||||
@@ -34,7 +34,7 @@ type semver = string
|
||||
/**
|
||||
* Platform plus architecture string like "darwin-x64"
|
||||
*/
|
||||
type platformArch = 'darwin-x64' | 'darwin-arm64' | 'linux-x64' | 'win32-x64'
|
||||
type platformArch = 'darwin-x64' | 'darwin-arm64' | 'linux-x64' | 'linux-arm64' | 'win32-x64'
|
||||
|
||||
interface ReleaseInformation {
|
||||
commit: commit
|
||||
|
||||
@@ -87,6 +87,7 @@ module.exports = {
|
||||
'darwin-x64': getUrl('darwin-x64'),
|
||||
'darwin-arm64': getUrl('darwin-arm64'),
|
||||
'linux-x64': getUrl('linux-x64'),
|
||||
'linux-arm64': getUrl('linux-arm64'),
|
||||
'win32-x64': getUrl('win32-x64'),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const _ = require('lodash')
|
||||
const awspublish = require('gulp-awspublish')
|
||||
const human = require('human-interval')
|
||||
const la = require('lazy-ass')
|
||||
@@ -112,7 +111,7 @@ const purgeDesktopAppAllPlatforms = function (version, zipName) {
|
||||
}
|
||||
|
||||
// all architectures we are building the test runner for
|
||||
const validPlatformArchs = ['darwin-arm64', 'darwin-x64', 'linux-x64', 'win32-x64']
|
||||
const validPlatformArchs = ['darwin-arm64', 'darwin-x64', 'linux-x64', 'linux-arm64', 'win32-x64']
|
||||
// simple check for platform-arch string
|
||||
// example: isValidPlatformArch("darwin") // FALSE
|
||||
const isValidPlatformArch = check.oneOf(validPlatformArchs)
|
||||
@@ -122,25 +121,12 @@ const getValidPlatformArchs = () => {
|
||||
}
|
||||
|
||||
const getUploadNameByOsAndArch = function (platform) {
|
||||
// just hard code for now...
|
||||
const arch = os.arch()
|
||||
|
||||
const uploadNames = {
|
||||
darwin: {
|
||||
'arm64': 'darwin-arm64',
|
||||
'x64': 'darwin-x64',
|
||||
},
|
||||
linux: {
|
||||
'x64': 'linux-x64',
|
||||
},
|
||||
win32: {
|
||||
'x64': 'win32-x64',
|
||||
},
|
||||
}
|
||||
const name = _.get(uploadNames[platform], arch)
|
||||
const name = [platform, arch].join('-')
|
||||
|
||||
if (!name) {
|
||||
throw new Error(`Cannot find upload name for OS: '${platform}' with arch: '${arch}'`)
|
||||
if (!isValidPlatformArch(name)) {
|
||||
throw new Error(`${name} is not a valid upload destination. Does validPlatformArchs need updating?`)
|
||||
}
|
||||
|
||||
la(isValidPlatformArch(name), 'formed invalid platform', name, 'from', platform, arch)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// checks if the terminal has all the variables set (especially on Linux Docker)
|
||||
|
||||
const assert = require('assert')
|
||||
const isLinux = process.platform === 'linux'
|
||||
const isMainLinux = process.platform === 'linux' && process.arch === 'x64'
|
||||
|
||||
if (isLinux) {
|
||||
if (isMainLinux) {
|
||||
assert.ok(process.env.TERM === 'xterm', `process.env.TERM=${process.env.TERM} and must be set to "xterm" for Docker to work`)
|
||||
}
|
||||
|
||||
|
||||
@@ -16233,10 +16233,10 @@ electron-to-chromium@^1.3.247, electron-to-chromium@^1.4.84:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.111.tgz#897613f6504f3f17c9381c7499a635b413e4df4e"
|
||||
integrity sha512-/s3+fwhKf1YK4k7btOImOzCQLpUjS6MaPf0ODTNuT4eTM1Bg4itBpLkydhOzJmpmH6Z9eXFyuuK5czsmzRzwtw==
|
||||
|
||||
electron@18.0.4:
|
||||
version "18.0.4"
|
||||
resolved "https://registry.yarnpkg.com/electron/-/electron-18.0.4.tgz#7b9b094db32805d4a7826d9f7a1b376d9d7b9f86"
|
||||
integrity sha512-xfsozNpFr3WzeM1EFlw2qqiqXbCrgQNBJJMlcC4/DUYVpkF8364SZenX7FFFA42NmwXiOEahkvvho/u7UrAcGg==
|
||||
electron@18.3.0:
|
||||
version "18.3.0"
|
||||
resolved "https://registry.npmjs.org/electron/-/electron-18.3.0.tgz#43de95979341e63f1b209c569a0ad148d98ae5b7"
|
||||
integrity sha512-2+pAUIViVvFOGE5mJKKi8F6ruyvQrcqdfsm/AUfz+6P05vbvR5ZsR6WBkr90mlyojHW5w/nAVX9ZSOtz3aHs4A==
|
||||
dependencies:
|
||||
"@electron/get" "^1.13.0"
|
||||
"@types/node" "^16.11.26"
|
||||
|
||||
Reference in New Issue
Block a user