github.com/tomsquest/goreleaser@v0.34.3-0.20171008022654-7d6ef4d338b3/pipeline/fpm/fpm.go (about) 1 // Package fpm implements the Pipe interface providing FPM bindings. 2 package fpm 3 4 import ( 5 "errors" 6 "fmt" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 11 "github.com/apex/log" 12 "github.com/goreleaser/goreleaser/context" 13 "github.com/goreleaser/goreleaser/internal/linux" 14 "github.com/goreleaser/goreleaser/pipeline" 15 "golang.org/x/sync/errgroup" 16 ) 17 18 // ErrNoFPM is shown when fpm cannot be found in $PATH 19 var ErrNoFPM = errors.New("fpm not present in $PATH") 20 21 // Pipe for fpm packaging 22 type Pipe struct{} 23 24 // Description of the pipe 25 func (Pipe) Description() string { 26 return "Creating Linux packages with fpm" 27 } 28 29 // Run the pipe 30 func (Pipe) Run(ctx *context.Context) error { 31 if len(ctx.Config.FPM.Formats) == 0 { 32 return pipeline.Skip("no output formats configured") 33 } 34 _, err := exec.LookPath("fpm") 35 if err != nil { 36 return ErrNoFPM 37 } 38 return doRun(ctx) 39 } 40 41 func doRun(ctx *context.Context) error { 42 var g errgroup.Group 43 for _, format := range ctx.Config.FPM.Formats { 44 for platform, groups := range ctx.Binaries { 45 if !strings.Contains(platform, "linux") { 46 log.WithField("platform", platform).Debug("skipped non-linux builds for fpm") 47 continue 48 } 49 format := format 50 arch := linux.Arch(platform) 51 for folder, binaries := range groups { 52 g.Go(func() error { 53 return create(ctx, format, folder, arch, binaries) 54 }) 55 } 56 } 57 } 58 return g.Wait() 59 } 60 61 func create(ctx *context.Context, format, folder, arch string, binaries []context.Binary) error { 62 var path = filepath.Join(ctx.Config.Dist, folder) 63 var file = path + "." + format 64 var log = log.WithField("format", format).WithField("arch", arch) 65 log.WithField("file", file).Info("creating fpm archive") 66 67 var options = basicOptions(ctx, format, arch, file) 68 69 for _, binary := range binaries { 70 // This basically tells fpm to put the binary in the /usr/local/bin 71 // binary=/usr/local/bin/binary 72 log.WithField("path", binary.Path). 73 WithField("name", binary.Name). 74 Debug("added binary to fpm package") 75 options = append(options, fmt.Sprintf( 76 "%s=%s", 77 binary.Path, 78 filepath.Join("/usr/local/bin", binary.Name), 79 )) 80 } 81 82 for src, dest := range ctx.Config.FPM.Files { 83 log.WithField("src", src). 84 WithField("dest", dest). 85 Debug("added an extra file to the fpm package") 86 options = append(options, fmt.Sprintf( 87 "%s=%s", 88 src, 89 dest, 90 )) 91 } 92 93 log.WithField("args", options).Debug("creating fpm package") 94 if out, err := exec.Command("fpm", options...).CombinedOutput(); err != nil { 95 return errors.New(string(out)) 96 } 97 ctx.AddArtifact(file) 98 return nil 99 } 100 101 func basicOptions(ctx *context.Context, format, arch, file string) []string { 102 var options = []string{ 103 "--input-type", "dir", 104 "--output-type", format, 105 "--name", ctx.Config.ProjectName, 106 "--version", ctx.Version, 107 "--architecture", arch, 108 "--package", file, 109 "--force", 110 } 111 112 if ctx.Config.FPM.Vendor != "" { 113 options = append(options, "--vendor", ctx.Config.FPM.Vendor) 114 } 115 if ctx.Config.FPM.Homepage != "" { 116 options = append(options, "--url", ctx.Config.FPM.Homepage) 117 } 118 if ctx.Config.FPM.Maintainer != "" { 119 options = append(options, "--maintainer", ctx.Config.FPM.Maintainer) 120 } 121 if ctx.Config.FPM.Description != "" { 122 options = append(options, "--description", ctx.Config.FPM.Description) 123 } 124 if ctx.Config.FPM.License != "" { 125 options = append(options, "--license", ctx.Config.FPM.License) 126 } 127 for _, dep := range ctx.Config.FPM.Dependencies { 128 options = append(options, "--depends", dep) 129 } 130 for _, conflict := range ctx.Config.FPM.Conflicts { 131 options = append(options, "--conflicts", conflict) 132 } 133 134 // FPM requires --rpm-os=linux if your rpm target is linux 135 if format == "rpm" { 136 options = append(options, "--rpm-os", "linux") 137 } 138 return options 139 }