react-native/Jenkinsfile
Nicholas Tate 926bfdb9f4 Container Testing Updates
Summary:
ericvicenti Here is the latest updates and fixes for the container testing. Everything should be good to go now, the update for `inotify.max_user_watches` should fix the E2E test issues you were seeing locally.

The update to the packer prevents excessively large filename lengths due to the hash used in the name and splits them into directories instead. I was getting errors locally on the E2E because the hash filename was over 248 characters which was causing issues on the base image file system. It might not have appeared in circle due to another file system being used with different limits. I can separate it out into another PR if you want though.

* Turned jenkins instrumentation parallelism up to 3
* Disabled various instrumentation tests that seemed to have inconsistent results from
Jenkins by default
* Install google-chrome in the android base image so the chrome debug E2E test does not fail
* Turned back on E2E tests

cc normanjoyner
Closes https://github.com/facebook/react-native/pull/13417

Differential Revision: D4876137

Pulled By: ericvicenti

fbshipit-source-id: 31e033c1e34b02acb5484478414197ac9eb11f95
2017-04-12 16:31:35 -07:00

207 lines
6.9 KiB
Groovy

import groovy.json.JsonSlurperClassic
def runPipeline() {
try {
ansiColor('xterm') {
runStages();
}
} catch(err) {
echo "Error: ${err}"
currentBuild.result = "FAILED"
}
}
def pullDockerImage(imageName) {
def result = sh(script: "docker pull ${imageName}", returnStatus: true)
if (result != 0) {
throw new Exception("Failed to pull image[${imageName}]")
}
}
def buildDockerfile(dockerfilePath = "Dockerfile", imageName) {
def buildCmd = "docker build -f ${dockerfilePath} -t ${imageName} ."
echo "${buildCmd}"
def result = sh(script: buildCmd, returnStatus: true)
if (result != 0) {
throw new Exception("Failed to build image[${imageName}] from '${dockerfilePath}'")
}
}
def runCmdOnDockerImage(imageName, cmd, run_opts = '') {
def result = sh(script: "docker run ${run_opts} -i ${imageName} sh -c '${cmd}'", returnStatus: true)
if(result != 0) {
throw new Exception("Failed to run cmd[${cmd}] on image[${imageName}]")
}
}
def calculateGithubInfo() {
return [
branch: env.BRANCH_NAME,
sha: sh(returnStdout: true, script: 'git rev-parse HEAD').trim(),
tag: null,
isPR: "${env.CHANGE_URL}".contains('/pull/')
]
}
def getParallelInstrumentationTests(testDir, parallelCount, imageName) {
def integrationTests = [:]
def testCount = sh(script: "ls ${testDir} | wc -l", returnStdout: true).trim().toInteger()
def testPerParallel = testCount.intdiv(parallelCount) + 1
def ignoredTests = 'CatalystNativeJavaToJSReturnValuesTestCase|CatalystUIManagerTestCase|CatalystMeasureLayoutTest|CatalystNativeJavaToJSArgumentsTestCase|CatalystNativeJSToJavaParametersTestCase|ReactScrollViewTestCase|ReactHorizontalScrollViewTestCase|ViewRenderingTestCase';
for (def x = 0; (x*testPerParallel) < testCount; x++) {
def offset = x
integrationTests["android integration tests: ${offset}"] = {
run: {
runCmdOnDockerImage(imageName, "bash /app/ContainerShip/scripts/run-android-docker-instrumentation-tests.sh --offset=${offset} --count=${testPerParallel} --ignore=\"${ignoredTests}\"", '--privileged --rm')
}
}
}
return integrationTests
}
def runStages() {
def buildInfo = [
image: [
name: "facebook/react-native",
tag: null
],
scm: [
branch: null,
sha: null,
tag: null,
isPR: false
]
]
node {
def jsDockerBuild, androidDockerBuild
def jsTag, androidTag, jsImageName, androidImageName, parallelInstrumentationTests
try {
stage('Setup') {
parallel(
'pull images': {
pullDockerImage('containership/android-base:latest')
}
)
}
stage('Build') {
checkout scm
def githubInfo = calculateGithubInfo()
buildInfo.scm.branch = githubInfo.branch
buildInfo.scm.sha = githubInfo.sha
buildInfo.scm.tag = githubInfo.tag
buildInfo.scm.isPR = githubInfo.isPR
buildInfo.image.tag = "${buildInfo.scm.sha}-${env.BUILD_TAG.replace(" ", "-").replace("/", "-").replace("%2F", "-")}"
jsTag = "${buildInfo.image.tag}"
androidTag = "${buildInfo.image.tag}"
jsImageName = "${buildInfo.image.name}-js:${jsTag}"
androidImageName = "${buildInfo.image.name}-android:${androidTag}"
parallelInstrumentationTests = getParallelInstrumentationTests('./ReactAndroid/src/androidTest/java/com/facebook/react/tests', 3, androidImageName)
parallel(
'javascript build': {
jsDockerBuild = docker.build("${jsImageName}", "-f ContainerShip/Dockerfile.javascript .")
},
'android build': {
androidDockerBuild = docker.build("${androidImageName}", "-f ContainerShip/Dockerfile.android .")
}
)
}
stage('Tests JS') {
try {
parallel(
'javascript flow': {
runCmdOnDockerImage(jsImageName, 'yarn run flow -- check', '--rm')
},
'javascript tests': {
runCmdOnDockerImage(jsImageName, 'yarn test --maxWorkers=4', '--rm')
},
'documentation tests': {
runCmdOnDockerImage(jsImageName, 'cd website && yarn test', '--rm')
},
'documentation generation': {
runCmdOnDockerImage(jsImageName, 'cd website && node ./server/generate.js', '--rm')
}
)
} catch(e) {
currentBuild.result = "FAILED"
echo "Test JS Stage Error: ${e}"
}
}
stage('Tests Android') {
try {
parallel(
'android unit tests': {
runCmdOnDockerImage(androidImageName, 'bash /app/ContainerShip/scripts/run-android-docker-unit-tests.sh', '--privileged --rm')
},
'android e2e tests': {
runCmdOnDockerImage(androidImageName, 'bash /app/ContainerShip/scripts/run-ci-e2e-tests.sh --android --js', '--privileged --rm')
}
)
} catch(e) {
currentBuild.result = "FAILED"
echo "Tests Android Stage Error: ${e}"
}
}
stage('Tests Android Instrumentation') {
// run all tests in parallel
try {
parallel(parallelInstrumentationTests)
} catch(e) {
currentBuild.result = "FAILED"
echo "Tests Android Instrumentation Stage Error: ${e}"
}
}
stage('Cleanup') {
cleanupImage(jsDockerBuild)
cleanupImage(androidDockerBuild)
}
} catch(err) {
cleanupImage(jsDockerBuild)
cleanupImage(androidDockerBuild)
throw err
}
}
}
def isMasterBranch() {
return env.GIT_BRANCH == 'master'
}
def gitCommit() {
return sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
}
def cleanupImage(image) {
if (image) {
try {
sh "docker ps -a | awk '{ print \$1,\$2 }' | grep ${image.id} | awk '{print \$1 }' | xargs -I {} docker rm {}"
sh "docker rmi -f ${image.id}"
} catch(e) {
echo "Error cleaning up ${image.id}"
echo "${e}"
}
}
}
runPipeline()