pipeline { agent { dockerfile { label 'linux' dir 'ci' } } parameters { string( name: 'ITERATIONS', description: 'Number of repeated integration test runs', defaultValue: params.ITERATIONS ?: '1000' ) } environment { /* Avoid cache poisoning by other jobs. */ GOCACHE = "${env.WORKSPACE_TMP}/go-build" GOPATH = "${env.WORKSPACE_TMP}/go" RUST_BACKTRACE = 1 } options { disableConcurrentBuilds() buildDiscarder(logRotator( numToKeepStr: '20', daysToKeepStr: '30', )) } stages { stage('Integration Tests') { matrix { axes { axis { name 'FEATURE' values 'libp2p' } } stages { stage('Tests') { options { lock('sync-integration-${env.GIT_COMMIT}') } stages { stage("BuildAndTest") { steps { script { /* To prevent rebuilding node for each test, tests are defined here */ def tests = ['ten_nodes_happy', 'two_nodes_happy', 'ten_nodes_one_down'] if (FEATURE == 'libp2p') { tests.add('mixnet') } runBuildAndTestsForFeature(FEATURE, tests) } } } } } } } } } post { failure { script { def discord = load "${WORKSPACE}/ci/discord.groovy" discord.sendMessage(header: 'Nightly Integration Tests Failed') } } success { script { def discord = load "${WORKSPACE}/ci/discord.groovy" discord.sendMessage(header: 'Nightly Integration Tests Passed') } } cleanup { cleanWs() } } } def runBuildAndTestsForFeature(feature, tests) { echo "Building node for feature: ${feature}" def build_node = "cargo build --all --no-default-features --features ${feature}" if (sh(script: build_node, returnStatus: true) != 0) { error("Build '${feature}' node failed") return } int iterations = params.ITERATIONS.toInteger() runTestCases(tests, iterations) } def runTestCases(test_cases, iterations) { for (int i = 0; i < iterations; i++) { echo "Running iteration ${i + 1} of ${iterations}" for (test_case in test_cases) { def test_cmd = "cargo test -p tests --all --no-default-features --features ${feature} ${test_case}" if (sh(script: test_cmd, returnStatus: true) != 0) { error("Test '${test_case}' failed on iteration ${i + 1}") return } } } }