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 }