22
33@Library (' apm@current' ) _
44
5+ import groovy.transform.Field
6+
7+ /**
8+ This is required to store the test suites we will use to trigger the E2E tests.
9+ */
10+ @Field def e2eTestSuites = []
11+
512pipeline {
613 agent none
714 environment {
8- BASE_DIR = ' src/github.com/elastic/beats'
15+ REPO = ' beats'
16+ BASE_DIR = " src/github.com/elastic/${ env.REPO} "
917 JOB_GCS_BUCKET = ' beats-ci-artifacts'
1018 JOB_GCS_BUCKET_STASH = ' beats-ci-temp'
1119 JOB_GCS_CREDENTIALS = ' beats-ci-gcs-plugin'
1220 DOCKERELASTIC_SECRET = ' secret/observability-team/ci/docker-registry/prod'
1321 DOCKER_REGISTRY = ' docker.elastic.co'
22+ GITHUB_CHECK_E2E_TESTS_NAME = ' E2E Tests'
1423 SNAPSHOT = " true"
1524 PIPELINE_LOG_LEVEL = " INFO"
1625 }
@@ -34,7 +43,7 @@ pipeline {
3443 }
3544 stages {
3645 stage(' Filter build' ) {
37- agent { label ' ubuntu && immutable' }
46+ agent { label ' ubuntu-18 && immutable' }
3847 when {
3948 beforeAgent true
4049 anyOf {
@@ -103,14 +112,14 @@ pipeline {
103112 ' x-pack/heartbeat' ,
104113 // 'x-pack/journalbeat',
105114 ' x-pack/metricbeat' ,
106- ' x-pack/packetbeat' ,
115+ // 'x-pack/packetbeat',
107116 ' x-pack/winlogbeat'
108117 )
109118 }
110119 }
111120 stages {
112121 stage(' Package Linux' ){
113- agent { label ' ubuntu && immutable' }
122+ agent { label ' ubuntu-18 && immutable' }
114123 options { skipDefaultCheckout() }
115124 when {
116125 beforeAgent true
@@ -142,6 +151,7 @@ pipeline {
142151 release()
143152 pushCIDockerImages()
144153 }
154+ prepareE2ETestForPackage(" ${ BEATS_FOLDER} " )
145155 }
146156 }
147157 stage(' Package Mac OS' ){
@@ -172,6 +182,13 @@ pipeline {
172182 }
173183 }
174184 }
185+ stage(' Run E2E Tests for Packages' ){
186+ agent { label ' ubuntu-18 && immutable' }
187+ options { skipDefaultCheckout() }
188+ steps {
189+ runE2ETests()
190+ }
191+ }
175192 }
176193 post {
177194 success {
@@ -190,68 +207,160 @@ pipeline {
190207
191208def pushCIDockerImages (){
192209 catchError(buildResult : ' UNSTABLE' , message : ' Unable to push Docker images' , stageResult : ' FAILURE' ) {
193- if (" ${ env.BEATS_FOLDER} " == " auditbeat" ) {
194- tagAndPush(' auditbeat-oss ' )
195- } else if (" ${ env.BEATS_FOLDER} " == " filebeat" ) {
196- tagAndPush(' filebeat-oss ' )
197- } else if (" ${ env.BEATS_FOLDER} " == " heartbeat" ) {
198- tagAndPush(' heartbeat-oss ' )
210+ if (env? .BEATS_FOLDER ?. endsWith( ' auditbeat' )) {
211+ tagAndPush(' auditbeat' )
212+ } else if (env? .BEATS_FOLDER ?. endsWith( ' filebeat' ) ) {
213+ tagAndPush(' filebeat' )
214+ } else if (env? .BEATS_FOLDER ?. endsWith( ' heartbeat' )) {
215+ tagAndPush(' heartbeat' )
199216 } else if (" ${ env.BEATS_FOLDER} " == " journalbeat" ){
200217 tagAndPush(' journalbeat' )
201- tagAndPush(' journalbeat-oss' )
202- } else if (" ${ env.BEATS_FOLDER} " == " metricbeat" ){
203- tagAndPush(' metricbeat-oss' )
218+ } else if (env?. BEATS_FOLDER ?. endsWith(' metricbeat' )) {
219+ tagAndPush(' metricbeat' )
204220 } else if (" ${ env.BEATS_FOLDER} " == " packetbeat" ){
205221 tagAndPush(' packetbeat' )
206- tagAndPush(' packetbeat-oss' )
207- } else if (" ${ env.BEATS_FOLDER} " == " x-pack/auditbeat" ){
208- tagAndPush(' auditbeat' )
209222 } else if (" ${ env.BEATS_FOLDER} " == " x-pack/elastic-agent" ) {
210223 tagAndPush(' elastic-agent' )
211- } else if (" ${ env.BEATS_FOLDER} " == " x-pack/filebeat" ){
212- tagAndPush(' filebeat' )
213- } else if (" ${ env.BEATS_FOLDER} " == " x-pack/heartbeat" ){
214- tagAndPush(' heartbeat' )
215- } else if (" ${ env.BEATS_FOLDER} " == " x-pack/metricbeat" ){
216- tagAndPush(' metricbeat' )
217224 }
218225 }
219226}
220227
221- def tagAndPush (name ){
228+ def tagAndPush (beatName ){
222229 def libbetaVer = env. BEAT_VERSION
230+ def aliasVersion = " "
223231 if (" ${ env.SNAPSHOT} " == " true" ){
232+ aliasVersion = libbetaVer. substring(0 , libbetaVer. lastIndexOf(" ." )) // remove third number in version
233+
224234 libbetaVer + = " -SNAPSHOT"
235+ aliasVersion + = " -SNAPSHOT"
225236 }
226237
227238 def tagName = " ${ libbetaVer} "
228239 if (isPR()) {
229240 tagName = " pr-${ env.CHANGE_ID} "
230241 }
231242
232- def oldName = " ${ DOCKER_REGISTRY} /beats/${ name} :${ libbetaVer} "
233- def newName = " ${ DOCKER_REGISTRY} /observability-ci/${ name} :${ tagName} "
234- def commitName = " ${ DOCKER_REGISTRY} /observability-ci/${ name} :${ env.GIT_BASE_COMMIT} "
235243 dockerLogin(secret : " ${ DOCKERELASTIC_SECRET} " , registry : " ${ DOCKER_REGISTRY} " )
236- retry(3 ){
237- sh(label :' Change tag and push' , script : """
238- docker tag ${ oldName} ${ newName}
239- docker push ${ newName}
240- docker tag ${ oldName} ${ commitName}
241- docker push ${ commitName}
242- """ )
244+
245+ // supported image flavours
246+ def variants = [" " , " -oss" , " -ubi8" ]
247+ variants. each { variant ->
248+ doTagAndPush(beatName, variant, libbetaVer, tagName)
249+ doTagAndPush(beatName, variant, libbetaVer, " ${ env.GIT_BASE_COMMIT} " )
250+
251+ if (! isPR() && aliasVersion != " " ) {
252+ doTagAndPush(beatName, variant, libbetaVer, aliasVersion)
253+ }
254+ }
255+ }
256+
257+ /**
258+ * @param beatName name of the Beat
259+ * @param variant name of the variant used to build the docker image name
260+ * @param sourceTag tag to be used as source for the docker tag command, usually under the 'beats' namespace
261+ * @param targetTag tag to be used as target for the docker tag command, usually under the 'observability-ci' namespace
262+ */
263+ def doTagAndPush (beatName , variant , sourceTag , targetTag ) {
264+ def sourceName = " ${ DOCKER_REGISTRY} /beats/${ beatName}${ variant} :${ sourceTag} "
265+ def targetName = " ${ DOCKER_REGISTRY} /observability-ci/${ beatName}${ variant} :${ targetTag} "
266+
267+ def iterations = 0
268+ retryWithSleep(retries : 3 , seconds : 5 , backoff : true ) {
269+ iterations++
270+ def status = sh(label : " Change tag and push ${ targetName} " , script : """
271+ docker tag ${ sourceName} ${ targetName}
272+ docker push ${ targetName}
273+ """ , returnStatus : true )
274+
275+ if ( status > 0 && iterations < 3 ) {
276+ error(" tag and push failed for ${ beatName} , retry" )
277+ } else if ( status > 0 ) {
278+ log(level : ' WARN' , text : " ${ beatName} doesn't have ${ variant} docker images. See https://github.com/elastic/beats/pull/21621" )
279+ }
280+ }
281+ }
282+
283+ def prepareE2ETestForPackage (String beat ){
284+ if (" ${ beat} " == " filebeat" || " ${ beat} " == " x-pack/filebeat" ) {
285+ e2eTestSuites. push(' fleet' )
286+ e2eTestSuites. push(' helm' )
287+ } else if (" ${ beat} " == " metricbeat" || " ${ beat} " == " x-pack/metricbeat" ) {
288+ e2eTestSuites. push(' ALL' )
289+ echo(" ${ beat} adds all test suites to the E2E tests job." )
290+ } else if (" ${ beat} " == " x-pack/elastic-agent" ) {
291+ e2eTestSuites. push(' fleet' )
292+ } else {
293+ echo(" ${ beat} does not add any test suite to the E2E tests job." )
294+ return
243295 }
244296}
245297
246298def release (){
247299 withBeatsEnv(){
248- dir(" ${ env.BEATS_FOLDER} " ) {
249- sh(label : " Release ${ env.BEATS_FOLDER} ${ env.PLATFORMS} " , script : ' mage package' )
300+ withEnv([
301+ " DEV=true"
302+ ]) {
303+ dir(" ${ env.BEATS_FOLDER} " ) {
304+ sh(label : " Release ${ env.BEATS_FOLDER} ${ env.PLATFORMS} " , script : ' mage package' )
305+ }
250306 }
251307 publishPackages(" ${ env.BEATS_FOLDER} " )
252308 }
253309}
254310
311+ def runE2ETests (){
312+ if (e2eTestSuites. size() == 0 ) {
313+ echo(" Not triggering E2E tests for PR-${ env.CHANGE_ID} because the changes does not affect the E2E." )
314+ return
315+ }
316+
317+ def suites = ' ' // empty value represents all suites in the E2E tests
318+
319+ catchError(buildResult : ' UNSTABLE' , message : ' Unable to run e2e tests' , stageResult : ' FAILURE' ) {
320+ def suitesSet = e2eTestSuites. toSet()
321+
322+ if (! suitesSet. contains(' ALL' )) {
323+ suitesSet. each { suite ->
324+ suites + = " ${ suite} ,"
325+ };
326+ }
327+
328+ triggerE2ETests(suites)
329+ }
330+ }
331+
332+ def triggerE2ETests (String suite ) {
333+ echo(" Triggering E2E tests for PR-${ env.CHANGE_ID} . Test suites: ${ suite} ." )
334+
335+ def branchName = isPR() ? " ${ env.CHANGE_TARGET} " : " ${ env.JOB_BASE_NAME} .x"
336+ def e2eTestsPipeline = " e2e-tests/e2e-testing-mbp/${ branchName} "
337+
338+ def parameters = [
339+ booleanParam(name : ' forceSkipGitChecks' , value : true ),
340+ booleanParam(name : ' forceSkipPresubmit' , value : true ),
341+ booleanParam(name : ' notifyOnGreenBuilds' , value : ! isPR()),
342+ string(name : ' runTestsSuites' , value : suite),
343+ string(name : ' GITHUB_CHECK_NAME' , value : env. GITHUB_CHECK_E2E_TESTS_NAME ),
344+ string(name : ' GITHUB_CHECK_REPO' , value : env. REPO ),
345+ string(name : ' GITHUB_CHECK_SHA1' , value : env. GIT_BASE_COMMIT ),
346+ ]
347+ if (isPR()) {
348+ def version = " pr-${ env.CHANGE_ID} "
349+ parameters. push(booleanParam(name : ' ELASTIC_AGENT_USE_CI_SNAPSHOTS' , value : true ))
350+ parameters. push(string(name : ' ELASTIC_AGENT_VERSION' , value : " ${ version} " ))
351+ parameters. push(string(name : ' METRICBEAT_VERSION' , value : " ${ version} " ))
352+ }
353+
354+ build(job : " ${ e2eTestsPipeline} " ,
355+ parameters : parameters,
356+ propagate : false ,
357+ wait : false
358+ )
359+
360+ def notifyContext = " ${ env.GITHUB_CHECK_E2E_TESTS_NAME} "
361+ githubNotify(context : " ${ notifyContext} " , description : " ${ notifyContext} ..." , status : ' PENDING' , targetUrl : " ${ env.JENKINS_URL} search/?q=${ e2eTestsPipeline.replaceAll('/','+')} " )
362+ }
363+
255364def withMacOSEnv (Closure body ){
256365 withEnvMask( vars : [
257366 [var : " KEYCHAIN_PASS" , password : getVaultSecret(secret : " secret/jenkins-ci/macos-codesign-keychain" ). data. password],
0 commit comments