diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container
index d75b1888d4..721c89b77f 100644
--- a/ci-scripts/Jenkinsfile-GitLab-Container
+++ b/ci-scripts/Jenkinsfile-GitLab-Container
@@ -219,28 +219,6 @@ pipeline {
}
}
}
- 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 {
diff --git a/ci-scripts/args_parse.py b/ci-scripts/args_parse.py
index 6206c67d69..16e23113ab 100644
--- a/ci-scripts/args_parse.py
+++ b/ci-scripts/args_parse.py
@@ -22,7 +22,7 @@ import constants as CONST
#-----------------------------------------------------------
-def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
+def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,CLUSTER):
force_local = False
date_fmt = None
@@ -53,7 +53,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranRepository=matchReg.group(1)
HTML.ranRepository=matchReg.group(1)
CONTAINERS.ranRepository=matchReg.group(1)
- SCA.ranRepository=matchReg.group(1)
CLUSTER.ranRepository=matchReg.group(1)
elif re.match(r'^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE):
@@ -66,7 +65,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranAllowMerge=True
HTML.ranAllowMerge=True
CONTAINERS.ranAllowMerge=True
- SCA.ranAllowMerge=True
CLUSTER.ranAllowMerge=True
elif re.match(r'^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE):
@@ -77,7 +75,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranBranch=matchReg.group(1)
HTML.ranBranch=matchReg.group(1)
CONTAINERS.ranBranch=matchReg.group(1)
- SCA.ranBranch=matchReg.group(1)
CLUSTER.ranBranch=matchReg.group(1)
elif re.match(r'^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE):
@@ -88,7 +85,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranCommitID=matchReg.group(1)
HTML.ranCommitID=matchReg.group(1)
CONTAINERS.ranCommitID=matchReg.group(1)
- SCA.ranCommitID=matchReg.group(1)
CLUSTER.ranCommitID=matchReg.group(1)
elif re.match(r'^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE):
if re.match(r'^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE):
@@ -99,7 +95,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
RAN.ranTargetBranch=matchReg.group(1)
HTML.ranTargetBranch=matchReg.group(1)
CONTAINERS.ranTargetBranch=matchReg.group(1)
- SCA.ranTargetBranch=matchReg.group(1)
CLUSTER.ranTargetBranch=matchReg.group(1)
elif re.match(r'^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE):
print("parameters --eNB*IPAddress ignored")
@@ -112,7 +107,6 @@ def ArgsParse(argvs,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER):
matchReg = re.match(r'^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE)
RAN.eNBSourceCodePath=matchReg.group(1)
CONTAINERS.eNBSourceCodePath=matchReg.group(1)
- SCA.eNBSourceCodePath=matchReg.group(1)
CLUSTER.eNBSourceCodePath=matchReg.group(1)
elif re.match(r'^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE):
print("parameter --eNB1SourceCodePath ignored")
diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py
index c7831136e2..461c64d133 100644
--- a/ci-scripts/cls_containerize.py
+++ b/ci-scripts/cls_containerize.py
@@ -184,11 +184,6 @@ class Containerize():
self.services = ''
self.deploymentTag = ''
- self.cli = ''
- self.cliBuildOptions = ''
- self.dockerfileprefix = ''
- self.host = ''
-
self.num_attempts = 1
self.flexricTag = ''
@@ -203,18 +198,7 @@ class Containerize():
cmd = cls_cmd.getConnection(node)
log_files = []
- # Checking the hostname to get adapted on cli and dockerfileprefixes
- cmd.run('hostnamectl')
- result = re.search('Ubuntu|Red Hat', cmd.getBefore())
- self.host = result.group(0)
- if self.host == 'Ubuntu':
- self.cli = 'docker'
- self.dockerfileprefix = '.ubuntu'
- self.cliBuildOptions = ''
- elif self.host == 'Red Hat':
- self.cli = 'sudo podman'
- self.dockerfileprefix = '.rhel9'
- self.cliBuildOptions = '--disable-compression'
+ dockerfileprefix = '.ubuntu'
# we always build the ran-build image with all targets
# Creating a tupple with the imageName, the DockerFile prefix pattern, targetName and sanitized option
@@ -232,23 +216,20 @@ class Containerize():
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', ''))
imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue', ''))
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
- if self.host == 'Red Hat':
- imageNames.append(('oai-physim', 'phySim', 'oai-physim', ''))
- if self.host == 'Ubuntu':
- imageNames.append(('oai-lte-ru', 'lteRU', 'oai-lte-ru', ''))
- # Building again the 5G images with Address Sanitizer
- imageNames.append(('ran-build', 'build', 'ran-build-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-enb', 'eNB', 'oai-enb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-gnb', 'gNB', 'oai-gnb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
- imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
- imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', ''))
- imageNames.append(('oai-nr-oru', 'nrORU.fhi72', 'oai-nr-oru', ''))
+ imageNames.append(('oai-lte-ru', 'lteRU', 'oai-lte-ru', ''))
+ # Building again the 5G images with Address Sanitizer
+ imageNames.append(('ran-build', 'build', 'ran-build-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-enb', 'eNB', 'oai-enb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-gnb', 'gNB', 'oai-gnb-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-lte-ue', 'lteUE', 'oai-lte-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup-asan', '--build-arg "BUILD_OPTION=--sanitize"'))
+ imageNames.append(('ran-build-fhi72', 'build.fhi72', 'ran-build-fhi72', ''))
+ imageNames.append(('oai-gnb', 'gNB.fhi72', 'oai-gnb-fhi72', ''))
+ imageNames.append(('oai-nr-oru', 'nrORU.fhi72', 'oai-nr-oru', ''))
result = re.search('build_cross_arm64', self.imageKind)
if result is not None:
- self.dockerfileprefix = '.ubuntu.cross-arm64'
+ dockerfileprefix = '.ubuntu.cross-arm64'
result = re.search('native_armv9', self.imageKind)
if result is not None:
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
@@ -263,10 +244,6 @@ class Containerize():
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
cmd.cd(lSourcePath)
- # if asterix, copy the entitlement and subscription manager configurations
- if self.host == 'Red Hat':
- cmd.run('mkdir -p ./etc-pki-entitlement')
- cmd.run('cp /etc/pki/entitlement/*.pem ./etc-pki-entitlement/')
baseImage = 'ran-base'
baseTag = 'develop'
@@ -275,7 +252,7 @@ class Containerize():
if (self.ranAllowMerge):
imageTag = 'ci-temp'
if self.ranTargetBranch == 'develop':
- cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{self.dockerfileprefix} | grep --colour=never -i INDEX')
+ cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{dockerfileprefix} | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
forceBaseImageBuild = True
@@ -289,31 +266,30 @@ class Containerize():
forceBaseImageBuild = True
# Let's remove any previous run artifacts if still there
- cmd.run(f"{self.cli} image prune --force")
+ cmd.run(f"docker image prune --force")
for image,pattern,name,option in imageNames:
- cmd.run(f"{self.cli} image rm {name}:{imageTag}", reportNonZero=False)
+ cmd.run(f"docker image rm {name}:{imageTag}", reportNonZero=False)
cmd.run(f'docker login -u oaicicd -p oaicicd {DEFAULT_REGISTRY}')
ubuntuImage = "ubuntu:noble"
# Build the base image only on Push Events (not on Merge Requests)
# On when the base image docker file is being modified.
if forceBaseImageBuild:
- cmd.run(f"{self.cli} image rm {baseImage}:{baseTag}")
+ cmd.run(f"docker image rm {baseImage}:{baseTag}")
logfile = f'{lSourcePath}/cmake_targets/log/ran-base.docker.log'
- if self.host == 'Ubuntu':
- option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
- cmd.run(f"{self.cli} build {self.cliBuildOptions} --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{self.dockerfileprefix} {option} . &> {logfile}", timeout=1600)
+ option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
+ cmd.run(f"docker build --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{dockerfileprefix} {option} . &> {logfile}", timeout=1600)
t = ("ran-base", archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
# First verify if the base image was properly created.
- ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
+ ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
allImagesSize = {}
if ret.returncode != 0:
logging.error('\u001B[1m Could not build properly ran-base\u001B[0m')
# Recover the name of the failed container?
- cmd.run(f"{self.cli} ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty {self.cli} rm -f")
- cmd.run(f"{self.cli} image prune --force")
+ cmd.run(f"docker ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty docker rm -f")
+ cmd.run(f"docker image prune --force")
cmd.close()
logging.error('\u001B[1m Building OAI Images Failed\u001B[0m')
HTML.CreateHtmlTestRow(self.imageKind, 'KO', CONST.ALL_PROCESSES_OK)
@@ -333,32 +309,31 @@ class Containerize():
for image,pattern,name,option in imageNames:
# the archived Dockerfiles have "ran-base:latest" as base image
# we need to update them with proper tag
- cmd.run(f'git checkout -- docker/Dockerfile.{pattern}{self.dockerfileprefix}')
- cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'git checkout -- docker/Dockerfile.{pattern}{dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
# target images should use the proper ran-build image
if image != 'ran-build' and "-asan" in name:
- cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif "fhi72" in name or name == "oai-nr-oru":
- cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif image != 'ran-build':
- cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{self.dockerfileprefix}')
+ cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
if image == 'oai-gnb-aerial':
cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2026.01.07.tar.gz .')
logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log'
- if self.host == 'Ubuntu':
- option = option + f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
- ret = cmd.run(f'{self.cli} build {self.cliBuildOptions} --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{self.dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200)
+ option = option + f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
+ ret = cmd.run(f'docker build --target {image} --tag {name}:{imageTag} --file docker/Dockerfile.{pattern}{dockerfileprefix} {option} . > {logfile} 2>&1', timeout=1200)
t = (name, archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
if image == 'oai-gnb-aerial':
cmd.run('rm -f nvipc_src.2026.01.07.tar.gz')
# check the status of the build
- ret = cmd.run(f"{self.cli} image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}")
+ ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {name}:{imageTag}")
if ret.returncode != 0:
logging.error('\u001B[1m Could not build properly ' + name + '\u001B[0m')
status = False
# Here we should check if the last container corresponds to a failed command and destroy it
- cmd.run(f"{self.cli} ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty {self.cli} rm -f")
+ cmd.run(f"docker ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty docker rm -f")
allImagesSize[name] = 'N/A -- Build Failed'
break
else:
@@ -372,16 +347,16 @@ class Containerize():
logging.debug(f'{name} size is unknown')
allImagesSize[name] = 'unknown'
# Now pruning dangling images in between target builds
- cmd.run(f"{self.cli} image prune --force")
+ cmd.run(f"docker image prune --force")
cmd.run(f'docker logout {DEFAULT_REGISTRY}')
# Remove all intermediate build images and clean up
- cmd.run(f"{self.cli} image rm ran-build:{imageTag} ran-build-asan:{imageTag} ran-build-fhi72:{imageTag} || true")
- cmd.run(f"{self.cli} volume prune --force")
+ cmd.run(f"docker image rm ran-build:{imageTag} ran-build-asan:{imageTag} ran-build-fhi72:{imageTag} || true")
+ cmd.run(f"docker volume prune --force")
# Remove some cached artifacts to prevent out of diskspace problem
logging.debug(cmd.run("df -h").stdout)
logging.debug(cmd.run("docker system df").stdout)
- cmd.run(f"{self.cli} buildx prune --filter until=1h --force")
+ cmd.run(f"docker buildx prune --filter until=1h --force")
logging.debug(cmd.run("df -h").stdout)
logging.debug(cmd.run("docker system df").stdout)
@@ -489,20 +464,12 @@ class Containerize():
cmd = cls_cmd.getConnection(node)
cmd.cd(lSourcePath)
- ret = cmd.run('hostnamectl')
- result = re.search('Ubuntu', ret.stdout)
- host = result.group(0)
- if host != 'Ubuntu':
- cmd.close()
- raise Exception("Can build unit tests only on Ubuntu server")
- logging.debug('running on Ubuntu as expected')
-
# check that ran-base image exists as we expect it
baseImage = 'ran-base'
baseTag = 'develop'
if self.ranAllowMerge:
if self.ranTargetBranch == 'develop':
- cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base{self.dockerfileprefix} | grep --colour=never -i INDEX')
+ cmd.run(f'git diff HEAD..origin/develop -- cmake_targets/build_oai cmake_targets/tools/build_helper docker/Dockerfile.base.ubuntu | grep --colour=never -i INDEX')
result = re.search('index', cmd.getBefore())
if result is not None:
baseTag = 'ci-temp'
diff --git a/ci-scripts/cls_oai_html.py b/ci-scripts/cls_oai_html.py
index 2f59ae1852..66d4b804ae 100644
--- a/ci-scripts/cls_oai_html.py
+++ b/ci-scripts/cls_oai_html.py
@@ -379,90 +379,6 @@ class HTMLManagement():
self.htmlFile.write(' \n')
self.htmlFile.close()
- def CreateHtmlTestRowCppCheckResults(self, CCR):
- if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
- return
- self.htmlFile = open('test_results.html', 'a')
- vId = 0
- for version in CCR.versions:
- self.htmlFile.write('
\n')
- self.htmlFile.write(' | Results for cppcheck v ' + version + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' NB ERRORS | \n')
- if CCR.nbErrors[vId] == 0:
- myColor = 'lightgreen'
- elif CCR.nbErrors[vId] < 20:
- myColor = 'orange'
- else:
- myColor = 'lightcoral'
- self.htmlFile.write(' ' + str(CCR.nbErrors[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' NB WARNINGS | \n')
- if CCR.nbWarnings[vId] == 0:
- myColor = 'lightgreen'
- elif CCR.nbWarnings[vId] < 20:
- myColor = 'orange'
- else:
- myColor = 'lightcoral'
- self.htmlFile.write(' ' + str(CCR.nbWarnings[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | ----------------- | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Memory leak | \n')
- self.htmlFile.write(' ' + str(CCR.nbMemLeaks[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Possible null pointer deference | \n')
- self.htmlFile.write(' ' + str(CCR.nbNullPtrs[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Uninitialized variable | \n')
- self.htmlFile.write(' ' + str(CCR.nbUninitVars[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Undefined behaviour shifting | \n')
- self.htmlFile.write(' ' + str(CCR.nbTooManyBitsShift[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Signed integer overflow | \n')
- self.htmlFile.write(' ' + str(CCR.nbIntegerOverflow[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Printf formatting issues | \n')
- self.htmlFile.write(' ' + str(CCR.nbInvalidPrintf[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Modulo result is predetermined | \n')
- self.htmlFile.write(' ' + str(CCR.nbModuloAlways[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Opposite Condition -> dead code | \n')
- self.htmlFile.write(' ' + str(CCR.nbOppoInnerCondition[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- self.htmlFile.write(' \n')
- self.htmlFile.write(' | \n')
- self.htmlFile.write(' Wrong Scanf Nb Args | \n')
- self.htmlFile.write(' ' + str(CCR.nbWrongScanfArg[vId]) + ' | \n')
- self.htmlFile.write('
\n')
- vId += 1
-
def CreateHtmlTestRowPhySimTestResult(self, testSummary, testResult):
if (self.htmlFooterCreated or (not self.htmlHeaderCreated)):
return
diff --git a/ci-scripts/cls_static_code_analysis.py b/ci-scripts/cls_static_code_analysis.py
index 603df581e3..3b4ee10f9b 100644
--- a/ci-scripts/cls_static_code_analysis.py
+++ b/ci-scripts/cls_static_code_analysis.py
@@ -27,160 +27,30 @@ import constants as CONST
import cls_cmd
from cls_ci_helper import archiveArtifact
-#-----------------------------------------------------------
-# Class Declaration
-#-----------------------------------------------------------
-class CppCheckResults():
-
- def __init__(self):
-
- self.variants = ['bionic', 'focal']
- self.versions = ['','']
- self.nbErrors = [0,0]
- self.nbWarnings = [0,0]
- self.nbNullPtrs = [0,0]
- self.nbMemLeaks = [0,0]
- self.nbUninitVars = [0,0]
- self.nbInvalidPrintf = [0,0]
- self.nbModuloAlways = [0,0]
- self.nbTooManyBitsShift = [0,0]
- self.nbIntegerOverflow = [0,0]
- self.nbWrongScanfArg = [0,0]
- self.nbPtrAddNotNull = [0,0]
- self.nbOppoInnerCondition = [0,0]
-
class StaticCodeAnalysis():
- def __init__(self):
-
- self.ranRepository = ''
- self.ranBranch = ''
- self.ranAllowMerge = False
- self.ranCommitID = ''
- self.ranTargetBranch = ''
- self.eNBSourceCodePath = ''
-
- def CppCheckAnalysis(self, ctx, node, HTML):
- if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '':
- HELP.GenericHelp(CONST.Version)
- sys.exit('Insufficient Parameter')
- lSourcePath = self.eNBSourceCodePath
-
- if not lSourcePath or not node:
- raise ValueError(f"{lSourcePath=} {node=}")
- logging.debug('Building on server: ' + node)
- cmd = cls_cmd.getConnection(node)
- # on RedHat/CentOS .git extension is mandatory
- result = re.search(r'([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository)
- if result is not None:
- full_ran_repo_name = self.ranRepository.replace('git/', 'git')
- else:
- full_ran_repo_name = self.ranRepository + '.git'
-
- cmd.cd(lSourcePath)
- logDir = f'{lSourcePath}/cmake_targets/log'
- cmd.run(f'mkdir -p {logDir}')
- cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal')
- cmd.run(f'sed -e "s@xenial@bionic@" {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.xenial > {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.bionic')
- cmd.run(f'docker build --tag oai-cppcheck:bionic --file {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.bionic . > {logDir}/cppcheck-bionic.txt 2>&1')
- cmd.run(f'sed -e "s@xenial@focal@" {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.xenial > {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.focal')
- cmd.run(f'docker build --tag oai-cppcheck:focal --file {lSourcePath}/ci-scripts/docker/Dockerfile.cppcheck.focal . > {logDir}/cppcheck-focal.txt 2>&1')
- cmd.run('docker image rm oai-cppcheck:bionic oai-cppcheck:focal')
-
- bionic = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-bionic.txt')
- focal = archiveArtifact(cmd, ctx, f'{logDir}/cppcheck-focal.txt')
- cmd.close()
-
- CCR = CppCheckResults()
- CCR_ref = CppCheckResults()
- vId = 0
- for variant in CCR.variants:
- filename = ctx.baseFilename() + '-cppcheck-'+ variant + '.txt'
- logging.info(f"will check file '{filename}'")
- if not os.path.isfile(filename):
- raise FileNotFoundError(f"{filename} is not a file")
- else:
- xmlStart = False
- with open(filename, 'r') as logfile:
- for line in logfile:
- ret = re.search(r'cppcheck version="(?P[0-9\.]+)"', str(line))
- if ret is not None:
- CCR.versions[vId] = ret.group('version')
- if re.search('RUN cat cmake_targets/log/cppcheck.xml', str(line)) is not None:
- xmlStart = True
- if xmlStart:
- if re.search('severity="error"', str(line)) is not None:
- CCR.nbErrors[vId] += 1
- if re.search('severity="warning"', str(line)) is not None:
- CCR.nbWarnings[vId] += 1
- if re.search('id="memleak"', str(line)) is not None:
- CCR.nbMemLeaks[vId] += 1
- if re.search('id="nullPointer"', str(line)) is not None:
- CCR.nbNullPtrs[vId] += 1
- if re.search('id="uninitvar"', str(line)) is not None:
- CCR.nbUninitVars[vId] += 1
- if re.search('id="invalidPrintfArgType_sint"|id="invalidPrintfArgType_uint"', str(line)) is not None:
- CCR.nbInvalidPrintf[vId] += 1
- if re.search('id="moduloAlwaysTrueFalse"', str(line)) is not None:
- CCR.nbModuloAlways[vId] += 1
- if re.search('id="shiftTooManyBitsSigned"', str(line)) is not None:
- CCR.nbTooManyBitsShift[vId] += 1
- if re.search('id="integerOverflow"', str(line)) is not None:
- CCR.nbIntegerOverflow[vId] += 1
- if re.search('id="wrongPrintfScanfArgNum"|id="invalidScanfArgType_int"', str(line)) is not None:
- CCR.nbWrongScanfArg[vId] += 1
- if re.search('id="pointerAdditionResultNotNull"', str(line)) is not None:
- CCR.nbPtrAddNotNull[vId] += 1
- if re.search('id="oppositeInnerCondition"', str(line)) is not None:
- CCR.nbOppoInnerCondition[vId] += 1
- vMsg = ''
- vMsg += '======== Variant ' + variant + ' - ' + CCR.versions[vId] + ' ========\n'
- vMsg += ' ' + str(CCR.nbErrors[vId]) + ' errors\n'
- vMsg += ' ' + str(CCR.nbWarnings[vId]) + ' warnings\n'
- vMsg += ' -- Details --\n'
- vMsg += ' Memory leak: ' + str(CCR.nbMemLeaks[vId]) + '\n'
- vMsg += ' Possible null pointer deference: ' + str(CCR.nbNullPtrs[vId]) + '\n'
- vMsg += ' Uninitialized variable: ' + str(CCR.nbUninitVars[vId]) + '\n'
- vMsg += ' Undefined behaviour shifting: ' + str(CCR.nbTooManyBitsShift[vId]) + '\n'
- vMsg += ' Signed integer overflow: ' + str(CCR.nbIntegerOverflow[vId]) + '\n'
- vMsg += '\n'
- vMsg += ' Printf formatting issue: ' + str(CCR.nbInvalidPrintf[vId]) + '\n'
- vMsg += ' Modulo result is predetermined: ' + str(CCR.nbModuloAlways[vId]) + '\n'
- vMsg += ' Opposite Condition -> dead code: ' + str(CCR.nbOppoInnerCondition[vId]) + '\n'
- vMsg += ' Wrong Scanf Nb Args: ' + str(CCR.nbWrongScanfArg[vId]) + '\n'
- for vLine in vMsg.split('\n'):
- logging.debug(vLine)
- vId += 1
-
- HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK)
- HTML.CreateHtmlTestRowCppCheckResults(CCR)
- logging.info('\u001B[1m Static Code Analysis Pass\u001B[0m')
-
- return True
-
- def LicenceAndFormattingCheck(self, ctx, node, HTML):
+ def LicenceAndFormattingCheck(ctx, node, HTML, d, branch, allowMerge, targetBranch):
# Workspace is no longer recreated from scratch.
# It implies that this method shall be called last within a build pipeline
# where workspace is already created
- lSourcePath = self.eNBSourceCodePath
- if not node or not lSourcePath:
- raise ValueError(f"{lSourcePath=} {node=}")
+ if not node or not d:
+ raise ValueError(f"{d=} {node=}")
logging.debug('Building on server: ' + node)
cmd = cls_cmd.getConnection(node)
check_options = ''
- if self.ranAllowMerge:
- check_options = f'--build-arg MERGE_REQUEST=true --build-arg SRC_BRANCH={self.ranBranch}'
- if self.ranTargetBranch == '':
- if self.ranBranch != 'develop' and self.ranBranch != 'origin/develop':
+ if allowMerge:
+ check_options = f'--build-arg MERGE_REQUEST=true --build-arg SRC_BRANCH={branch}'
+ if targetBranch == '':
+ if branch != 'develop' and branch != 'origin/develop':
check_options += ' --build-arg TARGET_BRANCH=develop'
else:
- check_options += f' --build-arg TARGET_BRANCH={self.ranTargetBranch}'
+ check_options += f' --build-arg TARGET_BRANCH={targetBranch}'
- logDir = f'{lSourcePath}/cmake_targets/log/'
+ logDir = f'{d}/cmake_targets/log/'
cmd.run(f'mkdir -p {logDir}')
cmd.run('docker image rm oai-formatting-check:latest')
- cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {lSourcePath}/ci-scripts/docker/Dockerfile.formatting.ubuntu {lSourcePath} > {logDir}/oai-formatting-check.txt 2>&1')
+ cmd.run(f'docker build --target oai-formatting-check --tag oai-formatting-check:latest {check_options} --file {d}/ci-scripts/docker/Dockerfile.formatting.ubuntu {d} > {logDir}/oai-formatting-check.txt 2>&1')
cmd.run('docker image rm oai-formatting-check:latest')
cmd.run('docker image prune --force')
diff --git a/ci-scripts/docker/Dockerfile.cppcheck.xenial b/ci-scripts/docker/Dockerfile.cppcheck.xenial
deleted file mode 100644
index fcb7f814ae..0000000000
--- a/ci-scripts/docker/Dockerfile.cppcheck.xenial
+++ /dev/null
@@ -1,41 +0,0 @@
-# SPDX-License-Identifier: LicenseRef-CSSL-1.0
-
-#---------------------------------------------------------------------
-#
-# Dockerfile for the Open-Air-Interface BUILD service
-# Valid for Ubuntu 22.04
-#
-#---------------------------------------------------------------------
-FROM ubuntu:xenial AS oai-cppcheck
-
-
-ENV DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update && \
- apt-get upgrade --yes && \
- apt-get install --yes \
- build-essential \
- vim \
- cppcheck
-
-WORKDIR /oai-ran
-COPY . .
-
-WORKDIR /oai-ran/common/utils/T
-RUN make
-
-WORKDIR /oai-ran
-RUN mkdir -p cmake_targets/log && \
- cppcheck --enable=warning --force --xml --xml-version=2 \
- --inline-suppr \
- -i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \
- --suppressions-list=ci-scripts/cppcheck_suppressions.list \
- -I common/utils \
- -I openair3/NAS/COMMON/UTIL \
- -j`nproc` . 2> cmake_targets/log/cppcheck.xml 1> cmake_targets/log/cppcheck_build.txt
-
-RUN grep -E -c 'severity="error' cmake_targets/log/cppcheck.xml
-
-RUN grep -E -c 'severity="warning' cmake_targets/log/cppcheck.xml
-
-RUN cat cmake_targets/log/cppcheck.xml
diff --git a/ci-scripts/main.py b/ci-scripts/main.py
index 27cf36bcf8..66e8b2091b 100644
--- a/ci-scripts/main.py
+++ b/ci-scripts/main.py
@@ -22,7 +22,7 @@ import constants as CONST
import cls_oaicitest #main class for OAI CI test framework
import cls_containerize #class Containerize for all container-based operations on RAN/UE objects
-import cls_static_code_analysis #class for static code analysis
+import cls_static_code_analysis as SCA
import cls_cluster # class for building/deploying on cluster
import cls_native # class for all native/source-based operations
from cls_ci_helper import TestCaseCtx
@@ -64,7 +64,6 @@ def ExecuteActionWithParam(action, ctx, node):
global RAN
global HTML
global CONTAINERS
- global SCA
global CLUSTER
if action == 'Build_eNB' or action == 'Build_Image' or action == 'Build_Proxy' or action == "Build_Cluster_Image" or action == "Build_Run_Tests":
RAN.Build_eNB_args=test.findtext('Build_eNB_args')
@@ -196,10 +195,7 @@ def ExecuteActionWithParam(action, ctx, node):
success = CONTAINERS.Create_Workspace(node, HTML)
elif action == 'LicenceAndFormattingCheck':
- success = SCA.LicenceAndFormattingCheck(ctx, node, HTML)
-
- elif action == 'Cppcheck_Analysis':
- success = SCA.CppCheckAnalysis(ctx, node, HTML)
+ success = SCA.StaticCodeAnalysis.LicenceAndFormattingCheck(ctx, node, HTML, RAN.eNBSourceCodePath, RAN.ranBranch, RAN.ranAllowMerge, RAN.ranTargetBranch)
elif action == 'Push_Local_Registry':
tag_prefix = test.findtext('tag_prefix') or ""
@@ -297,7 +293,6 @@ CiTestObj = cls_oaicitest.OaiCiTest()
RAN = ran.RANManagement()
HTML = cls_oai_html.HTMLManagement()
CONTAINERS = cls_containerize.Containerize()
-SCA = cls_static_code_analysis.StaticCodeAnalysis()
CLUSTER = cls_cluster.Cluster()
#-----------------------------------------------------------
@@ -307,7 +302,7 @@ CLUSTER = cls_cluster.Cluster()
import args_parse
# Force local execution, move all execution targets to localhost
force_local = False
-mode, force_local, date_fmt = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,SCA,CLUSTER)
+mode, force_local, date_fmt = args_parse.ArgsParse(sys.argv,CiTestObj,RAN,HTML,CONTAINERS,HELP,CLUSTER)
fmt = "%(levelname)8s: %(message)s"
if date_fmt:
fmt = "[%(asctime)s] %(levelname)s %(message)s"
diff --git a/ci-scripts/xml_class_list.yml b/ci-scripts/xml_class_list.yml
index 52b44e0e96..d762c4b316 100755
--- a/ci-scripts/xml_class_list.yml
+++ b/ci-scripts/xml_class_list.yml
@@ -23,7 +23,6 @@
- Deploy_Object
- Stop_Object
- Undeploy_Object
- - Cppcheck_Analysis
- Deploy_Run_OC_PhySim
- Build_Deploy_PhySim
- LicenceAndFormattingCheck
diff --git a/ci-scripts/xml_files/cppcheck.xml b/ci-scripts/xml_files/cppcheck.xml
deleted file mode 100644
index 061c39b5b8..0000000000
--- a/ci-scripts/xml_files/cppcheck.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- build-tab
- CPPCHECK Analysis
- wrench
-
-
- Create_Workspace
- Create new Workspace
- carabe
-
-
-
- Cppcheck_Analysis
- Static Code Analysis with cppcheck
- carabe
-
-
-
diff --git a/doc/README.md b/doc/README.md
index 37fe2a980d..d1dfc2dc4d 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -135,6 +135,7 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs.
- [clang-format.md](./clang-format.md): how to format the code. See also the
next entry for an error detection tool.
- [formatting](../tools/formatting/README.md) is a clang-format error detection tool
+- [cppcheck](../tools/cppcheck/README.md) for static code analysis
- [sanitizers.md](./dev_tools/sanitizers.md): how to run with ASan/UBSan/MemSAN/TSan
- [iwyu](../tools/iwyu/README.md) is a tool to detect `#include` errors
- [docker-dev-env](../tools/docker-dev-env/README.md) is a ubuntu24 docker development environment
diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md
index d348ffe355..361d774215 100644
--- a/doc/TESTBenches.md
+++ b/doc/TESTBenches.md
@@ -96,10 +96,6 @@ information on how the images are built.
- orion: Cross-compilation from Intel to ARM
- base image from `Dockerfile.base.ubuntu.cross-arm64`
- build image from `Dockerfile.build.ubuntu.cross-arm64` (no target images)
-- [RAN-cppcheck](https://jenkins-oai.eurecom.fr/job/RAN-cppcheck/)
- ~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
- - bellatrix
- - performs static code analysis, currently not actively enforced
- [RAN-RHEL8-Cluster-Image-Builder](https://jenkins-oai.eurecom.fr/job/RAN-RHEL8-Cluster-Image-Builder/)
~BUILD-ONLY ~4G-LTE ~5G-NR ~nrUE
- cluster (`Asterix-OC-oaicicd-session` resource): RHEL image build using the OpenShift Cluster (using gcc/clang)
diff --git a/tools/cppcheck/README.md b/tools/cppcheck/README.md
new file mode 100644
index 0000000000..414f35a68a
--- /dev/null
+++ b/tools/cppcheck/README.md
@@ -0,0 +1,28 @@
+
+
+# Static code analysis
+
+How to run static code analysis tool(s).
+
+[[_TOC_]]
+
+## cppcheck Overview
+
+This can run a (dockerized) cppcheck static code analysis. The docker-compose
+file represents the status as run as in the CI until it's removal (because it
+was not enforced). It is now here so that people could use it to find bugs (and
+use the tool more easily).
+
+## cppcheck Usage
+
+From the openairinterface5g root, simply run
+
+ ./tools/cppcheck/run-cppcheck.sh
+
+This will run cppcheck with options listed in this file, assuming you have it
+installed. Alternatively, you can run the CI version as of Ubuntu 20 with
+
+ cd tools/cppcheck && docker compose up --no-log-prefix
+
+You can upgrade to a newer version by modifying the `FROM` line in the
+docker-compose file.
diff --git a/tools/cppcheck/docker-compose.yaml b/tools/cppcheck/docker-compose.yaml
new file mode 100644
index 0000000000..8b8c5878d0
--- /dev/null
+++ b/tools/cppcheck/docker-compose.yaml
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: MIT
+
+services:
+ cppcheck:
+ image: cppcheck
+ build:
+ dockerfile_inline: |
+ FROM ubuntu:focal
+ RUN DEBIAN_FRONTEND=noninteractive apt update && apt install -y cppcheck
+ volumes:
+ - ../../:/code/
+ command:
+ bash -c "cd /code/ && ./tools/cppcheck/run-cppcheck.sh"
+
diff --git a/tools/cppcheck/run-cppcheck.sh b/tools/cppcheck/run-cppcheck.sh
new file mode 100755
index 0000000000..5a5df0c752
--- /dev/null
+++ b/tools/cppcheck/run-cppcheck.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# SPDX-License-Identifier: MIT
+
+cppcheck --enable=warning --force \
+ --inline-suppr \
+ --quiet \
+ -i openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.c \
+ --suppressions-list=tools/cppcheck/suppressions.list \
+ -I common/utils \
+ -I openair3/NAS/COMMON/UTIL \
+ -j`nproc` .
diff --git a/ci-scripts/cppcheck_suppressions.list b/tools/cppcheck/suppressions.list
similarity index 100%
rename from ci-scripts/cppcheck_suppressions.list
rename to tools/cppcheck/suppressions.list