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  }