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