github.com/ahmet2mir/goreleaser@v0.180.3-0.20210927151101-8e5ee5a9b8c5/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  	"os"
    10  	"strings"
    11  
    12  	"github.com/apex/log"
    13  	"github.com/goreleaser/goreleaser/internal/tmpl"
    14  	"github.com/goreleaser/goreleaser/pkg/context"
    15  	homedir "github.com/mitchellh/go-homedir"
    16  )
    17  
    18  // ErrMissingToken indicates an error when GITHUB_TOKEN, GITLAB_TOKEN and GITEA_TOKEN are all missing in the environment.
    19  var ErrMissingToken = errors.New("missing GITHUB_TOKEN, GITLAB_TOKEN and GITEA_TOKEN")
    20  
    21  // ErrMultipleTokens indicates that multiple tokens are defined. ATM only one of them if allowed.
    22  // See https://github.com/goreleaser/goreleaser/pull/809
    23  var ErrMultipleTokens = errors.New("multiple tokens defined. Only one is allowed")
    24  
    25  // Pipe for env.
    26  type Pipe struct{}
    27  
    28  func (Pipe) String() string {
    29  	return "loading environment variables"
    30  }
    31  
    32  func setDefaultTokenFiles(ctx *context.Context) {
    33  	env := &ctx.Config.EnvFiles
    34  	if env.GitHubToken == "" {
    35  		env.GitHubToken = "~/.config/goreleaser/github_token"
    36  	}
    37  	if env.GitLabToken == "" {
    38  		env.GitLabToken = "~/.config/goreleaser/gitlab_token"
    39  	}
    40  	if env.GiteaToken == "" {
    41  		env.GiteaToken = "~/.config/goreleaser/gitea_token"
    42  	}
    43  }
    44  
    45  // Run the pipe.
    46  func (Pipe) Run(ctx *context.Context) error {
    47  	templ := tmpl.New(ctx).WithEnvS(os.Environ())
    48  	for i := range ctx.Config.Env {
    49  		env, err := templ.Apply(ctx.Config.Env[i])
    50  		if err != nil {
    51  			return err
    52  		}
    53  		// XXX: this has no risk of panicking because it would already have
    54  		// panicked at `context.go`'s `splitEnv` method.
    55  		// Need to properly handle this at some point.
    56  		parts := strings.SplitN(env, "=", 2)
    57  		ctx.Env[parts[0]] = parts[1]
    58  	}
    59  
    60  	setDefaultTokenFiles(ctx)
    61  	githubToken, githubTokenErr := loadEnv("GITHUB_TOKEN", ctx.Config.EnvFiles.GitHubToken)
    62  	gitlabToken, gitlabTokenErr := loadEnv("GITLAB_TOKEN", ctx.Config.EnvFiles.GitLabToken)
    63  	giteaToken, giteaTokenErr := loadEnv("GITEA_TOKEN", ctx.Config.EnvFiles.GiteaToken)
    64  
    65  	numOfTokens := 0
    66  	if githubToken != "" {
    67  		numOfTokens++
    68  	}
    69  	if gitlabToken != "" {
    70  		numOfTokens++
    71  	}
    72  	if giteaToken != "" {
    73  		numOfTokens++
    74  	}
    75  	if numOfTokens > 1 {
    76  		return ErrMultipleTokens
    77  	}
    78  
    79  	noTokens := githubToken == "" && gitlabToken == "" && giteaToken == ""
    80  	noTokenErrs := githubTokenErr == nil && gitlabTokenErr == nil && giteaTokenErr == nil
    81  
    82  	if err := checkErrors(ctx, noTokens, noTokenErrs, gitlabTokenErr, githubTokenErr, giteaTokenErr); err != nil {
    83  		return err
    84  	}
    85  
    86  	if gitlabToken != "" {
    87  		log.Debug("token type: gitlab")
    88  		ctx.TokenType = context.TokenTypeGitLab
    89  		ctx.Token = gitlabToken
    90  	}
    91  
    92  	if giteaToken != "" {
    93  		log.Debug("token type: gitea")
    94  		ctx.TokenType = context.TokenTypeGitea
    95  		ctx.Token = giteaToken
    96  	}
    97  
    98  	if githubToken != "" {
    99  		log.Debug("token type: github")
   100  		ctx.Token = githubToken
   101  	}
   102  
   103  	if ctx.TokenType == "" {
   104  		ctx.TokenType = context.TokenTypeGitHub
   105  	}
   106  
   107  	return nil
   108  }
   109  
   110  func checkErrors(ctx *context.Context, noTokens, noTokenErrs bool, gitlabTokenErr, githubTokenErr, giteaTokenErr error) error {
   111  	if ctx.SkipTokenCheck || ctx.SkipPublish || ctx.Config.Release.Disable {
   112  		return nil
   113  	}
   114  
   115  	if noTokens && noTokenErrs {
   116  		return ErrMissingToken
   117  	}
   118  
   119  	if gitlabTokenErr != nil {
   120  		return fmt.Errorf("failed to load gitlab token: %w", gitlabTokenErr)
   121  	}
   122  
   123  	if githubTokenErr != nil {
   124  		return fmt.Errorf("failed to load github token: %w", githubTokenErr)
   125  	}
   126  
   127  	if giteaTokenErr != nil {
   128  		return fmt.Errorf("failed to load gitea token: %w", giteaTokenErr)
   129  	}
   130  	return nil
   131  }
   132  
   133  func loadEnv(env, path string) (string, error) {
   134  	val := os.Getenv(env)
   135  	if val != "" {
   136  		return val, nil
   137  	}
   138  	path, err := homedir.Expand(path)
   139  	if err != nil {
   140  		return "", err
   141  	}
   142  	f, err := os.Open(path) // #nosec
   143  	if os.IsNotExist(err) {
   144  		return "", nil
   145  	}
   146  	if err != nil {
   147  		return "", err
   148  	}
   149  	defer f.Close()
   150  	bts, _, err := bufio.NewReader(f).ReadLine()
   151  	return string(bts), err
   152  }