github.com/droot/goreleaser@v0.66.2-0.20180420030140-c2db5fb17157/pipeline/nfpm/nfpm.go (about) 1 // Package nfpm implements the Pipe interface providing NFPM bindings. 2 package nfpm 3 4 import ( 5 "os" 6 "path/filepath" 7 8 "golang.org/x/sync/errgroup" 9 10 "github.com/apex/log" 11 "github.com/goreleaser/nfpm" 12 "github.com/pkg/errors" 13 14 // blank imports here because the formats implementations need register 15 // themselves 16 _ "github.com/goreleaser/nfpm/deb" 17 _ "github.com/goreleaser/nfpm/rpm" 18 19 "github.com/goreleaser/goreleaser/context" 20 "github.com/goreleaser/goreleaser/internal/artifact" 21 "github.com/goreleaser/goreleaser/internal/filenametemplate" 22 "github.com/goreleaser/goreleaser/internal/linux" 23 "github.com/goreleaser/goreleaser/pipeline" 24 ) 25 26 const defaultNameTemplate = "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" 27 28 // Pipe for fpm packaging 29 type Pipe struct{} 30 31 func (Pipe) String() string { 32 return "creating Linux packages with nfpm" 33 } 34 35 // Default sets the pipe defaults 36 func (Pipe) Default(ctx *context.Context) error { 37 var fpm = &ctx.Config.NFPM 38 if fpm.Bindir == "" { 39 fpm.Bindir = "/usr/local/bin" 40 } 41 if fpm.NameTemplate == "" { 42 fpm.NameTemplate = defaultNameTemplate 43 } 44 if fpm.Files == nil { 45 fpm.Files = make(map[string]string) 46 } 47 return nil 48 } 49 50 // Run the pipe 51 func (Pipe) Run(ctx *context.Context) error { 52 if len(ctx.Config.NFPM.Formats) == 0 { 53 return pipeline.Skip("no output formats configured") 54 } 55 return doRun(ctx) 56 } 57 58 func doRun(ctx *context.Context) error { 59 var linuxBinaries = ctx.Artifacts.Filter(artifact.And( 60 artifact.ByType(artifact.Binary), 61 artifact.ByGoos("linux"), 62 )).GroupByPlatform() 63 var g errgroup.Group 64 sem := make(chan bool, ctx.Parallelism) 65 for _, format := range ctx.Config.NFPM.Formats { 66 for platform, artifacts := range linuxBinaries { 67 sem <- true 68 format := format 69 arch := linux.Arch(platform) 70 artifacts := artifacts 71 g.Go(func() error { 72 defer func() { 73 <-sem 74 }() 75 return create(ctx, format, arch, artifacts) 76 }) 77 } 78 } 79 return g.Wait() 80 } 81 82 func create(ctx *context.Context, format, arch string, binaries []artifact.Artifact) error { 83 name, err := filenametemplate.Apply( 84 ctx.Config.NFPM.NameTemplate, 85 filenametemplate.NewFields(ctx, ctx.Config.NFPM.Replacements, binaries...), 86 ) 87 if err != nil { 88 return err 89 } 90 var files = map[string]string{} 91 for k, v := range ctx.Config.NFPM.Files { 92 files[k] = v 93 } 94 var log = log.WithField("package", name+"."+format) 95 for _, binary := range binaries { 96 src := binary.Path 97 dst := filepath.Join(ctx.Config.NFPM.Bindir, binary.Name) 98 log.WithField("src", src).WithField("dst", dst).Debug("adding binary to package") 99 files[src] = dst 100 } 101 log.WithField("files", files).Debug("all archive files") 102 103 var info = nfpm.Info{ 104 Arch: arch, 105 Platform: "linux", 106 Conflicts: ctx.Config.NFPM.Conflicts, 107 Depends: ctx.Config.NFPM.Dependencies, 108 Recommends: ctx.Config.NFPM.Recommends, 109 Suggests: ctx.Config.NFPM.Suggests, 110 Name: ctx.Config.ProjectName, 111 Version: ctx.Git.CurrentTag, 112 Section: "", 113 Priority: "", 114 Maintainer: ctx.Config.NFPM.Maintainer, 115 Description: ctx.Config.NFPM.Description, 116 Vendor: ctx.Config.NFPM.Vendor, 117 Homepage: ctx.Config.NFPM.Homepage, 118 License: ctx.Config.NFPM.License, 119 Bindir: ctx.Config.NFPM.Bindir, 120 Files: files, 121 ConfigFiles: ctx.Config.NFPM.ConfigFiles, 122 } 123 124 if err = nfpm.Validate(info); err != nil { 125 return errors.Wrap(err, "invalid nfpm config") 126 } 127 128 packager, err := nfpm.Get(format) 129 if err != nil { 130 return err 131 } 132 133 var path = filepath.Join(ctx.Config.Dist, name+"."+format) 134 log.WithField("file", path).Info("creating") 135 w, err := os.Create(path) 136 if err != nil { 137 return err 138 } 139 defer w.Close() // nolint: errcheck 140 if err := packager.Package(nfpm.WithDefaults(info), w); err != nil { 141 return errors.Wrap(err, "nfpm failed") 142 } 143 if err := w.Close(); err != nil { 144 return errors.Wrap(err, "could not close package file") 145 } 146 ctx.Artifacts.Add(artifact.Artifact{ 147 Type: artifact.LinuxPackage, 148 Name: name + "." + format, 149 Path: path, 150 Goos: binaries[0].Goos, 151 Goarch: binaries[0].Goarch, 152 Goarm: binaries[0].Goarm, 153 }) 154 return nil 155 }