Merge remote-tracking branch 'origin/ci-push-local-repo' into integration_2026_w14 (!4017)

CI: Add stage to push to local git repository

This MR includes minor code cleanup and fixes for warnings reported by Jenkins.
It also introduces a new stage in ci-scripts/Jenkinsfile-GitLab-Container that
pushes the branch to a local repository after the merge. In a follow-up MR,
this local repository will be used as the source for cloning the branch,
replacing direct access to GitLab/GitHub.
This commit is contained in:
Jaroslava Fiedlerova
2026-04-03 09:09:06 +02:00
2 changed files with 128 additions and 41 deletions

View File

@@ -34,9 +34,7 @@ pipeline {
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()
env.JOB_TIMESTAMP = sh(returnStdout: true, script: 'date --utc --rfc-3339=seconds | sed -e "s#+00:00##"').trim()
echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
def allParametersPresent = true
@@ -112,6 +110,23 @@ pipeline {
}
}
}
stage ("Local-Repo-Push") {
steps {
script {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
triggerSlaveJob ('RAN-Local-Repo-Push', 'Local-Repo-Push')
}
}
}
post {
failure {
script {
echo "Push to local repository KO"
failingStages += '\n * RAN-Local-Repo-Push'
}
}
}
}
// Build Stages are Mandatory
stage ("Image Building Processes") {
when { expression {doBuild} }
@@ -855,25 +870,22 @@ pipeline {
// ---- Slave Job functions
def triggerSlaveJob (jobName, gitlabStatusName) {
if ("MERGE".equals(env.gitlabActionType)) {
MR_NUMBER = env.gitlabMergeRequestIid
} else {
MR_NUMBER = 'develop'
}
def MR_NUMBER = "MERGE".equals(env.gitlabActionType) ? env.gitlabMergeRequestIid : '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,
def localStatus = build job: jobName,
parameters: [
string(name: 'eNB_Repository', value: String.valueOf(GIT_URL)),
string(name: 'SourceRepo', value: String.valueOf(env.gitlabSourceRepoHttpUrl)),
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()
def localResult = localStatus.getResult()
echo "${jobName} Slave Job status is ${localResult}"
gitlabCommitStatus(name: gitlabStatusName) {
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
@@ -899,11 +911,11 @@ def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
// 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,
def localStatus = build job: jobName,
parameters: [
string(name: 'FULL_RAN_TAG', value: String.valueOf(fullRanTag))
], propagate: false
localResult = localStatus.getResult()
def localResult = localStatus.getResult()
echo "${jobName} Slave Job status is ${localResult}"
gitlabCommitStatus(name: gitlabStatusName) {
if (localStatus.resultIsBetterOrEqualTo('SUCCESS')) {
@@ -914,34 +926,6 @@ def triggerCN5GSlaveJob (jobName, gitlabStatusName) {
}
}
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
@@ -957,7 +941,7 @@ def finalizeSlaveJob(jobName) {
filter: 'test_results*.html',
selector: lastCompleted())
if (fileExists(fileName)) {
sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${JOB_TIMESTAMP}#' ${fileName}"
sh "sed -i -e 's#TEMPLATE_BUILD_TIME#${env.JOB_TIMESTAMP}#' ${fileName}"
} else {
sh "echo \"could not copy results from ${jobName}, please check pipeline ${BUILD_URL}\" > ${fileName}"
}

View File

@@ -0,0 +1,103 @@
#!/bin/groovy
/*
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
*/
// Location of the python executor node shall be in the same subnet as the others servers
def nodeExecutor = params.nodeExecutor
// SSH URL of the internal git repository
def internalRepoURL = params.internalRepoURL
// Name of the resource
def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}
pipeline {
agent {
label nodeExecutor
}
options {
ansiColor('xterm')
lock(extra: lockResources)
}
stages {
stage('Verify parameters') {
steps {
script {
def missingParams = []
if (!params.SourceRepo?.trim()) { missingParams << 'SourceRepo' }
if (!params.eNB_Branch?.trim()) { missingParams << 'eNB_Branch' }
if (!params.eNB_CommitID?.trim()) { missingParams << 'eNB_CommitID' }
if (!params.eNB_TargetBranch?.trim()) { missingParams << 'eNB_TargetBranch' }
if (!params.eNB_Repository?.trim()) { missingParams << 'eNB_Repository' }
if (missingParams) {
error "Missing required parameters: ${missingParams.join(', ')}"
}
echo "Source Repo : ${params.SourceRepo}"
echo "Source Branch : ${params.eNB_Branch}"
echo "Source Commit : ${params.eNB_CommitID}"
echo "Target Branch : ${params.eNB_TargetBranch}"
echo "Target Repo : ${params.eNB_Repository}"
}
}
}
stage('Prepare workspace') {
steps {
sh """
git config user.email "jenkins@openairinterface.org"
git config user.name "OAI Jenkins"
git remote remove source || true
git remote remove internal-repo || true
"""
}
}
stage('Add source repo & fetch branches') {
steps {
sh """
git remote add source ${params.SourceRepo} || true
git fetch source ${params.eNB_Branch}
git fetch origin ${params.eNB_TargetBranch}
"""
}
}
stage('Create temporary branch for CI') {
steps {
script {
def shortCommit = params.eNB_CommitID.take(8)
env.NEW_BRANCH = "${params.eNB_Branch}-${shortCommit}"
echo "New branch: ${env.NEW_BRANCH}"
}
sh """
# Checkout source commit
git checkout -B ${env.NEW_BRANCH} ${params.eNB_CommitID}
"""
}
}
stage('Merge target into source') {
steps {
sh """
echo "Merging target branch ${params.eNB_TargetBranch} into source branch ${env.NEW_BRANCH}"
if ! git merge --ff origin/${params.eNB_TargetBranch} \
-m "Merge ${params.eNB_TargetBranch} into ${params.eNB_Branch} for CI"; then
echo "Merge conflicts detected. Aborting."
git merge --abort || true
exit 1
fi
"""
}
}
stage('Push merged branch to internal repository') {
steps {
sh """
git remote add internal-repo ${internalRepoURL} || true
echo "Pushing ${env.NEW_BRANCH} to internal repo"
git push --force internal-repo ${env.NEW_BRANCH}
"""
}
}
}
}