blob: 3f7a36e8181d7cf44ca7a5d7c3f1eb143224188f [file] [log] [blame]
caviedesje9c2a432026-01-16 10:24:43 +01001/*
2 Licensed under the Apache License, Version 2.0 (the "License");
3 you may not use this file except in compliance with the License.
4 You may obtain a copy of the License at
5
6 http://www.apache.org/licenses/LICENSE-2.0
7
8 Unless required by applicable law or agreed to in writing, software
9 distributed under the License is distributed on an "AS IS" BASIS,
10 WITHOUT WARRANTIES OR CONDITIONS OF ANY, either express or
11 implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14*/
15
16def DEFAULT_MODULE_NAME = 'devops'
17
18pipeline {
19 agent { label 'pool' }
20 options { disableConcurrentBuilds() }
21 parameters {
22 // Core Gerrit / multibranch inputs
23 string(name: 'GERRIT_BRANCH', defaultValue: env.BRANCH_NAME ?: 'master', description: '')
24 string(name: 'GERRIT_PROJECT', defaultValue: 'osm/devops', description: '')
25 string(name: 'GERRIT_REFSPEC', defaultValue: env.GERRIT_REFSPEC ?: '', description: '')
26 string(name: 'GERRIT_PATCHSET_REVISION', defaultValue: env.GERRIT_PATCHSET_REVISION ?: '', description: '')
27 string(name: 'DOCKER_ARGS', defaultValue: '', description: 'Extra docker args for docker run')
28
29 // E2E test parameters
garciadeblas64c47c72026-01-21 09:02:03 +010030 string(name: 'OPENSTACK_BASE_IMAGE', defaultValue: 'ubuntu24.04', description: '')
caviedesje9c2a432026-01-16 10:24:43 +010031 string(name: 'OPENSTACK_OSM_FLAVOR', defaultValue: 'osm.sanity', description: '')
32 string(name: 'MODULE_NAME', defaultValue: 'devops', description: 'Name of the module under test')
33
34 // Pipeline control flags
35 booleanParam(name: 'DO_INSTALL', defaultValue: true, description: '')
36 booleanParam(name: 'DO_DOCKERPUSH', defaultValue: true, description: '')
37 booleanParam(name: 'DO_ROBOT', defaultValue: true, description: '')
38 booleanParam(name: 'SAVE_CONTAINER_ON_FAIL', defaultValue: false, description: '')
39 booleanParam(name: 'SAVE_CONTAINER_ON_PASS', defaultValue: false, description: '')
40
41 // Docker image configuration
42 string(name: 'IMAGENAME', defaultValue: 'opensourcemano/devops', description: 'Image name for publish (reserved)')
43 }
44 environment {
45 MDG = "${params.GERRIT_PROJECT?.contains('/') ? params.GERRIT_PROJECT.split('/')[1] : params.GERRIT_PROJECT}"
46 CONTAINER_NAME = "${params.GERRIT_PROJECT}-${params.GERRIT_BRANCH}".toLowerCase()
47 TEST_IMAGE = 'overdrive3000/tox-osm:v1.6'
48 DOCKER_REGISTRY = 'osm.etsi.org:5050/devops/cicd/'
49 }
50 stages {
51 stage('Prepare') { steps { sh 'env' } }
52
53 stage('Checkout') {
54 steps {
55 checkout scm
56 script {
57 sh "git fetch --tags"
58 if (params.GERRIT_REFSPEC?.trim()) { sh "git fetch origin ${params.GERRIT_REFSPEC}" }
59 if (params.GERRIT_PATCHSET_REVISION?.trim()) { sh "git checkout -f ${params.GERRIT_PATCHSET_REVISION}" }
60 sh "sudo git clean -dfx || git clean -dfx"
61 }
62 }
63 }
64
65 stage('License Scan') {
66 steps {
67 script {
68 def isMergeJob = env.JOB_NAME?.contains('merge')
garciadeblascc82cab2026-01-23 12:04:59 +010069 if (!isMergeJob) { sh 'tools/license_scan.sh' } else { echo 'skip the scan for merge' }
caviedesje9c2a432026-01-16 10:24:43 +010070 }
71 }
72 }
73
74 stage('Prepare Test Image') {
75 steps {
76 script {
77 // Use shared test image from registry; no local build needed
78 sh "docker pull ${env.TEST_IMAGE} || true"
79 }
80 }
81 }
82
83 stage('Tests') {
84 steps {
85 script {
86 def UID = sh(returnStdout: true, script: 'id -u').trim()
87 def GID = sh(returnStdout: true, script: 'id -g').trim()
88 def common = "-v ${env.WORKSPACE}:/tests -e UID=${UID} -e GID=${GID} " + (params.DOCKER_ARGS ?: '')
89
90 stage('Helm Tests') {
91 sh """
92 docker run --rm ${common} \
93 ${env.TEST_IMAGE} \
94 /tests/devops-stages/stage-test.sh
95 """
96 if (fileExists('coverage.xml')) { cobertura coberturaReportFile: 'coverage.xml' }
97 if (fileExists('nosetests.xml')) { junit 'nosetests.xml' }
98 }
99
100 stage('Changelog') {
101 sh 'mkdir -p changelog'
102 sh """
103 docker run --rm ${common} \
104 ${env.TEST_IMAGE} \
105 /bin/sh -lc 'devops/tools/generatechangelog-pipeline.sh > /tests/changelog/changelog-${MDG}.html'
106 """
107 }
108 }
109 }
110 }
111
112 stage('Build & Push Image') {
113 when { expression { return params.DO_DOCKERPUSH } }
114 steps {
115 script {
116 def moduleName = (env.MDG ?: DEFAULT_MODULE_NAME).toLowerCase()
117
118 if (!params.GERRIT_BRANCH) {
119 error 'GERRIT_BRANCH is required to tag the Docker image'
120 }
121 def sanitizedBranchName = params.GERRIT_BRANCH
122 .toLowerCase()
123 .replaceAll('[^a-z0-9._-]', '-')
124 def baseTagPrefix = "osm-${sanitizedBranchName}"
125 def buildNumber = env.BUILD_NUMBER ?: '0'
126 def isMergeJob = env.JOB_NAME?.contains('merge')
127 // Remove promotion logic from this stage
128 def moduleTags = []
129 if (isMergeJob) {
caviedesje3c90a82026-01-22 14:21:23 +0100130 moduleTags << "${baseTagPrefix}-merge"
caviedesje9c2a432026-01-16 10:24:43 +0100131 } else {
132 moduleTags << "${baseTagPrefix}-patchset-${buildNumber}"
133 }
134
135 def imageName = params.IMAGENAME ?: "opensourcemano/${moduleName}"
136 def primaryLocalImage = "${imageName}:${moduleTags[0]}"
137
138 withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'gitlab-registry',
139 usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
140 sh """
141 docker build -f Dockerfile -t ${primaryLocalImage} .
142 """
143 sh "docker login ${env.DOCKER_REGISTRY.split('/')[0]} -u ${USERNAME} -p ${PASSWORD}"
144 // Push build-scope tag(s) only. Promotion happens after tests.
145 moduleTags.each { tag ->
146 def localImage = "${imageName}:${tag}"
147 def remoteImage = "${env.DOCKER_REGISTRY}${imageName}:${tag}"
148 sh "docker tag ${localImage} ${remoteImage}"
149 sh "docker push ${remoteImage}"
150 }
151 // Stash the built image id for later promotion without rebuild
152 env.BUILT_IMAGE = primaryLocalImage
153 env.BUILT_TAG = moduleTags[0]
154 }
155 }
156 }
157 }
158
159 stage('E2E Test (robot)') {
160 when { expression { return params.DO_ROBOT && !env.JOB_NAME.contains('merge') } }
161 steps {
162 script {
163 def dowstreamJob = "osm-e2e/${params.GERRIT_BRANCH ?: 'master'}"
164 build job: dowstreamJob,
165 parameters: [
166 string(name: 'GERRIT_BRANCH', value: params.GERRIT_BRANCH ?: 'master'),
167 string(name: 'GERRIT_REFSPEC', value: params.GERRIT_REFSPEC ?: ''),
168 string(name: 'OPENSTACK_BASE_IMAGE', value: params.OPENSTACK_BASE_IMAGE),
169 string(name: 'OPENSTACK_OSM_FLAVOR', value: params.OPENSTACK_OSM_FLAVOR),
170 string(name: 'MODULE_NAME', value: params.MODULE_NAME ?: 'devops'),
171 string(name: 'CONTAINER_NAME', value: env.BUILT_TAG),
172 booleanParam(name: 'DO_ROBOT', value: params.DO_ROBOT),
173 booleanParam(name: 'DO_INSTALL', value: params.DO_INSTALL),
174 booleanParam(name: 'SAVE_CONTAINER_ON_FAIL', value: params.SAVE_CONTAINER_ON_FAIL),
175 booleanParam(name: 'SAVE_CONTAINER_ON_PASS', value: params.SAVE_CONTAINER_ON_PASS)
176 ]
177 }
178 }
179 }
180 }
181
182 post {
183 always {
184 // cleanWs()
185 deleteDir()
186 }
187 }
188}
189