github.com/triarius/goreleaser@v1.12.5/internal/pipe/env/env.go (about)

     1  // Package env implements the Pipe interface providing validation of
     2  // missing environment variables needed by the release process.
     3  package env
     4  
     5  import (
     6  	"bufio"
     7  	"errors"
     8  	"fmt"
     9  	"io/fs"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/caarlos0/log"
    14  	"github.com/triarius/goreleaser/internal/tmpl"
    15  	"github.com/triarius/goreleaser/pkg/context"
    16  	homedir "github.com/mitchellh/go-homedir"
    17  )
    18  
    19  // ErrMissingToken indicates an error when GITHUB_TOKEN, GITLAB_TOKEN and GITEA_TOKEN are all missing in the environment.
    20  var ErrMissingToken = errors.New("missing GITHUB_TOKEN, GITLAB_TOKEN and GITEA_TOKEN")
    21  
    22  // ErrMultipleTokens indicates that multiple tokens are defined. ATM only one of them if allowed.
    23  // See https://github.com/triarius/goreleaser/pull/809
    24  type ErrMultipleTokens struct {
    25  	tokens []string
    26  }
    27  
    28  func (e ErrMultipleTokens) Error() string {
    29  	return fmt.Sprintf("multiple tokens found, but only one is allowed: %s\n\nLearn more at https://goreleaser.com/errors/multiple-tokens\n", strings.Join(e.tokens, ", "))
    30  }
    31  
    32  // Pipe for env.
    33  type Pipe struct{}
    34  
    35  func (Pipe) String() string {
    36  	return "loading environment variables"
    37  }
    38  
    39  func setDefaultTokenFiles(ctx *context.Context) {
    40  	env := &ctx.Config.EnvFiles
    41  	if env.GitHubToken == "" {
    42  		env.GitHubToken = "~/.config/goreleaser/github_token"
    43  	}
    44  	if env.GitLabToken == "" {
    45  		env.GitLabToken = "~/.config/goreleaser/gitlab_token"
    46  	}
    47  	if env.GiteaToken == "" {
    48  		env.GiteaToken = "~/.config/goreleaser/gitea_token"
    49  	}
    50  }
    51  
    52  // Run the pipe.
    53  func (Pipe) Run(ctx *context.Context) error {
    54  	templ := tmpl.New(ctx).WithEnvS(os.Environ())
    55  	tEnv := []string{}
    56  	for i := range ctx.Config.Env {
    57  		env, err := templ.Apply(ctx.Config.Env[i])
    58  		if err != nil {
    59  			return err
    60  		}
    61  		tEnv = append(tEnv, env)
    62  	}
    63  	for k, v := range context.ToEnv(tEnv) {
    64  		ctx.Env[k] = v
    65  	}
    66  
    67  	setDefaultTokenFiles(ctx)
    68  	githubToken, githubTokenErr := loadEnv("GITHUB_TOKEN", ctx.Config.EnvFiles.GitHubToken)
    69  	gitlabToken, gitlabTokenErr := loadEnv("GITLAB_TOKEN", ctx.Config.EnvFiles.GitLabToken)
    70  	giteaToken, giteaTokenErr := loadEnv("GITEA_TOKEN", ctx.Config.EnvFiles.GiteaToken)
    71  
    72  	var tokens []string
    73  	if githubToken != "" {
    74  		tokens = append(tokens, "GITHUB_TOKEN")
    75  	}
    76  	if gitlabToken != "" {
    77  		tokens = append(tokens, "GITLAB_TOKEN")
    78  	}
    79  	if giteaToken != "" {
    80  		tokens = append(tokens, "GITEA_TOKEN")
    81  	}
    82  	if len(tokens) > 1 {
    83  		return ErrMultipleTokens{tokens}
    84  	}
    85  
    86  	noTokens := githubToken == "" && gitlabToken == "" && giteaToken == ""
    87  	noTokenErrs := githubTokenErr == nil && gitlabTokenErr == nil && giteaTokenErr == nil
    88  
    89  	if err := checkErrors(ctx, noTokens, noTokenErrs, gitlabTokenErr, githubTokenErr, giteaTokenErr); err != nil {
    90  		return err
    91  	}
    92  
    93  	if gitlabToken != "" {
    94  		log.Debug("token type: gitlab")
    95  		ctx.TokenType = context.TokenTypeGitLab
    96  		ctx.Token = gitlabToken
    97  	}
    98  
    99  	if giteaToken != "" {
   100  		log.Debug("token type: gitea")
   101  		ctx.TokenType = context.TokenTypeGitea
   102  		ctx.Token = giteaToken
   103  	}
   104  
   105  	if githubToken != "" {
   106  		log.Debug("token type: github")
   107  		ctx.Token = githubToken
   108  	}
   109  
   110  	if ctx.TokenType == "" {
   111  		ctx.TokenType = context.TokenTypeGitHub
   112  	}
   113  
   114  	return nil
   115  }
   116  
   117  func checkErrors(ctx *context.Context, noTokens, noTokenErrs bool, gitlabTokenErr, githubTokenErr, giteaTokenErr error) error {
   118  	if ctx.SkipTokenCheck || ctx.SkipPublish || ctx.Config.Release.Disable {
   119  		return nil
   120  	}
   121  
   122  	if noTokens && noTokenErrs {
   123  		return ErrMissingToken
   124  	}
   125  
   126  	if gitlabTokenErr != nil {
   127  		return fmt.Errorf("failed to load gitlab token: %w", gitlabTokenErr)
   128  	}
   129  
   130  	if githubTokenErr != nil {
   131  		return fmt.Errorf("failed to load github token: %w", githubTokenErr)
   132  	}
   133  
   134  	if giteaTokenErr != nil {
   135  		return fmt.Errorf("failed to load gitea token: %w", giteaTokenErr)
   136  	}
   137  	return nil
   138  }
   139  
   140  func loadEnv(env, path string) (string, error) {
   141  	val := os.Getenv(env)
   142  	if val != "" {
   143  		return val, nil
   144  	}
   145  	path, err := homedir.Expand(path)
   146  	if err != nil {
   147  		return "", err
   148  	}
   149  	f, err := os.Open(path) // #nosec
   150  	if errors.Is(err, fs.ErrNotExist) {
   151  		return "", nil
   152  	}
   153  	if err != nil {
   154  		return "", err
   155  	}
   156  	defer f.Close()
   157  	bts, _, err := bufio.NewReader(f).ReadLine()
   158  	return string(bts), err
   159  }