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  }