run rspec and selenium tests off main build node

[skip-docker-build]

fixes: CCI-290
flag = none

Test-Plan:
- build passes on PS.
- build passes in main-for-coverage
- build passes in main-for-plugins

Change-Id: Iafb84175bb27e8a90a4cac2c3c049df53ceb4776
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/230521
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Jacob Powell <spowell@instructure.com>
Reviewed-by: Derek Bender <djbender@instructure.com>
QA-Review: Jacob Powell <spowell@instructure.com>
Product-Review: Jacob Powell <spowell@instructure.com>
This commit is contained in:
Rex Fleischer 2020-03-19 07:42:53 -07:00
parent 127e5bcd75
commit b594098df5
7 changed files with 325 additions and 350 deletions

125
Jenkinsfile vendored
View File

@ -223,12 +223,13 @@ pipeline {
}
stage('Parallel Run Tests') {
parallel {
stage('Linters') {
when { expression { env.GERRIT_EVENT_TYPE != 'change-merged' && env.GERRIT_PROJECT == 'canvas-lms' && !isCovid() } }
steps {
skipIfPreviouslySuccessful("linters") {
script {
steps {
script {
def stages = [:]
if (env.GERRIT_EVENT_TYPE != 'change-merged' && env.GERRIT_PROJECT == 'canvas-lms' && !isCovid()) {
echo 'adding Linters'
stages['Linters'] = {
skipIfPreviouslySuccessful("linters") {
sh 'build/new-jenkins/linters/run-gergich.sh'
if (env.MASTER_BOUNCER_RUN == '1' && env.GERRIT_EVENT_TYPE == 'patchset-created') {
def credentials = load 'build/new-jenkins/groovy/credentials.groovy'
@ -239,90 +240,64 @@ pipeline {
}
}
}
}
stage('Vendored Gems') {
steps {
echo 'adding Vendored Gems'
stages['Vendored Gems'] = {
skipIfPreviouslySuccessful("vendored-gems") {
build(job: 'test-suites/vendored-gems', parameters: buildParameters)
}
}
}
stage('Javascript') {
steps {
echo 'adding Javascript'
stages['Javascript'] = {
skipIfPreviouslySuccessful("javascript") {
build(job: 'test-suites/JS', parameters: buildParameters)
}
}
}
stage('Contract Tests') {
steps {
echo 'adding Contract Tests'
stages['Contract Tests'] = {
skipIfPreviouslySuccessful("contract-tests") {
build(job: 'test-suites/contract-tests', parameters: buildParameters)
}
}
}
stage('Selenium Chrome') {
steps {
skipIfPreviouslySuccessful("selenium-chrome") {
build(
job: 'test-suites/selenium-chrome',
parameters: buildParameters + string(name: 'CI_NODE_TOTAL', value: env.SELENIUM_CI_NODE_TOTAL)
)
if (env.GERRIT_EVENT_TYPE != 'change-merged' && !isCovid()) {
echo 'adding Flakey Spec Catcher'
stages['Flakey Spec Catcher'] = {
skipIfPreviouslySuccessful("flakey-spec-catcher") {
build(
job: 'test-suites/flakey-spec-catcher',
parameters: buildParameters,
propagate: false,
wait: false
)
}
}
}
// // keep this around in case there is changes to the subbuilds that need to happen
// // and you have no other way to test it except by running a test build.
// stages['Test Subbuild'] = {
// skipIfPreviouslySuccessful("test-subbuild") {
// build(job: 'test-suites/test-subbuild', parameters: buildParameters)
// }
// }
// // Don't run these on all patch sets until we have them ready to report results.
// // Uncomment stage to run when developing.
// stages['Xbrowser'] = {
// skipIfPreviouslySuccessful("xbrowser") {
// build(job: 'test-suites/xbrowser', propagate: false, parameters: buildParameters)
// }
// }
def distribution = load 'build/new-jenkins/groovy/distribution.groovy'
distribution.stashBuildScripts()
distribution.addRSpecSuites(stages)
parallel(stages)
}
stage('RSpec') {
steps {
skipIfPreviouslySuccessful("rspec") {
build(
job: 'test-suites/rspec',
parameters: buildParameters + string(name: 'CI_NODE_TOTAL', value: env.RSPEC_CI_NODE_TOTAL)
)
}
}
}
stage ('Flakey Spec Catcher') {
when { expression { env.GERRIT_EVENT_TYPE != 'change-merged' && !isCovid() } }
steps {
skipIfPreviouslySuccessful("flakey-spec-catcher") {
build(
job: 'test-suites/flakey-spec-catcher',
parameters: buildParameters,
propagate: false,
wait: false
)
}
}
}
// // keep this around in case there is changes to the subbuilds that need to happen
// // and you have no other way to test it except by running a test build.
// stage('Test Subbuild') {
// steps {
// skipIfPreviouslySuccessful("test-subbuild") {
// build(job: 'test-suites/test-subbuild', parameters: buildParameters)
// }
// }
// }
// // Don't run these on all patch sets until we have them ready to report results.
// // Uncomment stage to run when developing.
// stage('Xbrowser') {
// steps {
// skipIfPreviouslySuccessful("xbrowser") {
// // propagate set to false until we can get tests passing
// build(job: 'test-suites/xbrowser', propagate: false, parameters: buildParameters)
// )
// }
// }
// }
}
}
@ -385,7 +360,13 @@ pipeline {
}
}
}
always {
script {
def rspec = load 'build/new-jenkins/groovy/rspec.groovy'
rspec.uploadSeleniumFailures()
rspec.uploadRSpecFailures()
}
}
cleanup {
sh 'build/new-jenkins/docker-cleanup.sh --allow-failure'
}

View File

@ -18,18 +18,20 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
def buildParameters = [
string(name: 'CANVAS_LMS_REFSPEC', value: "${env.CANVAS_LMS_REFSPEC}"),
string(name: 'RUN_COVERAGE', value: '1'),
string(name: 'POSTGRES', value: '9.5'),
string(name: 'RUBY_PASSENGER', value: '2.4-xenial'),
string(name: 'PATCHSET_TAG', value: "${env.DOCKER_REGISTRY_FQDN}/jenkins/canvas-lms:master")
]
pipeline {
agent { label 'canvas-docker' }
options { ansiColor('xterm') }
environment {
CANVAS_LMS_REFSPEC = "${env.CANVAS_LMS_REFSPEC}"
RUN_COVERAGE = '1'
POSTGRES = '9.5'
RUBY_PASSENGER = '2.4-xenial'
PATCHSET_TAG = "${env.DOCKER_REGISTRY_FQDN}/jenkins/canvas-lms:master"
COVERAGE = '1'
}
stages {
stage('Print Env Variables') {
steps {
@ -40,25 +42,48 @@ pipeline {
}
stage('Parallel Run Tests') {
parallel {
stage('JS') {
steps {
build(job: 'test-suites/JS', parameters: buildParameters)
}
}
steps {
script {
def stages = [:]
stage('Selenium Chrome') {
steps {
build(job: 'test-suites/selenium-chrome', parameters: buildParameters)
echo 'adding Javascript'
stages['Javascript'] = {
build(job: 'test-suites/JS', parameters: [
string(name: 'CANVAS_LMS_REFSPEC', value: env.CANVAS_LMS_REFSPEC),
string(name: 'RUN_COVERAGE', value: env.RUN_COVERAGE),
string(name: 'POSTGRES', value: env.POSTGRES),
string(name: 'RUBY_PASSENGER', value: env.RUBY_PASSENGER),
string(name: 'PATCHSET_TAG', value: env.PATCHSET_TAG)
])
}
}
stage('RSpec') {
steps {
build(job: 'test-suites/rspec', parameters: buildParameters)
}
def distribution = load 'build/new-jenkins/groovy/distribution.groovy'
distribution.stashBuildScripts()
distribution.addRSpecSuites(stages)
parallel(stages)
}
}
}
stage('Upload Coverage') {
steps {
script {
def rspec = load 'build/new-jenkins/groovy/rspec.groovy'
rspec.uploadSeleniumCoverage()
rspec.uploadRSpecCoverage()
}
}
}
}
post {
always {
script {
def rspec = load 'build/new-jenkins/groovy/rspec.groovy'
rspec.uploadSeleniumFailures()
rspec.uploadRSpecFailures()
}
}
}
}

View File

@ -1,122 +0,0 @@
#!/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/>.
*/
def runCoverage() {
def flags = load 'build/new-jenkins/groovy/commit-flags.groovy'
return env.RUN_COVERAGE == '1' || flags.forceRunCoverage() ? '1' : ''
}
def getImageTagVersion() {
def flags = load 'build/new-jenkins/groovy/commit-flags.groovy'
return env.RUN_COVERAGE == '1' ? 'master' : flags.getImageTagVersion()
}
pipeline {
agent { label 'canvas-docker' }
options { ansiColor('xterm') }
environment {
COMPOSE_FILE = 'docker-compose.new-jenkins.yml'
KNAPSACK_ENABLED = 1
KNAPSACK_GENERATE_REPORT = 'false'
KNAPSACK_TEST_FILE_PATTERN = '{spec,gems/plugins/*/spec_canvas}/**/*_spec.rb'
KNAPSACK_EXCLUDE_REGEX = '/selenium/'
KNAPSACK_TEST_DIR = 'spec'
COVERAGE = runCoverage()
}
stages {
stage ('Distribute RSpec Tests') {
steps {
script {
stash name: "build-scripts", includes: 'build/**/*'
stash name: "build-yml", includes: 'docker-compose.*.yml'
def nodes = [:];
def ci_node_total = env.CI_NODE_TOTAL as Integer
for(int i = 0; i < ci_node_total; i++) {
def index = i;
nodes["rspec set ${(i).toString().padLeft(2, '0')}"] = {
withEnv([
"CI_NODE_INDEX=$index",
"POSTGRES=$POSTGRES",
"RUBY_PASSENGER=$RUBY_PASSENGER",
"TEST_ENV_NUMBER=$index"
]) {
node('canvas-docker') {
stage("Running RSpec Set ${index}") {
try {
sh 'rm -vrf ./tmp'
unstash name: "build-scripts"
unstash name: "build-yml"
sh 'build/new-jenkins/docker-cleanup.sh'
sh 'mkdir -vp tmp'
timeout(time: 60) {
sh 'build/new-jenkins/print-env-excluding-secrets.sh'
sh 'build/new-jenkins/docker-compose-pull.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-with-retries.sh'
}
}
catch (ex) {
// copy spec failures to local
sh 'docker cp $(docker-compose ps -q web):/usr/src/app/log/spec_failures/ ./tmp/spec_failures/'
throw ex
}
finally {
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.stashSpecFailures(index)
if (env.COVERAGE == '1') {
sh 'docker cp $(docker-compose ps -q web):/usr/src/app/coverage/ ./tmp/spec_coverage/'
reports.stashSpecCoverage(index)
}
sh 'rm -vrf ./tmp'
sh 'build/new-jenkins/docker-cleanup.sh --allow-failure'
}
}
}
}
}
}
parallel(nodes)
}
}
}
stage('Upload Coverage') {
when { expression { env.COVERAGE == '1' } }
steps {
script {
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.publishSpecCoverageToS3(env.CI_NODE_TOTAL as Integer, "canvas-lms-rspec")
}
}
}
}
post {
failure {
script {
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.publishSpecFailuresAsHTML(env.CI_NODE_TOTAL as Integer)
}
}
}
}

View File

@ -1,125 +0,0 @@
#!/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/>.
*/
def runCoverage() {
def flags = load 'build/new-jenkins/groovy/commit-flags.groovy'
return env.RUN_COVERAGE == '1' || flags.forceRunCoverage() ? '1' : ''
}
def getImageTagVersion() {
def flags = load 'build/new-jenkins/groovy/commit-flags.groovy'
return env.RUN_COVERAGE == '1' ? 'master' : flags.getImageTagVersion()
}
pipeline {
agent { label 'canvas-docker' }
options { ansiColor('xterm') }
environment {
COMPOSE_FILE = 'docker-compose.new-jenkins.yml:docker-compose.new-jenkins-selenium.yml'
KNAPSACK_ENABLED = 1
KNAPSACK_GENERATE_REPORT = 'false'
KNAPSACK_TEST_FILE_PATTERN = '{spec/selenium,gems/plugins/*/spec_canvas/selenium}/**/*_spec.rb'
KNAPSACK_EXCLUDE_REGEX = '/performance/'
KNAPSACK_TEST_DIR = 'spec'
COVERAGE = runCoverage()
}
stages {
stage ('Distribute Selenium Tests') {
steps {
script {
stash name: "build-scripts", includes: 'build/**/*'
stash name: "build-yml", includes: 'docker-compose.*.yml'
def nodes = [:];
def ci_node_total = env.CI_NODE_TOTAL as Integer
for(int i = 0; i < ci_node_total; i++) {
def index = i;
nodes["selenium set ${(i).toString().padLeft(2, '0')}"] = {
withEnv([
"POSTGRES=$POSTGRES",
"RUBY_PASSENGER=$RUBY_PASSENGER",
"TEST_ENV_NUMBER=$index",
"CI_NODE_INDEX=$index",
]) {
node('canvas-docker') {
stage("Running Selenium Set ${index}") {
try {
sh 'rm -vrf ./tmp'
unstash name: "build-scripts"
unstash name: "build-yml"
sh 'build/new-jenkins/docker-cleanup.sh'
sh 'mkdir -vp tmp'
timeout(time: 60) {
sh 'build/new-jenkins/print-env-excluding-secrets.sh'
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-with-retries.sh'
}
}
finally {
// copy spec failures to local
sh 'mkdir -vp tmp'
sh(
script: 'docker cp $(docker-compose ps -q web):/usr/src/app/log/spec_failures/ ./tmp/spec_failures/',
returnStatus: true
)
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.stashSpecFailures(index)
if (env.COVERAGE == '1') {
sh 'docker cp $(docker-compose ps -q web):/usr/src/app/coverage/ ./tmp/spec_coverage/'
reports.stashSpecCoverage(index)
}
sh 'rm -vrf ./tmp'
sh 'build/new-jenkins/docker-cleanup.sh --allow-failure'
}
}
}
}
}
}
parallel(nodes)
}
}
}
stage('Upload Coverage') {
when { expression { env.COVERAGE == '1' } }
steps {
script {
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.publishSpecCoverageToS3(env.CI_NODE_TOTAL as Integer, "canvas-lms-selenium")
}
}
}
}
post {
always {
script {
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.publishSpecFailuresAsHTML(env.CI_NODE_TOTAL as Integer)
}
}
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2020 - 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/>.
*/
/**
* appends stages to the nodes based on the count passed into
* the closure.
*
* @nodes: the hash of nodes to be ran later
* @stage_count: the amount of nodes to add to the hash
* @stage_name_prefix: the name to prefix the stages with
* @stage_block: the closure thats exectued after unstashing build scripts
*/
def appendStagesAsBuildNodes(nodes,
stage_count,
stage_name_prefix,
stage_block) {
for(int i = 0; i < stage_count; i++) {
// make this a local variable so when the closure resolves
// it gets the correct number
def index = i;
// we cant use String.format, so... yea
def stage_name = "$stage_name_prefix ${index + 1}"
nodes[stage_name] = {
node('canvas-docker') {
stage(stage_name) {
// make sure to unstash
unstash name: "build-dir"
unstash name: "build-docker-compose"
stage_block(index)
}
}
}
}
}
/**
* use this in combination with appendStagesAsBuildNodes. this will
* stash the required files for running biulds that only require
* the build scripts
*/
def stashBuildScripts() {
stash name: "build-dir", includes: 'build/**/*'
stash name: "build-docker-compose", includes: 'docker-compose.*.yml'
}
/**
* common helper for adding both rspec and selenium tests to be ran
*/
def addRSpecSuites(stages) {
def rspec_config = load('build/new-jenkins/groovy/rspec.groovy').config()
def selenium_node_total = rspec_config.selenium_node_total
def rspec_node_total = rspec_config.rspec_node_total
echo 'adding Selenium Test Sets'
appendStagesAsBuildNodes(stages, selenium_node_total, "Selenium Test Set") { index ->
load('build/new-jenkins/groovy/rspec.groovy').runSeleniumSuite(selenium_node_total, index)
}
echo 'adding RSpec Test Sets'
appendStagesAsBuildNodes(stages, rspec_node_total, "RSpec Test Set") { index ->
load('build/new-jenkins/groovy/rspec.groovy').runRSpecSuite(rspec_node_total, index)
}
}
return this

View File

@ -16,18 +16,18 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
def stashSpecCoverage(index) {
def stashSpecCoverage(prefix, index) {
dir("tmp") {
stash name: "spec_coverage_${index}", includes: 'spec_coverage/**/*'
stash name: "${prefix}_spec_coverage_${index}", includes: 'spec_coverage/**/*'
}
}
def publishSpecCoverageToS3(ci_node_total, coverage_type) {
def publishSpecCoverageToS3(prefix, ci_node_total, coverage_type) {
sh 'rm -vrf ./coverage_nodes'
dir('coverage_nodes') {
for(int index = 0; index < ci_node_total; index++) {
dir("node_${index}") {
unstash "spec_coverage_${index}"
unstash "${prefix}_spec_coverage_${index}"
}
}
}
@ -46,24 +46,23 @@ def publishSpecCoverageToS3(ci_node_total, coverage_type) {
// this method is to ensure that the stashing is done in a way that
// is expected in publishSpecFailuresAsHTML
def stashSpecFailures(index) {
def stashSpecFailures(prefix, index) {
dir("tmp") {
stash name: "spec_failures_${index}", includes: 'spec_failures/**/*', allowEmpty: true
stash name: "${prefix}_spec_failures_${index}", includes: 'spec_failures/**/*', allowEmpty: true
}
}
def publishSpecFailuresAsHTML(ci_node_total) {
def publishSpecFailuresAsHTML(prefix, ci_node_total, report_name) {
sh 'rm -vrf ./compiled_failures'
dir('compiled_failures') {
for(int index = 0; index < ci_node_total; index++) {
dir ("node_${index}") {
try {
unstash "spec_failures_${index}"
unstash "${prefix}_spec_failures_${index}"
} catch(err) {
println (err)
}
}
}
buildIndexPage();
@ -76,7 +75,7 @@ def publishSpecFailuresAsHTML(ci_node_total) {
keepAll: true,
reportDir: 'compiled_failures',
reportFiles: htmlFiles.join(','),
reportName: 'Test Failures'
reportName: report_name
]
sh 'rm -vrf ./compiled_failures'
}

View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2020 - 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/>.
*/
def config() {
[
selenium_node_total: (env.SELENIUM_CI_NODE_TOTAL ?: '25') as Integer,
selenium_max_fail: (env.SELENIUM_MAX_FAIL ?: "100") as Integer,
selenium_reruns_retry: (env.SELENIUM_RERUN_RETRY ?: "3") as Integer,
rspec_node_total: (env.RSPEC_CI_NODE_TOTAL ?: '15') as Integer,
rspec_max_fail: (env.RSPEC_MAX_FAIL ?: "100") as Integer,
rspec_reruns_retry: (env.RSPEC_RERUN_RETRY ?: "1") as Integer
]
}
def runSeleniumSuite(total, index) {
_runRspecTestSuite(
total,
index,
'docker-compose.new-jenkins.yml:docker-compose.new-jenkins-selenium.yml',
'selenium',
config().selenium_max_fail,
config().selenium_reruns_retry,
'{spec/selenium,gems/plugins/*/spec_canvas/selenium}/**/*_spec.rb',
'/performance/'
)
}
def runRSpecSuite(total, index) {
_runRspecTestSuite(
total,
index,
'docker-compose.new-jenkins.yml',
'rspec',
config().rspec_max_fail,
config().rspec_reruns_retry,
'{spec,gems/plugins/*/spec_canvas}/**/*_spec.rb',
'/selenium/'
)
}
def _runRspecTestSuite(
total,
index,
compose,
prefix,
max_fail,
reruns_retry,
test_file_pattern,
exclude_regex) {
withEnv([
"TEST_ENV_NUMBER=$index",
"CI_NODE_INDEX=$index",
"CI_NODE_TOTAL=$total",
"COMPOSE_FILE=$compose",
"RERUNS_RETRY=$reruns_retry",
"MAX_FAIL=$max_fail",
"KNAPSACK_ENABLED=1",
"KNAPSACK_GENERATE_REPORT='false'",
"KNAPSACK_TEST_DIR=spec",
"KNAPSACK_TEST_FILE_PATTERN=$test_file_pattern",
"KNAPSACK_EXCLUDE_REGEX=$exclude_regex"
]) {
try {
sh 'rm -rf ./tmp'
sh 'build/new-jenkins/docker-cleanup.sh'
sh 'mkdir -p tmp'
timeout(time: 60) {
sh 'build/new-jenkins/print-env-excluding-secrets.sh'
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-with-retries.sh'
}
}
finally {
// copy spec failures to local
sh 'mkdir -p tmp'
sh(
script: 'docker cp $(docker-compose ps -q web):/usr/src/app/log/spec_failures/ ./tmp/spec_failures/',
returnStatus: true
)
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.stashSpecFailures(prefix, index)
if (env.COVERAGE == '1') {
sh 'docker cp $(docker-compose ps -q web):/usr/src/app/coverage/ ./tmp/spec_coverage/'
reports.stashSpecCoverage(prefix, index)
}
sh 'rm -rf ./tmp'
sh 'build/new-jenkins/docker-cleanup.sh --allow-failure'
}
}
}
def uploadSeleniumCoverage() {
_uploadCoverage('selenium', config().selenium_node_total, 'canvas-lms-selenium')
}
def uploadRSpecCoverage() {
_uploadCoverage('rspec', config().rspec_node_total, 'canvas-lms-rspec')
}
def _uploadCoverage(prefix, total, coverage_name) {
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.publishSpecCoverageToS3(prefix, total, coverage_name)
}
def uploadSeleniumFailures() {
_uploadSpecFailures('selenium', config().selenium_node_total, 'Selenium Test Failures')
}
def uploadRSpecFailures() {
_uploadSpecFailures('rspec', config().rspec_node_total, 'Rspec Test Failures')
}
def _uploadSpecFailures(prefix, total, test_name) {
def reports = load 'build/new-jenkins/groovy/reports.groovy'
reports.publishSpecFailuresAsHTML(prefix, total, test_name)
}
return this