diff --git a/modules/context/context.go b/modules/context/context.go index 53e02b9..52621e6 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -9,7 +9,9 @@ import ( "log" "os" "path" + "strconv" "strings" + "time" "code.gitea.io/sdk/gitea" "code.gitea.io/tea/modules/config" @@ -20,9 +22,7 @@ import ( "github.com/urfave/cli/v3" ) -var ( - errNotAGiteaRepo = errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository") -) +var errNotAGiteaRepo = errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository") // TeaContext contains all context derived during command initialization and wraps cli.Context type TeaContext struct { @@ -125,6 +125,16 @@ func InitCommand(cmd *cli.Command) *TeaContext { c.RepoSlug = repoFlag } + // override config user with env variable + envLogin := GetLoginByEnvVar() + if envLogin != nil { + _, err := utils.ValidateAuthenticationMethod(envLogin.URL, envLogin.Token, "", "", false, "", "") + if err != nil { + log.Fatal(err.Error()) + } + c.Login = envLogin + } + // override login from flag, or use default login if repo based detection failed if len(loginFlag) != 0 { c.Login = config.GetLoginByName(loginFlag) @@ -230,3 +240,40 @@ func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.L return repo, nil, "", errNotAGiteaRepo } + +// GetLoginByEnvVar returns a login based on environment variables, or nil if no login can be created +func GetLoginByEnvVar() *config.Login { + var token string + + giteaToken := os.Getenv("GITEA_TOKEN") + githubToken := os.Getenv("GH_TOKEN") + giteaInstanceURL := os.Getenv("GITEA_INSTANCE_URL") + instanceInsecure := os.Getenv("GITEA_INSTANCE_INSECURE") + insecure := false + if len(instanceInsecure) > 0 { + insecure, _ = strconv.ParseBool(instanceInsecure) + } + + // if no tokens are set, or no instance url for gitea fail fast + if len(giteaInstanceURL) == 0 || (len(giteaToken) == 0 && len(githubToken) == 0) { + return nil + } + + token = giteaToken + if len(giteaToken) == 0 { + token = githubToken + } + + return &config.Login{ + Name: "GITEA_LOGIN_VIA_ENV", + URL: giteaInstanceURL, + Token: token, + Insecure: insecure, + SSHKey: "", + SSHCertPrincipal: "", + SSHKeyFingerprint: "", + SSHAgent: false, + Created: time.Now().Unix(), + VersionCheck: false, + } +} diff --git a/modules/task/login_create.go b/modules/task/login_create.go index a0aacc0..4da591d 100644 --- a/modules/task/login_create.go +++ b/modules/task/login_create.go @@ -63,21 +63,17 @@ func CreateLogin(name, token, user, passwd, otp, scopes, sshKey, giteaURL, sshCe return fmt.Errorf("token already been used, delete login '%s' first", login.Name) } - if !sshAgent && sshCertPrincipal == "" && sshKey == "" { - // .. if we have enough information to authenticate - if len(token) == 0 && (len(user)+len(passwd)) == 0 { - return fmt.Errorf("No token set") - } else if len(user) != 0 && len(passwd) == 0 { - return fmt.Errorf("No password set") - } else if len(user) == 0 && len(passwd) != 0 { - return fmt.Errorf("No user set") - } - } - - // Normalize URL - serverURL, err := utils.NormalizeURL(giteaURL) + serverURL, err := utils.ValidateAuthenticationMethod( + giteaURL, + token, + user, + passwd, + sshAgent, + sshKey, + sshCertPrincipal, + ) if err != nil { - return fmt.Errorf("Unable to parse URL: %s", err) + return err } // check if it's a certificate the principal doesn't matter as the user diff --git a/modules/utils/validate.go b/modules/utils/validate.go new file mode 100644 index 0000000..9924c2f --- /dev/null +++ b/modules/utils/validate.go @@ -0,0 +1,38 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package utils + +import ( + "fmt" + "net/url" +) + +// ValidateAuthenticationMethod checks the provided authentication method parameters +func ValidateAuthenticationMethod( + giteaURL string, + token string, + user string, + passwd string, + sshAgent bool, + sshKey string, + sshCertPrincipal string, +) (*url.URL, error) { + // Normalize URL + serverURL, err := NormalizeURL(giteaURL) + if err != nil { + return nil, fmt.Errorf("Unable to parse URL: %s", err) + } + + if !sshAgent && sshCertPrincipal == "" && sshKey == "" { + // .. if we have enough information to authenticate + if len(token) == 0 && (len(user)+len(passwd)) == 0 { + return nil, fmt.Errorf("No token set") + } else if len(user) != 0 && len(passwd) == 0 { + return nil, fmt.Errorf("No password set") + } else if len(user) == 0 && len(passwd) != 0 { + return nil, fmt.Errorf("No user set") + } + } + return serverURL, nil +}