github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/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/extrafiles"
    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                 { return "calculating checksums" }
    24  func (Pipe) Skip(ctx *context.Context) bool { return ctx.Config.Checksum.Disable }
    25  
    26  // Default sets the pipe defaults.
    27  func (Pipe) Default(ctx *context.Context) error {
    28  	if ctx.Config.Checksum.NameTemplate == "" {
    29  		ctx.Config.Checksum.NameTemplate = "{{ .ProjectName }}_{{ .Version }}_checksums.txt"
    30  	}
    31  	if ctx.Config.Checksum.Algorithm == "" {
    32  		ctx.Config.Checksum.Algorithm = "sha256"
    33  	}
    34  	return nil
    35  }
    36  
    37  // Run the pipe.
    38  func (Pipe) Run(ctx *context.Context) (err error) {
    39  	filter := artifact.Or(
    40  		artifact.ByType(artifact.UploadableArchive),
    41  		artifact.ByType(artifact.UploadableBinary),
    42  		artifact.ByType(artifact.UploadableSourceArchive),
    43  		artifact.ByType(artifact.LinuxPackage),
    44  	)
    45  	if len(ctx.Config.Checksum.IDs) > 0 {
    46  		filter = artifact.And(filter, artifact.ByIDs(ctx.Config.Checksum.IDs...))
    47  	}
    48  
    49  	artifactList := ctx.Artifacts.Filter(filter).List()
    50  	if len(artifactList) == 0 {
    51  		return nil
    52  	}
    53  
    54  	extraFiles, err := extrafiles.Find(ctx.Config.Checksum.ExtraFiles)
    55  	if err != nil {
    56  		return err
    57  	}
    58  
    59  	for name, path := range extraFiles {
    60  		artifactList = append(artifactList, &artifact.Artifact{
    61  			Name: name,
    62  			Path: path,
    63  			Type: artifact.UploadableFile,
    64  		})
    65  	}
    66  
    67  	g := semerrgroup.New(ctx.Parallelism)
    68  	sumLines := make([]string, len(artifactList))
    69  	for i, artifact := range artifactList {
    70  		i := i
    71  		artifact := artifact
    72  		g.Go(func() error {
    73  			sumLine, err := checksums(ctx.Config.Checksum.Algorithm, artifact)
    74  			if err != nil {
    75  				return err
    76  			}
    77  			sumLines[i] = sumLine
    78  			return nil
    79  		})
    80  	}
    81  
    82  	err = g.Wait()
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	filename, err := tmpl.New(ctx).Apply(ctx.Config.Checksum.NameTemplate)
    88  	if err != nil {
    89  		return err
    90  	}
    91  	file, err := os.OpenFile(
    92  		filepath.Join(ctx.Config.Dist, filename),
    93  		os.O_APPEND|os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
    94  		0o644,
    95  	)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	defer file.Close()
   100  
   101  	ctx.Artifacts.Add(&artifact.Artifact{
   102  		Type: artifact.Checksum,
   103  		Path: file.Name(),
   104  		Name: filename,
   105  	})
   106  
   107  	// sort to ensure the signature is deterministic downstream
   108  	sort.Strings(sumLines)
   109  	_, err = file.WriteString(strings.Join(sumLines, ""))
   110  	return err
   111  }
   112  
   113  func checksums(algorithm string, artifact *artifact.Artifact) (string, error) {
   114  	log.WithField("file", artifact.Name).Info("checksumming")
   115  	sha, err := artifact.Checksum(algorithm)
   116  	if err != nil {
   117  		return "", err
   118  	}
   119  	return fmt.Sprintf("%v  %v\n", sha, artifact.Name), nil
   120  }