diff --git a/go.mod b/go.mod index 11a8898d..6bf80dcf 100644 --- a/go.mod +++ b/go.mod @@ -6,11 +6,10 @@ toolchain go1.23.2 require ( github.com/bitrise-io/bitrise v0.0.0-20230707121919-a5b9e2d27ea9 - github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.43 + github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.48.0.20260312091018-7447bc60506b github.com/bitrise-io/go-utils v1.0.15 - github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.31 - github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.77 - github.com/bitrise-steplib/steps-deploy-to-bitrise-io v0.0.0-20260105124642-5583d1ed06c4 + github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.33 + github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.79.0.20260312102256-0c898dd1f2a3 github.com/hashicorp/go-version v1.7.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/stretchr/testify v1.10.0 @@ -19,10 +18,11 @@ require ( require ( github.com/bitrise-io/envman v0.0.0-20240730123632-8066eeb61599 // indirect github.com/bitrise-io/go-steputils v1.0.6 // indirect - github.com/bitrise-io/go-xcode v1.3.1 // indirect + github.com/bitrise-io/go-xcode v1.3.3 // indirect github.com/bitrise-io/stepman v0.0.0-20240828074035-6ae1a5f5efde // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/globocom/go-buffer/v2 v2.0.0 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/kr/pretty v0.3.1 // indirect diff --git a/go.sum b/go.sum index 0c30e31b..30fa8176 100644 --- a/go.sum +++ b/go.sum @@ -4,21 +4,19 @@ github.com/bitrise-io/envman v0.0.0-20240730123632-8066eeb61599 h1:UaudsJR8LbzL7 github.com/bitrise-io/envman v0.0.0-20240730123632-8066eeb61599/go.mod h1:7yJQdVdq8BxJYq2xjG0yViQf/aspJLJ/xqk/OnP6lGE= github.com/bitrise-io/go-steputils v1.0.6 h1:eBRL70DWwEd7DWYGd5Ds7OSIY5HElzhoDOI6UuITKQg= github.com/bitrise-io/go-steputils v1.0.6/go.mod h1:YIUaQnIAyK4pCvQG0hYHVkSzKNT9uL2FWmkFNW4mfNI= -github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.43 h1:oahoCL46PPywHRBin54zrwDOhXlMPIXx6zdo1Hgkz1g= -github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.43/go.mod h1:SjWTgoD5wDyyIa+xPrA+U2UgL9K8Lx/xuLaK5LBCjXE= +github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.48.0.20260312091018-7447bc60506b h1:GIRdLWgdpa+qImAJlfuHAQppI7EFieCyNceVcUwNbo4= +github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.48.0.20260312091018-7447bc60506b/go.mod h1:CL1sOqz4+q4XK/OCjB8YNV27Xmz/Fo7v/QKxobmGIx4= github.com/bitrise-io/go-utils v1.0.1/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0RSY3tRI1heY= github.com/bitrise-io/go-utils v1.0.15 h1:KRQjNiPrkxBRM6G5fQy05v0p0r8wycWfKVb+Ko+Vtg0= github.com/bitrise-io/go-utils v1.0.15/go.mod h1:ZY1DI+fEpZuFpO9szgDeICM4QbqoWVt0RSY3tRI1heY= -github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.31 h1:Lay9mco4/T88oYY+kqZlpdWeU9aj32/qWMRwcTg812o= -github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.31/go.mod h1:3XUplo0dOWc3DqT2XA2SeHToDSg7+j1y1HTHibT2H68= -github.com/bitrise-io/go-xcode v1.3.1 h1:ioLPHQ+XnSafCpnFJl+d9+qdfIr0Z55yQRlEA66/XxI= -github.com/bitrise-io/go-xcode v1.3.1/go.mod h1:9OwsvrhZ4A2JxHVoEY7CPcABAKA+OE7FQqFfBfvbFuY= -github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.77 h1:GEE6KeA6Z/kmfoTWR+rOFvMLiH5cu7x3E+TBkmL1UtY= -github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.77/go.mod h1:66PiZrCN9O6f3ELTDx4clAQ8R0PglohhbE1sdfd1vP0= +github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.33 h1:2Skyp4yg8aNKLr5GB5amM9UK9n1yzIMT88Rb/ZBz8m4= +github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.33/go.mod h1:3XUplo0dOWc3DqT2XA2SeHToDSg7+j1y1HTHibT2H68= +github.com/bitrise-io/go-xcode v1.3.3 h1:aYkSMWP+1/n2ZabRy3OMfeaWmE4l1gAPq63azx06LIw= +github.com/bitrise-io/go-xcode v1.3.3/go.mod h1:9OwsvrhZ4A2JxHVoEY7CPcABAKA+OE7FQqFfBfvbFuY= +github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.79.0.20260312102256-0c898dd1f2a3 h1:dkLttfQ611MDG6XxschlL6jKR6oSXNvdeukboFRrhrY= +github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.79.0.20260312102256-0c898dd1f2a3/go.mod h1:5lzT1xKvLF9GdKd7BlMsJ1wVIz29I8tM2qep8HY2sUY= github.com/bitrise-io/stepman v0.0.0-20240828074035-6ae1a5f5efde h1:LinFhZG5OdayDh1T1JO8QANsNwQWzqORZ0A9EGHQ0ps= github.com/bitrise-io/stepman v0.0.0-20240828074035-6ae1a5f5efde/go.mod h1:Lq9nEqKerBD35w3eSU8lf83F7uZPkXfmRSZEUDJN40w= -github.com/bitrise-steplib/steps-deploy-to-bitrise-io v0.0.0-20260105124642-5583d1ed06c4 h1:neZDzBK4EbeNw8644E5cPP9eWHsAQpJ13GtYj38hBWI= -github.com/bitrise-steplib/steps-deploy-to-bitrise-io v0.0.0-20260105124642-5583d1ed06c4/go.mod h1:QYe/+OmcrDmON6wsW/yju0F1UOL+L8UBJt+eeYtUfCw= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/output/output.go b/output/output.go index 758f6053..7395da7f 100644 --- a/output/output.go +++ b/output/output.go @@ -10,8 +10,8 @@ import ( "github.com/bitrise-io/go-utils/v2/env" "github.com/bitrise-io/go-utils/v2/log" "github.com/bitrise-io/go-utils/ziputil" - "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3" - "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3" + "github.com/bitrise-io/go-xcode/v2/testresult/xcresult3" + "github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3" "github.com/bitrise-steplib/steps-xcode-test/testaddon" ) @@ -143,8 +143,7 @@ func (e exporter) ExportFlakyTestCases(xcResultPath string, useOldXCResultExtrac } func (e exporter) parseTestSummary(xcResultPath string, useOldXCResultExtractionMethod bool) (*model3.TestSummary, error) { - converter := xcresult3.Converter{} - converter.Setup(useOldXCResultExtractionMethod) + converter := xcresult3.NewConverter(useOldXCResultExtractionMethod) if !converter.Detect([]string{xcResultPath}) { return nil, nil } diff --git a/output/output_test.go b/output/output_test.go index 17ef5974..2d64e216 100644 --- a/output/output_test.go +++ b/output/output_test.go @@ -11,7 +11,7 @@ import ( "github.com/bitrise-io/go-utils/v2/fileutil" "github.com/bitrise-io/go-utils/v2/log" "github.com/bitrise-io/go-utils/v2/pathutil" - "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3" + "github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3" commonMocks "github.com/bitrise-steplib/steps-xcode-test/mocks" "github.com/bitrise-steplib/steps-xcode-test/output/mocks" "github.com/stretchr/testify/assert" diff --git a/vendor/github.com/bitrise-io/go-steputils/v2/export/atime_darwin.go b/vendor/github.com/bitrise-io/go-steputils/v2/export/atime_darwin.go new file mode 100644 index 00000000..ee0470a2 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/v2/export/atime_darwin.go @@ -0,0 +1,12 @@ +//go:build darwin || freebsd || netbsd || openbsd + +package export + +import ( + "syscall" + "time" +) + +func atimeFromStat(stat *syscall.Stat_t) time.Time { + return time.Unix(int64(stat.Atimespec.Sec), int64(stat.Atimespec.Nsec)) +} diff --git a/vendor/github.com/bitrise-io/go-steputils/v2/export/atime_linux.go b/vendor/github.com/bitrise-io/go-steputils/v2/export/atime_linux.go new file mode 100644 index 00000000..3799619c --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/v2/export/atime_linux.go @@ -0,0 +1,12 @@ +//go:build linux + +package export + +import ( + "syscall" + "time" +) + +func atimeFromStat(stat *syscall.Stat_t) time.Time { + return time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) +} diff --git a/vendor/github.com/bitrise-io/go-steputils/v2/export/export.go b/vendor/github.com/bitrise-io/go-steputils/v2/export/export.go index 31cab375..c92df432 100644 --- a/vendor/github.com/bitrise-io/go-steputils/v2/export/export.go +++ b/vendor/github.com/bitrise-io/go-steputils/v2/export/export.go @@ -2,9 +2,6 @@ package export import ( "fmt" - "io" - "log" - "os" "path/filepath" "github.com/bitrise-io/go-utils/v2/command" @@ -20,12 +17,16 @@ const ( // Exporter ... type Exporter struct { - cmdFactory command.Factory + cmdFactory command.Factory + fileManager FileManager } // NewExporter ... func NewExporter(cmdFactory command.Factory) Exporter { - return Exporter{cmdFactory: cmdFactory} + return Exporter{ + cmdFactory: cmdFactory, + fileManager: NewFileManager(), + } } // ExportOutput is used for exposing values for other steps. @@ -65,7 +66,7 @@ func (e *Exporter) ExportOutputFile(key, sourcePath, destinationPath string) err } if absSourcePath != absDestinationPath { - if err = copyFile(absSourcePath, absDestinationPath); err != nil { + if err = e.fileManager.CopyFile(absSourcePath, absDestinationPath); err != nil { return err } } @@ -106,6 +107,58 @@ func (e *Exporter) ExportOutputFilesZip(key string, sourcePaths []string, zipPat return e.ExportOutputFile(key, tempZipPath, zipPath) } +// ExportOutputDir is a convenience method for copying sourceDir to destinationDir and then exporting the +// absolute destination dir with ExportOutput() +// Note: symlinks are preserved during the copy operation +func (e *Exporter) ExportOutputDir(envKey, srcDir, dstDir string) error { + srcDir, err := filepath.Abs(srcDir) + if err != nil { + return err + } + srcInfo, err := e.fileManager.Lstat(srcDir) + if err != nil { + return fmt.Errorf("stat src root: %w", err) + } + if !srcInfo.IsDir() { + return fmt.Errorf("src is not a directory: %s", srcDir) + } + + dstDir, err = filepath.Abs(dstDir) + if err != nil { + return err + } + + if srcDir == dstDir { + return e.ExportOutput(envKey, dstDir) + } + + if err := e.fileManager.CopyDir(srcDir, dstDir); err != nil { + return err + } + + return e.ExportOutput(envKey, dstDir) +} + +// ExportStringToFileOutput is a convenience method for writing content to dst and then exporting the +// absolute dst path with ExportOutputFile() +func (e *Exporter) ExportStringToFileOutput(envKey, content, dst string) error { + if err := e.fileManager.WriteBytes(dst, []byte(content)); err != nil { + return err + } + + return e.ExportOutputFile(envKey, dst, dst) +} + +// ExportStringToFileOutputAndReturnLastNLines is similar to ExportStringToFileOutput but it also returns the +// last N lines of the content. +func (e *Exporter) ExportStringToFileOutputAndReturnLastNLines(envKey, content, dst string, lines int) (string, error) { + if err := e.ExportStringToFileOutput(envKey, content, dst); err != nil { + return "", err + } + + return e.fileManager.LastNLines(content, lines), nil +} + func zipFilePath() (string, error) { tmpDir, err := pathutil.NewPathProvider().CreateTempDir("__export_tmp_dir__") if err != nil { @@ -151,31 +204,6 @@ func getInputType(sourcePths []string) (string, error) { return "", nil } -func copyFile(source, destination string) error { - in, err := os.Open(source) - if err != nil { - return err - } - defer in.Close() //nolint:errcheck - - out, err := os.Create(destination) - if err != nil { - return err - } - defer func(out *os.File) { - err := out.Close() - if err != nil { - log.Fatalf("Failed to close output file: %s", err) - } - }(out) - - _, err = io.Copy(out, in) - if err != nil { - return err - } - return nil -} - func runExport(cmd command.Command) error { out, err := cmd.RunAndReturnTrimmedCombinedOutput() if err != nil { diff --git a/vendor/github.com/bitrise-io/go-steputils/v2/export/file_manager.go b/vendor/github.com/bitrise-io/go-steputils/v2/export/file_manager.go new file mode 100644 index 00000000..a52acd41 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/v2/export/file_manager.go @@ -0,0 +1,308 @@ +package export + +import ( + "fmt" + "io" + "io/fs" + "os" + "path/filepath" + "runtime" + "strings" + "syscall" + "time" + + "github.com/bitrise-io/go-steputils/v2/internal" + "github.com/bitrise-io/go-utils/v2/fileutil" +) + +// TODO: +// The extensions over the original fileutil.FileManager should be moved there in a separate ticket. + +// SysStat holds file system stat information. +type SysStat struct { + Uid int + Gid int +} + +// FileManager defines file management operations. +type FileManager interface { + fileutil.FileManager + + CopyFile(src, dst string) error + CopyDir(src, dst string) error + Lstat(path string) (os.FileInfo, error) + LastNLines(s string, n int) string +} + +// NewFileManager creates a new FileManager instance. +func NewFileManager() FileManager { + return &fileManager{ + wrapped: fileutil.NewFileManager(), + osProxy: internal.RealOS{}, + } +} + +// fileManager implements FileManager interface. +type fileManager struct { + wrapped fileutil.FileManager + osProxy internal.OsProxy +} + +// CopyFile copies a single file from src to dst. +func (fm *fileManager) CopyFile(src, dst string) error { + srcDir := filepath.Dir(src) + fsys := fm.osProxy.DirFS(srcDir) + + return fm.copyFileFS(fsys, filepath.Base(src), dst) +} + +// CopyFileFS is the excerpt from fs.CopyFS that copies a single file from fs.FS to dst path. +func (fm *fileManager) copyFileFS(fsys fs.FS, src, dst string) error { + r, err := fsys.Open(src) + if err != nil { + return err + } + defer r.Close() // nolint:errcheck + info, err := r.Stat() + if err != nil { + return err + } + w, err := fm.osProxy.OpenFile(dst, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0777) + if err != nil { + return err + } + + defer w.Close() // nolint:errcheck + if _, err := io.Copy(w, r); err != nil { + return &fs.PathError{Op: "Copy", Path: dst, Err: err} + } + if err := w.Sync(); err != nil { + return &fs.PathError{Op: "Sync", Path: dst, Err: err} + } + if err := fm.copyOwner(info, dst); err != nil { + return &fs.PathError{Op: "copyOwner", Path: dst, Err: err} + } + if err := fm.copyMode(info, dst); err != nil { + return &fs.PathError{Op: "copyMode", Path: dst, Err: err} + } + if err := fm.copyTimes(info, dst); err != nil { + return &fs.PathError{Op: "copyTimes", Path: dst, Err: err} + } + + return nil +} + +// CopyDir is a convenience method for copying a directory from src to dst. +// +// A copy of os.CopyFS because it messes up permissions when copying files +// from fs.FS +// +// CopyFS copies the file system fsys into the directory dir, +// creating dir if necessary. +// +// Preserves permissions and ownership when possible. +// +// CopyFS will not overwrite existing files. If a file name in fsys +// already exists in the destination, CopyFS will return an error +// such that errors.Is(err, fs.ErrExist) will be true. +// +// Symbolic links in dir are followed. +// +// New files added to fsys (including if dir is a subdirectory of fsys) +// while CopyFS is running are not guaranteed to be copied. +// +// Copying stops at and returns the first error encountered. +// Note: symlinks are preserved during the copy operation +func (fm *fileManager) CopyDir(src, dst string) error { + fsys := fm.osProxy.DirFS(src) + return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + newPath := filepath.Join(dst, path) + info, err := d.Info() + + // This is not exhausetive in the original implementation either. + // nolint:exhaustive + switch d.Type() { + case os.ModeDir: + if err != nil { + return err + } + if err := fm.osProxy.MkdirAll(newPath, 0777); err != nil { + return err + } + if err := fm.copyOwner(info, newPath); err != nil { + return err + } + if err := fm.copyMode(info, newPath); err != nil { + return err + } + return fm.copyTimes(info, newPath) + + case os.ModeSymlink: + srcPath := filepath.Join(src, path) + target, err := fm.osProxy.Readlink(srcPath) + if err != nil { + return err + } + if err := fm.osProxy.Symlink(target, newPath); err != nil { + return err + } + if err := fm.copyOwner(info, newPath); err != nil { + return err + } + return fm.copyTimes(info, newPath) + + case 0: + return fm.copyFileFS(fsys, path, newPath) + + default: + return &os.PathError{Op: "CopyFS", Path: path, Err: os.ErrInvalid} + } + }) +} + +// lchown ... +func (fm *fileManager) lchown(path string, uid, gid int) error { + return fm.osProxy.Lchown(path, uid, gid) +} + +// copyOwner invokes lchown to copy ownership from srcInfo to dstPath. +func (fm *fileManager) copyOwner(srcInfo os.FileInfo, dstPath string) error { + if runtime.GOOS == "windows" { + return nil + } + stat, ok := srcInfo.Sys().(*syscall.Stat_t) + if !ok { + return fmt.Errorf("missing Stat_t for symlink %s", dstPath) + } + // os.Lchown affects the link itself when given the link path + if err := fm.lchown(dstPath, int(stat.Uid), int(stat.Gid)); err != nil { + return fmt.Errorf("lchown(symlink) %s: %w", dstPath, err) + } + return nil +} + +// chtimes ... +func (fm *fileManager) chtimes(path string, atime, mtime time.Time) error { + return fm.osProxy.Chtimes(path, atime, mtime) +} + +// copyTimes invokes chtimes to copy access and modification times from srcInfo to dstPath. +func (fm *fileManager) copyTimes(srcInfo os.FileInfo, dstPath string) error { + if runtime.GOOS == "windows" { + // On Windows we only set mod time (atime setting optional) + if err := fm.chtimes(dstPath, srcInfo.ModTime(), srcInfo.ModTime()); err != nil { + // ignore or return depending on policy + return fmt.Errorf("chtimes %s: %w", dstPath, err) + } + + } else { + if stat, ok := srcInfo.Sys().(*syscall.Stat_t); ok { + // set times (for non-symlink paths we use os.chtimes) + if srcInfo.Mode()&os.ModeSymlink == 0 { + atime := atimeFromStat(stat) + mtime := srcInfo.ModTime() + if err := fm.chtimes(dstPath, atime, mtime); err != nil { + return fmt.Errorf("chtimes %s: %w", dstPath, err) + } + } + } + } + return nil +} + +// chmod ... +func (fm *fileManager) chmod(path string, mode os.FileMode) error { + return fm.osProxy.Chmod(path, mode) +} + +// copyMode invokes chmod to copy file mode from srcInfo to dstPath. +func (fm *fileManager) copyMode(srcInfo os.FileInfo, dstPath string) error { + return fm.chmod(dstPath, srcInfo.Mode()) +} + +// Lstat implements FileManager by delegating to os.Lstat via the osProxy. +func (fm *fileManager) Lstat(path string) (os.FileInfo, error) { + return fm.osProxy.Lstat(path) +} + +// LastNLines returns the last n lines of the given string s. +func (fm *fileManager) LastNLines(s string, n int) string { + if n <= 0 { + return "" + } + // normalize CRLF to LF if needed + if strings.Contains(s, "\r\n") { + s = strings.ReplaceAll(s, "\r\n", "\n") + } + + // skip trailing newlines so we don't count empty trailing lines + i := len(s) - 1 + for i >= 0 && s[i] == '\n' { + i-- + } + if i < 0 { + return "" // string was all newlines + } + + // scan backward counting '\n' occurrences + count := 0 + for ; i >= 0; i-- { + if s[i] == '\n' { + count++ + if count == n { + // substring after this newline is the last n lines + start := i + 1 + res := s[start:] + // trim trailing whitespace (spaces, tabs, newlines, etc.) + return strings.TrimRightFunc(res, func(r rune) bool { + return r == ' ' || r == '\t' || r == '\n' || r == '\r' || r == '\f' || r == '\v' + }) + } + } + } + + // fewer than n newlines => return whole string (trim trailing whitespace) + return strings.TrimRightFunc(s, func(r rune) bool { + return r == ' ' || r == '\t' || r == '\n' || r == '\r' || r == '\f' || r == '\v' + }) +} + +// ---------------------------------------------------------------- + +// Open - Implement FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) Open(path string) (*os.File, error) { return fm.wrapped.Open(path) } + +// OpenReaderIfExists - Implement FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) OpenReaderIfExists(path string) (io.Reader, error) { + return fm.wrapped.OpenReaderIfExists(path) +} + +// ReadDirEntryNames - FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) ReadDirEntryNames(path string) ([]string, error) { + return fm.wrapped.ReadDirEntryNames(path) +} + +// Remove - Implement FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) Remove(path string) error { return fm.wrapped.Remove(path) } + +// RemoveAll - FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) RemoveAll(path string) error { return fm.wrapped.RemoveAll(path) } + +// Write - Implement FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) Write(path string, value string, perm os.FileMode) error { + return fm.wrapped.Write(path, value, perm) +} + +// WriteBytes - Implement FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) WriteBytes(path string, value []byte) error { + return fm.wrapped.WriteBytes(path, value) +} + +// FileSizeInBytes - FileManager methods by delegating to the wrapped FileManager. +func (fm *fileManager) FileSizeInBytes(pth string) (int64, error) { + return fm.wrapped.FileSizeInBytes(pth) +} diff --git a/vendor/github.com/bitrise-io/go-steputils/v2/internal/os_proxy.go b/vendor/github.com/bitrise-io/go-steputils/v2/internal/os_proxy.go new file mode 100644 index 00000000..a4c456aa --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/v2/internal/os_proxy.go @@ -0,0 +1,63 @@ +package internal + +import ( + "io/fs" + "os" + "path/filepath" + "time" +) + +// OsProxy defines the subset of os package functions we want to proxy. +// Add more methods as you need them. +type OsProxy interface { + Stat(name string) (os.FileInfo, error) + Lstat(name string) (os.FileInfo, error) + Readlink(name string) (string, error) + Symlink(oldname, newname string) error + Mkdir(name string, perm os.FileMode) error + MkdirAll(path string, perm os.FileMode) error + Open(name string) (*os.File, error) + Create(name string) (*os.File, error) + Remove(name string) error + RemoveAll(path string) error + Rename(oldpath, newpath string) error + Chmod(name string, mode os.FileMode) error + Chown(name string, uid, gid int) error + Chtimes(name string, atime, mtime time.Time) error + Getwd() (string, error) + Abs(path string) (string, error) + DirFS(dir string) fs.FS + OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) + Lchown(name string, uid, gid int) error +} + +// RealOS is the default implementation that delegates to the real os package. +type RealOS struct{} + +func (RealOS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) } //nolint:revive +func (RealOS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) } //nolint:revive +func (RealOS) Readlink(name string) (string, error) { return os.Readlink(name) } //nolint:revive +func (RealOS) Symlink(oldname, newname string) error { return os.Symlink(oldname, newname) } //nolint:revive +func (RealOS) Mkdir(name string, perm os.FileMode) error { return os.Mkdir(name, perm) } //nolint:revive +func (RealOS) MkdirAll(path string, perm os.FileMode) error { return os.MkdirAll(path, perm) } //nolint:revive +func (RealOS) Open(name string) (*os.File, error) { return os.Open(name) } //nolint:revive +func (RealOS) Create(name string) (*os.File, error) { return os.Create(name) } //nolint:revive +func (RealOS) Remove(name string) error { return os.Remove(name) } //nolint:revive +func (RealOS) RemoveAll(path string) error { return os.RemoveAll(path) } //nolint:revive +func (RealOS) Rename(oldpath, newpath string) error { return os.Rename(oldpath, newpath) } //nolint:revive +func (RealOS) Chmod(name string, mode os.FileMode) error { return os.Chmod(name, mode) } //nolint:revive +func (RealOS) Chown(name string, uid, gid int) error { return os.Chown(name, uid, gid) } //nolint:revive +func (RealOS) Getwd() (string, error) { return os.Getwd() } //nolint:revive +func (RealOS) Abs(path string) (string, error) { return filepath.Abs(path) } //nolint:revive +func (RealOS) DirFS(dir string) fs.FS { return os.DirFS(dir) } //nolint:revive +func (RealOS) Lchown(name string, uid, gid int) error { return os.Lchown(name, uid, gid) } //nolint:revive + +//nolint:revive +func (RealOS) OpenFile(name string, flag int, perm os.FileMode) (*os.File, error) { + return os.OpenFile(name, flag, perm) +} + +//nolint:revive +func (RealOS) Chtimes(name string, atime, mtime time.Time) error { + return os.Chtimes(name, atime, mtime) +} diff --git a/vendor/github.com/bitrise-io/go-steputils/v2/stepconf/stepconf.go b/vendor/github.com/bitrise-io/go-steputils/v2/stepconf/stepconf.go index 37145932..9dd28c99 100644 --- a/vendor/github.com/bitrise-io/go-steputils/v2/stepconf/stepconf.go +++ b/vendor/github.com/bitrise-io/go-steputils/v2/stepconf/stepconf.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/bitrise-io/go-utils/v2/env" + "github.com/bitrise-io/go-utils/v2/parseutil" ) const ( @@ -89,7 +90,7 @@ func setField(field reflect.Value, value, constraint string) error { case reflect.String: field.SetString(value) case reflect.Bool: - b, err := parseBool(value) + b, err := parseutil.ParseBool(value) if err != nil { return errors.New("can't convert to bool") } @@ -453,19 +454,3 @@ func contains(s, opt string) bool { } return false } - -func parseBool(userInputStr string) (bool, error) { - if userInputStr == "" { - return false, errors.New("no string to parse") - } - userInputStr = strings.TrimSpace(userInputStr) - - lowercased := strings.ToLower(userInputStr) - if lowercased == "yes" || lowercased == "y" { - return true, nil - } - if lowercased == "no" || lowercased == "n" { - return false, nil - } - return strconv.ParseBool(lowercased) -} diff --git a/vendor/github.com/bitrise-io/go-steputils/v2/testasset/testasset.go b/vendor/github.com/bitrise-io/go-steputils/v2/testasset/testasset.go new file mode 100644 index 00000000..e6a30e91 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-steputils/v2/testasset/testasset.go @@ -0,0 +1,17 @@ +// Package testasset provides helpers for filtering test result attachments by file type. +package testasset + +import ( + "path/filepath" + "slices" + "strings" +) + +// AssetTypes is the list of supported attachment file extensions. +var AssetTypes = []string{".jpg", ".jpeg", ".png", ".txt", ".log", ".mp4", ".webm", ".ogg"} + +// IsSupportedAssetType reports whether the given file name has a supported attachment extension. +func IsSupportedAssetType(fileName string) bool { + ext := filepath.Ext(fileName) + return slices.Contains(AssetTypes, strings.ToLower(ext)) +} diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testreport/test_report.go b/vendor/github.com/bitrise-io/go-steputils/v2/testreport/test_report.go similarity index 78% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testreport/test_report.go rename to vendor/github.com/bitrise-io/go-steputils/v2/testreport/test_report.go index 31faa430..f4e12cb1 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testreport/test_report.go +++ b/vendor/github.com/bitrise-io/go-steputils/v2/testreport/test_report.go @@ -1,3 +1,4 @@ +// Package testreport defines the data structures for representing test results. package testreport import ( @@ -10,6 +11,7 @@ type TestReport struct { TestSuites []TestSuite `xml:"testsuite"` } +// TestSuite represents a collection of test cases. type TestSuite struct { XMLName xml.Name `xml:"testsuite"` Name string `xml:"name,attr"` @@ -25,6 +27,7 @@ type TestSuite struct { TestSuites []TestSuite `xml:"testsuite,omitempty"` } +// TestCase represents a single test case execution. type TestCase struct { XMLName xml.Name `xml:"testcase"` // ConfigurationHash is used to distinguish the same test case runs, @@ -44,6 +47,7 @@ type TestCase struct { SystemErr *SystemErr `xml:"system-err,omitempty"` } +// Failure represents a test case failure. type Failure struct { XMLName xml.Name `xml:"failure,omitempty"` Type string `xml:"type,attr,omitempty"` @@ -51,6 +55,7 @@ type Failure struct { Value string `xml:",chardata"` } +// Error represents a test case error. type Error struct { XMLName xml.Name `xml:"error,omitempty"` Type string `xml:"type,attr,omitempty"` @@ -58,29 +63,41 @@ type Error struct { Value string `xml:",chardata"` } +// Skipped represents a skipped test case. type Skipped struct { XMLName xml.Name `xml:"skipped,omitempty"` Message string `xml:"message,attr,omitempty"` Value string `xml:",chardata"` } +// Property represents a single key-value test property. type Property struct { XMLName xml.Name `xml:"property"` Name string `xml:"name,attr"` Value string `xml:"value,attr"` } +// Properties holds a list of test properties. type Properties struct { XMLName xml.Name `xml:"properties"` Property []Property `xml:"property"` } +// SystemOut holds captured standard output from a test case. type SystemOut struct { XMLName xml.Name `xml:"system-out,omitempty"` Value string `xml:",chardata"` } +// SystemErr holds a captured standard error from a test case. type SystemErr struct { XMLName xml.Name `xml:"system-err,omitempty"` Value string `xml:",chardata"` } + +// Converter is the interface that a test result converter must implement. +// It must be able to detect whether it can handle a set of files and run the conversion. +type Converter interface { + Detect([]string) bool + Convert() (TestReport, error) +} diff --git a/vendor/github.com/bitrise-io/go-utils/v2/log/log.go b/vendor/github.com/bitrise-io/go-utils/v2/log/log.go index 95d6b26f..835739c8 100644 --- a/vendor/github.com/bitrise-io/go-utils/v2/log/log.go +++ b/vendor/github.com/bitrise-io/go-utils/v2/log/log.go @@ -7,7 +7,8 @@ import ( "time" ) -// Logger ... +// Logger interface designed to provide only the necessary functionality used by our tooling. +// The lack of in-line printing is intentional. type Logger interface { Infof(format string, v ...interface{}) Warnf(format string, v ...interface{}) @@ -152,7 +153,9 @@ func (l *logger) TErrorf(format string, v ...interface{}) { // Println ... func (l *logger) Println() { - fmt.Println() + if _, err := fmt.Fprintln(l.stdout); err != nil { + fmt.Printf("failed to print newline: %s\n", err) + } } func (l *logger) timestampField() string { @@ -180,6 +183,6 @@ func (l *logger) createLogMsg(severity Severity, withTime bool, format string, v func (l *logger) printf(severity Severity, withTime bool, format string, v ...interface{}) { message := l.createLogMsg(severity, withTime, format, v...) if _, err := fmt.Fprintln(l.stdout, message); err != nil { - fmt.Printf("failed to print message: %s, error: %s\n", message, err) + fmt.Printf("failed to print message: %s: %s\n", message, err) } } diff --git a/vendor/github.com/bitrise-io/go-utils/v2/parseutil/parseutil.go b/vendor/github.com/bitrise-io/go-utils/v2/parseutil/parseutil.go new file mode 100644 index 00000000..6a9f3c22 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-utils/v2/parseutil/parseutil.go @@ -0,0 +1,110 @@ +package parseutil + +import ( + "errors" + "fmt" + "strconv" + "strings" +) + +// ParseBool parses a string representation of a boolean value. +// +// It accepts the following inputs (case-insensitive, whitespace trimmed): +// - Custom values: "yes", "y" (true), "no", "n" (false) +// - Standard values: "true", "t", "1" (true), "false", "f", "0" (false) +// +// Returns an error if the input is empty or cannot be parsed as a boolean. +func ParseBool(input string) (bool, error) { + // Validation + if input == "" { + return false, errors.New("no string to parse") + } + + // Normalization + normalized := strings.ToLower(strings.TrimSpace(input)) + + // Custom parsing + switch normalized { + case "yes", "y": + return true, nil + case "no", "n": + return false, nil + } + + // Delegate to stdlib + return strconv.ParseBool(normalized) +} + +// StringFrom converts any value to its string representation. +// +// If the value is already a string, it returns it directly for efficiency. +// Otherwise, it uses fmt.Sprintf with the %v verb to convert the value. +// +// This function always returns a string and never returns an error. +// +// Example: +// +// StringFrom("hello") // "hello" +// StringFrom(42) // "42" +// StringFrom(true) // "true" +// StringFrom(3.14) // "3.14" +func StringFrom(value interface{}) string { + if str, ok := value.(string); ok { + return str + } + return fmt.Sprintf("%v", value) +} + +// StringPtrFrom converts any value to its string representation and returns a pointer. +// +// This is a convenience function that calls StringFrom and returns a pointer to the result. +// +// Example: +// +// StringPtrFrom(42) // pointer to "42" +// StringPtrFrom("test") // pointer to "test" +func StringPtrFrom(value interface{}) *string { + result := StringFrom(value) + return &result +} + +// BoolFrom attempts to convert a value to a boolean. +// +// It returns (result, true) on success, or (false, false) if it fails. +// +// Conversion rules: +// - If the value is already a bool, it returns it directly +// - If the value can be converted to a string and parsed by ParseBool, the parsed result is returned +// - Otherwise, it returns (false, false) +func BoolFrom(value interface{}) (bool, bool) { + // Fast path: if already a bool, return it directly + if b, ok := value.(bool); ok { + return b, true + } + + // Try to convert to string and parse + str := StringFrom(value) + result, err := ParseBool(str) + if err != nil { + return false, false + } + return result, true +} + +// BoolPtrFrom attempts to convert a value to a boolean pointer. +// +// It returns (pointer, true) on success, or (nil, false) if it fails. +// This is a convenience function wrapping BoolFrom. +// +// Example: +// +// BoolPtrFrom(true) // (pointer to true, true) +// BoolPtrFrom("yes") // (pointer to true, true) +// BoolPtrFrom("invalid") // (nil, false) +func BoolPtrFrom(value interface{}) (*bool, bool) { + result, ok := BoolFrom(value) + if !ok { + return nil, false + } + return &result, true +} diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_invocation_record.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_invocation_record.go similarity index 51% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_invocation_record.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_invocation_record.go index df672fc5..2aa929b8 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_invocation_record.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_invocation_record.go @@ -4,11 +4,10 @@ import ( "fmt" "strings" - "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testreport" + "github.com/bitrise-io/go-steputils/v2/testreport" ) -// ActionsInvocationRecord ... -type ActionsInvocationRecord struct { +type actionsInvocationRecord struct { Actions struct { Values []struct { ActionResult struct { @@ -21,61 +20,53 @@ type ActionsInvocationRecord struct { } `json:"_values"` } `json:"actions"` - Issues Issues `json:"issues"` + Issues issues `json:"issues"` } -// Issues ... -type Issues struct { - TestFailureSummaries TestFailureSummaries `json:"testFailureSummaries"` +type issues struct { + TestFailureSummaries testFailureSummaries `json:"testFailureSummaries"` } -// TestFailureSummaries ... -type TestFailureSummaries struct { - Values []TestFailureSummary `json:"_values"` +type testFailureSummaries struct { + Values []testFailureSummary `json:"_values"` } -// TestFailureSummary ... -type TestFailureSummary struct { - DocumentLocationInCreatingWorkspace DocumentLocationInCreatingWorkspace `json:"documentLocationInCreatingWorkspace"` - Message Message `json:"message"` - ProducingTarget ProducingTarget `json:"producingTarget"` - TestCaseName TestCaseName `json:"testCaseName"` +type testFailureSummary struct { + DocumentLocationInCreatingWorkspace documentLocationInCreatingWorkspace `json:"documentLocationInCreatingWorkspace"` + Message message `json:"message"` + ProducingTarget producingTarget `json:"producingTarget"` + TestCaseName testCaseName `json:"testCaseName"` } -// URL ... -type URL struct { +type url struct { Value string `json:"_value"` } -// DocumentLocationInCreatingWorkspace ... -type DocumentLocationInCreatingWorkspace struct { - URL URL `json:"url"` +type documentLocationInCreatingWorkspace struct { + URL url `json:"url"` } -// ProducingTarget ... -type ProducingTarget struct { +type producingTarget struct { Value string `json:"_value"` } -// TestCaseName ... -type TestCaseName struct { +type testCaseName struct { Value string `json:"_value"` } -// Message ... -type Message struct { +type message struct { Value string `json:"_value"` } -func testCaseMatching(test ActionTestSummaryGroup, testCaseName string) bool { +func testCaseMatching(test actionTestSummaryGroup, tcName string) bool { class, method := test.references() - return testCaseName == class+"."+method || - testCaseName == fmt.Sprintf("-[%s %s]", class, method) + return tcName == class+"."+method || + tcName == fmt.Sprintf("-[%s %s]", class, method) } -// failure returns the ActionTestSummaryGroup's failure reason from the ActionsInvocationRecord. -func (r ActionsInvocationRecord) failure(test ActionTestSummaryGroup, testSuite testreport.TestSuite) string { +// failure returns the failure reason for the given test from the invocation record. +func (r actionsInvocationRecord) failure(test actionTestSummaryGroup, testSuite testreport.TestSuite) string { for _, failureSummary := range r.Issues.TestFailureSummaries.Values { if failureSummary.ProducingTarget.Value == testSuite.Name && testCaseMatching(test, failureSummary.TestCaseName.Value) { file, line := failureSummary.fileAndLineNumber() @@ -85,8 +76,8 @@ func (r ActionsInvocationRecord) failure(test ActionTestSummaryGroup, testSuite return "" } -// fileAndLineNumber unwraps the file path and line number descriptor from a given ActionTestSummaryGroup's. -func (s TestFailureSummary) fileAndLineNumber() (file string, line string) { +// fileAndLineNumber unwraps the file path and line number from the document location URL. +func (s testFailureSummary) fileAndLineNumber() (file string, line string) { // file:\/\/\/Users\/bitrisedeveloper\/Develop\/ios\/Xcode11Test\/Xcode11TestUITests\/Xcode11TestUITests.swift#CharacterRangeLen=0&EndingLineNumber=42&StartingLineNumber=42 if s.DocumentLocationInCreatingWorkspace.URL.Value != "" { i := strings.LastIndex(s.DocumentLocationInCreatingWorkspace.URL.Value, "#") diff --git a/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_plan_summary.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_plan_summary.go new file mode 100644 index 00000000..6605da4a --- /dev/null +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_plan_summary.go @@ -0,0 +1,93 @@ +package xcresult3 + +import "strconv" + +type actionTestPlanRunSummaries struct { + Summaries summaries `json:"summaries"` +} + +type summaries struct { + Values []summary `json:"_values"` +} + +type summary struct { + TestableSummaries testableSummaries `json:"testableSummaries"` +} + +type testableSummaries struct { + Values []actionTestableSummary `json:"_values"` +} + +type actionTestableSummary struct { + Name name `json:"name"` + Tests tests `json:"tests"` +} + +type tests struct { + Values []actionTestSummaryGroup `json:"_values"` +} + +type name struct { + Value string `json:"_value"` +} + +// tests returns actionTestSummaryGroup mapped by the container testableSummary name. +func (s actionTestPlanRunSummaries) tests() ([]string, map[string][]actionTestSummaryGroup) { + summaryGroupsByName := map[string][]actionTestSummaryGroup{} + + var testSuiteOrder []string + for _, smry := range s.Summaries.Values { + for _, testableSummary := range smry.TestableSummaries.Values { + // test suite + n := testableSummary.Name.Value + if _, found := summaryGroupsByName[n]; !found { + testSuiteOrder = append(testSuiteOrder, n) + } + + var ts []actionTestSummaryGroup + for _, test := range testableSummary.Tests.Values { + ts = append(ts, test.testsWithStatus()...) + } + + summaryGroupsByName[n] = ts + } + } + + return testSuiteOrder, summaryGroupsByName +} + +func (s actionTestPlanRunSummaries) failuresCount(testableSummaryName string) (failure int) { + _, testsByCase := s.tests() + ts := testsByCase[testableSummaryName] + for _, test := range ts { + if test.TestStatus.Value == "Failure" { + failure++ + } + } + return +} + +func (s actionTestPlanRunSummaries) skippedCount(testableSummaryName string) (skipped int) { + _, testsByCase := s.tests() + ts := testsByCase[testableSummaryName] + for _, test := range ts { + if test.TestStatus.Value == "Skipped" { + skipped++ + } + } + return +} + +func (s actionTestPlanRunSummaries) totalTime(testableSummaryName string) (time float64) { + _, testsByCase := s.tests() + ts := testsByCase[testableSummaryName] + for _, test := range ts { + if test.Duration.Value != "" { + d, err := strconv.ParseFloat(test.Duration.Value, 64) + if err == nil { + time += d + } + } + } + return +} diff --git a/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_summary.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_summary.go new file mode 100644 index 00000000..0b84ff73 --- /dev/null +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_summary.go @@ -0,0 +1,70 @@ +package xcresult3 + +import ( + "crypto/md5" + "encoding/hex" +) + +type attachment struct { + Filename struct { + Value string `json:"_value"` + } `json:"filename"` + + PayloadRef struct { + ID struct { + Value string `json:"_value"` + } + } `json:"payloadRef"` +} + +type attachments struct { + Values []attachment `json:"_values"` +} + +type actionTestActivitySummary struct { + Attachments attachments `json:"attachments"` +} + +type activitySummaries struct { + Values []actionTestActivitySummary `json:"_values"` +} + +type actionTestFailureSummary struct { + Message struct { + Value string `json:"_value"` + } `json:"message"` + + FileName struct { + Value string `json:"_value"` + } `json:"fileName"` + + LineNumber struct { + Value string `json:"_value"` + } `json:"lineNumber"` +} + +type failureSummaries struct { + Values []actionTestFailureSummary `json:"_values"` +} + +type configuration struct { + Hash string +} + +// UnmarshalJSON implements json.Unmarshaler by hashing the raw JSON bytes into an MD5 fingerprint. +func (c *configuration) UnmarshalJSON(data []byte) error { + if string(data) == "null" || string(data) == `""` { + return nil + } + + hash := md5.Sum(data) + c.Hash = hex.EncodeToString(hash[:]) + + return nil +} + +type actionTestSummary struct { + ActivitySummaries activitySummaries `json:"activitySummaries"` + FailureSummaries failureSummaries `json:"failureSummaries"` + Configuration configuration `json:"configuration"` +} diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_summary_group.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_summary_group.go similarity index 51% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_summary_group.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_summary_group.go index e2900c08..9f1065c2 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_summary_group.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/action_test_summary_group.go @@ -7,50 +7,42 @@ import ( "strings" ) -// ErrSummaryNotFound ... -var ErrSummaryNotFound = errors.New("no summaryRef.ID.Value found for test case") - -// ActionTestSummaryGroup ... -type ActionTestSummaryGroup struct { - Name Name `json:"name"` - Identifier Identifier `json:"identifier"` - Duration Duration `json:"duration"` - TestStatus TestStatus `json:"testStatus"` // only the inner-most tests will have a status, the ones which don't have "subtests" - SummaryRef SummaryRef `json:"summaryRef"` // only the inner-most tests will have a summaryRef, the ones which don't have "subtests" - Subtests Subtests `json:"subtests"` +var errSummaryNotFound = errors.New("no summaryRef.ID.Value found for test case") + +type actionTestSummaryGroup struct { + Name name `json:"name"` + Identifier identifier `json:"identifier"` + Duration duration `json:"duration"` + TestStatus testStatus `json:"testStatus"` // only the inner-most tests will have a status, the ones which don't have "subtests" + SummaryRef summaryRef `json:"summaryRef"` // only the inner-most tests will have a summaryRef, the ones which don't have "subtests" + Subtests subtests `json:"subtests"` } -// Subtests ... -type Subtests struct { - Values []ActionTestSummaryGroup `json:"_values"` +type subtests struct { + Values []actionTestSummaryGroup `json:"_values"` } -// ID ... -type ID struct { +type id struct { Value string `json:"_value"` } -// SummaryRef ... -type SummaryRef struct { - ID ID `json:"id"` +type summaryRef struct { + ID id `json:"id"` } -// TestStatus ... -type TestStatus struct { +type testStatus struct { Value string `json:"_value"` } -// Duration ... -type Duration struct { +type duration struct { Value string `json:"_value"` } -// Identifier ... -type Identifier struct { +type identifier struct { Value string `json:"_value"` } -func (g ActionTestSummaryGroup) references() (class, method string) { +func (g actionTestSummaryGroup) references() (class, method string) { // Xcode11TestUITests2/testFail() if g.Identifier.Value != "" { s := strings.Split(g.Identifier.Value, "/") @@ -61,33 +53,31 @@ func (g ActionTestSummaryGroup) references() (class, method string) { return } -// testsWithStatus returns ActionTestSummaryGroup with TestStatus defined. -func (g ActionTestSummaryGroup) testsWithStatus() (tests []ActionTestSummaryGroup) { +// testsWithStatus returns actionTestSummaryGroup entries with TestStatus set. +func (g actionTestSummaryGroup) testsWithStatus() (result []actionTestSummaryGroup) { if g.TestStatus.Value != "" { - tests = append(tests, g) + result = append(result, g) } for _, subtest := range g.Subtests.Values { - tests = append(tests, subtest.testsWithStatus()...) + result = append(result, subtest.testsWithStatus()...) } return } -// loadActionTestSummary ... -func (g ActionTestSummaryGroup) loadActionTestSummary(xcresultPath string, useLegacyFlag bool) (ActionTestSummary, error) { +func (g actionTestSummaryGroup) loadActionTestSummary(xcresultPath string, useLegacyFlag bool) (actionTestSummary, error) { if g.SummaryRef.ID.Value == "" { - return ActionTestSummary{}, ErrSummaryNotFound + return actionTestSummary{}, errSummaryNotFound } - var summary ActionTestSummary + var summary actionTestSummary if err := xcresulttoolGet(xcresultPath, g.SummaryRef.ID.Value, useLegacyFlag, &summary); err != nil { - return ActionTestSummary{}, fmt.Errorf("failed to load ActionTestSummary: %w", err) + return actionTestSummary{}, fmt.Errorf("failed to load action test summary: %w", err) } return summary, nil } -// exportScreenshots ... -func (g ActionTestSummaryGroup) exportScreenshots(resultPth, outputDir string, useLegacyFlag bool) error { +func (g actionTestSummaryGroup) exportScreenshots(resultPth, outputDir string, useLegacyFlag bool) error { if g.TestStatus.Value == "" { return nil } @@ -96,7 +86,7 @@ func (g ActionTestSummaryGroup) exportScreenshots(resultPth, outputDir string, u return nil } - var summary ActionTestSummary + var summary actionTestSummary if err := xcresulttoolGet(resultPth, g.SummaryRef.ID.Value, useLegacyFlag, &summary); err != nil { return err } diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/converter.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/converter.go similarity index 94% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/converter.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/converter.go index 292cec6c..9535542e 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/converter.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/converter.go @@ -20,9 +20,9 @@ import ( "github.com/bitrise-io/go-utils/log" "github.com/bitrise-io/go-utils/pathutil" "github.com/bitrise-io/go-xcode/xcodeproject/serialized" - "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3" - "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testasset" - "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testreport" + "github.com/bitrise-io/go-steputils/v2/testasset" + "github.com/bitrise-io/go-steputils/v2/testreport" + "github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3" ) // Converter ... @@ -58,8 +58,9 @@ func documentMajorVersion(pth string) (int, error) { return majorVersion(info) } -func (c *Converter) Setup(useOldXCResultExtractionMethod bool) { - c.useLegacyExtractionMethod = useOldXCResultExtractionMethod +// NewConverter creates a Converter with the given extraction method preference. +func NewConverter(useLegacy bool) *Converter { + return &Converter{useLegacyExtractionMethod: useLegacy} } // Detect ... @@ -100,7 +101,7 @@ func (c *Converter) Detect(files []string) bool { return false } -// XML ... +// Convert returns the test report parsed from the xcresult file. func (c *Converter) Convert() (testreport.TestReport, error) { supportsNewMethod, err := supportsNewExtractionMethods() if err != nil { @@ -138,7 +139,7 @@ func legacyParse(path string, useLegacyFlag bool) (testreport.TestReport, error) log.Debugf("Maximum parallelism: %d.", maxParallel) - _, summaries, err := Parse(path, useLegacyFlag) + _, summaries, err := loadXCResultData(path, useLegacyFlag) if err != nil { return testreport.TestReport{}, err } @@ -383,7 +384,7 @@ func connectAttachmentsToTestCases(xml testreport.TestReport, attachmentsMap map return xml, nil } -func testSuiteCountInSummaries(summaries []ActionTestPlanRunSummaries) int { +func testSuiteCountInSummaries(summaries []actionTestPlanRunSummaries) int { testSuiteCount := 0 for _, summary := range summaries { testSuiteOrder, _ := summary.tests() @@ -393,8 +394,8 @@ func testSuiteCountInSummaries(summaries []ActionTestPlanRunSummaries) int { } func genTestSuite(name string, - summary ActionTestPlanRunSummaries, - tests []ActionTestSummaryGroup, + summary actionTestPlanRunSummaries, + tests []actionTestSummaryGroup, testResultDir string, xcresultPath string, maxParallel int, @@ -422,7 +423,7 @@ func genTestSuite(name string, test := tests[testIdx] wg.Add(1) - go func(test ActionTestSummaryGroup, testIdx int) { + go func(test actionTestSummaryGroup, testIdx int) { defer wg.Done() testCase, err := genTestCase(test, xcresultPath, testResultDir, useLegacyFlag) @@ -446,7 +447,7 @@ func genTestSuite(name string, return testSuite, genTestSuiteErr } -func genTestCase(test ActionTestSummaryGroup, xcresultPath, testResultDir string, useLegacyFlag bool) (testreport.TestCase, error) { +func genTestCase(test actionTestSummaryGroup, xcresultPath, testResultDir string, useLegacyFlag bool) (testreport.TestCase, error) { var duartion float64 if test.Duration.Value != "" { var err error @@ -461,7 +462,7 @@ func genTestCase(test ActionTestSummaryGroup, xcresultPath, testResultDir string // For example, failed tests will always have a summary, but successful ones might have it or might not. // If they do not have it, then that means that they did not log anything to the console, // and they were not executed as device configuration tests. - if err != nil && !errors.Is(err, ErrSummaryNotFound) { + if err != nil && !errors.Is(err, errSummaryNotFound) { return testreport.TestCase{}, err } diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/logging.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/logging.go similarity index 100% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/logging.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/logging.go diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/conversion.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/conversion.go similarity index 93% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/conversion.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/conversion.go index f2edd0f6..2aaeb007 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/conversion.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/conversion.go @@ -6,6 +6,7 @@ import ( "time" ) +// Convert converts TestData into a TestSummary and a list of warnings. func Convert(data *TestData) (*TestSummary, []string, error) { var warnings []string summary := TestSummary{} @@ -102,9 +103,12 @@ func extractTestCases(nodes []TestNode, fallbackName string) ([]TestCaseWithRetr } func extractDuration(text string) time.Duration { - // Duration is in the format "123.456789s" or "123,456789s", so we need to replace the comma with a dot. - text = strings.Replace(text, ",", ".", -1) - duration, err := time.ParseDuration(text) + // Duration is in the format "123.456789s", "123,456789s" or "4m 34s", so we need to do some normalization. We + // need to replace the comma with a dot and remove the space to be able to parse it with time.ParseDuration. + normalized := strings.ReplaceAll(text, ",", ".") + normalized = strings.ReplaceAll(normalized, " ", "") + + duration, err := time.ParseDuration(normalized) if err != nil { return 0 } diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/data.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/data.go similarity index 56% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/data.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/data.go index 58a852ff..fa183b1d 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/data.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/data.go @@ -2,30 +2,36 @@ package model3 import "time" +// TestSummary holds the top-level test results grouped by test plans. type TestSummary struct { TestPlans []TestPlan } +// TestPlan represents a test plan and its test bundles. type TestPlan struct { Name string TestBundles []TestBundle } +// TestBundle represents a test bundle and its test suites. type TestBundle struct { Name string TestSuites []TestSuite } +// TestSuite represents a test suite and its test cases. type TestSuite struct { Name string TestCases []TestCaseWithRetries } +// TestCaseWithRetries holds a test case along with any retry attempts. type TestCaseWithRetries struct { TestCase Retries []TestCase } +// TestCase represents a single test case execution result. type TestCase struct { Name string ClassName string diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/export.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/export.go similarity index 80% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/export.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/export.go index b18d805b..f14c1e7f 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/export.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/export.go @@ -5,13 +5,16 @@ import ( "time" ) +// TestAttachmentDetails contains the test identifier and its list of attachments. type TestAttachmentDetails struct { TestIdentifier string `json:"testIdentifier"` Attachments []Attachment `json:"attachments"` } +// Timestamp is a time.Time that unmarshals from a Unix epoch float. type Timestamp time.Time +// Attachment describes a single exported test attachment file. type Attachment struct { ExportedFileName string `json:"exportedFileName"` SuggestedHumanReadableName string `json:"suggestedHumanReadableName"` @@ -23,6 +26,7 @@ type Attachment struct { RepetitionNumber int `json:"repetitionNumber"` } +// UnmarshalJSON decodes a Unix epoch float into a Timestamp. func (t *Timestamp) UnmarshalJSON(b []byte) error { var timestamp float64 if err := json.Unmarshal(b, ×tamp); err != nil { diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/testresults.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/testresults.go similarity index 82% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/testresults.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/testresults.go index 65eaad4f..37aab474 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3/testresults.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3/testresults.go @@ -1,5 +1,6 @@ package model3 +// TestNodeType identifies the kind of a node in the xcresulttool test tree. type TestNodeType string // These are all the types the xcresulttool (version 23500, format version 3.53) supports. @@ -21,8 +22,10 @@ const ( TestNodeTypeTestValue TestNodeType = "Test Value" ) +// TestResult represents the outcome of a test case. type TestResult string +// TestResult values reported by xcresulttool. const ( TestResultPassed TestResult = "Passed" TestResultFailed TestResult = "Failed" @@ -31,12 +34,14 @@ const ( TestResultUnknown TestResult = "unknown" ) +// TestData is the top-level structure returned by xcresulttool for a test run. type TestData struct { Devices []Devices `json:"devices"` TestNodes []TestNode `json:"testNodes"` TestPlanConfigurations []Configuration `json:"testPlanConfigurations"` } +// Devices describes a device that participated in the test run. type Devices struct { Identifier string `json:"deviceId"` Name string `json:"deviceName"` @@ -46,6 +51,7 @@ type Devices struct { OS string `json:"osVersion"` } +// TestNode is a node in the xcresulttool test tree (plan, bundle, suite, case, etc.). type TestNode struct { Identifier string `json:"nodeIdentifier"` Type TestNodeType `json:"nodeType"` @@ -57,6 +63,7 @@ type TestNode struct { Children []TestNode `json:"children"` } +// Configuration describes a test plan configuration used during the test run. type Configuration struct { Identifier string `json:"configurationId"` Name string `json:"configurationName"` diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/xcresult3.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/xcresult3.go similarity index 54% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/xcresult3.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/xcresult3.go index 94eb6490..0484aaf5 100644 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/xcresult3.go +++ b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/xcresult3.go @@ -1,18 +1,18 @@ package xcresult3 -import "github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3" +import "github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3" -// Parse parses the given xcresult file's ActionsInvocationRecord and the list of ActionTestPlanRunSummaries. -func Parse(pth string, useLegacyFlag bool) (*ActionsInvocationRecord, []ActionTestPlanRunSummaries, error) { - var r ActionsInvocationRecord +// loadXCResultData loads the actions invocation record and test plan run summaries from an xcresult file. +func loadXCResultData(pth string, useLegacyFlag bool) (*actionsInvocationRecord, []actionTestPlanRunSummaries, error) { + var r actionsInvocationRecord if err := xcresulttoolGet(pth, "", useLegacyFlag, &r); err != nil { return nil, nil, err } - var summaries []ActionTestPlanRunSummaries + var summaries []actionTestPlanRunSummaries for _, action := range r.Actions.Values { refID := action.ActionResult.TestsRef.ID.Value - var s ActionTestPlanRunSummaries + var s actionTestPlanRunSummaries if err := xcresulttoolGet(pth, refID, useLegacyFlag, &s); err != nil { return nil, nil, err } @@ -21,6 +21,7 @@ func Parse(pth string, useLegacyFlag bool) (*ActionsInvocationRecord, []ActionTe return &r, summaries, nil } +// ParseTestResults parses the test results from the given xcresult file. func ParseTestResults(pth string) (*model3.TestData, error) { var data model3.TestData if err := xcresulttoolGet(pth, "", false, &data); err != nil { diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/xcresulttool.go b/vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/xcresulttool.go similarity index 100% rename from vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/xcresulttool.go rename to vendor/github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/xcresulttool.go diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/LICENSE b/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/LICENSE deleted file mode 100644 index a6a5c39a..00000000 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Bitrise - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_plan_summary.go b/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_plan_summary.go deleted file mode 100644 index 8f1808c0..00000000 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_plan_summary.go +++ /dev/null @@ -1,100 +0,0 @@ -package xcresult3 - -import "strconv" - -// ActionTestPlanRunSummaries ... -type ActionTestPlanRunSummaries struct { - Summaries Summaries `json:"summaries"` -} - -// Summaries ... -type Summaries struct { - Values []Summary `json:"_values"` -} - -// Summary ... -type Summary struct { - TestableSummaries TestableSummaries `json:"testableSummaries"` -} - -// TestableSummaries ... -type TestableSummaries struct { - Values []ActionTestableSummary `json:"_values"` -} - -// ActionTestableSummary ... -type ActionTestableSummary struct { - Name Name `json:"name"` - Tests Tests `json:"tests"` -} - -// Tests ... -type Tests struct { - Values []ActionTestSummaryGroup `json:"_values"` -} - -// Name ... -type Name struct { - Value string `json:"_value"` -} - -// tests returns ActionTestSummaryGroup mapped by the container TestableSummary name. -func (s ActionTestPlanRunSummaries) tests() ([]string, map[string][]ActionTestSummaryGroup) { - summaryGroupsByName := map[string][]ActionTestSummaryGroup{} - - var testSuiteOrder []string - for _, summary := range s.Summaries.Values { - for _, testableSummary := range summary.TestableSummaries.Values { - // test suite - name := testableSummary.Name.Value - if _, found := summaryGroupsByName[name]; !found { - testSuiteOrder = append(testSuiteOrder, name) - } - - var tests []ActionTestSummaryGroup - for _, test := range testableSummary.Tests.Values { - tests = append(tests, test.testsWithStatus()...) - } - - summaryGroupsByName[name] = tests - } - } - - return testSuiteOrder, summaryGroupsByName -} - -func (s ActionTestPlanRunSummaries) failuresCount(testableSummaryName string) (failure int) { - _, testsByCase := s.tests() - tests := testsByCase[testableSummaryName] - for _, test := range tests { - if test.TestStatus.Value == "Failure" { - failure++ - } - } - return -} - -func (s ActionTestPlanRunSummaries) skippedCount(testableSummaryName string) (skipped int) { - _, testsByCase := s.tests() - tests := testsByCase[testableSummaryName] - for _, test := range tests { - if test.TestStatus.Value == "Skipped" { - skipped++ - } - } - return -} - -func (s ActionTestPlanRunSummaries) totalTime(testableSummaryName string) (time float64) { - _, testsByCase := s.tests() - tests := testsByCase[testableSummaryName] - for _, test := range tests { - if test.Duration.Value != "" { - d, err := strconv.ParseFloat(test.Duration.Value, 64) - if err == nil { - time += d - } - } - } - return -} diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_summary.go b/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_summary.go deleted file mode 100644 index 8745d56d..00000000 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/action_test_summary.go +++ /dev/null @@ -1,78 +0,0 @@ -package xcresult3 - -import ( - "crypto/md5" - "encoding/hex" -) - -// Attachment ... -type Attachment struct { - Filename struct { - Value string `json:"_value"` - } `json:"filename"` - - PayloadRef struct { - ID struct { - Value string `json:"_value"` - } - } `json:"payloadRef"` -} - -// Attachments ... -type Attachments struct { - Values []Attachment `json:"_values"` -} - -// ActionTestActivitySummary ... -type ActionTestActivitySummary struct { - Attachments Attachments `json:"attachments"` -} - -// ActivitySummaries ... -type ActivitySummaries struct { - Values []ActionTestActivitySummary `json:"_values"` -} - -// ActionTestFailureSummary ... -type ActionTestFailureSummary struct { - Message struct { - Value string `json:"_value"` - } `json:"message"` - - FileName struct { - Value string `json:"_value"` - } `json:"fileName"` - - LineNumber struct { - Value string `json:"_value"` - } `json:"lineNumber"` -} - -// FailureSummaries ... -type FailureSummaries struct { - Values []ActionTestFailureSummary `json:"_values"` -} - -// Configuration ... -type Configuration struct { - Hash string -} - -// UnmarshalJSON ... -func (c *Configuration) UnmarshalJSON(data []byte) error { - if string(data) == "null" || string(data) == `""` { - return nil - } - - hash := md5.Sum(data) - c.Hash = hex.EncodeToString(hash[:]) - - return nil -} - -// ActionTestSummary ... -type ActionTestSummary struct { - ActivitySummaries ActivitySummaries `json:"activitySummaries"` - FailureSummaries FailureSummaries `json:"failureSummaries"` - Configuration Configuration `json:"configuration"` -} diff --git a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testasset/testasset.go b/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testasset/testasset.go deleted file mode 100644 index 33107b6d..00000000 --- a/vendor/github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testasset/testasset.go +++ /dev/null @@ -1,25 +0,0 @@ -package testasset - -import ( - "os" - "path/filepath" - "slices" - "strings" -) - -var AssetTypes = []string{".jpg", ".jpeg", ".png", ".txt", ".log"} -var VideoTypes = []string{".mp4", ".webm", ".ogg"} // These video types are also supported on the UI - -func IsSupportedAssetType(fileName string) bool { - ext := filepath.Ext(fileName) - - if slices.Contains(AssetTypes, strings.ToLower(ext)) { - return true - } - - if os.Getenv("ENABLE_TEST_VIDEO_UPLOAD") == "true" { - return slices.Contains(VideoTypes, strings.ToLower(ext)) - } - - return false -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 5f34869b..9ffd8394 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -14,13 +14,16 @@ github.com/bitrise-io/envman/models ## explicit; go 1.15 github.com/bitrise-io/go-steputils/cache github.com/bitrise-io/go-steputils/tools -# github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.43 -## explicit; go 1.17 +# github.com/bitrise-io/go-steputils/v2 v2.0.0-alpha.48.0.20260312091018-7447bc60506b +## explicit; go 1.21 github.com/bitrise-io/go-steputils/v2/export +github.com/bitrise-io/go-steputils/v2/internal github.com/bitrise-io/go-steputils/v2/ruby github.com/bitrise-io/go-steputils/v2/stepconf github.com/bitrise-io/go-steputils/v2/stepenv +github.com/bitrise-io/go-steputils/v2/testasset github.com/bitrise-io/go-steputils/v2/testquarantine +github.com/bitrise-io/go-steputils/v2/testreport # github.com/bitrise-io/go-utils v1.0.15 ## explicit; go 1.13 github.com/bitrise-io/go-utils/colorstring @@ -34,7 +37,7 @@ github.com/bitrise-io/go-utils/pointers github.com/bitrise-io/go-utils/progress github.com/bitrise-io/go-utils/stringutil github.com/bitrise-io/go-utils/ziputil -# github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.31 +# github.com/bitrise-io/go-utils/v2 v2.0.0-alpha.33 ## explicit; go 1.17 github.com/bitrise-io/go-utils/v2/command github.com/bitrise-io/go-utils/v2/env @@ -43,18 +46,21 @@ github.com/bitrise-io/go-utils/v2/filedownloader github.com/bitrise-io/go-utils/v2/fileutil github.com/bitrise-io/go-utils/v2/log github.com/bitrise-io/go-utils/v2/log/colorstring +github.com/bitrise-io/go-utils/v2/parseutil github.com/bitrise-io/go-utils/v2/pathutil github.com/bitrise-io/go-utils/v2/retry github.com/bitrise-io/go-utils/v2/retryhttp -# github.com/bitrise-io/go-xcode v1.3.1 +# github.com/bitrise-io/go-xcode v1.3.3 ## explicit; go 1.20 github.com/bitrise-io/go-xcode/xcodeproject/serialized -# github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.77 +# github.com/bitrise-io/go-xcode/v2 v2.0.0-alpha.79.0.20260312102256-0c898dd1f2a3 ## explicit; go 1.22 github.com/bitrise-io/go-xcode/v2/destination github.com/bitrise-io/go-xcode/v2/errorfinder github.com/bitrise-io/go-xcode/v2/logio github.com/bitrise-io/go-xcode/v2/simulator +github.com/bitrise-io/go-xcode/v2/testresult/xcresult3 +github.com/bitrise-io/go-xcode/v2/testresult/xcresult3/model3 github.com/bitrise-io/go-xcode/v2/xcconfig github.com/bitrise-io/go-xcode/v2/xcodecache github.com/bitrise-io/go-xcode/v2/xcodecommand @@ -62,18 +68,14 @@ github.com/bitrise-io/go-xcode/v2/xcodeversion # github.com/bitrise-io/stepman v0.0.0-20240828074035-6ae1a5f5efde ## explicit; go 1.18 github.com/bitrise-io/stepman/models -# github.com/bitrise-steplib/steps-deploy-to-bitrise-io v0.0.0-20260105124642-5583d1ed06c4 -## explicit; go 1.22 -github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3 -github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/converters/xcresult3/model3 -github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testasset -github.com/bitrise-steplib/steps-deploy-to-bitrise-io/test/testreport # github.com/davecgh/go-spew v1.1.1 ## explicit github.com/davecgh/go-spew/spew # github.com/globocom/go-buffer/v2 v2.0.0 ## explicit; go 1.13 github.com/globocom/go-buffer/v2 +# github.com/google/go-cmp v0.6.0 +## explicit; go 1.13 # github.com/hashicorp/go-cleanhttp v0.5.2 ## explicit; go 1.13 github.com/hashicorp/go-cleanhttp