Skip to content

Commit 9d8431b

Browse files
feat: add a mage command to package system tests (#27295) (#27550)
* feat: add a mage command to package system tests * chore: delegate prints to the caller * chore: do not keep writing tar file in memory * chore: update comment Co-authored-by: Jaime Soriano Pastor <[email protected]> * chore: handle error while traversing the filesystem Co-authored-by: Jaime Soriano Pastor <[email protected]> (cherry picked from commit 7f086e5) Co-authored-by: Manuel de la Peña <[email protected]>
1 parent c8f2122 commit 9d8431b

File tree

4 files changed

+162
-18
lines changed

4 files changed

+162
-18
lines changed

.ci/scripts/search_system_tests.py

Lines changed: 0 additions & 10 deletions
This file was deleted.

Jenkinsfile

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ def withBeatsEnv(Map args = [:], Closure body) {
668668
error("Error '${err.toString()}'")
669669
} finally {
670670
if (archive) {
671-
archiveTestOutput(testResults: testResults, artifacts: artifacts, id: args.id, upload: upload)
671+
archiveTestOutput(directory: directory, testResults: testResults, artifacts: artifacts, id: args.id, upload: upload)
672672
}
673673
tearDown()
674674
}
@@ -766,6 +766,8 @@ def getCommonModuleInTheChangeSet(String directory) {
766766
* to bypass some issues when working with big repositories.
767767
*/
768768
def archiveTestOutput(Map args = [:]) {
769+
def directory = args.get('directory', '')
770+
769771
catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE') {
770772
if (isUnix()) {
771773
fixPermissions("${WORKSPACE}")
@@ -789,13 +791,20 @@ def archiveTestOutput(Map args = [:]) {
789791
}
790792
if (args.upload) {
791793
catchError(buildResult: 'SUCCESS', message: 'Failed to archive the build test results', stageResult: 'SUCCESS') {
792-
def folder = cmd(label: 'Find system-tests', returnStdout: true, script: 'python .ci/scripts/search_system_tests.py').trim()
793-
log(level: 'INFO', text: "system-tests='${folder}'. If no empty then let's create a tarball")
794-
if (folder.trim()) {
795-
// TODO: nodeOS() should support ARM
796-
def os_suffix = isArm() ? 'linux' : nodeOS()
797-
def name = folder.replaceAll('/', '-').replaceAll('\\\\', '-').replaceAll('build', '').replaceAll('^-', '') + '-' + os_suffix
798-
tarAndUploadArtifacts(file: "${name}.tgz", location: folder)
794+
withMageEnv(version: "${env.GO_VERSION}"){
795+
dir(directory){
796+
cmd(label: "Archive system tests files", script: 'mage packageSystemTests')
797+
}
798+
}
799+
def fileName = 'build/system-tests-*.tar.gz' // see dev-tools/mage/target/common/package.go#PackageSystemTests method
800+
dir("${BASE_DIR}"){
801+
cmd(label: "List files to upload", script: "ls -l ${BASE_DIR}/${fileName}")
802+
googleStorageUploadExt(
803+
bucket: "gs://${JOB_GCS_BUCKET}/${env.JOB_NAME}-${env.BUILD_ID}",
804+
credentialsId: "${JOB_GCS_EXT_CREDENTIALS}",
805+
pattern: "${BASE_DIR}/${fileName}",
806+
sharedPublicly: true
807+
)
799808
}
800809
}
801810
}

dev-tools/mage/common.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,73 @@ func unzip(sourceFile, destinationDir string) error {
353353
return nil
354354
}
355355

356+
// Tar compress a directory using tar + gzip algorithms
357+
func Tar(src string, targetFile string) error {
358+
fmt.Printf(">> creating TAR file from directory: %s, target: %s\n", src, targetFile)
359+
360+
f, err := os.Create(targetFile)
361+
if err != nil {
362+
return fmt.Errorf("error creating tar file: %w", err)
363+
}
364+
defer f.Close()
365+
366+
// tar > gzip > file
367+
zr := gzip.NewWriter(f)
368+
tw := tar.NewWriter(zr)
369+
370+
// walk through every file in the folder
371+
filepath.Walk(src, func(file string, fi os.FileInfo, errFn error) error {
372+
if errFn != nil {
373+
return fmt.Errorf("error traversing the file system: %w", errFn)
374+
}
375+
376+
// if a symlink, skip file
377+
if fi.Mode().Type() == os.ModeSymlink {
378+
fmt.Printf(">> skipping symlink: %s\n", file)
379+
return nil
380+
}
381+
382+
// generate tar header
383+
header, err := tar.FileInfoHeader(fi, file)
384+
if err != nil {
385+
return fmt.Errorf("error getting file info header: %w", err)
386+
}
387+
388+
// must provide real name
389+
// (see https://golang.org/src/archive/tar/common.go?#L626)
390+
header.Name = filepath.ToSlash(file)
391+
392+
// write header
393+
if err := tw.WriteHeader(header); err != nil {
394+
return fmt.Errorf("error writing header: %w", err)
395+
}
396+
397+
// if not a dir, write file content
398+
if !fi.IsDir() {
399+
data, err := os.Open(file)
400+
if err != nil {
401+
return fmt.Errorf("error opening file: %w", err)
402+
}
403+
defer data.Close()
404+
if _, err := io.Copy(tw, data); err != nil {
405+
return fmt.Errorf("error compressing file: %w", err)
406+
}
407+
}
408+
return nil
409+
})
410+
411+
// produce tar
412+
if err := tw.Close(); err != nil {
413+
return fmt.Errorf("error closing tar file: %w", err)
414+
}
415+
// produce gzip
416+
if err := zr.Close(); err != nil {
417+
return fmt.Errorf("error closing gzip file: %w", err)
418+
}
419+
420+
return nil
421+
}
422+
356423
func untar(sourceFile, destinationDir string) error {
357424
file, err := os.Open(sourceFile)
358425
if err != nil {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package common
19+
20+
import (
21+
"fmt"
22+
"os"
23+
"path/filepath"
24+
"strings"
25+
26+
devtools "github.com/elastic/beats/v7/dev-tools/mage"
27+
)
28+
29+
// PackageSystemTests packages the python system tests results
30+
func PackageSystemTests() error {
31+
excludeds := []string{".ci", ".git", ".github", "vendor", "dev-tools"}
32+
33+
// include run as it's the directory we want to compress
34+
systemTestsDir := filepath.Join("build", "system-tests", "run")
35+
files, err := devtools.FindFilesRecursive(func(path string, _ os.FileInfo) bool {
36+
base := filepath.Base(path)
37+
for _, excluded := range excludeds {
38+
if strings.HasPrefix(base, excluded) {
39+
return false
40+
}
41+
}
42+
43+
return strings.HasPrefix(path, systemTestsDir)
44+
})
45+
if err != nil {
46+
return err
47+
}
48+
49+
if len(files) == 0 {
50+
fmt.Printf(">> there are no system test files under %s", systemTestsDir)
51+
return nil
52+
}
53+
54+
// create a plain directory layout for all beats
55+
beat := devtools.MustExpand("{{ repo.SubDir }}")
56+
beat = strings.ReplaceAll(beat, string(os.PathSeparator), "-")
57+
58+
targetFile := devtools.MustExpand("{{ elastic_beats_dir }}/build/system-tests-" + beat + ".tar.gz")
59+
parent := filepath.Dir(targetFile)
60+
if !fileExists(parent) {
61+
fmt.Printf(">> creating parent dir: %s", parent)
62+
os.Mkdir(parent, 0750)
63+
}
64+
65+
err = devtools.Tar(systemTestsDir, targetFile)
66+
if err != nil {
67+
fmt.Printf(">> %s", err)
68+
return err
69+
}
70+
71+
return nil
72+
}
73+
74+
// fileExists returns true if the specified file exists.
75+
func fileExists(file string) bool {
76+
_, err := os.Stat(file)
77+
return !os.IsNotExist(err)
78+
}

0 commit comments

Comments
 (0)