Commit b9197553 authored by Raphael Defosseux's avatar Raphael Defosseux

CI: update README, initial Jenkins pipeline skeleton, moved dockerfiles

Signed-off-by: default avatarRaphael Defosseux <raphael.defosseux@eurecom.fr>
parent 396896be
# Private Repository for initial development on OpenAir Core-Network 5G #
------------------------------------------------------------------------------
**AMF Repository**
OPENAIR-CN-5G
An implementation of the 5G Core network by the OpenAirInterface community.
------------------------------------------------------------------------------
OPENAIR-CN-5G is an implementation of the 3GPP specifications for the 5G Core Network.
At the moment, it contains the following network elements.
Each has its own repository: this repository (`oai-cn5g-amf`) is meant for the
**Access and Mobility Management Function** (also knwon as **AMF**).
# Licence info
It is distributed under `OAI Public License V1.1`.
See [OAI Website for more details](https://www.openairinterface.org/?page_id=698).
The text for `OAI Public License V1.1` is also available under [LICENSE](LICENSE)
file at the root of this repository.
# Where to start
The Openair-CN-5G AMF code is written, executed, and tested on UBUNTU server bionic version.
Other Linux distributions support will be added later on.
More details on the supported feature set is available on this [page](docs/FEATURE_SET.md).
# Collaborative work
This source code is managed through a GITLAB server, a collaborative development platform:
* URL: [https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-amf](https://gitlab.eurecom.fr/oai/cn5g/oai-cn5g-amf).
Process is explained in [CONTRIBUTING](CONTRIBUTING.md) file.
# Contribution requests
In a general way, anybody who is willing can contribute on any part of the
code in any network component.
Contributions can be simple bugfixes, advices and remarks on the design,
architecture, coding/implementation.
# Release Notes
They are available on the [CHANGELOG](CHANGELOG.md) file.
#!/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 CN executor node
def cn_ci_host = params.Host_CN_CI_Server
// for lock
def cn_ci_resource = params.DockerContainers
// Location of the 2nd CN executor
def new_host_flag = false
def new_host = ""
def new_host_user = ""
// Tags/Branches to use
def amf_tag = "develop"
def amf_branch = "develop"
//-------------------------------------------------------------------------------
// Pipeline start
pipeline {
agent {
label cn_ci_host
}
options {
disableConcurrentBuilds()
timestamps()
ansiColor('xterm')
lock(cn_ci_resource)
gitLabConnection('OAI GitLab')
gitlabBuilds(builds: [
"Build AMF Image",
"Static Code Analysis",
"Code Formatting Checker"
])
}
stages {
stage ('Verify Parameters') {
steps {
script {
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
JOB_TIMESTAMP = sh returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"'
JOB_TIMESTAMP = JOB_TIMESTAMP.trim()
if (params.Host_CN_CI_2nd_Server_Flag != null) {
new_host_flag = params.Host_CN_CI_2nd_Server_Flag
if (new_host_flag) {
new_host = params.Host_CN_CI_2nd_Server
new_host_user = params.Host_CN_CI_2nd_Server_Login
echo "1st Node is ${NODE_NAME}"
echo "2nd Node is ${new_host}"
} else {
echo "Node is ${NODE_NAME}"
}
} else {
echo "Node is ${NODE_NAME}"
}
}
}
}
stage ('Prepare Source Code') {
steps {
script {
sh "git clean -x -d -f > /dev/null 2>&1"
if ("MERGE".equals(env.gitlabActionType)) {
gitCommitAuthorEmailAddr = env.gitlabUserEmail
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
sh "./ci-scripts/doGitLabMerge.sh --src-branch ${env.gitlabSourceBranch} --src-commit ${env.gitlabMergeRequestLastCommit} --target-branch ${env.gitlabTargetBranch} --target-commit ${GIT_COMMIT}"
amf_tag = "ci-temp"
amf_branch = env.gitlabSourceBranch
} else {
echo "Git Branch is ${GIT_BRANCH}"
echo "Git Commit is ${GIT_COMMIT}"
gitCommitAuthorEmailAddr = sh returnStdout: true, script: 'git log -n1 --pretty=format:%ae ${GIT_COMMIT}'
gitCommitAuthorEmailAddr = gitCommitAuthorEmailAddr.trim()
echo "GitLab Usermail is ${gitCommitAuthorEmailAddr}"
sh "git log -n1 --pretty=format:\"%s\" > .git/CI_COMMIT_MSG"
}
sh "tar -cjhf /tmp/openair-amf.tar.bz2 ."
sh "mv /tmp/openair-amf.tar.bz2 ."
copyTo2ndServer('openair-amf.tar.bz2', new_host_flag, new_host_user, new_host)
sh "mkdir -p archives"
if (new_host_flag) {
sh "mkdir -p archives/oai-amf-cfg"
}
}
}
post {
failure {
script {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): Merge Conflicts -- Cannot perform CI"
addGitLabMRComment comment: message
currentBuild.result = 'FAILURE'
}
}
}
}
stage('Build Core Network Function') {
parallel {
stage ('Build AMF Image') {
steps {
script {
gitlabCommitStatus(name: "Build AMF Image") {
myShCmd('docker image prune --force', new_host_flag, new_host_user, new_host)
if ("PUSH".equals(env.gitlabActionType)) {
// Currently this pipeline only runs for pushes to `develop` branch
// First clean image registry
try {
myShCmd('docker image rm oai-amf:develop', new_host_flag, new_host_user, new_host)
} catch (Exception e) {
echo "Maybe a previous build went wrong"
}
}
myShCmd('docker build --target oai-amf --tag oai-amf:' + amf_tag + ' --file docker/Dockerfile.ubuntu.18.04 --build-arg NEEDED_GIT_PROXY="http://proxy.eurecom.fr:8080" . > archives/amf_docker_image_build.log 2>&1', new_host_flag, new_host_user, new_host)
myShCmd('docker image ls >> archives/amf_docker_image_build.log', new_host_flag, new_host_user, new_host)
}
}
}
post {
always {
script {
copyFrom2ndServer('archives/amf_docker_image_build.log', 'archives', new_host_flag, new_host_user, new_host)
}
}
success {
sh "echo 'OAI-AMF DOCKER IMAGE BUILD: OK' >> archives/amf_docker_image_build.log"
}
unsuccessful {
sh "echo 'OAI-AMF DOCKER IMAGE BUILD: KO' >> archives/amf_docker_image_build.log"
}
}
}
// Running CPPCHECK in parallel to gain time
stage ('Static Code Analysis') {
steps {
script {
gitlabCommitStatus(name: "Static Code Analysis") {
// Running on xenial to have 1.72 version of cppcheck
myShCmd('docker run --name ci-cn-cppcheck -d ubuntu:xenial /bin/bash -c "sleep infinity"', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-cppcheck /bin/bash -c "apt-get update && apt-get upgrade --yes" > archives/cppcheck_install.log', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-cppcheck /bin/bash -c "apt-get install --yes cppcheck bzip2" >> archives/cppcheck_install.log', new_host_flag, new_host_user, new_host)
myShCmd('docker cp ./openair-amf.tar.bz2 ci-cn-cppcheck:/home', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-cppcheck /bin/bash -c "cd /home && tar -xjf openair-amf.tar.bz2"', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-cppcheck /bin/bash -c "rm -f /home/openair-amf.tar.bz2"', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-cppcheck /bin/bash -c "cd /home && cppcheck --enable=warning --force --xml --xml-version=2 --suppressions-list=ci-scripts/cppcheck_suppressions.list src 2> cppcheck.xml 1> cppcheck_build.log"', new_host_flag, new_host_user, new_host)
}
}
}
post {
always {
script {
myShCmd('docker cp ci-cn-cppcheck:/home/cppcheck.xml archives', new_host_flag, new_host_user, new_host)
myShCmd('docker cp ci-cn-cppcheck:/home/cppcheck_build.log archives', new_host_flag, new_host_user, new_host)
copyFrom2ndServer('archives/cppcheck*.*', 'archives', new_host_flag, new_host_user, new_host)
// no need to keep the cppcheck container
myShCmd('docker rm -f ci-cn-cppcheck', new_host_flag, new_host_user, new_host)
}
}
success {
sh "echo 'CPPCHECK: OK' >> archives/cppcheck_install.log"
}
unsuccessful {
sh "echo 'CPPCHECK: KO' >> archives/cppcheck_install.log"
}
}
}
// Running CLANG-FORMATTING check in parallel to gain time
stage ('Code Formatting Checker') {
steps {
script {
gitlabCommitStatus(name: "Code Formatting Checker") {
myShCmd('docker run --name ci-cn-clang-formatter -d ubuntu:bionic /bin/bash -c "sleep infinity"', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-clang-formatter /bin/bash -c "apt-get update && apt-get upgrade --yes" > archives/clang_format_install.log', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-clang-formatter /bin/bash -c "apt-get install --yes git tree bzip2" >> archives/clang_format_install.log', new_host_flag, new_host_user, new_host)
myShCmd('docker cp ./openair-amf.tar.bz2 ci-cn-clang-formatter:/home', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-clang-formatter /bin/bash -c "cd /home && tar -xjf openair-amf.tar.bz2"', new_host_flag, new_host_user, new_host)
myShCmd('docker exec -it ci-cn-clang-formatter /bin/bash -c "rm -f /home/openair-amf.tar.bz2"', new_host_flag, new_host_user, new_host)
// We install a dedicated version (installed on our CI server).
myShCmd('docker cp /opt/clang-format/9.0.0/bin/clang-format ci-cn-clang-formatter:/usr/local/bin', new_host_flag, new_host_user, new_host)
if ("MERGE".equals(env.gitlabActionType)) {
myShCmd('docker exec -it ci-cn-clang-formatter /bin/bash -c "cd /home && ./ci-scripts/checkCodingFormattingRules.sh --src-branch ' + env.gitlabSourceBranch +' --target-branch ' + env.gitlabTargetBranch + '"', new_host_flag, new_host_user, new_host)
} else {
myShCmd('docker exec -it ci-cn-clang-formatter /bin/bash -c "cd /home && ./ci-scripts/checkCodingFormattingRules.sh"', new_host_flag, new_host_user, new_host)
}
}
}
}
post {
always {
script {
myShCmd('docker cp ci-cn-clang-formatter:/home/src/oai_rules_result.txt src', new_host_flag, new_host_user, new_host)
// May not have been generated
try {
myShCmd('docker cp ci-cn-clang-formatter:/home/src/oai_rules_result_list.txt src', new_host_flag, new_host_user, new_host)
} catch (Exception e) {
echo "Failed to copy src/oai_rules_result_list.txt! It may not have been generated. That's OK!"
}
copyFrom2ndServer('archives/clang_format*.*', 'archives', new_host_flag, new_host_user, new_host)
copyFrom2ndServer('src/oai_rules*.*', 'src', new_host_flag, new_host_user, new_host)
// no need to keep the clang-formatter container
myShCmd('docker rm -f ci-cn-clang-formatter', new_host_flag, new_host_user, new_host)
}
}
}
}
}
}
}
post {
success {
script {
if ("MERGE".equals(env.gitlabActionType)) {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): passed (" + BUILD_URL + ")"
echo "This is a MERGE event"
addGitLabMRComment comment: message
}
}
}
unsuccessful {
script {
if ("MERGE".equals(env.gitlabActionType)) {
def message = "OAI " + JOB_NAME + " build (" + BUILD_ID + "): failed (" + BUILD_URL + ")"
echo "This is a MERGE event"
addGitLabMRComment comment: message
}
}
}
cleanup {
script {
// Removing temporary / intermediate images
try {
if ("MERGE".equals(env.gitlabActionType)) {
myShCmd('docker image rm --force oai-amf:ci-temp', new_host_flag, new_host_user, new_host)
}
} catch (Exception e) {
echo "We failed to delete the OAI-AMF temp image"
}
try {
myShCmd('docker image prune --force', new_host_flag, new_host_user, new_host)
} catch (Exception e) {
echo "We failed to prune all unneeded intermediate images"
}
// Zipping all archived log files
sh "zip -r -qq docker_logs.zip archives"
if (fileExists('docker_logs.zip')) {
archiveArtifacts artifacts: 'docker_logs.zip'
}
// Generating the HTML report
if ("MERGE".equals(env.gitlabActionType)) {
sh "python3 ci-scripts/generateHtmlReport.py --job_name=${JOB_NAME} --job_id=${BUILD_ID} --job_url=${BUILD_URL} --git_url=${GIT_URL} --git_src_branch=${env.gitlabSourceBranch} --git_src_commit=${env.gitlabMergeRequestLastCommit} --git_pull_request=True --git_target_branch=${env.gitlabTargetBranch} --git_target_commit=${GIT_COMMIT}"
} else {
sh "python3 ci-scripts/generateHtmlReport.py --job_name=${JOB_NAME} --job_id=${BUILD_ID} --job_url=${BUILD_URL} --git_url=${GIT_URL} --git_src_branch=${GIT_BRANCH} --git_src_commit=${GIT_COMMIT}"
}
sh "sed -i -e 's#TEMPLATE_TIME#${JOB_TIMESTAMP}#' test_results_oai_amf.html"
if (fileExists('test_results_oai_amf.html')) {
archiveArtifacts artifacts: 'test_results_oai_amf.html'
}
// Sending email to commiter
emailext attachmentsPattern: '*results*.html',
body: '''Hi,
Here are attached HTML report files for $PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!
Regards,
OAI CI Team''',
replyTo: 'no-reply@openairinterface.org',
subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!',
to: gitCommitAuthorEmailAddr
}
}
}
}
def copyTo2ndServer(filename, flag, user, host) {
if (flag) {
if ("openair-amf.tar.bz2".equals(filename)) {
sh "ssh ${user}@${host} 'rm -rf /tmp/CI-CN-AMF'"
sh "ssh ${user}@${host} 'mkdir -p /tmp/CI-CN-AMF'"
}
sh "scp ${filename} ${user}@${host}:/tmp/CI-CN-AMF"
if ("openair-amf.tar.bz2".equals(filename)) {
sh "ssh ${user}@${host} 'cd /tmp/CI-CN-AMF && tar -xjf ${filename}'"
sh "ssh ${user}@${host} 'mkdir -p /tmp/CI-CN-AMF/archives'"
sh "ssh ${user}@${host} 'mkdir -p /tmp/CI-CN-AMF/archives/oai-amf-cfg'"
}
}
}
def copyFrom2ndServer(filename, target, flag, user, host) {
if (flag) {
sh "scp ${user}@${host}:/tmp/CI-CN-AMF/${filename} ${target}"
}
}
def myShCmd(cmd, flag, user, host) {
if (flag) {
sh "ssh -t -t ${user}@${host} 'cd /tmp/CI-CN-AMF && ${cmd}'"
} else {
sh "${cmd}"
}
}
def myShRetCmd(cmd, flag, user, host) {
if (flag) {
ret = sh returnStdout: true, script: "ssh -t -t ${user}@${host} 'cd /tmp/CI-CN-AMF && ${cmd}'"
} else {
ret = sh returnStdout: true, script: "${cmd}"
}
ret = ret.trim()
return ret
}
......@@ -30,7 +30,7 @@
#---------------------------------------------------------------------
FROM ubuntu:bionic as oai-amf-builder
ARG EURECOM_PROXY
ARG NEEDED_GIT_PROXY
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe
......@@ -42,7 +42,7 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get upgrade --yes && DE
&& rm -rf /var/lib/apt/lists/*
# Some GIT configuration commands quite useful
RUN /bin/bash -c "if [[ -v EURECOM_PROXY ]]; then git config --global http.proxy $EURECOM_PROXY; fi"
RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi"
RUN git config --global https.postBuffer 123289600
RUN git config --global http.sslverify false
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment