artifacts_uploader.go 3.03 KB
Newer Older
1
package helpers
2
3

import (
4
	"errors"
Kamil Trzciński's avatar
Kamil Trzciński committed
5
	"fmt"
6
7
	"io"
	"os"
8
	"path"
9
10
	"time"

11
	"github.com/sirupsen/logrus"
12
	"github.com/urfave/cli"
13

14
15
16
17
	"gitlab.com/gitlab-org/gitlab-runner/common"
	"gitlab.com/gitlab-org/gitlab-runner/helpers/archives"
	"gitlab.com/gitlab-org/gitlab-runner/helpers/formatter"
	"gitlab.com/gitlab-org/gitlab-runner/network"
18
19
20
)

type ArtifactsUploaderCommand struct {
21
	common.JobCredentials
Kamil Trzcinski's avatar
Kamil Trzcinski committed
22
23
24
	fileArchiver
	retryHelper
	network common.Network
25

Kamil Trzciński's avatar
Kamil Trzciński committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
	Name     string                `long:"name" description:"The name of the archive"`
	ExpireIn string                `long:"expire-in" description:"When to expire artifacts"`
	Format   common.ArtifactFormat `long:"format" description:"Format of generated artifacts"`
	Type     string                `long:"type" description:"Type of generated artifacts"`
}

func (c *ArtifactsUploaderCommand) generateZipArchive(w *io.PipeWriter) {
	err := archives.CreateZipArchive(w, c.sortedFiles())
	w.CloseWithError(err)
}

func (c *ArtifactsUploaderCommand) createReadStream() (string, io.ReadCloser, error) {
	artifactsName := path.Base(c.Name)

	switch c.Format {
	case common.ArtifactFormatZip, "":
		pr, pw := io.Pipe()
		go c.generateZipArchive(pw)
		return artifactsName + ".zip", pr, nil

	case common.ArtifactFormatRaw:
		if len(c.files) == 0 {
			return "", nil, errors.New("no file to upload")
		}
		if len(c.files) > 1 {
			return "", nil, errors.New("raw format accepts only single file to upload")
		}

		file, err := os.Open(c.sortedFiles()[0])
		return artifactsName, file, err

	default:
		return "", nil, fmt.Errorf("unsupported archive format: %s", c.Format)
	}
60
61
}

Kamil Trzcinski's avatar
Kamil Trzcinski committed
62
func (c *ArtifactsUploaderCommand) createAndUpload() (bool, error) {
Kamil Trzciński's avatar
Kamil Trzciński committed
63
64
65
66
67
	artifactsName, stream, err := c.createReadStream()
	if err != nil {
		return false, err
	}
	defer stream.Close()
68
69

	// Create the archive
Kamil Trzciński's avatar
Kamil Trzciński committed
70
71
72
73
74
75
	options := common.ArtifactsOptions{
		BaseName: artifactsName,
		ExpireIn: c.ExpireIn,
		Format:   c.Format,
		Type:     c.Type,
	}
76

77
	// Upload the data
Kamil Trzciński's avatar
Kamil Trzciński committed
78
	switch c.network.UploadRawArtifacts(c.JobCredentials, stream, options) {
Kamil Trzcinski's avatar
Kamil Trzcinski committed
79
80
81
82
83
84
85
86
87
88
89
	case common.UploadSucceeded:
		return false, nil
	case common.UploadForbidden:
		return false, os.ErrPermission
	case common.UploadTooLarge:
		return false, errors.New("Too large")
	case common.UploadFailed:
		return true, os.ErrInvalid
	default:
		return false, os.ErrInvalid
	}
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
}

func (c *ArtifactsUploaderCommand) Execute(*cli.Context) {
	formatter.SetRunnerFormatter()

	if len(c.URL) == 0 || len(c.Token) == 0 {
		logrus.Fatalln("Missing runner credentials")
	}
	if c.ID <= 0 {
		logrus.Fatalln("Missing build ID")
	}

	// Enumerate files
	err := c.enumerate()
	if err != nil {
		logrus.Fatalln(err)
	}

	// If the upload fails, exit with a non-zero exit code to indicate an issue?
Kamil Trzcinski's avatar
Kamil Trzcinski committed
109
110
111
	err = c.doRetry(c.createAndUpload)
	if err != nil {
		logrus.Fatalln(err)
112
113
114
115
	}
}

func init() {
Kamil Trzcinski's avatar
Kamil Trzcinski committed
116
	common.RegisterCommand2("artifacts-uploader", "create and upload build artifacts (internal)", &ArtifactsUploaderCommand{
117
		network: network.NewGitLabClient(),
Kamil Trzcinski's avatar
Kamil Trzcinski committed
118
119
120
121
		retryHelper: retryHelper{
			Retry:     2,
			RetryTime: time.Second,
		},
122
		Name: "artifacts",
Kamil Trzcinski's avatar
Kamil Trzcinski committed
123
	})
124
}