github.phpd.cn/goreleaser/goreleaser@v0.92.0/internal/tmpl/tmpl.go (about)

     1  // Package tmpl provides templating utilities for goreleser
     2  package tmpl
     3  
     4  import (
     5  	"bytes"
     6  	"text/template"
     7  	"time"
     8  
     9  	"github.com/Masterminds/semver"
    10  	"github.com/goreleaser/goreleaser/internal/artifact"
    11  	"github.com/goreleaser/goreleaser/pkg/context"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // Template holds data that can be applied to a template string
    16  type Template struct {
    17  	fields fields
    18  }
    19  
    20  type fields map[string]interface{}
    21  
    22  const (
    23  	// general keys
    24  	projectName = "ProjectName"
    25  	version     = "Version"
    26  	tag         = "Tag"
    27  	commit      = "Commit"
    28  	shortCommit = "ShortCommit"
    29  	fullCommit  = "FullCommit"
    30  	gitURL      = "GitURL"
    31  	major       = "Major"
    32  	minor       = "Minor"
    33  	patch       = "Patch"
    34  	env         = "Env"
    35  	date        = "Date"
    36  	timestamp   = "Timestamp"
    37  
    38  	// artifact-only keys
    39  	os           = "Os"
    40  	arch         = "Arch"
    41  	arm          = "Arm"
    42  	binary       = "Binary"
    43  	artifactName = "ArtifactName"
    44  )
    45  
    46  // New Template
    47  func New(ctx *context.Context) *Template {
    48  	return &Template{
    49  		fields: fields{
    50  			projectName: ctx.Config.ProjectName,
    51  			version:     ctx.Version,
    52  			tag:         ctx.Git.CurrentTag,
    53  			commit:      ctx.Git.Commit,
    54  			shortCommit: ctx.Git.ShortCommit,
    55  			fullCommit:  ctx.Git.FullCommit,
    56  			gitURL:      ctx.Git.URL,
    57  			env:         ctx.Env,
    58  			date:        time.Now().UTC().Format(time.RFC3339),
    59  			timestamp:   time.Now().UTC().Unix(),
    60  		},
    61  	}
    62  }
    63  
    64  // WithArtifact populates fields from the artifact and replacements
    65  func (t *Template) WithArtifact(a artifact.Artifact, replacements map[string]string) *Template {
    66  	var bin = a.Extra[binary]
    67  	if bin == "" {
    68  		bin = t.fields[projectName].(string)
    69  	}
    70  	t.fields[os] = replace(replacements, a.Goos)
    71  	t.fields[arch] = replace(replacements, a.Goarch)
    72  	t.fields[arm] = replace(replacements, a.Goarm)
    73  	t.fields[binary] = bin
    74  	t.fields[artifactName] = a.Name
    75  	return t
    76  }
    77  
    78  // Apply applies the given string against the fields stored in the template.
    79  func (t *Template) Apply(s string) (string, error) {
    80  	var out bytes.Buffer
    81  	tmpl, err := template.New("tmpl").
    82  		Option("missingkey=error").
    83  		Funcs(template.FuncMap{
    84  			"time": func(s string) string {
    85  				return time.Now().UTC().Format(s)
    86  			},
    87  		}).
    88  		Parse(s)
    89  	if err != nil {
    90  		return "", err
    91  	}
    92  
    93  	sv, err := semver.NewVersion(t.fields[tag].(string))
    94  	if err != nil {
    95  		return "", errors.Wrap(err, "tmpl")
    96  	}
    97  	t.fields[major] = sv.Major()
    98  	t.fields[minor] = sv.Minor()
    99  	t.fields[patch] = sv.Patch()
   100  
   101  	err = tmpl.Execute(&out, t.fields)
   102  	return out.String(), err
   103  }
   104  
   105  func replace(replacements map[string]string, original string) string {
   106  	result := replacements[original]
   107  	if result == "" {
   108  		return original
   109  	}
   110  	return result
   111  }