2019-11-25 14:06:34 +08:00
|
|
|
#!/usr/bin/env groovy
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2019 - present Instructure, Inc.
|
|
|
|
*
|
|
|
|
* This file is part of Canvas.
|
|
|
|
*
|
|
|
|
* Canvas is free software: you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU Affero General Public License as published by the Free
|
|
|
|
* Software Foundation, version 3 of the License.
|
|
|
|
*
|
|
|
|
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License along
|
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2020-02-20 03:50:26 +08:00
|
|
|
@groovy.transform.Field
|
|
|
|
def result_test_count = -1
|
|
|
|
@groovy.transform.Field
|
|
|
|
def result_node_count = -1
|
|
|
|
|
2019-11-25 14:06:34 +08:00
|
|
|
def getImageTagVersion() {
|
|
|
|
def flags = load 'build/new-jenkins/groovy/commit-flags.groovy'
|
|
|
|
return flags.getImageTagVersion()
|
|
|
|
}
|
|
|
|
|
2020-02-20 03:50:26 +08:00
|
|
|
def computeTestCount() {
|
|
|
|
// oops, probably should have added an easier way to _count_ tests...
|
|
|
|
sh 'rm -rf tmp'
|
|
|
|
sh 'mkdir tmp'
|
|
|
|
sh 'chmod 777 tmp'
|
|
|
|
sh """
|
|
|
|
docker run --volume \$WORKSPACE/.git:/usr/src/app/.git \
|
|
|
|
--volume \$WORKSPACE/tmp:/usr/src/app/tmp \
|
|
|
|
\$PATCHSET_TAG \
|
|
|
|
bundle exec flakey_spec_catcher --use-parent --dry-run-quiet > tmp/test_list
|
|
|
|
"""
|
|
|
|
def raw_result = readFile('tmp/test_list').trim()
|
|
|
|
echo "raw result from catcher: \n====\n$raw_result\n===="
|
|
|
|
def test_count = 0
|
|
|
|
if (raw_result) {
|
|
|
|
test_count = raw_result.split('\n').length
|
|
|
|
}
|
|
|
|
echo "expected tests to run: $test_count"
|
|
|
|
result_test_count = test_count
|
|
|
|
}
|
|
|
|
|
|
|
|
def computeDistributedCount() {
|
|
|
|
if (result_test_count < 0)
|
|
|
|
throw IllegalStateException("call computeTestCount() first")
|
|
|
|
// this type of distributed thing always needs a hard cutoff
|
|
|
|
if (env.DISTRIBUTED_CUT_OFF.toInteger() < result_test_count)
|
|
|
|
throw IllegalStateException("unable to process more than ${env.DISTRIBUTED_CUT_OFF} tests")
|
|
|
|
if (result_test_count == 0) {
|
|
|
|
result_node_count = 0
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// force a round down
|
|
|
|
// this will have the following node counts.
|
|
|
|
// test | nodes
|
|
|
|
// 1-14 | 1
|
|
|
|
// 15-24 | 2
|
|
|
|
// 25-34 | 3
|
|
|
|
// ...
|
|
|
|
def distributed_offset = env.DISTRIBUTED_OFFSET.toInteger()
|
|
|
|
def distributed_factor = env.DISTRIBUTED_FACTOR.toInteger()
|
|
|
|
result_node_count = (int) ((result_test_count + distributed_offset) / distributed_factor)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def executeFlakeySpecCatcher(prefix = 'main') {
|
|
|
|
sh 'rm -rf tmp'
|
|
|
|
try {
|
2020-02-28 00:55:06 +08:00
|
|
|
timeout(30) {
|
2020-02-20 03:50:26 +08:00
|
|
|
sh 'build/new-jenkins/docker-compose-pull.sh'
|
|
|
|
sh 'build/new-jenkins/docker-compose-pull-selenium.sh'
|
|
|
|
sh 'build/new-jenkins/docker-compose-build-up.sh'
|
|
|
|
sh 'build/new-jenkins/docker-compose-create-migrate-database.sh'
|
|
|
|
sh 'build/new-jenkins/rspec-flakey-spec-catcher.sh'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally {
|
|
|
|
sh "mkdir -p tmp/$prefix"
|
2020-02-15 06:02:23 +08:00
|
|
|
sh(
|
2020-02-27 05:25:18 +08:00
|
|
|
script: "docker cp \$(docker-compose ps -q web):/usr/src/app/tmp/fsc.out ./tmp/$prefix/fsc.out",
|
2020-02-20 03:50:26 +08:00
|
|
|
returnStatus: true
|
|
|
|
)
|
|
|
|
archiveArtifacts(artifacts: "tmp/$prefix/fsc.out", allowEmptyArchive: true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-25 14:06:34 +08:00
|
|
|
pipeline {
|
|
|
|
agent { label 'canvas-docker' }
|
|
|
|
options { ansiColor('xterm') }
|
|
|
|
|
|
|
|
environment {
|
|
|
|
COMPOSE_FILE = 'docker-compose.new-jenkins.yml:docker-compose.new-jenkins-selenium.yml:docker-compose.new-jenkins-flakey-spec-catcher.yml'
|
2020-02-20 03:50:26 +08:00
|
|
|
// there will be a node for every 10 tests
|
|
|
|
DISTRIBUTED_FACTOR = '10'
|
|
|
|
// this causes distribution to trigger at an offset
|
|
|
|
DISTRIBUTED_OFFSET = '5'
|
|
|
|
// if someone is trying to update more than these amount of tests, then just fail.
|
|
|
|
// that will be at DISTRIBUTED_CUT_OFF / DISTRIBUTED_FACTOR nodes.
|
|
|
|
DISTRIBUTED_CUT_OFF = '300'
|
2019-11-25 14:06:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
stages {
|
|
|
|
stage('Checkout and clean') {
|
|
|
|
steps {
|
|
|
|
timeout(time: 5) {
|
|
|
|
sh 'build/new-jenkins/docker-cleanup.sh'
|
2020-02-13 01:14:18 +08:00
|
|
|
sh 'rm -rf ./tmp/'
|
2019-11-25 14:06:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stage('Print Env Variables') {
|
|
|
|
steps {
|
|
|
|
sh 'build/new-jenkins/print-env-excluding-secrets.sh'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-20 03:50:26 +08:00
|
|
|
stage("Compute Build Distribution") {
|
2019-11-25 14:06:34 +08:00
|
|
|
steps {
|
2020-02-20 03:50:26 +08:00
|
|
|
script {
|
|
|
|
computeTestCount()
|
|
|
|
computeDistributedCount()
|
|
|
|
echo "expected nodes to run on for $result_test_count tests: $result_node_count"
|
2019-11-25 14:06:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-20 03:50:26 +08:00
|
|
|
stage("Run Flakey Spec Catcher") {
|
|
|
|
when { expression { result_test_count > 0 } }
|
2019-11-25 14:06:34 +08:00
|
|
|
steps {
|
2020-02-20 03:50:26 +08:00
|
|
|
script {
|
|
|
|
if (result_node_count <= 1) {
|
|
|
|
echo "running on this node"
|
|
|
|
executeFlakeySpecCatcher()
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
echo "running on multiple nodes: $result_node_count"
|
|
|
|
def nodes = [:];
|
|
|
|
for(int i = 0; i < result_node_count; i++) {
|
|
|
|
// make sure to create a new index variable so this value gets
|
|
|
|
// captured by the lambda for FSC_NODE_INDEX
|
|
|
|
def index = i
|
|
|
|
def node_number = (index).toString().padLeft(2, '0')
|
|
|
|
nodes["flakey set $node_number"] = {
|
|
|
|
withEnv(["FSC_NODE_TOTAL=$result_node_count", "FSC_NODE_INDEX=$index"]) {
|
|
|
|
node('canvas-docker') {
|
|
|
|
stage("Running Flakey Set $node_number") {
|
|
|
|
try {
|
|
|
|
sh 'rm -rf ./tmp'
|
|
|
|
checkout scm
|
|
|
|
sh 'build/new-jenkins/docker-cleanup.sh'
|
|
|
|
executeFlakeySpecCatcher("node$node_number")
|
|
|
|
}
|
|
|
|
finally {
|
|
|
|
sh 'rm -rf ./tmp'
|
|
|
|
sh 'build/new-jenkins/docker-cleanup.sh --allow-failure'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-15 06:02:23 +08:00
|
|
|
parallel(nodes)
|
2020-02-20 03:50:26 +08:00
|
|
|
}
|
2019-11-25 14:06:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-13 01:14:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
post {
|
|
|
|
cleanup {
|
|
|
|
sh 'rm -rf ./tmp/'
|
|
|
|
sh 'build/new-jenkins/docker-cleanup.sh --allow-failure'
|
|
|
|
}
|
2019-11-25 14:06:34 +08:00
|
|
|
}
|
|
|
|
}
|