github.com/nilium/gitlab-runner@v12.5.0+incompatible/commands/helpers/artifacts_uploader.go (about) 1 package helpers 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "time" 10 11 "github.com/sirupsen/logrus" 12 "github.com/urfave/cli" 13 14 "gitlab.com/gitlab-org/gitlab-runner/common" 15 "gitlab.com/gitlab-org/gitlab-runner/helpers/archives" 16 "gitlab.com/gitlab-org/gitlab-runner/log" 17 "gitlab.com/gitlab-org/gitlab-runner/network" 18 ) 19 20 const DefaultUploadName = "default" 21 22 type ArtifactsUploaderCommand struct { 23 common.JobCredentials 24 fileArchiver 25 retryHelper 26 network common.Network 27 28 Name string `long:"name" description:"The name of the archive"` 29 ExpireIn string `long:"expire-in" description:"When to expire artifacts"` 30 Format common.ArtifactFormat `long:"artifact-format" description:"Format of generated artifacts"` 31 Type string `long:"artifact-type" description:"Type of generated artifacts"` 32 } 33 34 func (c *ArtifactsUploaderCommand) generateZipArchive(w *io.PipeWriter) { 35 err := archives.CreateZipArchive(w, c.sortedFiles()) 36 w.CloseWithError(err) 37 } 38 39 func (c *ArtifactsUploaderCommand) generateGzipStream(w *io.PipeWriter) { 40 err := archives.CreateGzipArchive(w, c.sortedFiles()) 41 w.CloseWithError(err) 42 } 43 44 func (c *ArtifactsUploaderCommand) openRawStream() (io.ReadCloser, error) { 45 fileNames := c.sortedFiles() 46 if len(fileNames) > 1 { 47 return nil, errors.New("only one file can be send as raw") 48 } 49 50 return os.Open(fileNames[0]) 51 } 52 53 func (c *ArtifactsUploaderCommand) createReadStream() (string, io.ReadCloser, error) { 54 if len(c.files) == 0 { 55 return "", nil, nil 56 } 57 58 name := filepath.Base(c.Name) 59 if name == "" || name == "." { 60 name = DefaultUploadName 61 } 62 63 switch c.Format { 64 case common.ArtifactFormatZip, common.ArtifactFormatDefault: 65 pr, pw := io.Pipe() 66 go c.generateZipArchive(pw) 67 68 return name + ".zip", pr, nil 69 70 case common.ArtifactFormatGzip: 71 pr, pw := io.Pipe() 72 go c.generateGzipStream(pw) 73 74 return name + ".gz", pr, nil 75 76 case common.ArtifactFormatRaw: 77 file, err := c.openRawStream() 78 79 return name, file, err 80 81 default: 82 return "", nil, fmt.Errorf("unsupported archive format: %s", c.Format) 83 } 84 } 85 86 func (c *ArtifactsUploaderCommand) createAndUpload() error { 87 artifactsName, stream, err := c.createReadStream() 88 if err != nil { 89 return err 90 } 91 if stream == nil { 92 logrus.Errorln("No files to upload") 93 94 return nil 95 } 96 defer stream.Close() 97 98 // Create the archive 99 options := common.ArtifactsOptions{ 100 BaseName: artifactsName, 101 ExpireIn: c.ExpireIn, 102 Format: c.Format, 103 Type: c.Type, 104 } 105 106 // Upload the data 107 switch c.network.UploadRawArtifacts(c.JobCredentials, stream, options) { 108 case common.UploadSucceeded: 109 return nil 110 case common.UploadForbidden: 111 return os.ErrPermission 112 case common.UploadTooLarge: 113 return errors.New("too large") 114 case common.UploadFailed: 115 return retryableErr{err: os.ErrInvalid} 116 default: 117 return os.ErrInvalid 118 } 119 } 120 121 func (c *ArtifactsUploaderCommand) Execute(*cli.Context) { 122 log.SetRunnerFormatter() 123 124 if len(c.URL) == 0 || len(c.Token) == 0 { 125 logrus.Fatalln("Missing runner credentials") 126 } 127 if c.ID <= 0 { 128 logrus.Fatalln("Missing build ID") 129 } 130 131 // Enumerate files 132 err := c.enumerate() 133 if err != nil { 134 logrus.Fatalln(err) 135 } 136 137 // If the upload fails, exit with a non-zero exit code to indicate an issue? 138 err = c.doRetry(c.createAndUpload) 139 if err != nil { 140 logrus.Fatalln(err) 141 } 142 } 143 144 func init() { 145 common.RegisterCommand2("artifacts-uploader", "create and upload build artifacts (internal)", &ArtifactsUploaderCommand{ 146 network: network.NewGitLabClient(), 147 retryHelper: retryHelper{ 148 Retry: 2, 149 RetryTime: time.Second, 150 }, 151 Name: "artifacts", 152 }) 153 }