CI: Generalize PhySim tests, run PhySims on Gracehopper This changeset generalizes/harmonizes the CI infrastructure for physim testing, and adds a new pipeline for physim tests on Gracehopper machines. Specifically: - Refactor the existing CI code for running and analyzing physical simulators. The existing code assumed those tests are deployed using OpenShift. Instead, OpenShift/Helm-specificities (e.g., running a "release") have been removed, and instead of hardcoding the deployment of the physical simulators using a script for Helm, the function takes any script that can deploy using Helm/docker/from source. The overall appearance is the same. - Add a new pipeline RAN-PhySim-GraceHopper-5G that executes physical simulators on gracehopper. Reporting is done in the same way as for existing physical simulators (e.g., like in the RAN-PhySim-Cluster-5G pipeline), but deployed in docker instead of helm. -> some tests don't work reliably on ARM yet and are skipped - the RAN-gNB-N300-Timing-Phytest-LDPC pipeline has been reworked to use the same code for testing T2 offload, with ctest, and the same reporting. - the CUDA LDPC test XML has been removed, as these tests don't work reliably. - add a new macro add_timed_physim_test() that allows to define thresholds to be checked, so that ctest will check for them. see the documentation for more information
896 lines
31 KiB
Groovy
896 lines
31 KiB
Groovy
#!/bin/groovy
|
|
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
// Location of the executor node
|
|
def nodeExecutor = params.nodeExecutor
|
|
|
|
// Tags to shorten pipeline duration
|
|
def doBuild = true
|
|
def do4Gtest = false
|
|
def do5Gtest = false
|
|
def do5GUeTest = false
|
|
|
|
//
|
|
def gitCommitAuthorEmailAddr
|
|
|
|
// list of failing stages
|
|
def failingStages = ""
|
|
|
|
pipeline {
|
|
agent {
|
|
label nodeExecutor
|
|
}
|
|
options {
|
|
timestamps()
|
|
gitLabConnection('OAI GitLab')
|
|
ansiColor('xterm')
|
|
}
|
|
|
|
stages {
|
|
stage ("Verify Parameters") {
|
|
steps {
|
|
script {
|
|
JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
|
|
JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
|
|
|
|
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
|
|
def allParametersPresent = true
|
|
|
|
echo '\u2705 \u001B[32mVerify Labels\u001B[0m'
|
|
if ("MERGE".equals(env.gitlabActionType)) {
|
|
LABEL_CHECK = sh returnStdout: true, script: 'ci-scripts/checkGitLabMergeRequestLabels.sh --mr-id ' + env.gitlabMergeRequestIid
|
|
LABEL_CHECK = LABEL_CHECK.trim()
|
|
if (LABEL_CHECK == 'NONE') {
|
|
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Your merge request should have one of the mandatory labels:\n\n"
|
|
message += " - ~documentation (don't perform any stages)\n"
|
|
message += " - ~BUILD-ONLY (execute only build stages)\n"
|
|
message += " - ~4G-LTE (perform 4G tests)\n"
|
|
message += " - ~5G-NR (perform 5G tests)\n"
|
|
message += " - ~CI (perform both 4G and 5G tests)\n"
|
|
message += " - ~nrUE (perform only 5G-UE related tests including physims excluding LDPC tests)\n\n"
|
|
message += "Not performing CI due to lack of labels"
|
|
addGitLabMRComment comment: message
|
|
error('Not performing CI due to lack of labels')
|
|
} else if (LABEL_CHECK == 'FULL') {
|
|
do4Gtest = true
|
|
do5Gtest = true
|
|
do5GUeTest = true
|
|
} else if (LABEL_CHECK == "SHORTEN-4G") {
|
|
do4Gtest = true
|
|
} else if (LABEL_CHECK == 'SHORTEN-5G') {
|
|
do5Gtest = true
|
|
} else if (LABEL_CHECK == 'SHORTEN-5G-UE') {
|
|
do5GUeTest = true
|
|
} else if (LABEL_CHECK == 'SHORTEN-4G-5G-UE') {
|
|
do4Gtest = true
|
|
do5GUeTest = true
|
|
} else if (LABEL_CHECK == 'documentation') {
|
|
doBuild = false
|
|
} else {
|
|
// is "BUILD-ONLY", will only build
|
|
}
|
|
} else {
|
|
do4Gtest = true
|
|
do5Gtest = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("Verify Guidelines") {
|
|
steps {
|
|
echo "Git URL is ${GIT_URL}"
|
|
echo "GitLab Act is ${env.gitlabActionType}"
|
|
script {
|
|
if ("MERGE".equals(env.gitlabActionType)) {
|
|
// since a bit, in push events, gitlabUserEmail is not populated
|
|
gitCommitAuthorEmailAddr = env.gitlabUserEmail
|
|
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
|
|
// GitLab-Jenkins plugin integration is lacking to perform the merge by itself
|
|
// Doing it manually --> it may have merge conflicts
|
|
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
|
|
} else {
|
|
echo "Git Branch is ${GIT_BRANCH}"
|
|
echo "Git Commit is ${GIT_COMMIT}"
|
|
// since a bit, in push events, gitlabUserEmail is not populated
|
|
gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}'
|
|
gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim()
|
|
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
|
|
}
|
|
}
|
|
}
|
|
post {
|
|
failure {
|
|
script {
|
|
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI"
|
|
addGitLabMRComment comment: message
|
|
currentBuild.result = 'FAILURE'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Build Stages are Mandatory
|
|
stage ("Image Building Processes") {
|
|
when { expression {doBuild} }
|
|
parallel {
|
|
stage ("Ubuntu-Image-Builder") {
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-Ubuntu18-Image-Builder', 'Ubuntu-Image-Builder')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
ubuntuBuildStatus = finalizeSlaveJob('RAN-Ubuntu18-Image-Builder')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += ubuntuBuildStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("Ubuntu-ARM-Image-Builder") {
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-Ubuntu-ARM-Image-Builder', 'Ubuntu-ARM-Image-Builder')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
ubuntuArmBuildStatus = finalizeSlaveJob('RAN-Ubuntu-ARM-Image-Builder')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += ubuntuArmBuildStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("RHEL-Cluster-Image-Builder") {
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-RHEL8-Cluster-Image-Builder', 'RHEL-Cluster-Image-Builder')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
rhelBuildStatus = finalizeSlaveJob('RAN-RHEL8-Cluster-Image-Builder')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += rhelBuildStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("cppcheck") {
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-cppcheck', 'cppcheck')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
cppcheckStatus = finalizeSlaveJob('RAN-cppcheck')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += cppcheckStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("ARM-Cross-Compile") {
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-ARM-Cross-Compile-Builder', 'ARM-Cross-Compilation')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
armBuildStatus = finalizeSlaveJob('RAN-ARM-Cross-Compile-Builder')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += armBuildStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("Image Test Processes") {
|
|
when { expression {doBuild} }
|
|
parallel {
|
|
stage ("PhySim-Cluster-5G") {
|
|
when { expression {do5Gtest || do5GUeTest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-PhySim-Cluster-5G', 'PhySim-Cluster-5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
physim5GStatus = finalizeSlaveJob('RAN-PhySim-Cluster-5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += physim5GStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("PhySim-GraceHopper-5G") {
|
|
when { expression {do5Gtest || do5GUeTest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-PhySim-GraceHopper-5G', 'PhySim-GraceHopper-5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
physimGH5GStatus = finalizeSlaveJob('RAN-PhySim-GraceHopper-5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += physimGH5GStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("PhySim-Cluster-4G") {
|
|
when { expression {do4Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-PhySim-Cluster-4G', 'PhySim-Cluster-4G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
physim4GStatus = finalizeSlaveJob('RAN-PhySim-Cluster-4G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += physim4GStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("RF-Sim-Test-4G") {
|
|
when { expression {do4Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-RF-Sim-Test-4G', 'RF-Sim-Test-4G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
rfSim4GStatus = finalizeSlaveJob('RAN-RF-Sim-Test-4G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += rfSim4GStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("RF-Sim-Test-5G") {
|
|
when { expression {do5Gtest || do5GUeTest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-RF-Sim-Test-5G', 'RF-Sim-Test-5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
rfSim5GStatus = finalizeSlaveJob('RAN-RF-Sim-Test-5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += rfSim5GStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("OAI-FLEXRIC-RAN-Integration-Test") {
|
|
when { expression {do5Gtest || do5GUeTest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('OAI-FLEXRIC-RAN-Integration-Test', 'OAI-FLEXRIC-RAN-Integration-Test')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
flexricRAN5GStatus = finalizeSlaveJob('OAI-FLEXRIC-RAN-Integration-Test')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += flexricRAN5GStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("L2-Sim-Test-4G") {
|
|
when { expression {do4Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-L2-Sim-Test-4G', 'L2-Sim-Test-4G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
l2Sim4GStatus = finalizeSlaveJob('RAN-L2-Sim-Test-4G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += l2Sim4GStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("LTE-B200-FDD-LTEBOX-Container") {
|
|
when { expression {do4Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-LTE-FDD-LTEBOX-Container', 'LTE-FDD-LTEBOX-Container')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
lteTDDB200Status = finalizeSlaveJob('RAN-LTE-FDD-LTEBOX-Container')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += lteTDDB200Status
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Pipeline to test OAI LTE-UE
|
|
stage ("LTE-B200-FDD-OAIUE-OAICN4G-Container") {
|
|
when { expression {do4Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-LTE-FDD-OAIUE-OAICN4G-Container', 'LTE-FDD-OAIUE-OAICN4G-Container')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
lteFDDB200OAIUEStatus = finalizeSlaveJob('RAN-LTE-FDD-OAIUE-OAICN4G-Container')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += lteFDDB200OAIUEStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("LTE-B200-TDD-LTEBOX-Container") {
|
|
when { expression {do4Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-LTE-TDD-LTEBOX-Container', 'LTE-TDD-LTEBOX-Container')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
lteFDDB200Status = finalizeSlaveJob('RAN-LTE-TDD-LTEBOX-Container')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += lteFDDB200Status
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("NSA-B200-Module-LTEBOX-Container") {
|
|
when { expression {do4Gtest || do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-NSA-B200-Module-LTEBOX-Container', 'NSA-B200-Module-LTEBOX-Container')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
nsaTDDB200Status = finalizeSlaveJob('RAN-NSA-B200-Module-LTEBOX-Container')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += nsaTDDB200Status
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("SA-B200-Module-SABOX-Container") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-SA-B200-Module-SABOX-Container', 'SA-B200-Module-SABOX-Container')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
saTDDB200Status = finalizeSlaveJob('RAN-SA-B200-Module-SABOX-Container')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += saTDDB200Status
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("gNB-N300-Timing-Phytest-LDPC") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-gNB-N300-Timing-Phytest-LDPC', 'gNB-N300-Timing-Phytest-LDPC')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
phytestLDPCoffloadStatus = finalizeSlaveJob('RAN-gNB-N300-Timing-Phytest-LDPC')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += phytestLDPCoffloadStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("LTE-TDD-2x2-Container") {
|
|
when { expression {do4Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-LTE-TDD-2x2-Container', 'LTE-TDD-2x2-Container')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
lteTDD2x2N3xxStatus = finalizeSlaveJob('RAN-LTE-TDD-2x2-Container')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += lteTDD2x2N3xxStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("SA-AW2S-CN5G") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-SA-AW2S-CN5G', 'SA-AW2S-CN5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
saAW2SStatus = finalizeSlaveJob('RAN-SA-AW2S-CN5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += saAW2SStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("Sanity-Check OAI-CN5G") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerCN5GSlaveJob ('OAI-CN5G-COTS-UE-Test', 'OAI-CN5G-COTS-UE-Test')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
cn5gCOTSUESanityCheck = finalizeSlaveJob('OAI-CN5G-COTS-UE-Test')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += cn5gCOTSUESanityCheck
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("SA-AERIAL-CN5G") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-SA-AERIAL-CN5G', 'SA-AERIAL-CN5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
saAERIALStatus = finalizeSlaveJob('RAN-SA-AERIAL-CN5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += saAERIALStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("SA-2x2-Module-CN5G") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-SA-2x2-Module-CN5G', 'SA-2x2-Module-CN5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
saTDD2x2Status = finalizeSlaveJob('RAN-SA-2x2-Module-CN5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += saTDD2x2Status
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("SA-FHI72-CN5G") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-SA-FHI72-CN5G', 'SA-FHI72-CN5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
saFHI72Status = finalizeSlaveJob('RAN-SA-FHI72-CN5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += saFHI72Status
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("SA-Handover-CN5G") {
|
|
when { expression {do5Gtest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-SA-Handover-CN5G', 'SA-Handover-CN5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
saHandoverStatus = finalizeSlaveJob('RAN-SA-Handover-CN5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += saHandoverStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("SA-OAIUE-CN5G") {
|
|
when { expression {do5Gtest || do5GUeTest} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-SA-OAIUE-CN5G', 'SA-OAIUE-CN5G')
|
|
}
|
|
}
|
|
post {
|
|
always {
|
|
script {
|
|
// Using a unique variable name for each test stage to avoid overwriting on a global variable
|
|
// due to parallel-time concurrency
|
|
saOAIUEStatus = finalizeSlaveJob('RAN-SA-OAIUE-CN5G')
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += saOAIUEStatus
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stage ("DockerHub-Push") {
|
|
when { expression {doBuild && "PUSH".equals(env.gitlabActionType)} }
|
|
steps {
|
|
script {
|
|
triggerSlaveJob ('RAN-DockerHub-Push', 'DockerHub-Push')
|
|
}
|
|
}
|
|
post {
|
|
failure {
|
|
script {
|
|
echo "Push to Docker-Hub KO"
|
|
currentBuild.result = 'FAILURE'
|
|
failingStages += '\n * RAN-DockerHub-Push'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
post {
|
|
success {
|
|
script {
|
|
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")"
|
|
if ("MERGE".equals(env.gitlabActionType)) {
|
|
addGitLabMRComment comment: message
|
|
def message2 = message + " -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")"
|
|
}
|
|
echo "Pipeline is SUCCESSFUL"
|
|
}
|
|
}
|
|
failure {
|
|
script {
|
|
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")"
|
|
if ("MERGE".equals(env.gitlabActionType)) {
|
|
def fullMessage = message + '\n\nList of failing test stages:' + failingStages
|
|
addGitLabMRComment comment: fullMessage
|
|
def message2 = message + " -- MergeRequest #" + env.gitlabMergeRequestIid + " (" + env.gitlabMergeRequestTitle + ")"
|
|
}
|
|
echo "Pipeline FAILED"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---- Slave Job functions
|
|
|
|
def triggerSlaveJob (jobName, gitlabStatusName) {
|
|
if ("MERGE".equals(env.gitlabActionType)) {
|
|
MR_NUMBER = env.gitlabMergeRequestIid
|
|
} else {
|
|
MR_NUMBER = 'develop'
|
|
}
|
|
// Workaround for the "cancelled" GitLab pipeline notification
|
|
// The slave job is triggered with the propagate false so the following commands are executed
|
|
// Its status is now PASS/SUCCESS from a stage pipeline point of view
|
|
// localStatus variable MUST be analyzed to properly assess the status
|
|
localStatus = build job: jobName,
|
|
parameters: [
|
|
string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)),
|
|
string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)),
|
|
string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
|
|
string(name: 'eNB_MR', value: String.valueOf(MR_NUMBER)),
|
|
booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)),
|
|
string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch))
|
|
], propagate: false
|
|
localResult = localStatus.getResult()
|
|
echo "${jobName} Slave Job status is ${localResult}"
|
|
gitlabCommitStatus(name: gitlabStatusName) {
|
|
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
|
|
echo "${jobName} Slave Job is OK"
|
|
} else {
|
|
error "${jobName} Slave Job is KO"
|
|
}
|
|
}
|
|
}
|
|
|
|
def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
|
|
if ("MERGE".equals(env.gitlabActionType)) {
|
|
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.gitlabMergeRequestLastCommit
|
|
shortenShaOne = shortenShaOne.trim()
|
|
branchName = env.gitlabSourceBranch.replaceAll("/", "-").trim()
|
|
fullRanTag = 'porcepix.sboai.cs.eurecom.fr/oai-gnb:' + env.gitlabSourceBranch + '-' + shortenShaOne
|
|
} else {
|
|
shortenShaOne = sh returnStdout: true, script: 'git log -1 --pretty=format:"%h" --abbrev=8 ' + env.GIT_COMMIT
|
|
shortenShaOne = shortenShaOne.trim()
|
|
fullRanTag = 'porcepix.sboai.cs.eurecom.fr/oai-gnb:develop-' + shortenShaOne
|
|
}
|
|
// Workaround for the "cancelled" GitLab pipeline notification
|
|
// The slave job is triggered with the propagate false so the following commands are executed
|
|
// Its status is now PASS/SUCCESS from a stage pipeline point of view
|
|
// localStatus variable MUST be analyzed to properly assess the status
|
|
localStatus = build job: jobName,
|
|
parameters: [
|
|
string(name: 'FULL_RAN_TAG', value: String.valueOf(fullRanTag))
|
|
], propagate: false
|
|
localResult = localStatus.getResult()
|
|
echo "${jobName} Slave Job status is ${localResult}"
|
|
gitlabCommitStatus(name: gitlabStatusName) {
|
|
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
|
|
echo "${jobName} Slave Job is OK"
|
|
} else {
|
|
error "${jobName} Slave Job is KO"
|
|
}
|
|
}
|
|
}
|
|
|
|
def triggerSlaveJobNoGitLab (jobName) {
|
|
if ("MERGE".equals(env.gitlabActionType)) {
|
|
MR_NUMBER = env.gitlabMergeRequestIid
|
|
} else {
|
|
MR_NUMBER = 'develop'
|
|
}
|
|
// Workaround for the "cancelled" GitLab pipeline notification
|
|
// The slave job is triggered with the propagate false so the following commands are executed
|
|
// Its status is now PASS/SUCCESS from a stage pipeline point of view
|
|
// localStatus variable MUST be analyzed to properly assess the status
|
|
localStatus = build job: jobName,
|
|
parameters: [
|
|
string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)),
|
|
string(name: 'eNB_Branch', value: String.valueOf(env.gitlabSourceBranch)),
|
|
string(name: 'eNB_CommitID', value: String.valueOf(env.gitlabMergeRequestLastCommit)),
|
|
string(name: 'eNB_MR', value: String.valueOf(MR_NUMBER)),
|
|
booleanParam(name: 'eNB_mergeRequest', value: "MERGE".equals(env.gitlabActionType)),
|
|
string(name: 'eNB_TargetBranch', value: String.valueOf(env.gitlabTargetBranch))
|
|
], propagate: false
|
|
localResult = localStatus.getResult()
|
|
echo "${jobName} Slave Job status is ${localResult}"
|
|
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
|
|
echo "${jobName} Slave Job is OK"
|
|
} else {
|
|
error "${jobName} Slave Job is KO"
|
|
}
|
|
}
|
|
|
|
def finalizeSlaveJob(jobName) {
|
|
lock ('Parent-Lock') {
|
|
// In case of any non-success, we are retrieving the HTML report of the last completed
|
|
// slave job. The only drop-back is that we may retrieve the HTML report of a previous build
|
|
if (jobName == 'OAI-CN5G-COTS-UE-Test') {
|
|
fileName = "test_results_oai_cn5g_cots_ue.html"
|
|
} else {
|
|
fileName = "test_results-${jobName}.html"
|
|
}
|
|
artifactUrl = BUILD_URL
|
|
if (!fileExists(fileName)) {
|
|
copyArtifacts(projectName: jobName,
|
|
filter: 'test_results*.html',
|
|
selector: lastCompleted())
|
|
if (fileExists(fileName)) {
|
|
sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' ${fileName}"
|
|
} else {
|
|
sh "echo \"could not copy results from ${jobName}, please check pipeline ${BUILD_URL}\" > ${fileName}"
|
|
}
|
|
archiveArtifacts artifacts: fileName
|
|
// BUILD_URL is like http://server:port/jenkins/job/foo/15/
|
|
// no need to add a prefixed '/'
|
|
artifactUrl += 'artifact/' + fileName
|
|
}
|
|
artifactUrl = "\n * [${jobName}](${artifactUrl})"
|
|
return artifactUrl
|
|
}
|
|
}
|