cache_archiver.go 2.36 KB
Newer Older
1
package helpers
2 3

import (
4 5 6 7 8
	"net/http"
	"os"
	"path/filepath"
	"time"

9
	"github.com/sirupsen/logrus"
10
	"github.com/urfave/cli"
11

12 13 14
	"gitlab.com/gitlab-org/gitlab-runner/common"
	"gitlab.com/gitlab-org/gitlab-runner/helpers/archives"
	"gitlab.com/gitlab-org/gitlab-runner/helpers/url"
15
	"gitlab.com/gitlab-org/gitlab-runner/log"
16 17 18
)

type CacheArchiverCommand struct {
Kamil Trzciński's avatar
Kamil Trzciński committed
19
	fileArchiver
20
	retryHelper
21 22 23
	File    string `long:"file" description:"The path to file"`
	URL     string `long:"url" description:"URL of remote cache resource"`
	Timeout int    `long:"timeout" description:"Overall timeout for cache uploading request (in minutes)"`
24 25 26 27 28 29 30 31 32 33

	client *CacheClient
}

func (c *CacheArchiverCommand) getClient() *CacheClient {
	if c.client == nil {
		c.client = NewCacheClient(c.Timeout)
	}

	return c.client
34 35
}

36
func (c *CacheArchiverCommand) upload() error {
37
	logrus.Infoln("Uploading", filepath.Base(c.File), "to", url_helpers.CleanURL(c.URL))
38 39 40

	file, err := os.Open(c.File)
	if err != nil {
41
		return err
42 43 44 45 46
	}
	defer file.Close()

	fi, err := file.Stat()
	if err != nil {
47
		return err
48 49 50 51
	}

	req, err := http.NewRequest("PUT", c.URL, file)
	if err != nil {
52
		return retryableErr{err: err}
53 54 55 56 57
	}
	req.Header.Set("Content-Type", "application/octet-stream")
	req.Header.Set("Last-Modified", fi.ModTime().Format(http.TimeFormat))
	req.ContentLength = fi.Size()

58
	resp, err := c.getClient().Do(req)
59
	if err != nil {
60
		return retryableErr{err: err}
61 62 63
	}
	defer resp.Body.Close()

64
	return retryOnServerError(resp)
65 66 67
}

func (c *CacheArchiverCommand) Execute(*cli.Context) {
68 69
	log.SetRunnerFormatter()

70 71 72 73 74 75 76 77 78 79 80 81 82
	if c.File == "" {
		logrus.Fatalln("Missing --file")
	}

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

	// Check if list of files changed
	if !c.isFileChanged(c.File) {
		logrus.Infoln("Archive is up to date!")
83

84 85 86 87 88 89 90 91
		return
	}

	// Create archive
	err = archives.CreateZipFile(c.File, c.sortedFiles())
	if err != nil {
		logrus.Fatalln(err)
	}
92 93 94

	// Upload archive if needed
	if c.URL != "" {
95 96
		err := c.doRetry(c.upload)
		if err != nil {
97
			logrus.Fatalln(err)
98
		}
99 100
	} else {
		logrus.Infoln("No URL provided, cache will be not uploaded to shared cache server. Cache will be stored only locally.")
101
	}
102 103 104
}

func init() {
105 106 107 108 109 110
	common.RegisterCommand2("cache-archiver", "create and upload cache artifacts (internal)", &CacheArchiverCommand{
		retryHelper: retryHelper{
			Retry:     2,
			RetryTime: time.Second,
		},
	})
111
}