diff --git a/conf.example.yml b/conf.example.yml index f4cf528..37717c7 100644 --- a/conf.example.yml +++ b/conf.example.yml @@ -276,6 +276,8 @@ destination: bucket: your-bucket-name accesskey: your-access-key # can be an environment variable, just don't add a $ in front of it secretkey: your-secret-key # can be an environment variable, just don't add a $ in front of it + token: your-token # can be an environment variable, just don't add a $ in front of it + zip: false # if true, will zip the entire git repo into a single zip file and upload that instead usessl: true # wheter to use ssl or not cron: 0 22 * * * # optional - when cron is not provided, the program runs once and exits. # Otherwise, it runs according to the cron schedule. diff --git a/gickup_spec.json b/gickup_spec.json index ba07a9c..40c0e03 100644 --- a/gickup_spec.json +++ b/gickup_spec.json @@ -542,6 +542,10 @@ "token": { "type": "string", "description": "The token to authenticate against the S3 server" + }, + "zip": { + "type": "boolean", + "description": "If true, zip the entire Git repo into a single zip file and upload that instead" } }, "additionalProperties": false @@ -1107,4 +1111,4 @@ "additionalProperties": false } } -} +} \ No newline at end of file diff --git a/main.go b/main.go index 6dc67c0..3fabb43 100644 --- a/main.go +++ b/main.go @@ -33,6 +33,7 @@ import ( "github.com/cooperspencer/gickup/metrics/prometheus" "github.com/cooperspencer/gickup/types" "github.com/cooperspencer/gickup/whatever" + "github.com/cooperspencer/gickup/zip" "github.com/robfig/cron/v3" "github.com/rs/zerolog" "github.com/rs/zerolog/log" @@ -189,10 +190,14 @@ func backup(repos []types.Repo, conf *types.Conf) { repotime := time.Now() status := 0 + logOp := "pushing" + if d.Zip { + logOp = "zipping and pushing" + } log.Info(). Str("stage", "s3"). Str("url", d.Endpoint). - Msgf("pushing %s to %s", types.Blue(r.Name), d.Bucket) + Msgf("%s %s to %s", logOp, types.Blue(r.Name), d.Bucket) if !cli.Dry { tempname := fmt.Sprintf("s3-%x", repotime) @@ -210,7 +215,8 @@ func backup(repos []types.Repo, conf *types.Conf) { } defer os.RemoveAll(tempdir) - _, err = local.TempClone(r, path.Join(tempdir, r.Name)) + tempClonePath := path.Join(tempdir, r.Name) + _, err = local.TempClone(r, tempClonePath) if err != nil { if err == git.NoErrAlreadyUpToDate { log.Info(). @@ -241,6 +247,21 @@ func backup(repos []types.Repo, conf *types.Conf) { if err != nil { log.Error().Str("stage", "s3").Str("endpoint", d.Endpoint).Str("bucket", d.Bucket).Msg(err.Error()) } + + if d.Zip { + log.Info(). + Msgf("zipping %s", types.Green(r.Name)) + err := zip.Zip(tempClonePath, []string{tempClonePath}) + if err != nil { + log.Error(). + Str("stage", "zip"). + Str("url", r.URL). + Str("repo", r.Name). + Msg(err.Error()) + log.Error().Msgf("Skipping backup of %s due to error while zipping", r.Name) + continue + } + } err = s3.UploadDirToS3(tempdir, d) if err != nil { log.Error().Str("stage", "s3").Str("endpoint", d.Endpoint).Str("bucket", d.Bucket).Msg(err.Error()) diff --git a/types/types.go b/types/types.go index fefb75d..1a7285a 100644 --- a/types/types.go +++ b/types/types.go @@ -543,6 +543,7 @@ type S3Repo struct { Region string `yaml:"region"` UseSSL bool `yaml:"usessl"` Structured bool `yaml:"structured"` + Zip bool `yaml:"zip"` } func (s3 S3Repo) GetKey(accessString string) (string, error) { diff --git a/zip/zip.go b/zip/zip.go index 320f8a6..a876508 100644 --- a/zip/zip.go +++ b/zip/zip.go @@ -9,6 +9,8 @@ import ( "path/filepath" ) +// Create a Zip file `{repository}.zip` and recursively add the contents of all paths in the `tozip` array to it. +// Deletes the original contents of `repository` such that only the newly created Zip file remains. func Zip(repository string, tozip []string) error { file, err := os.Create(fmt.Sprintf("%s.zip", repository)) if err != nil {