ci: Trigger an arm test on VSTS after CircleCI build (#14898)
* ci: Trigger an arm test on VSTS after CircleCI build
This commit is contained in:
parent
1acd840c38
commit
038b56e31e
12 changed files with 289 additions and 94 deletions
|
@ -182,6 +182,11 @@ step-nodejs-headers-build: &step-nodejs-headers-build
|
|||
cd src
|
||||
ninja -C out/Default third_party/electron_node:headers
|
||||
|
||||
step-nodejs-headers-store: &step-nodejs-headers-store
|
||||
store_artifacts:
|
||||
path: src/out/Default/gen/node_headers.tar.gz
|
||||
destination: node_headers.tar.gz
|
||||
|
||||
step-electron-publish: &step-electron-publish
|
||||
run:
|
||||
name: Publish Electron Dist
|
||||
|
@ -314,6 +319,17 @@ step-maybe-native-mksnapshot-store: &step-maybe-native-mksnapshot-store
|
|||
path: src/out/native_mksnapshot/mksnapshot.zip
|
||||
destination: native_mksnapshot.zip
|
||||
|
||||
step-maybe-trigger-arm-test: &step-maybe-trigger-arm-test
|
||||
run:
|
||||
name: Trigger an arm test on VSTS if applicable
|
||||
command: |
|
||||
cd src
|
||||
# Only run for non-fork prs
|
||||
if [ "$TRIGGER_ARM_TEST" == "true" ] && [ -z "$CIRCLE_PR_NUMBER" ]; then
|
||||
#Trigger VSTS job, passing along CircleCI job number and branch to build
|
||||
echo "Triggering electron-$TARGET_ARCH-testing build on VSTS"
|
||||
node electron/script/ci-release-build.js --job=electron-$TARGET_ARCH-testing --ci=VSTS --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
|
||||
fi
|
||||
# Lists of steps.
|
||||
steps-checkout: &steps-checkout
|
||||
steps:
|
||||
|
@ -377,12 +393,16 @@ steps-electron-build-for-tests: &steps-electron-build-for-tests
|
|||
|
||||
# Node.js headers
|
||||
- *step-nodejs-headers-build
|
||||
- *step-nodejs-headers-store
|
||||
|
||||
- *step-show-sccache-stats
|
||||
|
||||
# Save all data needed for a further tests run.
|
||||
- *step-persist-data-for-tests
|
||||
|
||||
# Trigger tests on arm hardware if needed
|
||||
- *step-maybe-trigger-arm-test
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
- *step-maybe-notify-slack-success
|
||||
|
||||
|
@ -416,6 +436,7 @@ steps-electron-build-for-publish: &steps-electron-build-for-publish
|
|||
|
||||
# Node.js headers
|
||||
- *step-nodejs-headers-build
|
||||
- *step-nodejs-headers-store
|
||||
|
||||
# ffmpeg
|
||||
- *step-ffmpeg-gn-gen
|
||||
|
@ -713,6 +734,7 @@ jobs:
|
|||
<<: *env-arm
|
||||
<<: *env-testing-build
|
||||
<<: *env-enable-sccache
|
||||
TRIGGER_ARM_TEST: true
|
||||
<<: *steps-electron-build-for-tests
|
||||
|
||||
linux-arm-ffmpeg:
|
||||
|
@ -768,6 +790,7 @@ jobs:
|
|||
<<: *env-arm64
|
||||
<<: *env-testing-build
|
||||
<<: *env-enable-sccache
|
||||
TRIGGER_ARM_TEST: true
|
||||
<<: *steps-electron-build-for-tests
|
||||
|
||||
linux-arm64-ffmpeg:
|
||||
|
|
61
Dockerfile.arm32v7
Normal file
61
Dockerfile.arm32v7
Normal file
|
@ -0,0 +1,61 @@
|
|||
FROM arm32v7/ubuntu:16.04
|
||||
|
||||
RUN groupadd --gid 1000 builduser \
|
||||
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
|
||||
|
||||
# Set up TEMP directory
|
||||
ENV TEMP=/tmp
|
||||
RUN chmod a+rwx /tmp
|
||||
|
||||
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
curl \
|
||||
gperf \
|
||||
git \
|
||||
libasound2 \
|
||||
libasound2-dev \
|
||||
libcap-dev \
|
||||
libcups2-dev \
|
||||
libdbus-1-dev \
|
||||
libgconf-2-4 \
|
||||
libgconf2-dev \
|
||||
libgnome-keyring-dev \
|
||||
libgtk2.0-0 \
|
||||
libgtk2.0-dev \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-dev \
|
||||
libnotify-bin \
|
||||
libnss3 \
|
||||
libnss3-dev \
|
||||
libxss1 \
|
||||
libxtst-dev \
|
||||
libxtst6 \
|
||||
lsb-release \
|
||||
locales \
|
||||
nano \
|
||||
python-setuptools \
|
||||
python-pip \
|
||||
python-dbusmock \
|
||||
sudo \
|
||||
unzip \
|
||||
wget \
|
||||
xvfb \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# crcmod is required by gsutil, which is used for filling the gclient git cache
|
||||
RUN pip install -U crcmod
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
|
||||
RUN usermod -aG sudo builduser
|
||||
RUN echo 'builduser ALL=(ALL:ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||
|
||||
WORKDIR /home/builduser
|
|
@ -1,35 +0,0 @@
|
|||
FROM multiarch/debian-debootstrap:arm64-jessie
|
||||
|
||||
RUN apt-get update && apt-get install -y\
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
curl \
|
||||
gperf \
|
||||
libasound2 \
|
||||
libasound2-dev \
|
||||
libcap-dev \
|
||||
libcups2-dev \
|
||||
libdbus-1-dev \
|
||||
libgconf-2-4 \
|
||||
libgconf2-dev \
|
||||
libgnome-keyring-dev \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-dev \
|
||||
libnotify-bin \
|
||||
libnotify-dev \
|
||||
libnss3 \
|
||||
libnss3-dev \
|
||||
libx11-xcb-dev \
|
||||
libxss1 \
|
||||
libxtst-dev \
|
||||
libxtst6 \
|
||||
python-dbusmock \
|
||||
wget \
|
||||
xvfb
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
ADD tools/run-electron.sh /run-electron.sh
|
||||
RUN chmod a+x /run-electron.sh
|
||||
CMD sh /run-electron.sh
|
|
@ -3,14 +3,13 @@ FROM arm64v8/ubuntu:16.04
|
|||
RUN groupadd --gid 1000 builduser \
|
||||
&& useradd --uid 1000 --gid builduser --shell /bin/bash --create-home builduser
|
||||
|
||||
RUN groupadd --gid 114 jenkins \
|
||||
&& useradd --uid 110 --gid jenkins --shell /bin/bash --create-home jenkins
|
||||
|
||||
# Set up TEMP directory
|
||||
ENV TEMP=/tmp
|
||||
RUN chmod a+rwx /tmp
|
||||
|
||||
RUN apt-get update && apt-get install -y\
|
||||
RUN dpkg --add-architecture armhf
|
||||
|
||||
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
|
@ -19,6 +18,7 @@ RUN apt-get update && apt-get install -y\
|
|||
git \
|
||||
libasound2 \
|
||||
libasound2-dev \
|
||||
libc6:armhf \
|
||||
libcap-dev \
|
||||
libcups2-dev \
|
||||
libdbus-1-dev \
|
||||
|
@ -29,35 +29,37 @@ RUN apt-get update && apt-get install -y\
|
|||
libgtk2.0-dev \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-dev \
|
||||
libnotify-dev \
|
||||
libnotify-bin \
|
||||
libnss3 \
|
||||
libnss3-dev \
|
||||
libx11-xcb-dev \
|
||||
libstdc++6:armhf \
|
||||
libxss1 \
|
||||
libxtst-dev \
|
||||
libxtst6 \
|
||||
lsb-release \
|
||||
locales \
|
||||
ninja \
|
||||
nano \
|
||||
python-setuptools \
|
||||
python-pip \
|
||||
python-dbusmock \
|
||||
sudo \
|
||||
unzip \
|
||||
wget \
|
||||
xvfb
|
||||
xvfb \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||
RUN apt-get update && apt-get install -y nodejs
|
||||
# Install Node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install crcmod
|
||||
# crcmod is required by gsutil, which is used for filling the gclient git cache
|
||||
RUN pip install -U crcmod
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
|
||||
# Install ninja in /usr/local
|
||||
RUN cd /usr/local && git clone https://github.com/martine/ninja.git -b v1.5.3
|
||||
RUN cd /usr/local/ninja && ./configure.py --bootstrap
|
||||
RUN usermod -aG sudo builduser
|
||||
RUN echo 'builduser ALL=(ALL:ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||
|
||||
USER builduser
|
||||
WORKDIR /home/builduser
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
FROM multiarch/debian-debootstrap:armhf-jessie
|
||||
|
||||
RUN apt-get update && apt-get install -y\
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
curl \
|
||||
gperf \
|
||||
libasound2 \
|
||||
libasound2-dev \
|
||||
libcap-dev \
|
||||
libcups2-dev \
|
||||
libdbus-1-dev \
|
||||
libgconf-2-4 \
|
||||
libgconf2-dev \
|
||||
libgnome-keyring-dev \
|
||||
libgtk-3-0 \
|
||||
libgtk-3-dev \
|
||||
libnotify-bin \
|
||||
libnotify-dev \
|
||||
libnss3 \
|
||||
libnss3-dev \
|
||||
libx11-xcb-dev \
|
||||
libxss1 \
|
||||
libxtst-dev \
|
||||
libxtst6 \
|
||||
python-dbusmock \
|
||||
git \
|
||||
wget \
|
||||
xvfb
|
||||
|
||||
ADD tools/xvfb-init.sh /etc/init.d/xvfb
|
||||
RUN chmod a+x /etc/init.d/xvfb
|
||||
ADD tools/run-electron.sh /run-electron.sh
|
||||
RUN chmod a+x /run-electron.sh
|
||||
CMD sh /run-electron.sh
|
|
@ -1,4 +1,4 @@
|
|||
require('dotenv-safe').load()
|
||||
if (!process.env.CI) require('dotenv-safe').load()
|
||||
|
||||
const assert = require('assert')
|
||||
const request = require('request')
|
||||
|
@ -22,6 +22,11 @@ const vstsJobs = [
|
|||
'electron-release-osx-x64'
|
||||
]
|
||||
|
||||
const vstsArmJobs = [
|
||||
'electron-arm-testing',
|
||||
'electron-arm64-testing'
|
||||
]
|
||||
|
||||
async function makeRequest (requestOptions, parseResponse) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request(requestOptions, (err, res, body) => {
|
||||
|
@ -135,7 +140,9 @@ function buildCircleCI (targetBranch, options) {
|
|||
}
|
||||
|
||||
async function buildVSTS (targetBranch, options) {
|
||||
if (options.job) {
|
||||
if (options.armTest) {
|
||||
assert(vstsArmJobs.includes(options.job), `Unknown VSTS CI arm test job name: ${options.job}. Valid values are: ${vstsArmJobs}.`)
|
||||
} else if (options.job) {
|
||||
assert(vstsJobs.includes(options.job), `Unknown VSTS CI job name: ${options.job}. Valid values are: ${vstsJobs}.`)
|
||||
}
|
||||
console.log(`Triggering VSTS to run build on branch: ${targetBranch} with release flag.`)
|
||||
|
@ -143,8 +150,12 @@ async function buildVSTS (targetBranch, options) {
|
|||
ELECTRON_RELEASE: 1
|
||||
}
|
||||
|
||||
if (!options.ghRelease) {
|
||||
environmentVariables.UPLOAD_TO_S3 = 1
|
||||
if (options.armTest) {
|
||||
environmentVariables.CIRCLE_BUILD_NUM = options.circleBuildNum
|
||||
} else {
|
||||
if (!options.ghRelease) {
|
||||
environmentVariables.UPLOAD_TO_S3 = 1
|
||||
}
|
||||
}
|
||||
|
||||
const requestOpts = {
|
||||
|
@ -226,12 +237,13 @@ module.exports = runRelease
|
|||
|
||||
if (require.main === module) {
|
||||
const args = require('minimist')(process.argv.slice(2), {
|
||||
boolean: ['ghRelease', 'automaticRelease']
|
||||
boolean: ['ghRelease', 'automaticRelease', 'armTest']
|
||||
})
|
||||
const targetBranch = args._[0]
|
||||
if (args._.length < 1) {
|
||||
console.log(`Trigger CI to build release builds of electron.
|
||||
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor|VSTS] [--ghRelease] [--automaticRelease] TARGET_BRANCH
|
||||
Usage: ci-release-build.js [--job=CI_JOB_NAME] [--ci=CircleCI|AppVeyor|VSTS]
|
||||
[--ghRelease] [--automaticRelease] [--armTest] [--circleBuildNum=xxx] TARGET_BRANCH
|
||||
`)
|
||||
process.exit(0)
|
||||
}
|
||||
|
|
78
script/download-circleci-artifacts.js
Normal file
78
script/download-circleci-artifacts.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
const args = require('minimist')(process.argv.slice(2))
|
||||
const nugget = require('nugget')
|
||||
const request = require('request')
|
||||
|
||||
async function makeRequest (requestOptions, parseResponse) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request(requestOptions, (err, res, body) => {
|
||||
if (!err && res.statusCode >= 200 && res.statusCode < 300) {
|
||||
if (parseResponse) {
|
||||
const build = JSON.parse(body)
|
||||
resolve(build)
|
||||
} else {
|
||||
resolve(body)
|
||||
}
|
||||
} else {
|
||||
console.error('Error occurred while requesting:', requestOptions.url)
|
||||
if (parseResponse) {
|
||||
try {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || JSON.parse(res.body), requestOptions)
|
||||
} catch (err) {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions)
|
||||
}
|
||||
} else {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions)
|
||||
}
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function downloadArtifact (name, buildNum, dest) {
|
||||
const circleArtifactUrl = `https://circleci.com/api/v1.1/project/github/electron/electron/${args.buildNum}/artifacts?circle-token=${process.env.CIRCLE_TOKEN}`
|
||||
const artifacts = await makeRequest({
|
||||
method: 'GET',
|
||||
url: circleArtifactUrl,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
}, true).catch(err => {
|
||||
console.log('Error calling CircleCI:', err)
|
||||
})
|
||||
const artifactToDownload = artifacts.find(artifact => {
|
||||
return (artifact.path === name)
|
||||
})
|
||||
if (!artifactToDownload) {
|
||||
console.log(`Could not find artifact called ${name} to download for build #${buildNum}.`)
|
||||
process.exit(1)
|
||||
} else {
|
||||
console.log(`Downloading ${artifactToDownload.url}.`)
|
||||
await downloadFile(artifactToDownload.url, dest)
|
||||
console.log(`Successfully downloaded ${name}.`)
|
||||
}
|
||||
}
|
||||
|
||||
function downloadFile (url, directory) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const nuggetOpts = {
|
||||
dir: directory
|
||||
}
|
||||
nugget(url, nuggetOpts, (err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (!args.name || !args.buildNum || !args.dest) {
|
||||
console.log(`Download CircleCI artifacts.
|
||||
Usage: download-circleci-artifacts.js [--buildNum=CIRCLE_BUILD_NUMBER] [--name=artifactName] [--dest]`)
|
||||
process.exit(0)
|
||||
} else {
|
||||
downloadArtifact(args.name, args.buildNum, args.dest)
|
||||
}
|
|
@ -10,7 +10,7 @@ const isCI = remote.getGlobal('isCi')
|
|||
|
||||
describe('desktopCapturer', () => {
|
||||
before(function () {
|
||||
if (!features.isDesktopCapturerEnabled()) {
|
||||
if (!features.isDesktopCapturerEnabled() || process.arch.indexOf('arm') === 0) {
|
||||
// It's been disabled during build time.
|
||||
this.skip()
|
||||
return
|
||||
|
|
|
@ -15,6 +15,7 @@ const { app } = remote.require('electron')
|
|||
|
||||
const skip = process.platform !== 'linux' ||
|
||||
process.arch === 'ia32' ||
|
||||
process.arch.indexOf('arm') === 0 ||
|
||||
!process.env.DBUS_SESSION_BUS_ADDRESS;
|
||||
|
||||
(skip ? describe.skip : describe)('Notification module (dbus)', () => {
|
||||
|
|
65
vsts-arm-test-steps.yml
Normal file
65
vsts-arm-test-steps.yml
Normal file
|
@ -0,0 +1,65 @@
|
|||
steps:
|
||||
- task: CopyFiles@2
|
||||
displayName: 'Copy Files to: src/electron'
|
||||
inputs:
|
||||
TargetFolder: src/electron
|
||||
|
||||
- bash: |
|
||||
cd src/electron
|
||||
npm install --verbose
|
||||
displayName: 'NPM install'
|
||||
|
||||
- bash: |
|
||||
export ZIP_DEST=$PWD/src/out/Default
|
||||
mkdir -p $ZIP_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=dist.zip --dest=$ZIP_DEST
|
||||
cd $ZIP_DEST
|
||||
unzip -o dist.zip
|
||||
displayName: 'Download and unzip dist files for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
export NODE_HEADERS_DEST=$PWD/src/out/Default/gen
|
||||
mkdir -p $NODE_HEADERS_DEST
|
||||
cd src/electron
|
||||
node script/download-circleci-artifacts.js --buildNum=$CIRCLE_BUILD_NUM --name=node_headers.tar.gz --dest=$NODE_HEADERS_DEST
|
||||
cd $NODE_HEADERS_DEST
|
||||
tar xzf node_headers.tar.gz
|
||||
displayName: 'Download and untar node header files for test'
|
||||
env:
|
||||
CIRCLE_TOKEN: $(CIRCLECI_TOKEN)
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
export npm_config_nodedir=$PWD/out/Default/gen/node_headers
|
||||
cd electron/spec
|
||||
npm install --verbose
|
||||
displayName: Install test modules
|
||||
|
||||
- bash: |
|
||||
sh -e /etc/init.d/xvfb start
|
||||
displayName: Setup for headless testing
|
||||
env:
|
||||
DISPLAY: ":99.0"
|
||||
|
||||
- bash: |
|
||||
cd src
|
||||
./out/Default/electron electron/spec --ci --enable-logging
|
||||
displayName: 'Run Electron tests'
|
||||
timeoutInMinutes: 10
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: 'Publish Test Results'
|
||||
inputs:
|
||||
testResultsFiles: '*.xml'
|
||||
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/src/junit/'
|
||||
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: mspremier.PostBuildCleanup.PostBuildCleanup-task.PostBuildCleanup@3
|
||||
displayName: 'Clean Agent Directories'
|
||||
|
||||
condition: always()
|
12
vsts-arm32v7.yml
Normal file
12
vsts-arm32v7.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
resources:
|
||||
containers:
|
||||
- container: arm32v7-test-container
|
||||
image: electronbuilds/arm32v7:0.0.1
|
||||
|
||||
jobs:
|
||||
- job: Test_Arm32v7
|
||||
container: arm32v7-test-container
|
||||
displayName: Test Arm on Arm32v7 hardware
|
||||
timeoutInMinutes: 30
|
||||
steps:
|
||||
- template: vsts-arm-test-steps.yml
|
12
vsts-arm64v8.yml
Normal file
12
vsts-arm64v8.yml
Normal file
|
@ -0,0 +1,12 @@
|
|||
resources:
|
||||
containers:
|
||||
- container: arm64v8-test-container
|
||||
image: electronbuilds/arm64v8:0.0.4
|
||||
|
||||
jobs:
|
||||
- job: Test_Arm64
|
||||
container: arm64v8-test-container
|
||||
displayName: Test Arm64 on Arm64 hardware
|
||||
timeoutInMinutes: 30
|
||||
steps:
|
||||
- template: vsts-arm-test-steps.yml
|
Loading…
Reference in a new issue