github.com/szyn/goreleaser@v0.76.1-0.20180517112710-333da09a1297/pipeline/checksums/checksums.go (about)

     1  // Package checksums provides a Pipe that creates .checksums files for
     2  // each artifact.
     3  package checksums
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  	"text/template"
    11  
    12  	"github.com/apex/log"
    13  	"golang.org/x/sync/errgroup"
    14  
    15  	"github.com/goreleaser/goreleaser/checksum"
    16  	"github.com/goreleaser/goreleaser/context"
    17  	"github.com/goreleaser/goreleaser/internal/artifact"
    18  )
    19  
    20  // Pipe for checksums
    21  type Pipe struct{}
    22  
    23  func (Pipe) String() string {
    24  	return "calculating checksums"
    25  }
    26  
    27  // Default sets the pipe defaults
    28  func (Pipe) Default(ctx *context.Context) error {
    29  	if ctx.Config.Checksum.NameTemplate == "" {
    30  		ctx.Config.Checksum.NameTemplate = "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
    31  	}
    32  	return nil
    33  }
    34  
    35  // Run the pipe
    36  func (Pipe) Run(ctx *context.Context) (err error) {
    37  	filename, err := filenameFor(ctx)
    38  	if err != nil {
    39  		return err
    40  	}
    41  	file, err := os.OpenFile(
    42  		filepath.Join(ctx.Config.Dist, filename),
    43  		os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
    44  		0444,
    45  	)
    46  	if err != nil {
    47  		return err
    48  	}
    49  	defer file.Close() // nolint: errcheck
    50  
    51  	var g errgroup.Group
    52  	var semaphore = make(chan bool, ctx.Parallelism)
    53  	for _, artifact := range ctx.Artifacts.Filter(
    54  		artifact.Or(
    55  			artifact.ByType(artifact.UploadableArchive),
    56  			artifact.ByType(artifact.UploadableBinary),
    57  			artifact.ByType(artifact.LinuxPackage),
    58  		),
    59  	).List() {
    60  		semaphore <- true
    61  		artifact := artifact
    62  		g.Go(func() error {
    63  			defer func() {
    64  				<-semaphore
    65  			}()
    66  			return checksums(ctx, file, artifact)
    67  		})
    68  	}
    69  	ctx.Artifacts.Add(artifact.Artifact{
    70  		Type: artifact.Checksum,
    71  		Path: file.Name(),
    72  		Name: filename,
    73  	})
    74  	return g.Wait()
    75  }
    76  
    77  func checksums(ctx *context.Context, file *os.File, artifact artifact.Artifact) error {
    78  	log.WithField("file", artifact.Name).Info("checksumming")
    79  	sha, err := checksum.SHA256(artifact.Path)
    80  	if err != nil {
    81  		return err
    82  	}
    83  	_, err = file.WriteString(fmt.Sprintf("%v  %v\n", sha, artifact.Name))
    84  	return err
    85  }
    86  
    87  func filenameFor(ctx *context.Context) (string, error) {
    88  	var out bytes.Buffer
    89  	t, err := template.New("checksums").
    90  		Option("missingkey=error").
    91  		Parse(ctx.Config.Checksum.NameTemplate)
    92  	if err != nil {
    93  		return "", err
    94  	}
    95  	err = t.Execute(&out, struct {
    96  		ProjectName string
    97  		Tag         string
    98  		Version     string
    99  		Env         map[string]string
   100  	}{
   101  		ProjectName: ctx.Config.ProjectName,
   102  		Tag:         ctx.Git.CurrentTag,
   103  		Version:     ctx.Version,
   104  		Env:         ctx.Env,
   105  	})
   106  	return out.String(), err
   107  }