github.com/joselitofilho/goreleaser@v0.155.1-0.20210123221854-e4891856c593/internal/pipe/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  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/apex/log"
    13  	"github.com/goreleaser/goreleaser/internal/artifact"
    14  	"github.com/goreleaser/goreleaser/internal/pipe"
    15  	"github.com/goreleaser/goreleaser/internal/semerrgroup"
    16  	"github.com/goreleaser/goreleaser/internal/tmpl"
    17  	"github.com/goreleaser/goreleaser/pkg/context"
    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  	if ctx.Config.Checksum.Algorithm == "" {
    33  		ctx.Config.Checksum.Algorithm = "sha256"
    34  	}
    35  	return nil
    36  }
    37  
    38  // Run the pipe.
    39  func (Pipe) Run(ctx *context.Context) (err error) {
    40  	if ctx.Config.Checksum.Disable {
    41  		return pipe.Skip("checksum.disable is set")
    42  	}
    43  	filter := artifact.Or(
    44  		artifact.ByType(artifact.UploadableArchive),
    45  		artifact.ByType(artifact.UploadableBinary),
    46  		artifact.ByType(artifact.UploadableSourceArchive),
    47  		artifact.ByType(artifact.LinuxPackage),
    48  	)
    49  	if len(ctx.Config.Checksum.IDs) > 0 {
    50  		filter = artifact.And(filter, artifact.ByIDs(ctx.Config.Checksum.IDs...))
    51  	}
    52  
    53  	artifactList := ctx.Artifacts.Filter(filter).List()
    54  	if len(artifactList) == 0 {
    55  		return nil
    56  	}
    57  
    58  	var g = semerrgroup.New(ctx.Parallelism)
    59  	sumLines := make([]string, len(artifactList))
    60  	for i, artifact := range artifactList {
    61  		i := i
    62  		artifact := artifact
    63  		g.Go(func() error {
    64  			sumLine, err := checksums(ctx.Config.Checksum.Algorithm, artifact)
    65  			if err != nil {
    66  				return err
    67  			}
    68  			sumLines[i] = sumLine
    69  			return nil
    70  		})
    71  	}
    72  
    73  	err = g.Wait()
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	filename, err := tmpl.New(ctx).Apply(ctx.Config.Checksum.NameTemplate)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	file, err := os.OpenFile(
    83  		filepath.Join(ctx.Config.Dist, filename),
    84  		os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
    85  		0644,
    86  	)
    87  	if err != nil {
    88  		return err
    89  	}
    90  	defer file.Close()
    91  
    92  	ctx.Artifacts.Add(&artifact.Artifact{
    93  		Type: artifact.Checksum,
    94  		Path: file.Name(),
    95  		Name: filename,
    96  	})
    97  
    98  	// sort to ensure the signature is deterministic downstream
    99  	sort.Strings(sumLines)
   100  	_, err = file.WriteString(strings.Join(sumLines, ""))
   101  	return err
   102  }
   103  
   104  func checksums(algorithm string, artifact *artifact.Artifact) (string, error) {
   105  	log.WithField("file", artifact.Name).Info("checksumming")
   106  	sha, err := artifact.Checksum(algorithm)
   107  	if err != nil {
   108  		return "", err
   109  	}
   110  	return fmt.Sprintf("%v  %v\n", sha, artifact.Name), nil
   111  }