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  }