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 }