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:
parent
127e5bcd75
commit
b594098df5
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue