You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02:00 
			
		
		
		
	Pass down context.Context (#371)
* pass context down to remote clients * make tests work * add ctx to Refresh() and use it * bitbucketserver * code format * plugin interface: add todo context * solve todo * RM TODO by using context.WithTimeout * refactor & fix * Apply suggestions from code review Co-authored-by: Anbraten <anton@ju60.de> * go fmt * Update server/remote/coding/coding.go Co-authored-by: Anbraten <anton@ju60.de> Co-authored-by: Anbraten <anton@ju60.de>
This commit is contained in:
		| @@ -333,9 +333,9 @@ func PostApproval(c *gin.Context) { | ||||
| 		for _, item := range buildItems { | ||||
| 			uri := fmt.Sprintf("%s/%s/%d", server.Config.Server.Host, repo.FullName, build.Number) | ||||
| 			if len(buildItems) > 1 { | ||||
| 				err = remote_.Status(user, repo, build, uri, item.Proc) | ||||
| 				err = remote_.Status(c, user, repo, build, uri, item.Proc) | ||||
| 			} else { | ||||
| 				err = remote_.Status(user, repo, build, uri, nil) | ||||
| 				err = remote_.Status(c, user, repo, build, uri, nil) | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err) | ||||
| @@ -373,7 +373,7 @@ func PostDecline(c *gin.Context) { | ||||
| 	} | ||||
|  | ||||
| 	uri := fmt.Sprintf("%s/%s/%d", server.Config.Server.Host, repo.FullName, build.Number) | ||||
| 	err = remote_.Status(user, repo, build, uri, nil) | ||||
| 	err = remote_.Status(c, user, repo, build, uri, nil) | ||||
| 	if err != nil { | ||||
| 		logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err) | ||||
| 	} | ||||
| @@ -426,7 +426,7 @@ func PostBuild(c *gin.Context) { | ||||
| 	// may be stale. Therefore, we should refresh prior to dispatching | ||||
| 	// the job. | ||||
| 	if refresher, ok := remote_.(remote.Refresher); ok { | ||||
| 		ok, _ := refresher.Refresh(user) | ||||
| 		ok, _ := refresher.Refresh(c, user) | ||||
| 		if ok { | ||||
| 			store.UpdateUser(c, user) | ||||
| 		} | ||||
|   | ||||
| @@ -155,7 +155,7 @@ func PostHook(c *gin.Context) { | ||||
| 	// may be stale. Therefore, we should refresh prior to dispatching | ||||
| 	// the build. | ||||
| 	if refresher, ok := remote_.(remote.Refresher); ok { | ||||
| 		ok, err := refresher.Refresh(user) | ||||
| 		ok, err := refresher.Refresh(c, user) | ||||
| 		if err != nil { | ||||
| 			logrus.Errorf("failed to refresh oauth2 token: %s", err) | ||||
| 		} else if ok { | ||||
| @@ -168,7 +168,7 @@ func PostHook(c *gin.Context) { | ||||
|  | ||||
| 	// fetch the build file from the remote | ||||
| 	configFetcher := shared.NewConfigFetcher(remote_, user, repo, build) | ||||
| 	remoteYamlConfigs, err := configFetcher.Fetch() | ||||
| 	remoteYamlConfigs, err := configFetcher.Fetch(c) | ||||
| 	if err != nil { | ||||
| 		logrus.Errorf("error: %s: cannot find %s in %s: %s", repo.FullName, repo.Config, build.Ref, err) | ||||
| 		c.AbortWithError(404, err) | ||||
| @@ -278,9 +278,9 @@ func PostHook(c *gin.Context) { | ||||
| 		for _, item := range buildItems { | ||||
| 			uri := fmt.Sprintf("%s/%s/%d", server.Config.Server.Host, repo.FullName, build.Number) | ||||
| 			if len(buildItems) > 1 { | ||||
| 				err = remote_.Status(user, repo, build, uri, item.Proc) | ||||
| 				err = remote_.Status(c, user, repo, build, uri, item.Proc) | ||||
| 			} else { | ||||
| 				err = remote_.Status(user, repo, build, uri, nil) | ||||
| 				err = remote_.Status(c, user, repo, build, uri, nil) | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err) | ||||
|   | ||||
| @@ -75,13 +75,13 @@ func PostRepo(c *gin.Context) { | ||||
| 		sig, | ||||
| 	) | ||||
|  | ||||
| 	err = r.Activate(user, repo, link) | ||||
| 	err = r.Activate(c, user, repo, link) | ||||
| 	if err != nil { | ||||
| 		c.String(500, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	from, err := r.Repo(user, repo.Owner, repo.Name) | ||||
| 	from, err := r.Repo(c, user, repo.Owner, repo.Name) | ||||
| 	if err == nil { | ||||
| 		repo.Update(from) | ||||
| 	} | ||||
| @@ -187,7 +187,10 @@ func DeleteRepo(c *gin.Context) { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	r.Deactivate(user, repo, server.Config.Server.Host) | ||||
| 	if err := r.Deactivate(c, user, repo, server.Config.Server.Host); err != nil { | ||||
| 		c.AbortWithError(http.StatusInternalServerError, err) | ||||
| 		return | ||||
| 	} | ||||
| 	c.JSON(200, repo) | ||||
| } | ||||
|  | ||||
| @@ -212,14 +215,14 @@ func RepairRepo(c *gin.Context) { | ||||
| 		sig, | ||||
| 	) | ||||
|  | ||||
| 	r.Deactivate(user, repo, host) | ||||
| 	err = r.Activate(user, repo, link) | ||||
| 	_ = r.Deactivate(c, user, repo, host) | ||||
| 	err = r.Activate(c, user, repo, link) | ||||
| 	if err != nil { | ||||
| 		c.String(500, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	from, err := r.Repo(user, repo.Owner, repo.Name) | ||||
| 	from, err := r.Repo(c, user, repo.Owner, repo.Name) | ||||
| 	if err == nil { | ||||
| 		repo.Name = from.Name | ||||
| 		repo.Owner = from.Owner | ||||
| @@ -255,7 +258,7 @@ func MoveRepo(c *gin.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	from, err := r.Repo(user, owner, name) | ||||
| 	from, err := r.Repo(c, user, owner, name) | ||||
| 	if err != nil { | ||||
| 		c.AbortWithError(http.StatusInternalServerError, err) | ||||
| 		return | ||||
| @@ -298,8 +301,9 @@ func MoveRepo(c *gin.Context) { | ||||
| 		sig, | ||||
| 	) | ||||
|  | ||||
| 	r.Deactivate(user, repo, host) | ||||
| 	err = r.Activate(user, repo, link) | ||||
| 	// TODO: check if we should handle that error | ||||
| 	r.Deactivate(c, user, repo, host) | ||||
| 	err = r.Activate(c, user, repo, link) | ||||
| 	if err != nil { | ||||
| 		c.String(500, err.Error()) | ||||
| 		return | ||||
|   | ||||
| @@ -54,7 +54,7 @@ func GetFeed(c *gin.Context) { | ||||
| 			Perms:  store.FromContext(c), | ||||
| 			Match:  shared.NamespaceFilter(config.OwnersWhitelist), | ||||
| 		} | ||||
| 		if err := sync.Sync(user); err != nil { | ||||
| 		if err := sync.Sync(c, user); err != nil { | ||||
| 			logrus.Debugf("sync error: %s: %s", user.Login, err) | ||||
| 		} else { | ||||
| 			logrus.Debugf("sync complete: %s", user.Login) | ||||
| @@ -100,7 +100,7 @@ func GetRepos(c *gin.Context) { | ||||
| 			Match:  shared.NamespaceFilter(config.OwnersWhitelist), | ||||
| 		} | ||||
|  | ||||
| 		if err := sync.Sync(user); err != nil { | ||||
| 		if err := sync.Sync(c, user); err != nil { | ||||
| 			logrus.Debugf("sync error: %s: %s", user.Login, err) | ||||
| 		} else { | ||||
| 			logrus.Debugf("sync complete: %s", user.Login) | ||||
|   | ||||
| @@ -338,12 +338,12 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error { | ||||
| 		} | ||||
|  | ||||
| 		if !isMultiPipeline(procs) { | ||||
| 			s.updateRemoteStatus(repo, build, nil) | ||||
| 			s.updateRemoteStatus(c, repo, build, nil) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if isMultiPipeline(procs) { | ||||
| 		s.updateRemoteStatus(repo, build, proc) | ||||
| 		s.updateRemoteStatus(c, repo, build, proc) | ||||
| 	} | ||||
|  | ||||
| 	if err := s.logger.Close(c, id); err != nil { | ||||
| @@ -416,17 +416,17 @@ func buildStatus(procs []*model.Proc) string { | ||||
| 	return status | ||||
| } | ||||
|  | ||||
| func (s *RPC) updateRemoteStatus(repo *model.Repo, build *model.Build, proc *model.Proc) { | ||||
| func (s *RPC) updateRemoteStatus(ctx context.Context, repo *model.Repo, build *model.Build, proc *model.Proc) { | ||||
| 	user, err := s.store.GetUser(repo.UserID) | ||||
| 	if err == nil { | ||||
| 		if refresher, ok := s.remote.(remote.Refresher); ok { | ||||
| 			ok, _ := refresher.Refresh(user) | ||||
| 			ok, _ := refresher.Refresh(ctx, user) | ||||
| 			if ok { | ||||
| 				s.store.UpdateUser(user) | ||||
| 			} | ||||
| 		} | ||||
| 		uri := fmt.Sprintf("%s/%s/%d", server.Config.Server.Host, repo.FullName, build.Number) | ||||
| 		err = s.remote.Status(user, repo, build, uri, proc) | ||||
| 		err = s.remote.Status(ctx, user, repo, build, uri, proc) | ||||
| 		if err != nil { | ||||
| 			logrus.Errorf("error setting commit status for %s/%d: %v", repo.FullName, build.Number, err) | ||||
| 		} | ||||
|   | ||||
| @@ -9,13 +9,13 @@ type builtin struct { | ||||
| 	globals []*model.Environ | ||||
| } | ||||
|  | ||||
| // New returns a new local registry service. | ||||
| // Filesystem returns a new local registry service. | ||||
| func Filesystem(params []string) model.EnvironService { | ||||
| 	var globals []*model.Environ | ||||
|  | ||||
| 	for _, item := range params { | ||||
| 		kvpair := strings.SplitN(item, ":", 2) | ||||
| 		globals = append(globals, &model.Environ{Name: kvpair[0], Value: kvpair[1]}) | ||||
| 		kvPair := strings.SplitN(item, ":", 2) | ||||
| 		globals = append(globals, &model.Environ{Name: kvPair[0], Value: kvPair[1]}) | ||||
| 	} | ||||
| 	return &builtin{globals} | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package internal | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| @@ -11,7 +12,7 @@ import ( | ||||
|  | ||||
| // Send makes an http request to the given endpoint, writing the input | ||||
| // to the request body and unmarshaling the output from the response body. | ||||
| func Send(method, path string, in, out interface{}) error { | ||||
| func Send(ctx context.Context, method, path string, in, out interface{}) error { | ||||
| 	uri, err := url.Parse(path) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -29,7 +30,7 @@ func Send(method, path string, in, out interface{}) error { | ||||
| 	} | ||||
|  | ||||
| 	// creates a new http request to bitbucket. | ||||
| 	req, err := http.NewRequest(method, uri.String(), buf) | ||||
| 	req, err := http.NewRequestWithContext(ctx, method, uri.String(), buf) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package sender | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/woodpecker-ci/woodpecker/server/model" | ||||
| @@ -22,7 +23,7 @@ func (p *plugin) SenderAllowed(user *model.User, repo *model.Repo, build *model. | ||||
| 		"build":  build, | ||||
| 		"config": conf, | ||||
| 	} | ||||
| 	err := internal.Send("POST", path, &data, nil) | ||||
| 	err := internal.Send(context.TODO(), "POST", path, &data, nil) | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
| @@ -31,21 +32,21 @@ func (p *plugin) SenderAllowed(user *model.User, repo *model.Repo, build *model. | ||||
|  | ||||
| func (p *plugin) SenderCreate(repo *model.Repo, sender *model.Sender) error { | ||||
| 	path := fmt.Sprintf("%s/senders/%s/%s", p.endpoint, repo.Owner, repo.Name) | ||||
| 	return internal.Send("POST", path, sender, nil) | ||||
| 	return internal.Send(context.TODO(), "POST", path, sender, nil) | ||||
| } | ||||
|  | ||||
| func (p *plugin) SenderUpdate(repo *model.Repo, sender *model.Sender) error { | ||||
| 	path := fmt.Sprintf("%s/senders/%s/%s", p.endpoint, repo.Owner, repo.Name) | ||||
| 	return internal.Send("PUT", path, sender, nil) | ||||
| 	return internal.Send(context.TODO(), "PUT", path, sender, nil) | ||||
| } | ||||
|  | ||||
| func (p *plugin) SenderDelete(repo *model.Repo, login string) error { | ||||
| 	path := fmt.Sprintf("%s/senders/%s/%s/%s", p.endpoint, repo.Owner, repo.Name, login) | ||||
| 	return internal.Send("DELETE", path, nil, nil) | ||||
| 	return internal.Send(context.TODO(), "DELETE", path, nil, nil) | ||||
| } | ||||
|  | ||||
| func (p *plugin) SenderList(repo *model.Repo) (out []*model.Sender, err error) { | ||||
| 	path := fmt.Sprintf("%s/senders/%s/%s", p.endpoint, repo.Owner, repo.Name) | ||||
| 	err = internal.Send("GET", path, nil, out) | ||||
| 	err = internal.Send(context.TODO(), "GET", path, nil, out) | ||||
| 	return out, err | ||||
| } | ||||
|   | ||||
| @@ -134,7 +134,7 @@ type Queue interface { | ||||
| 	// Push pushes a task to the tail of this queue. | ||||
| 	Push(c context.Context, task *Task) error | ||||
|  | ||||
| 	// Push pushes a task to the tail of this queue. | ||||
| 	// PushAtOnce pushes a task to the tail of this queue. | ||||
| 	PushAtOnce(c context.Context, tasks []*Task) error | ||||
|  | ||||
| 	// Poll retrieves and removes a task head of this queue. | ||||
| @@ -149,13 +149,13 @@ type Queue interface { | ||||
| 	// Error signals the task is complete with errors. | ||||
| 	Error(c context.Context, id string, err error) error | ||||
|  | ||||
| 	// Error signals the task is complete with errors. | ||||
| 	// ErrorAtOnce signals the task is complete with errors. | ||||
| 	ErrorAtOnce(c context.Context, id []string, err error) error | ||||
|  | ||||
| 	// Evict removes a pending task from the queue. | ||||
| 	Evict(c context.Context, id string) error | ||||
|  | ||||
| 	// Evict removes a pending task from the queue. | ||||
| 	// EvictAtOnce removes a pending task from the queue. | ||||
| 	EvictAtOnce(c context.Context, id []string) error | ||||
|  | ||||
| 	// Wait waits until the task is complete. | ||||
| @@ -164,9 +164,9 @@ type Queue interface { | ||||
| 	// Info returns internal queue information. | ||||
| 	Info(c context.Context) InfoT | ||||
|  | ||||
| 	// Stops the queue from handing out new work items in Poll | ||||
| 	// Pause stops the queue from handing out new work items in Poll | ||||
| 	Pause() | ||||
|  | ||||
| 	// Starts the queue again, Poll returns new items | ||||
| 	// Resume starts the queue again, Poll returns new items | ||||
| 	Resume() | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package bitbucket | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| @@ -53,7 +54,7 @@ func New(client, secret string) remote.Remote { | ||||
|  | ||||
| // Login authenticates an account with Bitbucket using the oauth2 protocol. The | ||||
| // Bitbucket account details are returned when the user is successfully authenticated. | ||||
| func (c *config) Login(w http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (c *config) Login(ctx context.Context, w http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| 	config := c.newConfig(server.Config.Server.Host) | ||||
|  | ||||
| 	// get the OAuth errors | ||||
| @@ -72,12 +73,12 @@ func (c *config) Login(w http.ResponseWriter, req *http.Request) (*model.User, e | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	token, err := config.Exchange(oauth2.NoContext, code) | ||||
| 	token, err := config.Exchange(ctx, code) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	client := internal.NewClient(c.API, config.Client(oauth2.NoContext, token)) | ||||
| 	client := internal.NewClient(ctx, c.API, config.Client(ctx, token)) | ||||
| 	curr, err := client.FindCurrent() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -87,8 +88,8 @@ func (c *config) Login(w http.ResponseWriter, req *http.Request) (*model.User, e | ||||
|  | ||||
| // Auth uses the Bitbucket oauth2 access token and refresh token to authenticate | ||||
| // a session and return the Bitbucket account login. | ||||
| func (c *config) Auth(token, secret string) (string, error) { | ||||
| 	client := c.newClientToken(token, secret) | ||||
| func (c *config) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	client := c.newClientToken(ctx, token, secret) | ||||
| 	user, err := client.FindCurrent() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| @@ -98,10 +99,10 @@ func (c *config) Auth(token, secret string) (string, error) { | ||||
|  | ||||
| // Refresh refreshes the Bitbucket oauth2 access token. If the token is | ||||
| // refreshed the user is updated and a true value is returned. | ||||
| func (c *config) Refresh(user *model.User) (bool, error) { | ||||
| func (c *config) Refresh(ctx context.Context, user *model.User) (bool, error) { | ||||
| 	config := c.newConfig("") | ||||
| 	source := config.TokenSource( | ||||
| 		oauth2.NoContext, &oauth2.Token{RefreshToken: user.Secret}) | ||||
| 		ctx, &oauth2.Token{RefreshToken: user.Secret}) | ||||
|  | ||||
| 	token, err := source.Token() | ||||
| 	if err != nil || len(token.AccessToken) == 0 { | ||||
| @@ -115,12 +116,12 @@ func (c *config) Refresh(user *model.User) (bool, error) { | ||||
| } | ||||
|  | ||||
| // Teams returns a list of all team membership for the Bitbucket account. | ||||
| func (c *config) Teams(u *model.User) ([]*model.Team, error) { | ||||
| func (c *config) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	opts := &internal.ListTeamOpts{ | ||||
| 		PageLen: 100, | ||||
| 		Role:    "member", | ||||
| 	} | ||||
| 	resp, err := c.newClient(u).ListTeams(opts) | ||||
| 	resp, err := c.newClient(ctx, u).ListTeams(opts) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -128,8 +129,8 @@ func (c *config) Teams(u *model.User) ([]*model.Team, error) { | ||||
| } | ||||
|  | ||||
| // Repo returns the named Bitbucket repository. | ||||
| func (c *config) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	repo, err := c.newClient(u).FindRepo(owner, name) | ||||
| func (c *config) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	repo, err := c.newClient(ctx, u).FindRepo(owner, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -138,8 +139,8 @@ func (c *config) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
|  | ||||
| // Repos returns a list of all repositories for Bitbucket account, including | ||||
| // organization repositories. | ||||
| func (c *config) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| 	client := c.newClient(u) | ||||
| func (c *config) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	client := c.newClient(ctx, u) | ||||
|  | ||||
| 	var all []*model.Repo | ||||
|  | ||||
| @@ -171,8 +172,8 @@ func (c *config) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| // does not have an endpoint to access user permissions, we attempt to fetch | ||||
| // the repository hook list, which is restricted to administrators to calculate | ||||
| // administrative access to a repository. | ||||
| func (c *config) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| 	client := c.newClient(u) | ||||
| func (c *config) Perm(ctx context.Context, u *model.User, owner, name string) (*model.Perm, error) { | ||||
| 	client := c.newClient(ctx, u) | ||||
|  | ||||
| 	perms := new(model.Perm) | ||||
| 	repo, err := client.FindRepo(owner, name) | ||||
| @@ -200,40 +201,40 @@ func (c *config) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // File fetches the file from the Bitbucket repository and returns its contents. | ||||
| func (c *config) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	config, err := c.newClient(u).FindSource(r.Owner, r.Name, b.Commit, f) | ||||
| func (c *config) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	config, err := c.newClient(ctx, u).FindSource(r.Owner, r.Name, b.Commit, f) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return []byte(*config), err | ||||
| } | ||||
|  | ||||
| func (c *config) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| func (c *config) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	return nil, fmt.Errorf("Not implemented") | ||||
| } | ||||
|  | ||||
| // Status creates a build status for the Bitbucket commit. | ||||
| func (c *config) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| func (c *config) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	status := internal.BuildStatus{ | ||||
| 		State: convertStatus(b.Status), | ||||
| 		Desc:  convertDesc(b.Status), | ||||
| 		Key:   "Drone", | ||||
| 		Url:   link, | ||||
| 	} | ||||
| 	return c.newClient(u).CreateStatus(r.Owner, r.Name, b.Commit, &status) | ||||
| 	return c.newClient(ctx, u).CreateStatus(r.Owner, r.Name, b.Commit, &status) | ||||
| } | ||||
|  | ||||
| // Activate activates the repository by registering repository push hooks with | ||||
| // the Bitbucket repository. Prior to registering hook, previously created hooks | ||||
| // are deleted. | ||||
| func (c *config) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| func (c *config) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	rawurl, err := url.Parse(link) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	c.Deactivate(u, r, link) | ||||
| 	c.Deactivate(ctx, u, r, link) | ||||
|  | ||||
| 	return c.newClient(u).CreateHook(r.Owner, r.Name, &internal.Hook{ | ||||
| 	return c.newClient(ctx, u).CreateHook(r.Owner, r.Name, &internal.Hook{ | ||||
| 		Active: true, | ||||
| 		Desc:   rawurl.Host, | ||||
| 		Events: []string{"repo:push"}, | ||||
| @@ -243,8 +244,8 @@ func (c *config) Activate(u *model.User, r *model.Repo, link string) error { | ||||
|  | ||||
| // Deactivate deactives the repository be removing repository push hooks from | ||||
| // the Bitbucket repository. | ||||
| func (c *config) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
| 	client := c.newClient(u) | ||||
| func (c *config) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	client := c.newClient(ctx, u) | ||||
|  | ||||
| 	hooks, err := client.ListHooks(r.Owner, r.Name, &internal.ListOpts{}) | ||||
| 	if err != nil { | ||||
| @@ -274,13 +275,14 @@ func (c *config) Hook(req *http.Request) (*model.Repo, *model.Build, error) { | ||||
| } | ||||
|  | ||||
| // helper function to return the bitbucket oauth2 client | ||||
| func (c *config) newClient(u *model.User) *internal.Client { | ||||
| 	return c.newClientToken(u.Token, u.Secret) | ||||
| func (c *config) newClient(ctx context.Context, u *model.User) *internal.Client { | ||||
| 	return c.newClientToken(ctx, u.Token, u.Secret) | ||||
| } | ||||
|  | ||||
| // helper function to return the bitbucket oauth2 client | ||||
| func (c *config) newClientToken(token, secret string) *internal.Client { | ||||
| func (c *config) newClientToken(ctx context.Context, token, secret string) *internal.Client { | ||||
| 	return internal.NewClientToken( | ||||
| 		ctx, | ||||
| 		c.API, | ||||
| 		c.Client, | ||||
| 		c.Secret, | ||||
|   | ||||
| @@ -16,6 +16,7 @@ package bitbucket | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
| @@ -35,6 +36,7 @@ func Test_bitbucket(t *testing.T) { | ||||
| 	c := &config{URL: s.URL, API: s.URL} | ||||
|  | ||||
| 	g := goblin.Goblin(t) | ||||
| 	ctx := context.Background() | ||||
| 	g.Describe("Bitbucket client", func() { | ||||
|  | ||||
| 		g.After(func() { | ||||
| @@ -61,13 +63,13 @@ func Test_bitbucket(t *testing.T) { | ||||
| 			g.It("Should redirect to authorize", func() { | ||||
| 				w := httptest.NewRecorder() | ||||
| 				r, _ := http.NewRequest("GET", "", nil) | ||||
| 				_, err := c.Login(w, r) | ||||
| 				_, err := c.Login(ctx, w, r) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(w.Code).Equal(http.StatusSeeOther) | ||||
| 			}) | ||||
| 			g.It("Should return authenticated user", func() { | ||||
| 				r, _ := http.NewRequest("GET", "?code=code", nil) | ||||
| 				u, err := c.Login(nil, r) | ||||
| 				u, err := c.Login(ctx, nil, r) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(u.Login).Equal(fakeUser.Login) | ||||
| 				g.Assert(u.Token).Equal("2YotnFZFEjr1zCsicMWpAA") | ||||
| @@ -76,54 +78,48 @@ func Test_bitbucket(t *testing.T) { | ||||
| 			g.It("Should handle failure to exchange code", func() { | ||||
| 				w := httptest.NewRecorder() | ||||
| 				r, _ := http.NewRequest("GET", "?code=code_bad_request", nil) | ||||
| 				_, err := c.Login(w, r) | ||||
| 				_, err := c.Login(ctx, w, r) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should handle failure to resolve user", func() { | ||||
| 				r, _ := http.NewRequest("GET", "?code=code_user_not_found", nil) | ||||
| 				_, err := c.Login(nil, r) | ||||
| 				_, err := c.Login(ctx, nil, r) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should handle authentication errors", func() { | ||||
| 				r, _ := http.NewRequest("GET", "?error=invalid_scope", nil) | ||||
| 				_, err := c.Login(nil, r) | ||||
| 				_, err := c.Login(ctx, nil, r) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Given an access token", func() { | ||||
| 			g.It("Should return the authenticated user", func() { | ||||
| 				login, err := c.Auth( | ||||
| 					fakeUser.Token, | ||||
| 					fakeUser.Secret, | ||||
| 				) | ||||
| 				login, err := c.Auth(ctx, fakeUser.Token, fakeUser.Secret) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(login).Equal(fakeUser.Login) | ||||
| 			}) | ||||
| 			g.It("Should handle a failure to resolve user", func() { | ||||
| 				_, err := c.Auth( | ||||
| 					fakeUserNotFound.Token, | ||||
| 					fakeUserNotFound.Secret, | ||||
| 				) | ||||
| 				_, err := c.Auth(ctx, fakeUserNotFound.Token, fakeUserNotFound.Secret) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Given a refresh token", func() { | ||||
| 			g.It("Should return a refresh access token", func() { | ||||
| 				ok, err := c.Refresh(fakeUserRefresh) | ||||
| 				ok, err := c.Refresh(ctx, fakeUserRefresh) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(ok).IsTrue() | ||||
| 				g.Assert(fakeUserRefresh.Token).Equal("2YotnFZFEjr1zCsicMWpAA") | ||||
| 				g.Assert(fakeUserRefresh.Secret).Equal("tGzv3JOkF0XG5Qx2TlKWIA") | ||||
| 			}) | ||||
| 			g.It("Should handle an empty access token", func() { | ||||
| 				ok, err := c.Refresh(fakeUserRefreshEmpty) | ||||
| 				ok, err := c.Refresh(ctx, fakeUserRefreshEmpty) | ||||
| 				g.Assert(err == nil).IsFalse() | ||||
| 				g.Assert(ok).IsFalse() | ||||
| 			}) | ||||
| 			g.It("Should handle a failure to refresh", func() { | ||||
| 				ok, err := c.Refresh(fakeUserRefreshFail) | ||||
| 				ok, err := c.Refresh(ctx, fakeUserRefreshFail) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 				g.Assert(ok).IsFalse() | ||||
| 			}) | ||||
| @@ -131,61 +127,37 @@ func Test_bitbucket(t *testing.T) { | ||||
|  | ||||
| 		g.Describe("When requesting a repository", func() { | ||||
| 			g.It("Should return the details", func() { | ||||
| 				repo, err := c.Repo( | ||||
| 					fakeUser, | ||||
| 					fakeRepo.Owner, | ||||
| 					fakeRepo.Name, | ||||
| 				) | ||||
| 				repo, err := c.Repo(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repo.FullName).Equal(fakeRepo.FullName) | ||||
| 			}) | ||||
| 			g.It("Should handle not found errors", func() { | ||||
| 				_, err := c.Repo( | ||||
| 					fakeUser, | ||||
| 					fakeRepoNotFound.Owner, | ||||
| 					fakeRepoNotFound.Name, | ||||
| 				) | ||||
| 				_, err := c.Repo(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When requesting repository permissions", func() { | ||||
| 			g.It("Should handle not found errors", func() { | ||||
| 				_, err := c.Perm( | ||||
| 					fakeUser, | ||||
| 					fakeRepoNotFound.Owner, | ||||
| 					fakeRepoNotFound.Name, | ||||
| 				) | ||||
| 				_, err := c.Perm(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should authorize read access", func() { | ||||
| 				perm, err := c.Perm( | ||||
| 					fakeUser, | ||||
| 					fakeRepoReadOnly.Owner, | ||||
| 					fakeRepoReadOnly.Name, | ||||
| 				) | ||||
| 				perm, err := c.Perm(ctx, fakeUser, fakeRepoReadOnly.Owner, fakeRepoReadOnly.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 				g.Assert(perm.Push).IsFalse() | ||||
| 				g.Assert(perm.Admin).IsFalse() | ||||
| 			}) | ||||
| 			g.It("Should authorize write access", func() { | ||||
| 				perm, err := c.Perm( | ||||
| 					fakeUser, | ||||
| 					fakeRepoWriteOnly.Owner, | ||||
| 					fakeRepoWriteOnly.Name, | ||||
| 				) | ||||
| 				perm, err := c.Perm(ctx, fakeUser, fakeRepoWriteOnly.Owner, fakeRepoWriteOnly.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| 				g.Assert(perm.Admin).IsFalse() | ||||
| 			}) | ||||
| 			g.It("Should authorize admin access", func() { | ||||
| 				perm, err := c.Perm( | ||||
| 					fakeUser, | ||||
| 					fakeRepoAdmin.Owner, | ||||
| 					fakeRepoAdmin.Name, | ||||
| 				) | ||||
| 				perm, err := c.Perm(ctx, fakeUser, fakeRepoAdmin.Owner, fakeRepoAdmin.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| @@ -195,67 +167,67 @@ func Test_bitbucket(t *testing.T) { | ||||
|  | ||||
| 		g.Describe("When requesting user repositories", func() { | ||||
| 			g.It("Should return the details", func() { | ||||
| 				repos, err := c.Repos(fakeUser) | ||||
| 				repos, err := c.Repos(ctx, fakeUser) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repos[0].FullName).Equal(fakeRepo.FullName) | ||||
| 			}) | ||||
| 			g.It("Should handle organization not found errors", func() { | ||||
| 				_, err := c.Repos(fakeUserNoTeams) | ||||
| 				_, err := c.Repos(ctx, fakeUserNoTeams) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should handle not found errors", func() { | ||||
| 				_, err := c.Repos(fakeUserNoRepos) | ||||
| 				_, err := c.Repos(ctx, fakeUserNoRepos) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When requesting user teams", func() { | ||||
| 			g.It("Should return the details", func() { | ||||
| 				teams, err := c.Teams(fakeUser) | ||||
| 				teams, err := c.Teams(ctx, fakeUser) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(teams[0].Login).Equal("superfriends") | ||||
| 				g.Assert(teams[0].Avatar).Equal("http://i.imgur.com/ZygP55A.jpg") | ||||
| 			}) | ||||
| 			g.It("Should handle not found error", func() { | ||||
| 				_, err := c.Teams(fakeUserNoTeams) | ||||
| 				_, err := c.Teams(ctx, fakeUserNoTeams) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When downloading a file", func() { | ||||
| 			g.It("Should return the bytes", func() { | ||||
| 				raw, err := c.File(fakeUser, fakeRepo, fakeBuild, "file") | ||||
| 				raw, err := c.File(ctx, fakeUser, fakeRepo, fakeBuild, "file") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(len(raw) != 0).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should handle not found error", func() { | ||||
| 				_, err := c.File(fakeUser, fakeRepo, fakeBuild, "file_not_found") | ||||
| 				_, err := c.File(ctx, fakeUser, fakeRepo, fakeBuild, "file_not_found") | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When activating a repository", func() { | ||||
| 			g.It("Should error when malformed hook", func() { | ||||
| 				err := c.Activate(fakeUser, fakeRepo, "%gh&%ij") | ||||
| 				err := c.Activate(ctx, fakeUser, fakeRepo, "%gh&%ij") | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should create the hook", func() { | ||||
| 				err := c.Activate(fakeUser, fakeRepo, "http://127.0.0.1") | ||||
| 				err := c.Activate(ctx, fakeUser, fakeRepo, "http://127.0.0.1") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When deactivating a repository", func() { | ||||
| 			g.It("Should error when listing hooks fails", func() { | ||||
| 				err := c.Deactivate(fakeUser, fakeRepoNoHooks, "http://127.0.0.1") | ||||
| 				err := c.Deactivate(ctx, fakeUser, fakeRepoNoHooks, "http://127.0.0.1") | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should successfully remove hooks", func() { | ||||
| 				err := c.Deactivate(fakeUser, fakeRepo, "http://127.0.0.1") | ||||
| 				err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://127.0.0.1") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should successfully deactivate when hook already removed", func() { | ||||
| 				err := c.Deactivate(fakeUser, fakeRepoEmptyHook, "http://127.0.0.1") | ||||
| 				err := c.Deactivate(ctx, fakeUser, fakeRepoEmptyHook, "http://127.0.0.1") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
| @@ -283,7 +255,7 @@ func Test_bitbucket(t *testing.T) { | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should update the status", func() { | ||||
| 			err := c.Status(fakeUser, fakeRepo, fakeBuild, "http://127.0.0.1", nil) | ||||
| 			err := c.Status(ctx, fakeUser, fakeRepo, fakeBuild, "http://127.0.0.1", nil) | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 		}) | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,7 @@ package internal | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @@ -50,19 +51,24 @@ const ( | ||||
| type Client struct { | ||||
| 	*http.Client | ||||
| 	base string | ||||
| 	ctx  context.Context | ||||
| } | ||||
|  | ||||
| func NewClient(url string, client *http.Client) *Client { | ||||
| 	return &Client{client, url} | ||||
| func NewClient(ctx context.Context, url string, client *http.Client) *Client { | ||||
| 	return &Client{ | ||||
| 		Client: client, | ||||
| 		base:   url, | ||||
| 		ctx:    ctx, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func NewClientToken(url, client, secret string, token *oauth2.Token) *Client { | ||||
| func NewClientToken(ctx context.Context, url, client, secret string, token *oauth2.Token) *Client { | ||||
| 	config := &oauth2.Config{ | ||||
| 		ClientID:     client, | ||||
| 		ClientSecret: secret, | ||||
| 		Endpoint:     bitbucket.Endpoint, | ||||
| 	} | ||||
| 	return NewClient(url, config.Client(oauth2.NoContext, token)) | ||||
| 	return NewClient(ctx, url, config.Client(ctx, token)) | ||||
| } | ||||
|  | ||||
| func (c *Client) FindCurrent() (*Account, error) { | ||||
| @@ -172,7 +178,6 @@ func (c *Client) GetPermission(fullName string) (*RepoPerm, error) { | ||||
| } | ||||
|  | ||||
| func (c *Client) do(rawurl, method string, in, out interface{}) (*string, error) { | ||||
|  | ||||
| 	uri, err := url.Parse(rawurl) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -190,7 +195,7 @@ func (c *Client) do(rawurl, method string, in, out interface{}) (*string, error) | ||||
| 	} | ||||
|  | ||||
| 	// creates a new http request to bitbucket. | ||||
| 	req, err := http.NewRequest(method, uri.String(), buf) | ||||
| 	req, err := http.NewRequestWithContext(c.ctx, method, uri.String(), buf) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|   | ||||
| @@ -18,6 +18,7 @@ package bitbucketserver | ||||
| // quality or security standards expected of this project. Please use with caution. | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/tls" | ||||
| 	"crypto/x509" | ||||
| @@ -103,7 +104,7 @@ func New(opts Opts) (remote.Remote, error) { | ||||
| 	return config, nil | ||||
| } | ||||
|  | ||||
| func (c *Config) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (c *Config) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| 	requestToken, u, err := c.Consumer.GetRequestTokenAndUrl("oob") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -119,7 +120,7 @@ func (c *Config) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	client := internal.NewClientWithToken(c.URL, c.Consumer, accessToken.Token) | ||||
| 	client := internal.NewClientWithToken(ctx, c.URL, c.Consumer, accessToken.Token) | ||||
|  | ||||
| 	user, err := client.FindCurrentUser() | ||||
| 	if err != nil { | ||||
| @@ -131,12 +132,12 @@ func (c *Config) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| } | ||||
|  | ||||
| // Auth is not supported by the Stash driver. | ||||
| func (*Config) Auth(token, secret string) (string, error) { | ||||
| func (*Config) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	return "", fmt.Errorf("Not Implemented") | ||||
| } | ||||
|  | ||||
| // Teams is not supported by the Stash driver. | ||||
| func (*Config) Teams(u *model.User) ([]*model.Team, error) { | ||||
| func (*Config) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	var teams []*model.Team | ||||
| 	return teams, nil | ||||
| } | ||||
| @@ -146,16 +147,16 @@ func (*Config) TeamPerm(u *model.User, org string) (*model.Perm, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (c *Config) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	repo, err := internal.NewClientWithToken(c.URL, c.Consumer, u.Token).FindRepo(owner, name) | ||||
| func (c *Config) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	repo, err := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token).FindRepo(owner, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return convertRepo(repo), nil | ||||
| } | ||||
|  | ||||
| func (c *Config) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| 	repos, err := internal.NewClientWithToken(c.URL, c.Consumer, u.Token).FindRepos() | ||||
| func (c *Config) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	repos, err := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token).FindRepos() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -167,24 +168,24 @@ func (c *Config) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| 	return all, nil | ||||
| } | ||||
|  | ||||
| func (c *Config) Perm(u *model.User, owner, repo string) (*model.Perm, error) { | ||||
| 	client := internal.NewClientWithToken(c.URL, c.Consumer, u.Token) | ||||
| func (c *Config) Perm(ctx context.Context, u *model.User, owner, repo string) (*model.Perm, error) { | ||||
| 	client := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token) | ||||
|  | ||||
| 	return client.FindRepoPerms(owner, repo) | ||||
| } | ||||
|  | ||||
| func (c *Config) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	client := internal.NewClientWithToken(c.URL, c.Consumer, u.Token) | ||||
| func (c *Config) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	client := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token) | ||||
|  | ||||
| 	return client.FindFileForRepo(r.Owner, r.Name, f, b.Ref) | ||||
| } | ||||
|  | ||||
| func (c *Config) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| func (c *Config) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	return nil, fmt.Errorf("Not implemented") | ||||
| } | ||||
|  | ||||
| // Status is not supported by the bitbucketserver driver. | ||||
| func (c *Config) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| func (c *Config) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	status := internal.BuildStatus{ | ||||
| 		State: convertStatus(b.Status), | ||||
| 		Desc:  convertDesc(b.Status), | ||||
| @@ -193,7 +194,7 @@ func (c *Config) Status(u *model.User, r *model.Repo, b *model.Build, link strin | ||||
| 		Url:   link, | ||||
| 	} | ||||
|  | ||||
| 	client := internal.NewClientWithToken(c.URL, c.Consumer, u.Token) | ||||
| 	client := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token) | ||||
|  | ||||
| 	return client.CreateStatus(b.Commit, &status) | ||||
| } | ||||
| @@ -217,14 +218,14 @@ func (c *Config) Netrc(user *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (c *Config) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| 	client := internal.NewClientWithToken(c.URL, c.Consumer, u.Token) | ||||
| func (c *Config) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	client := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token) | ||||
|  | ||||
| 	return client.CreateHook(r.Owner, r.Name, link) | ||||
| } | ||||
|  | ||||
| func (c *Config) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
| 	client := internal.NewClientWithToken(c.URL, c.Consumer, u.Token) | ||||
| func (c *Config) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	client := internal.NewClientWithToken(ctx, c.URL, c.Consumer, u.Token) | ||||
| 	return client.DeleteHook(r.Owner, r.Name, link) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,7 @@ package internal | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @@ -48,20 +49,27 @@ type Client struct { | ||||
| 	client      *http.Client | ||||
| 	base        string | ||||
| 	accessToken string | ||||
| 	ctx         context.Context | ||||
| } | ||||
|  | ||||
| func NewClientWithToken(url string, consumer *oauth.Consumer, AccessToken string) *Client { | ||||
| func NewClientWithToken(ctx context.Context, url string, consumer *oauth.Consumer, AccessToken string) *Client { | ||||
| 	var token oauth.AccessToken | ||||
| 	token.Token = AccessToken | ||||
| 	client, err := consumer.MakeHttpClient(&token) | ||||
| 	if err != nil { | ||||
| 		log.Error(err) | ||||
| 	} | ||||
| 	return &Client{client, url, AccessToken} | ||||
|  | ||||
| 	return &Client{ | ||||
| 		client:      client, | ||||
| 		base:        url, | ||||
| 		accessToken: AccessToken, | ||||
| 		ctx:         ctx, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *Client) FindCurrentUser() (*User, error) { | ||||
| 	CurrentUserIdResponse, err := c.client.Get(fmt.Sprintf(currentUserId, c.base)) | ||||
| 	CurrentUserIdResponse, err := c.doGet(fmt.Sprintf(currentUserId, c.base)) | ||||
| 	if CurrentUserIdResponse != nil { | ||||
| 		defer CurrentUserIdResponse.Body.Close() | ||||
| 	} | ||||
| @@ -75,7 +83,7 @@ func (c *Client) FindCurrentUser() (*User, error) { | ||||
| 	} | ||||
| 	login := string(bits) | ||||
|  | ||||
| 	CurrentUserResponse, err := c.client.Get(fmt.Sprintf(pathUser, c.base, login)) | ||||
| 	CurrentUserResponse, err := c.doGet(fmt.Sprintf(pathUser, c.base, login)) | ||||
| 	if CurrentUserResponse != nil { | ||||
| 		defer CurrentUserResponse.Body.Close() | ||||
| 	} | ||||
| @@ -100,7 +108,7 @@ func (c *Client) FindCurrentUser() (*User, error) { | ||||
|  | ||||
| func (c *Client) FindRepo(owner string, name string) (*Repo, error) { | ||||
| 	urlString := fmt.Sprintf(pathRepo, c.base, owner, name) | ||||
| 	response, err := c.client.Get(urlString) | ||||
| 	response, err := c.doGet(urlString) | ||||
| 	if response != nil { | ||||
| 		defer response.Body.Close() | ||||
| 	} | ||||
| @@ -128,7 +136,7 @@ func (c *Client) FindRepoPerms(owner string, repo string) (*model.Perm, error) { | ||||
| 		return perms, err | ||||
| 	} | ||||
| 	// Must have admin to be able to list hooks. If have access the enable perms | ||||
| 	resp, err := c.client.Get(fmt.Sprintf(pathHook, c.base, owner, repo, hookName)) | ||||
| 	resp, err := c.doGet(fmt.Sprintf(pathHook, c.base, owner, repo, hookName)) | ||||
| 	if resp != nil { | ||||
| 		defer resp.Body.Close() | ||||
| 	} | ||||
| @@ -141,7 +149,7 @@ func (c *Client) FindRepoPerms(owner string, repo string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| func (c *Client) FindFileForRepo(owner string, repo string, fileName string, ref string) ([]byte, error) { | ||||
| 	response, err := c.client.Get(fmt.Sprintf(pathSource, c.base, owner, repo, fileName, ref)) | ||||
| 	response, err := c.doGet(fmt.Sprintf(pathSource, c.base, owner, repo, fileName, ref)) | ||||
| 	if response != nil { | ||||
| 		defer response.Body.Close() | ||||
| 	} | ||||
| @@ -203,7 +211,7 @@ func (c *Client) DeleteHook(owner string, name string, link string) error { | ||||
|  | ||||
| func (c *Client) GetHookDetails(owner string, name string) (*HookPluginDetails, error) { | ||||
| 	urlString := fmt.Sprintf(pathHookDetails, c.base, owner, name, hookName) | ||||
| 	response, err := c.client.Get(urlString) | ||||
| 	response, err := c.doGet(urlString) | ||||
| 	if response != nil { | ||||
| 		defer response.Body.Close() | ||||
| 	} | ||||
| @@ -218,7 +226,7 @@ func (c *Client) GetHookDetails(owner string, name string) (*HookPluginDetails, | ||||
|  | ||||
| func (c *Client) GetHooks(owner string, name string) (*HookSettings, error) { | ||||
| 	urlString := fmt.Sprintf(pathHookSettings, c.base, owner, name, hookName) | ||||
| 	response, err := c.client.Get(urlString) | ||||
| 	response, err := c.doGet(urlString) | ||||
| 	if response != nil { | ||||
| 		defer response.Body.Close() | ||||
| 	} | ||||
| @@ -233,9 +241,22 @@ func (c *Client) GetHooks(owner string, name string) (*HookSettings, error) { | ||||
|  | ||||
| //TODO: make these as as general do with the action | ||||
|  | ||||
| //Helper function to help create get | ||||
| func (c *Client) doGet(url string) (*http.Response, error) { | ||||
| 	request, err := http.NewRequestWithContext(c.ctx, "GET", url, nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	request.Header.Add("Content-Type", "application/json") | ||||
| 	return c.client.Do(request) | ||||
| } | ||||
|  | ||||
| //Helper function to help create the hook | ||||
| func (c *Client) doPut(url string, body []byte) error { | ||||
| 	request, err := http.NewRequest("PUT", url, bytes.NewBuffer(body)) | ||||
| 	request, err := http.NewRequestWithContext(c.ctx, "PUT", url, bytes.NewBuffer(body)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	request.Header.Add("Content-Type", "application/json") | ||||
| 	response, err := c.client.Do(request) | ||||
| 	if response != nil { | ||||
| @@ -258,7 +279,10 @@ func (c *Client) doPost(url string, status *BuildStatus) error { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	request, err := http.NewRequest("POST", url, buf) | ||||
| 	request, err := http.NewRequestWithContext(c.ctx, "POST", url, buf) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	request.Header.Add("Content-Type", "application/json") | ||||
| 	response, err := c.client.Do(request) | ||||
| 	if response != nil { | ||||
| @@ -269,7 +293,10 @@ func (c *Client) doPost(url string, status *BuildStatus) error { | ||||
|  | ||||
| //Helper function to do delete on the hook | ||||
| func (c *Client) doDelete(url string) error { | ||||
| 	request, err := http.NewRequest("DELETE", url, nil) | ||||
| 	request, err := http.NewRequestWithContext(c.ctx, "DELETE", url, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	response, err := c.client.Do(request) | ||||
| 	if response != nil { | ||||
| 		defer response.Body.Close() | ||||
| @@ -281,7 +308,7 @@ func (c *Client) doDelete(url string) error { | ||||
| func (c *Client) paginatedRepos(start int) ([]*Repo, error) { | ||||
| 	limit := 1000 | ||||
| 	requestUrl := fmt.Sprintf(pathRepos, c.base, strconv.Itoa(start), strconv.Itoa(limit)) | ||||
| 	response, err := c.client.Get(requestUrl) | ||||
| 	response, err := c.doGet(requestUrl) | ||||
| 	if response != nil { | ||||
| 		defer response.Body.Close() | ||||
| 	} | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package coding | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| @@ -25,7 +26,6 @@ import ( | ||||
| 	"github.com/woodpecker-ci/woodpecker/server/remote" | ||||
| 	"github.com/woodpecker-ci/woodpecker/server/remote/coding/internal" | ||||
|  | ||||
| 	"golang.org/x/net/context" | ||||
| 	"golang.org/x/oauth2" | ||||
| ) | ||||
|  | ||||
| @@ -78,7 +78,7 @@ type Coding struct { | ||||
|  | ||||
| // Login authenticates the session and returns the | ||||
| // remote user details. | ||||
| func (c *Coding) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (c *Coding) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| 	config := c.newConfig(server.Config.Server.Host) | ||||
|  | ||||
| 	// get the OAuth errors | ||||
| @@ -97,12 +97,12 @@ func (c *Coding) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	token, err := config.Exchange(c.newContext(), code) | ||||
| 	token, err := config.Exchange(c.newContext(ctx), code) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	user, err := c.newClientToken(token.AccessToken, token.RefreshToken).GetCurrentUser() | ||||
| 	user, err := c.newClientToken(ctx, token.AccessToken).GetCurrentUser() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -119,8 +119,8 @@ func (c *Coding) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
|  | ||||
| // Auth authenticates the session and returns the remote user | ||||
| // login for the given token and secret | ||||
| func (c *Coding) Auth(token, secret string) (string, error) { | ||||
| 	user, err := c.newClientToken(token, secret).GetCurrentUser() | ||||
| func (c *Coding) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	user, err := c.newClientToken(ctx, token).GetCurrentUser() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| @@ -130,9 +130,9 @@ func (c *Coding) Auth(token, secret string) (string, error) { | ||||
| // Refresh refreshes an oauth token and expiration for the given | ||||
| // user. It returns true if the token was refreshed, false if the | ||||
| // token was not refreshed, and error if it failed to refersh. | ||||
| func (c *Coding) Refresh(u *model.User) (bool, error) { | ||||
| func (c *Coding) Refresh(ctx context.Context, u *model.User) (bool, error) { | ||||
| 	config := c.newConfig("") | ||||
| 	source := config.TokenSource(c.newContext(), &oauth2.Token{RefreshToken: u.Secret}) | ||||
| 	source := config.TokenSource(c.newContext(ctx), &oauth2.Token{RefreshToken: u.Secret}) | ||||
| 	token, err := source.Token() | ||||
| 	if err != nil || len(token.AccessToken) == 0 { | ||||
| 		return false, err | ||||
| @@ -145,9 +145,9 @@ func (c *Coding) Refresh(u *model.User) (bool, error) { | ||||
| } | ||||
|  | ||||
| // Teams fetches a list of team memberships from the remote system. | ||||
| func (c *Coding) Teams(u *model.User) ([]*model.Team, error) { | ||||
| func (c *Coding) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	// EMPTY: not implemented in Coding OAuth API | ||||
| 	return nil, nil | ||||
| 	return nil, fmt.Errorf("Not implemented") | ||||
| } | ||||
|  | ||||
| // TeamPerm fetches the named organization permissions from | ||||
| @@ -158,12 +158,13 @@ func (c *Coding) TeamPerm(u *model.User, org string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // Repo fetches the named repository from the remote system. | ||||
| func (c *Coding) Repo(u *model.User, owner, repo string) (*model.Repo, error) { | ||||
| 	project, err := c.newClient(u).GetProject(owner, repo) | ||||
| func (c *Coding) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client := c.newClient(ctx, u) | ||||
| 	project, err := client.GetProject(owner, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	depot, err := c.newClient(u).GetDepot(owner, repo) | ||||
| 	depot, err := client.GetDepot(owner, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -181,15 +182,16 @@ func (c *Coding) Repo(u *model.User, owner, repo string) (*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Repos fetches a list of repos from the remote system. | ||||
| func (c *Coding) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| 	projectList, err := c.newClient(u).GetProjectList() | ||||
| func (c *Coding) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	client := c.newClient(ctx, u) | ||||
| 	projectList, err := client.GetProjectList() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	repos := make([]*model.Repo, 0) | ||||
| 	for _, project := range projectList { | ||||
| 		depot, err := c.newClient(u).GetDepot(project.Owner, project.Name) | ||||
| 		depot, err := client.GetDepot(project.Owner, project.Name) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @@ -211,8 +213,8 @@ func (c *Coding) Repos(u *model.User) ([]*model.Repo, error) { | ||||
|  | ||||
| // Perm fetches the named repository permissions from | ||||
| // the remote system for the specified user. | ||||
| func (c *Coding) Perm(u *model.User, owner, repo string) (*model.Perm, error) { | ||||
| 	project, err := c.newClient(u).GetProject(owner, repo) | ||||
| func (c *Coding) Perm(ctx context.Context, u *model.User, owner, repo string) (*model.Perm, error) { | ||||
| 	project, err := c.newClient(ctx, u).GetProject(owner, repo) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -228,20 +230,20 @@ func (c *Coding) Perm(u *model.User, owner, repo string) (*model.Perm, error) { | ||||
|  | ||||
| // File fetches a file from the remote repository and returns in string | ||||
| // format. | ||||
| func (c *Coding) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	data, err := c.newClient(u).GetFile(r.Owner, r.Name, b.Commit, f) | ||||
| func (c *Coding) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	data, err := c.newClient(ctx, u).GetFile(r.Owner, r.Name, b.Commit, f) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return data, nil | ||||
| } | ||||
|  | ||||
| func (c *Coding) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| func (c *Coding) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	return nil, fmt.Errorf("Not implemented") | ||||
| } | ||||
|  | ||||
| // Status sends the commit status to the remote system. | ||||
| func (c *Coding) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| func (c *Coding) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	// EMPTY: not implemented in Coding OAuth API | ||||
| 	return nil | ||||
| } | ||||
| @@ -264,14 +266,14 @@ func (c *Coding) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
| } | ||||
|  | ||||
| // Activate activates a repository by creating the post-commit hook. | ||||
| func (c *Coding) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| 	return c.newClient(u).AddWebhook(r.Owner, r.Name, link) | ||||
| func (c *Coding) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	return c.newClient(ctx, u).AddWebhook(r.Owner, r.Name, link) | ||||
| } | ||||
|  | ||||
| // Deactivate deactivates a repository by removing all previously created | ||||
| // post-commit hooks matching the given link. | ||||
| func (c *Coding) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
| 	return c.newClient(u).RemoveWebhook(r.Owner, r.Name, link) | ||||
| func (c *Coding) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	return c.newClient(ctx, u).RemoveWebhook(r.Owner, r.Name, link) | ||||
| } | ||||
|  | ||||
| // Hook parses the post-commit hook from the Request body and returns the | ||||
| @@ -286,11 +288,11 @@ func (c *Coding) Hook(r *http.Request) (*model.Repo, *model.Build, error) { | ||||
|  | ||||
| // helper function to return the Coding oauth2 context using an HTTPClient that | ||||
| // disables TLS verification if disabled in the remote settings. | ||||
| func (c *Coding) newContext() context.Context { | ||||
| func (c *Coding) newContext(ctx context.Context) context.Context { | ||||
| 	if !c.SkipVerify { | ||||
| 		return oauth2.NoContext | ||||
| 		return ctx | ||||
| 	} | ||||
| 	return context.WithValue(nil, oauth2.HTTPClient, &http.Client{ | ||||
| 	return context.WithValue(ctx, oauth2.HTTPClient, &http.Client{ | ||||
| 		Transport: &http.Transport{ | ||||
| 			Proxy: http.ProxyFromEnvironment, | ||||
| 			TLSClientConfig: &tls.Config{ | ||||
| @@ -315,12 +317,12 @@ func (c *Coding) newConfig(redirect string) *oauth2.Config { | ||||
| } | ||||
|  | ||||
| // helper function to return the Coding oauth2 client | ||||
| func (c *Coding) newClient(u *model.User) *internal.Client { | ||||
| 	return c.newClientToken(u.Token, u.Secret) | ||||
| func (c *Coding) newClient(ctx context.Context, u *model.User) *internal.Client { | ||||
| 	return c.newClientToken(ctx, u.Token) | ||||
| } | ||||
|  | ||||
| // helper function to return the Coding oauth2 client | ||||
| func (c *Coding) newClientToken(token, secret string) *internal.Client { | ||||
| func (c *Coding) newClientToken(ctx context.Context, token string) *internal.Client { | ||||
| 	client := &http.Client{ | ||||
| 		Transport: &http.Transport{ | ||||
| 			Proxy: http.ProxyFromEnvironment, | ||||
| @@ -329,7 +331,7 @@ func (c *Coding) newClientToken(token, secret string) *internal.Client { | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	return internal.NewClient(c.URL, "/api", token, "drone", client) | ||||
| 	return internal.NewClient(ctx, c.URL, "/api", token, "drone", client) | ||||
| } | ||||
|  | ||||
| func (c *Coding) resourceLink(resourcePath string) string { | ||||
|   | ||||
| @@ -16,6 +16,7 @@ package coding | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
| @@ -33,6 +34,7 @@ func Test_coding(t *testing.T) { | ||||
| 	s := httptest.NewServer(fixtures.Handler()) | ||||
| 	c := &Coding{URL: s.URL} | ||||
|  | ||||
| 	ctx := context.Background() | ||||
| 	g := goblin.Goblin(t) | ||||
| 	g.Describe("Coding", func() { | ||||
|  | ||||
| @@ -67,13 +69,13 @@ func Test_coding(t *testing.T) { | ||||
| 			g.It("Should redirect to authorize", func() { | ||||
| 				w := httptest.NewRecorder() | ||||
| 				r, _ := http.NewRequest("GET", "", nil) | ||||
| 				_, err := c.Login(w, r) | ||||
| 				_, err := c.Login(ctx, w, r) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(w.Code).Equal(http.StatusSeeOther) | ||||
| 			}) | ||||
| 			g.It("Should return authenticated user", func() { | ||||
| 				r, _ := http.NewRequest("GET", "?code=code", nil) | ||||
| 				u, err := c.Login(nil, r) | ||||
| 				u, err := c.Login(ctx, nil, r) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(u.Login).Equal(fakeUser.Login) | ||||
| 				g.Assert(u.Token).Equal(fakeUser.Token) | ||||
| @@ -83,43 +85,33 @@ func Test_coding(t *testing.T) { | ||||
|  | ||||
| 		g.Describe("Given an access token", func() { | ||||
| 			g.It("Should return the anthenticated user", func() { | ||||
| 				login, err := c.Auth( | ||||
| 					fakeUser.Token, | ||||
| 					fakeUser.Secret, | ||||
| 				) | ||||
| 				login, err := c.Auth(ctx, fakeUser.Token, fakeUser.Secret) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(login).Equal(fakeUser.Login) | ||||
| 			}) | ||||
| 			g.It("Should handle a failure to resolve user", func() { | ||||
| 				_, err := c.Auth( | ||||
| 					fakeUserNotFound.Token, | ||||
| 					fakeUserNotFound.Secret, | ||||
| 				) | ||||
| 				_, err := c.Auth(ctx, fakeUserNotFound.Token, fakeUserNotFound.Secret) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Given a refresh token", func() { | ||||
| 			g.It("Should return a refresh access token", func() { | ||||
| 				ok, err := c.Refresh(fakeUserRefresh) | ||||
| 				ok, err := c.Refresh(ctx, fakeUserRefresh) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(ok).IsTrue() | ||||
| 				g.Assert(fakeUserRefresh.Token).Equal("VDZupx0usVRV4oOd1FCu4xUxgk8SY0TK") | ||||
| 				g.Assert(fakeUserRefresh.Secret).Equal("BenBQq7TWZ7Cp0aUM47nQjTz2QHNmTWcPctB609n") | ||||
| 			}) | ||||
| 			g.It("Should handle an invalid refresh token", func() { | ||||
| 				ok, _ := c.Refresh(fakeUserRefreshInvalid) | ||||
| 				ok, _ := c.Refresh(ctx, fakeUserRefreshInvalid) | ||||
| 				g.Assert(ok).IsFalse() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When requesting a repository", func() { | ||||
| 			g.It("Should return the details", func() { | ||||
| 				repo, err := c.Repo( | ||||
| 					fakeUser, | ||||
| 					fakeRepo.Owner, | ||||
| 					fakeRepo.Name, | ||||
| 				) | ||||
| 				repo, err := c.Repo(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repo.FullName).Equal(fakeRepo.FullName) | ||||
| 				g.Assert(repo.Avatar).Equal(s.URL + fakeRepo.Avatar) | ||||
| @@ -130,57 +122,49 @@ func Test_coding(t *testing.T) { | ||||
| 				g.Assert(repo.IsPrivate).Equal(fakeRepo.IsPrivate) | ||||
| 			}) | ||||
| 			g.It("Should handle not found errors", func() { | ||||
| 				_, err := c.Repo( | ||||
| 					fakeUser, | ||||
| 					fakeRepoNotFound.Owner, | ||||
| 					fakeRepoNotFound.Name, | ||||
| 				) | ||||
| 				_, err := c.Repo(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When requesting repository permissions", func() { | ||||
| 			g.It("Should authorize admin access for project owner", func() { | ||||
| 				perm, err := c.Perm(fakeUser, "demo1", "perm_owner") | ||||
| 				perm, err := c.Perm(ctx, fakeUser, "demo1", "perm_owner") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| 				g.Assert(perm.Admin).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should authorize admin access for project admin", func() { | ||||
| 				perm, err := c.Perm(fakeUser, "demo1", "perm_admin") | ||||
| 				perm, err := c.Perm(ctx, fakeUser, "demo1", "perm_admin") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| 				g.Assert(perm.Admin).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should authorize read access for project member", func() { | ||||
| 				perm, err := c.Perm(fakeUser, "demo1", "perm_member") | ||||
| 				perm, err := c.Perm(ctx, fakeUser, "demo1", "perm_member") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| 				g.Assert(perm.Admin).IsFalse() | ||||
| 			}) | ||||
| 			g.It("Should authorize no access for project guest", func() { | ||||
| 				perm, err := c.Perm(fakeUser, "demo1", "perm_guest") | ||||
| 				perm, err := c.Perm(ctx, fakeUser, "demo1", "perm_guest") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsFalse() | ||||
| 				g.Assert(perm.Push).IsFalse() | ||||
| 				g.Assert(perm.Admin).IsFalse() | ||||
| 			}) | ||||
| 			g.It("Should handle not found errors", func() { | ||||
| 				_, err := c.Perm( | ||||
| 					fakeUser, | ||||
| 					fakeRepoNotFound.Owner, | ||||
| 					fakeRepoNotFound.Name, | ||||
| 				) | ||||
| 				_, err := c.Perm(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When downloading a file", func() { | ||||
| 			g.It("Should return file for specified build", func() { | ||||
| 				data, err := c.File(fakeUser, fakeRepo, fakeBuild, ".drone.yml") | ||||
| 				data, err := c.File(ctx, fakeUser, fakeRepo, fakeBuild, ".drone.yml") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(string(data)).Equal("pipeline:\n  test:\n    image: golang:1.6\n    commands:\n      - go test\n") | ||||
| 			}) | ||||
| @@ -213,22 +197,22 @@ func Test_coding(t *testing.T) { | ||||
|  | ||||
| 		g.Describe("When activating a repository", func() { | ||||
| 			g.It("Should create the hook", func() { | ||||
| 				err := c.Activate(fakeUser, fakeRepo, "http://127.0.0.1") | ||||
| 				err := c.Activate(ctx, fakeUser, fakeRepo, "http://127.0.0.1") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should update the hook when exists", func() { | ||||
| 				err := c.Activate(fakeUser, fakeRepo, "http://127.0.0.2") | ||||
| 				err := c.Activate(ctx, fakeUser, fakeRepo, "http://127.0.0.2") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("When deactivating a repository", func() { | ||||
| 			g.It("Should successfully remove hook", func() { | ||||
| 				err := c.Deactivate(fakeUser, fakeRepo, "http://127.0.0.3") | ||||
| 				err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://127.0.0.3") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should successfully deactivate when hook already removed", func() { | ||||
| 				err := c.Deactivate(fakeUser, fakeRepo, "http://127.0.0.4") | ||||
| 				err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://127.0.0.4") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package internal | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| @@ -29,6 +30,7 @@ type Client struct { | ||||
| 	token   string | ||||
| 	agent   string | ||||
| 	client  *http.Client | ||||
| 	ctx     context.Context | ||||
| } | ||||
|  | ||||
| type GenericAPIResponse struct { | ||||
| @@ -36,13 +38,14 @@ type GenericAPIResponse struct { | ||||
| 	Data json.RawMessage `json:"data,omitempty"` | ||||
| } | ||||
|  | ||||
| func NewClient(baseURL, apiPath, token, agent string, client *http.Client) *Client { | ||||
| func NewClient(ctx context.Context, baseURL, apiPath, token, agent string, client *http.Client) *Client { | ||||
| 	return &Client{ | ||||
| 		baseURL: baseURL, | ||||
| 		apiPath: apiPath, | ||||
| 		token:   token, | ||||
| 		agent:   agent, | ||||
| 		client:  client, | ||||
| 		ctx:     ctx, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -63,10 +66,10 @@ func (c *Client) Do(method, u string, params url.Values) ([]byte, error) { | ||||
| 	var req *http.Request | ||||
| 	var err error | ||||
| 	if method != "GET" { | ||||
| 		req, err = http.NewRequest(method, rawURL+"?access_token="+c.token, strings.NewReader(params.Encode())) | ||||
| 		req, err = http.NewRequestWithContext(c.ctx, method, rawURL+"?access_token="+c.token, strings.NewReader(params.Encode())) | ||||
| 		req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8") | ||||
| 	} else { | ||||
| 		req, err = http.NewRequest("GET", rawURL+"?"+params.Encode(), nil) | ||||
| 		req, err = http.NewRequestWithContext(c.ctx, "GET", rawURL+"?"+params.Encode(), nil) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("fail to create request for url %q: %v", rawURL, err) | ||||
|   | ||||
| @@ -91,7 +91,7 @@ func New(opts Opts) (remote.Remote, error) { | ||||
|  | ||||
| // Login authenticates an account with Gitea using basic authentication. The | ||||
| // Gitea account details are returned when the user is successfully authenticated. | ||||
| func (c *Gitea) Login(w http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (c *Gitea) Login(ctx context.Context, w http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| 	config := &oauth2.Config{ | ||||
| 		ClientID:     c.ClientID, | ||||
| 		ClientSecret: c.ClientSecret, | ||||
| @@ -123,7 +123,7 @@ func (c *Gitea) Login(w http.ResponseWriter, req *http.Request) (*model.User, er | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	client, err := c.newClientToken(token.AccessToken) | ||||
| 	client, err := c.newClientToken(ctx, token.AccessToken) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -144,8 +144,8 @@ func (c *Gitea) Login(w http.ResponseWriter, req *http.Request) (*model.User, er | ||||
|  | ||||
| // Auth uses the Gitea oauth2 access token and refresh token to authenticate | ||||
| // a session and return the Gitea account login. | ||||
| func (c *Gitea) Auth(token, _ string) (string, error) { | ||||
| 	client, err := c.newClientToken(token) | ||||
| func (c *Gitea) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	client, err := c.newClientToken(ctx, token) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| @@ -158,7 +158,7 @@ func (c *Gitea) Auth(token, _ string) (string, error) { | ||||
|  | ||||
| // Refresh refreshes the Gitea oauth2 access token. If the token is | ||||
| // refreshed the user is updated and a true value is returned. | ||||
| func (c *Gitea) Refresh(user *model.User) (bool, error) { | ||||
| func (c *Gitea) Refresh(ctx context.Context, user *model.User) (bool, error) { | ||||
| 	config := &oauth2.Config{ | ||||
| 		ClientID:     c.ClientID, | ||||
| 		ClientSecret: c.ClientSecret, | ||||
| @@ -167,7 +167,7 @@ func (c *Gitea) Refresh(user *model.User) (bool, error) { | ||||
| 			TokenURL: fmt.Sprintf(accessTokenURL, c.URL), | ||||
| 		}, | ||||
| 	} | ||||
| 	source := config.TokenSource(context.TODO(), &oauth2.Token{RefreshToken: user.Secret}) | ||||
| 	source := config.TokenSource(ctx, &oauth2.Token{RefreshToken: user.Secret}) | ||||
|  | ||||
| 	token, err := source.Token() | ||||
| 	if err != nil || len(token.AccessToken) == 0 { | ||||
| @@ -181,8 +181,8 @@ func (c *Gitea) Refresh(user *model.User) (bool, error) { | ||||
| } | ||||
|  | ||||
| // Teams is supported by the Gitea driver. | ||||
| func (c *Gitea) Teams(u *model.User) ([]*model.Team, error) { | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| func (c *Gitea) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -222,8 +222,8 @@ func (c *Gitea) TeamPerm(u *model.User, org string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // Repo returns the named Gitea repository. | ||||
| func (c *Gitea) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| func (c *Gitea) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -240,10 +240,10 @@ func (c *Gitea) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
|  | ||||
| // Repos returns a list of all repositories for the Gitea account, including | ||||
| // organization repositories. | ||||
| func (c *Gitea) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| func (c *Gitea) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	repos := make([]*model.Repo, 0, perPage) | ||||
|  | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -278,8 +278,8 @@ func (c *Gitea) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Perm returns the user permissions for the named Gitea repository. | ||||
| func (c *Gitea) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| func (c *Gitea) Perm(ctx context.Context, u *model.User, owner, name string) (*model.Perm, error) { | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -292,8 +292,8 @@ func (c *Gitea) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // File fetches the file from the Gitea repository and returns its contents. | ||||
| func (c *Gitea) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| func (c *Gitea) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -302,10 +302,10 @@ func (c *Gitea) File(u *model.User, r *model.Repo, b *model.Build, f string) ([] | ||||
| 	return cfg, err | ||||
| } | ||||
|  | ||||
| func (c *Gitea) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| func (c *Gitea) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	var configs []*remote.FileMeta | ||||
|  | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -321,7 +321,7 @@ func (c *Gitea) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]* | ||||
| 	for _, e := range tree.Entries { | ||||
| 		// Filter path matching pattern and type file (blob) | ||||
| 		if m, _ := filepath.Match(f, e.Path); m && e.Type == "blob" { | ||||
| 			data, err := c.File(u, r, b, e.Path) | ||||
| 			data, err := c.File(ctx, u, r, b, e.Path) | ||||
| 			if err != nil { | ||||
| 				return nil, fmt.Errorf("multi-pipeline cannot get %s: %s", e.Path, err) | ||||
| 			} | ||||
| @@ -337,8 +337,8 @@ func (c *Gitea) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]* | ||||
| } | ||||
|  | ||||
| // Status is supported by the Gitea driver. | ||||
| func (c *Gitea) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| func (c *Gitea) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -381,7 +381,7 @@ func (c *Gitea) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
|  | ||||
| // Activate activates the repository by registering post-commit hooks with | ||||
| // the Gitea repository. | ||||
| func (c *Gitea) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| func (c *Gitea) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	config := map[string]string{ | ||||
| 		"url":          link, | ||||
| 		"secret":       r.Hash, | ||||
| @@ -394,7 +394,7 @@ func (c *Gitea) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| 		Active: true, | ||||
| 	} | ||||
|  | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -404,8 +404,8 @@ func (c *Gitea) Activate(u *model.User, r *model.Repo, link string) error { | ||||
|  | ||||
| // Deactivate deactives the repository be removing repository push hooks from | ||||
| // the Gitea repository. | ||||
| func (c *Gitea) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
| 	client, err := c.newClientToken(u.Token) | ||||
| func (c *Gitea) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	client, err := c.newClientToken(ctx, u.Token) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -431,14 +431,14 @@ func (c *Gitea) Hook(r *http.Request) (*model.Repo, *model.Build, error) { | ||||
| } | ||||
|  | ||||
| // helper function to return the Gitea client with Token | ||||
| func (c *Gitea) newClientToken(token string) (*gitea.Client, error) { | ||||
| func (c *Gitea) newClientToken(ctx context.Context, token string) (*gitea.Client, error) { | ||||
| 	httpClient := &http.Client{} | ||||
| 	if c.SkipVerify { | ||||
| 		httpClient.Transport = &http.Transport{ | ||||
| 			TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | ||||
| 		} | ||||
| 	} | ||||
| 	return gitea.NewClient(c.URL, gitea.SetToken(token), gitea.SetHTTPClient(httpClient)) | ||||
| 	return gitea.NewClient(c.URL, gitea.SetToken(token), gitea.SetHTTPClient(httpClient), gitea.SetContext(ctx)) | ||||
| } | ||||
|  | ||||
| const ( | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package gitea | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
|  | ||||
| @@ -33,6 +34,7 @@ func Test_gitea(t *testing.T) { | ||||
| 		SkipVerify: true, | ||||
| 	}) | ||||
|  | ||||
| 	ctx := context.Background() | ||||
| 	g := goblin.Goblin(t) | ||||
| 	g.Describe("Gitea", func() { | ||||
|  | ||||
| @@ -89,7 +91,7 @@ func Test_gitea(t *testing.T) { | ||||
|  | ||||
| 		g.Describe("Requesting a repository", func() { | ||||
| 			g.It("Should return the repository details", func() { | ||||
| 				repo, err := c.Repo(fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				repo, err := c.Repo(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repo.Owner).Equal(fakeRepo.Owner) | ||||
| 				g.Assert(repo.Name).Equal(fakeRepo.Name) | ||||
| @@ -99,57 +101,57 @@ func Test_gitea(t *testing.T) { | ||||
| 				g.Assert(repo.Link).Equal("http://localhost/test_name/repo_name") | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Repo(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				_, err := c.Repo(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Requesting repository permissions", func() { | ||||
| 			g.It("Should return the permission details", func() { | ||||
| 				perm, err := c.Perm(fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				perm, err := c.Perm(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Admin).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Perm(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				_, err := c.Perm(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Requesting a repository list", func() { | ||||
| 			g.It("Should return the repository list", func() { | ||||
| 				repos, err := c.Repos(fakeUser) | ||||
| 				repos, err := c.Repos(ctx, fakeUser) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repos[0].Owner).Equal(fakeRepo.Owner) | ||||
| 				g.Assert(repos[0].Name).Equal(fakeRepo.Name) | ||||
| 				g.Assert(repos[0].FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name) | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Repos(fakeUserNoRepos) | ||||
| 				_, err := c.Repos(ctx, fakeUserNoRepos) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should register repository hooks", func() { | ||||
| 			err := c.Activate(fakeUser, fakeRepo, "http://localhost") | ||||
| 			err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should remove repository hooks", func() { | ||||
| 			err := c.Deactivate(fakeUser, fakeRepo, "http://localhost") | ||||
| 			err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost") | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return a repository file", func() { | ||||
| 			raw, err := c.File(fakeUser, fakeRepo, fakeBuild, ".drone.yml") | ||||
| 			raw, err := c.File(ctx, fakeUser, fakeRepo, fakeBuild, ".drone.yml") | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 			g.Assert(string(raw)).Equal("{ platform: linux/amd64 }") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return nil from send build status", func() { | ||||
| 			err := c.Status(fakeUser, fakeRepo, fakeBuild, "http://gitea.io", nil) | ||||
| 			err := c.Status(ctx, fakeUser, fakeRepo, fakeBuild, "http://gitea.io", nil) | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 		}) | ||||
|  | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package github | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| @@ -28,8 +29,8 @@ import ( | ||||
| 	"github.com/woodpecker-ci/woodpecker/server/model" | ||||
| 	"github.com/woodpecker-ci/woodpecker/server/remote" | ||||
|  | ||||
| 	// TODO upgrade to v39 to pass context down | ||||
| 	"github.com/google/go-github/github" | ||||
| 	"golang.org/x/net/context" | ||||
| 	"golang.org/x/oauth2" | ||||
| ) | ||||
|  | ||||
| @@ -82,9 +83,6 @@ func New(opts Opts) (remote.Remote, error) { | ||||
| 		r.API = r.URL + "/api/v3/" | ||||
| 	} | ||||
|  | ||||
| 	// Hack to enable oauth2 access in older GHE | ||||
| 	// TODO: dont use deprecated func | ||||
| 	oauth2.RegisterBrokenAuthHeaderProvider(r.URL) | ||||
| 	return r, nil | ||||
| } | ||||
|  | ||||
| @@ -104,7 +102,7 @@ type client struct { | ||||
| } | ||||
|  | ||||
| // Login authenticates the session and returns the remote user details. | ||||
| func (c *client) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (c *client) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| 	config := c.newConfig(req) | ||||
|  | ||||
| 	// get the OAuth errors | ||||
| @@ -126,12 +124,12 @@ func (c *client) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	token, err := config.Exchange(c.newContext(), code) | ||||
| 	token, err := config.Exchange(c.newContext(ctx), code) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	client := c.newClientToken(token.AccessToken) | ||||
| 	client := c.newClientToken(ctx, token.AccessToken) | ||||
| 	user, _, err := client.Users.Get("") | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -155,8 +153,8 @@ func (c *client) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| } | ||||
|  | ||||
| // Auth returns the GitHub user login for the given access token. | ||||
| func (c *client) Auth(token, secret string) (string, error) { | ||||
| 	client := c.newClientToken(token) | ||||
| func (c *client) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	client := c.newClientToken(ctx, token) | ||||
| 	user, _, err := client.Users.Get("") | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| @@ -165,8 +163,8 @@ func (c *client) Auth(token, secret string) (string, error) { | ||||
| } | ||||
|  | ||||
| // Teams returns a list of all team membership for the GitHub account. | ||||
| func (c *client) Teams(u *model.User) ([]*model.Team, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
|  | ||||
| 	opts := new(github.ListOptions) | ||||
| 	opts.Page = 1 | ||||
| @@ -184,8 +182,8 @@ func (c *client) Teams(u *model.User) ([]*model.Team, error) { | ||||
| } | ||||
|  | ||||
| // Repo returns the named GitHub repository. | ||||
| func (c *client) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
| 	repo, _, err := client.Repositories.Get(owner, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -195,8 +193,8 @@ func (c *client) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
|  | ||||
| // Repos returns a list of all repositories for GitHub account, including | ||||
| // organization repositories. | ||||
| func (c *client) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
|  | ||||
| 	opts := new(github.RepositoryListOptions) | ||||
| 	opts.PerPage = 100 | ||||
| @@ -215,8 +213,8 @@ func (c *client) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Perm returns the user permissions for the named GitHub repository. | ||||
| func (c *client) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) Perm(ctx context.Context, u *model.User, owner, name string) (*model.Perm, error) { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
| 	repo, _, err := client.Repositories.Get(owner, name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -225,8 +223,8 @@ func (c *client) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // File fetches the file from the GitHub repository and returns its contents. | ||||
| func (c *client) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
|  | ||||
| 	opts := new(github.RepositoryContentGetOptions) | ||||
| 	opts.Ref = b.Commit | ||||
| @@ -240,8 +238,8 @@ func (c *client) File(u *model.User, r *model.Repo, b *model.Build, f string) ([ | ||||
| 	return data.Decode() | ||||
| } | ||||
|  | ||||
| func (c *client) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
|  | ||||
| 	opts := new(github.RepositoryContentGetOptions) | ||||
| 	opts.Ref = b.Commit | ||||
| @@ -255,7 +253,7 @@ func (c *client) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([] | ||||
|  | ||||
| 	for _, file := range data { | ||||
| 		go func(path string) { | ||||
| 			content, err := c.File(u, r, b, path) | ||||
| 			content, err := c.File(ctx, u, r, b, path) | ||||
| 			if err != nil { | ||||
| 				errc <- err | ||||
| 			} else { | ||||
| @@ -305,8 +303,8 @@ func (c *client) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
|  | ||||
| // Deactivate deactives the repository be removing registered push hooks from | ||||
| // the GitHub repository. | ||||
| func (c *client) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
| 	hooks, _, err := client.Repositories.ListHooks(r.Owner, r.Name, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| @@ -321,11 +319,11 @@ func (c *client) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
|  | ||||
| // helper function to return the GitHub oauth2 context using an HTTPClient that | ||||
| // disables TLS verification if disabled in the remote settings. | ||||
| func (c *client) newContext() context.Context { | ||||
| func (c *client) newContext(ctx context.Context) context.Context { | ||||
| 	if !c.SkipVerify { | ||||
| 		return oauth2.NoContext | ||||
| 		return ctx | ||||
| 	} | ||||
| 	return context.WithValue(nil, oauth2.HTTPClient, &http.Client{ | ||||
| 	return context.WithValue(ctx, oauth2.HTTPClient, &http.Client{ | ||||
| 		Transport: &http.Transport{ | ||||
| 			Proxy: http.ProxyFromEnvironment, | ||||
| 			TLSClientConfig: &tls.Config{ | ||||
| @@ -359,11 +357,11 @@ func (c *client) newConfig(req *http.Request) *oauth2.Config { | ||||
| } | ||||
|  | ||||
| // helper function to return the GitHub oauth2 client | ||||
| func (c *client) newClientToken(token string) *github.Client { | ||||
| func (c *client) newClientToken(ctx context.Context, token string) *github.Client { | ||||
| 	ts := oauth2.StaticTokenSource( | ||||
| 		&oauth2.Token{AccessToken: token}, | ||||
| 	) | ||||
| 	tc := oauth2.NewClient(oauth2.NoContext, ts) | ||||
| 	tc := oauth2.NewClient(ctx, ts) | ||||
| 	if c.SkipVerify { | ||||
| 		tc.Transport.(*oauth2.Transport).Base = &http.Transport{ | ||||
| 			Proxy: http.ProxyFromEnvironment, | ||||
| @@ -427,8 +425,8 @@ func matchingHooks(hooks []github.Hook, rawurl string) *github.Hook { | ||||
|  | ||||
| // Status sends the commit status to the remote system. | ||||
| // An example would be the GitHub pull request status. | ||||
| func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| func (c *client) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
| 	switch b.Event { | ||||
| 	case "deployment": | ||||
| 		return deploymentStatus(client, r, b, link) | ||||
| @@ -486,11 +484,11 @@ func deploymentStatus(client *github.Client, r *model.Repo, b *model.Build, link | ||||
|  | ||||
| // Activate activates a repository by creating the post-commit hook and | ||||
| // adding the SSH deploy key, if applicable. | ||||
| func (c *client) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| 	if err := c.Deactivate(u, r, link); err != nil { | ||||
| func (c *client) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	if err := c.Deactivate(ctx, u, r, link); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	client := c.newClientToken(u.Token) | ||||
| 	client := c.newClientToken(ctx, u.Token) | ||||
| 	hook := &github.Hook{ | ||||
| 		Name: github.String("web"), | ||||
| 		Events: []string{ | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package github | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
|  | ||||
| @@ -34,6 +35,7 @@ func Test_github(t *testing.T) { | ||||
| 		SkipVerify: true, | ||||
| 	}) | ||||
|  | ||||
| 	ctx := context.Background() | ||||
| 	g := goblin.Goblin(t) | ||||
| 	g.Describe("GitHub", func() { | ||||
|  | ||||
| @@ -95,7 +97,7 @@ func Test_github(t *testing.T) { | ||||
|  | ||||
| 		g.Describe("Requesting a repository", func() { | ||||
| 			g.It("Should return the repository details", func() { | ||||
| 				repo, err := c.Repo(fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				repo, err := c.Repo(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repo.Owner).Equal(fakeRepo.Owner) | ||||
| 				g.Assert(repo.Name).Equal(fakeRepo.Name) | ||||
| @@ -105,21 +107,21 @@ func Test_github(t *testing.T) { | ||||
| 				g.Assert(repo.Link).Equal(fakeRepo.Link) | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Repo(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				_, err := c.Repo(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Requesting repository permissions", func() { | ||||
| 			g.It("Should return the permission details", func() { | ||||
| 				perm, err := c.Perm(fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				perm, err := c.Perm(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Admin).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Perm(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				_, err := c.Perm(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package gitlab | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| @@ -113,7 +114,7 @@ func Load(config string) *Gitlab { | ||||
|  | ||||
| // Login authenticates the session and returns the | ||||
| // remote user details. | ||||
| func (g *Gitlab) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (g *Gitlab) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
|  | ||||
| 	var config = &oauth2.Config{ | ||||
| 		ClientId:     g.Client, | ||||
| @@ -193,7 +194,7 @@ func (g *Gitlab) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| 	return user, nil | ||||
| } | ||||
|  | ||||
| func (g *Gitlab) Auth(token, secret string) (string, error) { | ||||
| func (g *Gitlab) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	client := NewClient(g.URL, token, g.SkipVerify) | ||||
| 	login, err := client.CurrentUser() | ||||
| 	if err != nil { | ||||
| @@ -202,7 +203,7 @@ func (g *Gitlab) Auth(token, secret string) (string, error) { | ||||
| 	return login.Username, nil | ||||
| } | ||||
|  | ||||
| func (g *Gitlab) Teams(u *model.User) ([]*model.Team, error) { | ||||
| func (g *Gitlab) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	groups, err := client.AllGroups() | ||||
| 	if err != nil { | ||||
| @@ -218,7 +219,7 @@ func (g *Gitlab) Teams(u *model.User) ([]*model.Team, error) { | ||||
| } | ||||
|  | ||||
| // Repo fetches the named repository from the remote system. | ||||
| func (g *Gitlab) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| func (g *Gitlab) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, owner, name) | ||||
| 	if err != nil { | ||||
| @@ -257,7 +258,7 @@ func (g *Gitlab) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Repos fetches a list of repos from the remote system. | ||||
| func (g *Gitlab) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| func (g *Gitlab) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
|  | ||||
| 	var repos = []*model.Repo{} | ||||
| @@ -297,7 +298,7 @@ func (g *Gitlab) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Perm fetches the named repository from the remote system. | ||||
| func (g *Gitlab) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| func (g *Gitlab) Perm(ctx context.Context, u *model.User, owner, name string) (*model.Perm, error) { | ||||
|  | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, owner, name) | ||||
| @@ -324,35 +325,35 @@ func (g *Gitlab) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // File fetches a file from the remote repository and returns in string format. | ||||
| func (g *Gitlab) File(user *model.User, repo *model.Repo, build *model.Build, f string) ([]byte, error) { | ||||
| 	var client = NewClient(g.URL, user.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, repo.Owner, repo.Name) | ||||
| func (g *Gitlab) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	var client = NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, r.Owner, r.Name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	out, err := client.RepoRawFileRef(id, build.Commit, f) | ||||
| 	out, err := client.RepoRawFileRef(id, b.Commit, f) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, err | ||||
| } | ||||
|  | ||||
| func (c *Gitlab) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| func (c *Gitlab) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	return nil, fmt.Errorf("Not implemented") | ||||
| } | ||||
|  | ||||
| // NOTE Currently gitlab doesn't support status for commits and events, | ||||
| //      also if we want get MR status in gitlab we need implement a special plugin for gitlab, | ||||
| //      gitlab uses API to fetch build status on client side. But for now we skip this. | ||||
| func (g *Gitlab) Status(u *model.User, repo *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| func (g *Gitlab) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
|  | ||||
| 	status := getStatus(b.Status) | ||||
| 	desc := getDesc(b.Status) | ||||
|  | ||||
| 	client.SetStatus( | ||||
| 		ns(repo.Owner, repo.Name), | ||||
| 		ns(r.Owner, r.Name), | ||||
| 		b.Commit, | ||||
| 		status, | ||||
| 		desc, | ||||
| @@ -407,9 +408,9 @@ func (g *Gitlab) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
|  | ||||
| // Activate activates a repository by adding a Post-commit hook and | ||||
| // a Public Deploy key, if applicable. | ||||
| func (g *Gitlab) Activate(user *model.User, repo *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, user.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, repo.Owner, repo.Name) | ||||
| func (g *Gitlab) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, r.Owner, r.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -432,9 +433,9 @@ func (g *Gitlab) Activate(user *model.User, repo *model.Repo, link string) error | ||||
|  | ||||
| // Deactivate removes a repository by removing all the post-commit hooks | ||||
| // which are equal to link and removing the SSH deploy key. | ||||
| func (g *Gitlab) Deactivate(user *model.User, repo *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, user.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, repo.Owner, repo.Name) | ||||
| func (g *Gitlab) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, r.Owner, r.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|   | ||||
| @@ -16,6 +16,7 @@ package gitlab | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"net/http" | ||||
| 	"testing" | ||||
|  | ||||
| @@ -43,13 +44,14 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		Owner: "diaspora", | ||||
| 	} | ||||
|  | ||||
| 	ctx := context.Background() | ||||
| 	g := goblin.Goblin(t) | ||||
| 	g.Describe("Gitlab Plugin", func() { | ||||
| 		// Test projects method | ||||
| 		g.Describe("AllProjects", func() { | ||||
| 			g.It("Should return only non-archived projects is hidden", func() { | ||||
| 				gitlab.HideArchives = true | ||||
| 				_projects, err := gitlab.Repos(&user) | ||||
| 				_projects, err := gitlab.Repos(ctx, &user) | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(len(_projects)).Equal(1) | ||||
| @@ -57,7 +59,7 @@ func Test_Gitlab(t *testing.T) { | ||||
|  | ||||
| 			g.It("Should return all the projects", func() { | ||||
| 				gitlab.HideArchives = false | ||||
| 				_projects, err := gitlab.Repos(&user) | ||||
| 				_projects, err := gitlab.Repos(ctx, &user) | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(len(_projects)).Equal(2) | ||||
| @@ -67,7 +69,7 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test repository method | ||||
| 		g.Describe("Repo", func() { | ||||
| 			g.It("Should return valid repo", func() { | ||||
| 				_repo, err := gitlab.Repo(&user, "diaspora", "diaspora-client") | ||||
| 				_repo, err := gitlab.Repo(ctx, &user, "diaspora", "diaspora-client") | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(_repo.Name).Equal("diaspora-client") | ||||
| @@ -76,7 +78,7 @@ func Test_Gitlab(t *testing.T) { | ||||
| 			}) | ||||
|  | ||||
| 			g.It("Should return error, when repo not exist", func() { | ||||
| 				_, err := gitlab.Repo(&user, "not-existed", "not-existed") | ||||
| 				_, err := gitlab.Repo(ctx, &user, "not-existed", "not-existed") | ||||
|  | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| @@ -85,21 +87,21 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test permissions method | ||||
| 		g.Describe("Perm", func() { | ||||
| 			g.It("Should return repo permissions", func() { | ||||
| 				perm, err := gitlab.Perm(&user, "diaspora", "diaspora-client") | ||||
| 				perm, err := gitlab.Perm(ctx, &user, "diaspora", "diaspora-client") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Admin).Equal(true) | ||||
| 				g.Assert(perm.Pull).Equal(true) | ||||
| 				g.Assert(perm.Push).Equal(true) | ||||
| 			}) | ||||
| 			g.It("Should return repo permissions when user is admin", func() { | ||||
| 				perm, err := gitlab.Perm(&user, "brightbox", "puppet") | ||||
| 				perm, err := gitlab.Perm(ctx, &user, "brightbox", "puppet") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Admin).Equal(true) | ||||
| 				g.Assert(perm.Pull).Equal(true) | ||||
| 				g.Assert(perm.Push).Equal(true) | ||||
| 			}) | ||||
| 			g.It("Should return error, when repo is not exist", func() { | ||||
| 				_, err := gitlab.Perm(&user, "not-existed", "not-existed") | ||||
| 				_, err := gitlab.Perm(ctx, &user, "not-existed", "not-existed") | ||||
|  | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| @@ -108,13 +110,13 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test activate method | ||||
| 		g.Describe("Activate", func() { | ||||
| 			g.It("Should be success", func() { | ||||
| 				err := gitlab.Activate(&user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
| 				err := gitlab.Activate(ctx, &user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
|  | ||||
| 			g.It("Should be failed, when token not given", func() { | ||||
| 				err := gitlab.Activate(&user, &repo, "http://example.com/api/hook/test/test") | ||||
| 				err := gitlab.Activate(ctx, &user, &repo, "http://example.com/api/hook/test/test") | ||||
|  | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| @@ -123,7 +125,7 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test deactivate method | ||||
| 		g.Describe("Deactivate", func() { | ||||
| 			g.It("Should be success", func() { | ||||
| 				err := gitlab.Deactivate(&user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
| 				err := gitlab.Deactivate(ctx, &user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package gitlab3 | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| @@ -113,7 +114,7 @@ func Load(config string) *Gitlab { | ||||
|  | ||||
| // Login authenticates the session and returns the | ||||
| // remote user details. | ||||
| func (g *Gitlab) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (g *Gitlab) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
|  | ||||
| 	var config = &oauth2.Config{ | ||||
| 		ClientId:     g.Client, | ||||
| @@ -193,7 +194,7 @@ func (g *Gitlab) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| 	return user, nil | ||||
| } | ||||
|  | ||||
| func (g *Gitlab) Auth(token, secret string) (string, error) { | ||||
| func (g *Gitlab) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	client := NewClient(g.URL, token, g.SkipVerify) | ||||
| 	login, err := client.CurrentUser() | ||||
| 	if err != nil { | ||||
| @@ -202,7 +203,7 @@ func (g *Gitlab) Auth(token, secret string) (string, error) { | ||||
| 	return login.Username, nil | ||||
| } | ||||
|  | ||||
| func (g *Gitlab) Teams(u *model.User) ([]*model.Team, error) { | ||||
| func (g *Gitlab) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	groups, err := client.AllGroups() | ||||
| 	if err != nil { | ||||
| @@ -218,7 +219,7 @@ func (g *Gitlab) Teams(u *model.User) ([]*model.Team, error) { | ||||
| } | ||||
|  | ||||
| // Repo fetches the named repository from the remote system. | ||||
| func (g *Gitlab) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| func (g *Gitlab) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, owner, name) | ||||
| 	if err != nil { | ||||
| @@ -257,7 +258,7 @@ func (g *Gitlab) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Repos fetches a list of repos from the remote system. | ||||
| func (g *Gitlab) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| func (g *Gitlab) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
|  | ||||
| 	var repos = []*model.Repo{} | ||||
| @@ -297,7 +298,7 @@ func (g *Gitlab) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Perm fetches the named repository from the remote system. | ||||
| func (g *Gitlab) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| func (g *Gitlab) Perm(ctx context.Context, u *model.User, owner, name string) (*model.Perm, error) { | ||||
|  | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, owner, name) | ||||
| @@ -324,7 +325,7 @@ func (g *Gitlab) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // File fetches a file from the remote repository and returns in string format. | ||||
| func (g *Gitlab) File(user *model.User, repo *model.Repo, build *model.Build, f string) ([]byte, error) { | ||||
| func (g *Gitlab) File(ctx context.Context, user *model.User, repo *model.Repo, build *model.Build, f string) ([]byte, error) { | ||||
| 	var client = NewClient(g.URL, user.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, repo.Owner, repo.Name) | ||||
| 	if err != nil { | ||||
| @@ -338,21 +339,21 @@ func (g *Gitlab) File(user *model.User, repo *model.Repo, build *model.Build, f | ||||
| 	return out, err | ||||
| } | ||||
|  | ||||
| func (c *Gitlab) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| func (c *Gitlab) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	return nil, fmt.Errorf("Not implemented") | ||||
| } | ||||
|  | ||||
| // NOTE Currently gitlab doesn't support status for commits and events, | ||||
| //      also if we want get MR status in gitlab we need implement a special plugin for gitlab, | ||||
| //      gitlab uses API to fetch build status on client side. But for now we skip this. | ||||
| func (g *Gitlab) Status(u *model.User, repo *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| func (g *Gitlab) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	client := NewClient(g.URL, u.Token, g.SkipVerify) | ||||
|  | ||||
| 	status := getStatus(b.Status) | ||||
| 	desc := getDesc(b.Status) | ||||
|  | ||||
| 	client.SetStatus( | ||||
| 		ns(repo.Owner, repo.Name), | ||||
| 		ns(r.Owner, r.Name), | ||||
| 		b.Commit, | ||||
| 		status, | ||||
| 		desc, | ||||
| @@ -407,9 +408,9 @@ func (g *Gitlab) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
|  | ||||
| // Activate activates a repository by adding a Post-commit hook and | ||||
| // a Public Deploy key, if applicable. | ||||
| func (g *Gitlab) Activate(user *model.User, repo *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, user.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, repo.Owner, repo.Name) | ||||
| func (g *Gitlab) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, r.Owner, r.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -432,9 +433,9 @@ func (g *Gitlab) Activate(user *model.User, repo *model.Repo, link string) error | ||||
|  | ||||
| // Deactivate removes a repository by removing all the post-commit hooks | ||||
| // which are equal to link and removing the SSH deploy key. | ||||
| func (g *Gitlab) Deactivate(user *model.User, repo *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, user.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, repo.Owner, repo.Name) | ||||
| func (g *Gitlab) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	var client = NewClient(g.URL, u.Token, g.SkipVerify) | ||||
| 	id, err := GetProjectId(g, client, r.Owner, r.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|   | ||||
| @@ -49,7 +49,7 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		g.Describe("AllProjects", func() { | ||||
| 			g.It("Should return only non-archived projects is hidden", func() { | ||||
| 				gitlab.HideArchives = true | ||||
| 				_projects, err := gitlab.Repos(&user) | ||||
| 				_projects, err := gitlab.Repos(nil, &user) | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(len(_projects)).Equal(1) | ||||
| @@ -57,7 +57,7 @@ func Test_Gitlab(t *testing.T) { | ||||
|  | ||||
| 			g.It("Should return all the projects", func() { | ||||
| 				gitlab.HideArchives = false | ||||
| 				_projects, err := gitlab.Repos(&user) | ||||
| 				_projects, err := gitlab.Repos(nil, &user) | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(len(_projects)).Equal(2) | ||||
| @@ -67,7 +67,7 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test repository method | ||||
| 		g.Describe("Repo", func() { | ||||
| 			g.It("Should return valid repo", func() { | ||||
| 				_repo, err := gitlab.Repo(&user, "diaspora", "diaspora-client") | ||||
| 				_repo, err := gitlab.Repo(nil, &user, "diaspora", "diaspora-client") | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(_repo.Name).Equal("diaspora-client") | ||||
| @@ -76,7 +76,7 @@ func Test_Gitlab(t *testing.T) { | ||||
| 			}) | ||||
|  | ||||
| 			g.It("Should return error, when repo not exist", func() { | ||||
| 				_, err := gitlab.Repo(&user, "not-existed", "not-existed") | ||||
| 				_, err := gitlab.Repo(nil, &user, "not-existed", "not-existed") | ||||
|  | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| @@ -85,21 +85,21 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test permissions method | ||||
| 		g.Describe("Perm", func() { | ||||
| 			g.It("Should return repo permissions", func() { | ||||
| 				perm, err := gitlab.Perm(&user, "diaspora", "diaspora-client") | ||||
| 				perm, err := gitlab.Perm(nil, &user, "diaspora", "diaspora-client") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Admin).Equal(true) | ||||
| 				g.Assert(perm.Pull).Equal(true) | ||||
| 				g.Assert(perm.Push).Equal(true) | ||||
| 			}) | ||||
| 			g.It("Should return repo permissions when user is admin", func() { | ||||
| 				perm, err := gitlab.Perm(&user, "brightbox", "puppet") | ||||
| 				perm, err := gitlab.Perm(nil, &user, "brightbox", "puppet") | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Admin).Equal(true) | ||||
| 				g.Assert(perm.Pull).Equal(true) | ||||
| 				g.Assert(perm.Push).Equal(true) | ||||
| 			}) | ||||
| 			g.It("Should return error, when repo is not exist", func() { | ||||
| 				_, err := gitlab.Perm(&user, "not-existed", "not-existed") | ||||
| 				_, err := gitlab.Perm(nil, &user, "not-existed", "not-existed") | ||||
|  | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| @@ -108,13 +108,13 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test activate method | ||||
| 		g.Describe("Activate", func() { | ||||
| 			g.It("Should be success", func() { | ||||
| 				err := gitlab.Activate(&user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
| 				err := gitlab.Activate(nil, &user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
|  | ||||
| 			g.It("Should be failed, when token not given", func() { | ||||
| 				err := gitlab.Activate(&user, &repo, "http://example.com/api/hook/test/test") | ||||
| 				err := gitlab.Activate(nil, &user, &repo, "http://example.com/api/hook/test/test") | ||||
|  | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| @@ -123,7 +123,7 @@ func Test_Gitlab(t *testing.T) { | ||||
| 		// Test deactivate method | ||||
| 		g.Describe("Deactivate", func() { | ||||
| 			g.It("Should be success", func() { | ||||
| 				err := gitlab.Deactivate(&user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
| 				err := gitlab.Deactivate(nil, &user, &repo, "http://example.com/api/hook/test/test?access_token=token") | ||||
|  | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 			}) | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package gogs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| @@ -68,7 +69,7 @@ func New(opts Opts) (remote.Remote, error) { | ||||
|  | ||||
| // Login authenticates an account with Gogs using basic authentication. The | ||||
| // Gogs account details are returned when the user is successfully authenticated. | ||||
| func (c *client) Login(res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| func (c *client) Login(ctx context.Context, res http.ResponseWriter, req *http.Request) (*model.User, error) { | ||||
| 	var ( | ||||
| 		username = req.FormValue("username") | ||||
| 		password = req.FormValue("password") | ||||
| @@ -122,12 +123,12 @@ func (c *client) Login(res http.ResponseWriter, req *http.Request) (*model.User, | ||||
| } | ||||
|  | ||||
| // Auth is not supported by the Gogs driver. | ||||
| func (c *client) Auth(token, secret string) (string, error) { | ||||
| func (c *client) Auth(ctx context.Context, token, secret string) (string, error) { | ||||
| 	return "", fmt.Errorf("Not Implemented") | ||||
| } | ||||
|  | ||||
| // Teams is not supported by the Gogs driver. | ||||
| func (c *client) Teams(u *model.User) ([]*model.Team, error) { | ||||
| func (c *client) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| 	orgs, err := client.ListMyOrgs() | ||||
| 	if err != nil { | ||||
| @@ -142,7 +143,7 @@ func (c *client) Teams(u *model.User) ([]*model.Team, error) { | ||||
| } | ||||
|  | ||||
| // Repo returns the named Gogs repository. | ||||
| func (c *client) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
| func (c *client) Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| 	repo, err := client.GetRepo(owner, name) | ||||
| 	if err != nil { | ||||
| @@ -153,7 +154,7 @@ func (c *client) Repo(u *model.User, owner, name string) (*model.Repo, error) { | ||||
|  | ||||
| // Repos returns a list of all repositories for the Gogs account, including | ||||
| // organization repositories. | ||||
| func (c *client) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| func (c *client) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	repos := []*model.Repo{} | ||||
|  | ||||
| 	client := c.newClientToken(u.Token) | ||||
| @@ -169,7 +170,7 @@ func (c *client) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| } | ||||
|  | ||||
| // Perm returns the user permissions for the named Gogs repository. | ||||
| func (c *client) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| func (c *client) Perm(ctx context.Context, u *model.User, owner, name string) (*model.Perm, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| 	repo, err := client.GetRepo(owner, name) | ||||
| 	if err != nil { | ||||
| @@ -179,7 +180,7 @@ func (c *client) Perm(u *model.User, owner, name string) (*model.Perm, error) { | ||||
| } | ||||
|  | ||||
| // File fetches the file from the Gogs repository and returns its contents. | ||||
| func (c *client) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| func (c *client) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	client := c.newClientToken(u.Token) | ||||
| 	ref := b.Commit | ||||
|  | ||||
| @@ -202,12 +203,12 @@ func (c *client) File(u *model.User, r *model.Repo, b *model.Build, f string) ([ | ||||
| 	return cfg, err | ||||
| } | ||||
|  | ||||
| func (c *client) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| func (c *client) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	return nil, fmt.Errorf("Not implemented") | ||||
| } | ||||
|  | ||||
| // Status is not supported by the Gogs driver. | ||||
| func (c *client) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| func (c *client) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @@ -231,7 +232,7 @@ func (c *client) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
|  | ||||
| // Activate activates the repository by registering post-commit hooks with | ||||
| // the Gogs repository. | ||||
| func (c *client) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| func (c *client) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	config := map[string]string{ | ||||
| 		"url":          link, | ||||
| 		"secret":       r.Hash, | ||||
| @@ -250,7 +251,7 @@ func (c *client) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| } | ||||
|  | ||||
| // Deactivate is not supported by the Gogs driver. | ||||
| func (c *client) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
| func (c *client) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package gogs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
|  | ||||
| @@ -34,6 +35,7 @@ func Test_gogs(t *testing.T) { | ||||
| 		SkipVerify: true, | ||||
| 	}) | ||||
|  | ||||
| 	ctx := context.Background() | ||||
| 	g := goblin.Goblin(t) | ||||
| 	g.Describe("Gogs", func() { | ||||
|  | ||||
| @@ -88,7 +90,7 @@ func Test_gogs(t *testing.T) { | ||||
|  | ||||
| 		g.Describe("Requesting a repository", func() { | ||||
| 			g.It("Should return the repository details", func() { | ||||
| 				repo, err := c.Repo(fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				repo, err := c.Repo(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repo.Owner).Equal(fakeRepo.Owner) | ||||
| 				g.Assert(repo.Name).Equal(fakeRepo.Name) | ||||
| @@ -98,52 +100,52 @@ func Test_gogs(t *testing.T) { | ||||
| 				g.Assert(repo.Link).Equal("http://localhost/test_name/repo_name") | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Repo(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				_, err := c.Repo(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Requesting repository permissions", func() { | ||||
| 			g.It("Should return the permission details", func() { | ||||
| 				perm, err := c.Perm(fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				perm, err := c.Perm(ctx, fakeUser, fakeRepo.Owner, fakeRepo.Name) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(perm.Admin).IsTrue() | ||||
| 				g.Assert(perm.Push).IsTrue() | ||||
| 				g.Assert(perm.Pull).IsTrue() | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Perm(fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				_, err := c.Perm(ctx, fakeUser, fakeRepoNotFound.Owner, fakeRepoNotFound.Name) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.Describe("Requesting a repository list", func() { | ||||
| 			g.It("Should return the repository list", func() { | ||||
| 				repos, err := c.Repos(fakeUser) | ||||
| 				repos, err := c.Repos(ctx, fakeUser) | ||||
| 				g.Assert(err == nil).IsTrue() | ||||
| 				g.Assert(repos[0].Owner).Equal(fakeRepo.Owner) | ||||
| 				g.Assert(repos[0].Name).Equal(fakeRepo.Name) | ||||
| 				g.Assert(repos[0].FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name) | ||||
| 			}) | ||||
| 			g.It("Should handle a not found error", func() { | ||||
| 				_, err := c.Repos(fakeUserNoRepos) | ||||
| 				_, err := c.Repos(ctx, fakeUserNoRepos) | ||||
| 				g.Assert(err != nil).IsTrue() | ||||
| 			}) | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should register repositroy hooks", func() { | ||||
| 			err := c.Activate(fakeUser, fakeRepo, "http://localhost") | ||||
| 			err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return a repository file", func() { | ||||
| 			raw, err := c.File(fakeUser, fakeRepo, fakeBuild, ".drone.yml") | ||||
| 			raw, err := c.File(ctx, fakeUser, fakeRepo, fakeBuild, ".drone.yml") | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 			g.Assert(string(raw)).Equal("{ platform: linux/amd64 }") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return a repository file from a ref", func() { | ||||
| 			raw, err := c.File(fakeUser, fakeRepo, fakeBuildWithRef, ".drone.yml") | ||||
| 			raw, err := c.File(ctx, fakeUser, fakeRepo, fakeBuildWithRef, ".drone.yml") | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 			g.Assert(string(raw)).Equal("{ platform: linux/amd64 }") | ||||
| 		}) | ||||
| @@ -162,9 +164,9 @@ func Test_gogs(t *testing.T) { | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should return no-op for usupporeted features", func() { | ||||
| 			_, err1 := c.Auth("octocat", "4vyW6b49Z") | ||||
| 			err2 := c.Status(nil, nil, nil, "", nil) | ||||
| 			err3 := c.Deactivate(nil, nil, "") | ||||
| 			_, err1 := c.Auth(ctx, "octocat", "4vyW6b49Z") | ||||
| 			err2 := c.Status(ctx, nil, nil, nil, "", nil) | ||||
| 			err3 := c.Deactivate(ctx, nil, nil, "") | ||||
| 			g.Assert(err1 != nil).IsTrue() | ||||
| 			g.Assert(err2 == nil).IsTrue() | ||||
| 			g.Assert(err3 == nil).IsTrue() | ||||
|   | ||||
| @@ -1,296 +0,0 @@ | ||||
| // Code generated by mockery v0.0.0-dev. DO NOT EDIT. | ||||
|  | ||||
| package mocks | ||||
|  | ||||
| import ( | ||||
| 	http "net/http" | ||||
|  | ||||
| 	mock "github.com/stretchr/testify/mock" | ||||
| 	model "github.com/woodpecker-ci/woodpecker/server/model" | ||||
|  | ||||
| 	remote "github.com/woodpecker-ci/woodpecker/server/remote" | ||||
| ) | ||||
|  | ||||
| // Remote is an autogenerated mock type for the Remote type | ||||
| type Remote struct { | ||||
| 	mock.Mock | ||||
| } | ||||
|  | ||||
| // Activate provides a mock function with given fields: u, r, link | ||||
| func (_m *Remote) Activate(u *model.User, r *model.Repo, link string) error { | ||||
| 	ret := _m.Called(u, r, link) | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, *model.Repo, string) error); ok { | ||||
| 		r0 = rf(u, r, link) | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // Auth provides a mock function with given fields: token, secret | ||||
| func (_m *Remote) Auth(token string, secret string) (string, error) { | ||||
| 	ret := _m.Called(token, secret) | ||||
|  | ||||
| 	var r0 string | ||||
| 	if rf, ok := ret.Get(0).(func(string, string) string); ok { | ||||
| 		r0 = rf(token, secret) | ||||
| 	} else { | ||||
| 		r0 = ret.Get(0).(string) | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(string, string) error); ok { | ||||
| 		r1 = rf(token, secret) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Deactivate provides a mock function with given fields: u, r, link | ||||
| func (_m *Remote) Deactivate(u *model.User, r *model.Repo, link string) error { | ||||
| 	ret := _m.Called(u, r, link) | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, *model.Repo, string) error); ok { | ||||
| 		r0 = rf(u, r, link) | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // Dir provides a mock function with given fields: u, r, b, f | ||||
| func (_m *Remote) Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	ret := _m.Called(u, r, b, f) | ||||
|  | ||||
| 	var r0 []*remote.FileMeta | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, *model.Repo, *model.Build, string) []*remote.FileMeta); ok { | ||||
| 		r0 = rf(u, r, b, f) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]*remote.FileMeta) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User, *model.Repo, *model.Build, string) error); ok { | ||||
| 		r1 = rf(u, r, b, f) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // File provides a mock function with given fields: u, r, b, f | ||||
| func (_m *Remote) File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	ret := _m.Called(u, r, b, f) | ||||
|  | ||||
| 	var r0 []byte | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, *model.Repo, *model.Build, string) []byte); ok { | ||||
| 		r0 = rf(u, r, b, f) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]byte) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User, *model.Repo, *model.Build, string) error); ok { | ||||
| 		r1 = rf(u, r, b, f) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Hook provides a mock function with given fields: r | ||||
| func (_m *Remote) Hook(r *http.Request) (*model.Repo, *model.Build, error) { | ||||
| 	ret := _m.Called(r) | ||||
|  | ||||
| 	var r0 *model.Repo | ||||
| 	if rf, ok := ret.Get(0).(func(*http.Request) *model.Repo); ok { | ||||
| 		r0 = rf(r) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Repo) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 *model.Build | ||||
| 	if rf, ok := ret.Get(1).(func(*http.Request) *model.Build); ok { | ||||
| 		r1 = rf(r) | ||||
| 	} else { | ||||
| 		if ret.Get(1) != nil { | ||||
| 			r1 = ret.Get(1).(*model.Build) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r2 error | ||||
| 	if rf, ok := ret.Get(2).(func(*http.Request) error); ok { | ||||
| 		r2 = rf(r) | ||||
| 	} else { | ||||
| 		r2 = ret.Error(2) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1, r2 | ||||
| } | ||||
|  | ||||
| // Login provides a mock function with given fields: w, r | ||||
| func (_m *Remote) Login(w http.ResponseWriter, r *http.Request) (*model.User, error) { | ||||
| 	ret := _m.Called(w, r) | ||||
|  | ||||
| 	var r0 *model.User | ||||
| 	if rf, ok := ret.Get(0).(func(http.ResponseWriter, *http.Request) *model.User); ok { | ||||
| 		r0 = rf(w, r) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.User) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(http.ResponseWriter, *http.Request) error); ok { | ||||
| 		r1 = rf(w, r) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Netrc provides a mock function with given fields: u, r | ||||
| func (_m *Remote) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
| 	ret := _m.Called(u, r) | ||||
|  | ||||
| 	var r0 *model.Netrc | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, *model.Repo) *model.Netrc); ok { | ||||
| 		r0 = rf(u, r) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Netrc) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User, *model.Repo) error); ok { | ||||
| 		r1 = rf(u, r) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Perm provides a mock function with given fields: u, owner, repo | ||||
| func (_m *Remote) Perm(u *model.User, owner string, repo string) (*model.Perm, error) { | ||||
| 	ret := _m.Called(u, owner, repo) | ||||
|  | ||||
| 	var r0 *model.Perm | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, string, string) *model.Perm); ok { | ||||
| 		r0 = rf(u, owner, repo) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Perm) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User, string, string) error); ok { | ||||
| 		r1 = rf(u, owner, repo) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Repo provides a mock function with given fields: u, owner, repo | ||||
| func (_m *Remote) Repo(u *model.User, owner string, repo string) (*model.Repo, error) { | ||||
| 	ret := _m.Called(u, owner, repo) | ||||
|  | ||||
| 	var r0 *model.Repo | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, string, string) *model.Repo); ok { | ||||
| 		r0 = rf(u, owner, repo) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Repo) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User, string, string) error); ok { | ||||
| 		r1 = rf(u, owner, repo) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Repos provides a mock function with given fields: u | ||||
| func (_m *Remote) Repos(u *model.User) ([]*model.Repo, error) { | ||||
| 	ret := _m.Called(u) | ||||
|  | ||||
| 	var r0 []*model.Repo | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User) []*model.Repo); ok { | ||||
| 		r0 = rf(u) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]*model.Repo) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User) error); ok { | ||||
| 		r1 = rf(u) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Status provides a mock function with given fields: u, r, b, link, proc | ||||
| func (_m *Remote) Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	ret := _m.Called(u, r, b, link, proc) | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, *model.Repo, *model.Build, string, *model.Proc) error); ok { | ||||
| 		r0 = rf(u, r, b, link, proc) | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // Teams provides a mock function with given fields: u | ||||
| func (_m *Remote) Teams(u *model.User) ([]*model.Team, error) { | ||||
| 	ret := _m.Called(u) | ||||
|  | ||||
| 	var r0 []*model.Team | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User) []*model.Team); ok { | ||||
| 		r0 = rf(u) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]*model.Team) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User) error); ok { | ||||
| 		r1 = rf(u) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
							
								
								
									
										298
									
								
								server/remote/mocks/remote.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								server/remote/mocks/remote.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,298 @@ | ||||
| // Code generated by mockery v1.0.0. DO NOT EDIT. | ||||
|  | ||||
| package mocks | ||||
|  | ||||
| import ( | ||||
| 	context "context" | ||||
| 	http "net/http" | ||||
|  | ||||
| 	mock "github.com/stretchr/testify/mock" | ||||
|  | ||||
| 	model "github.com/woodpecker-ci/woodpecker/server/model" | ||||
|  | ||||
| 	remote "github.com/woodpecker-ci/woodpecker/server/remote" | ||||
| ) | ||||
|  | ||||
| // Remote is an autogenerated mock type for the Remote type | ||||
| type Remote struct { | ||||
| 	mock.Mock | ||||
| } | ||||
|  | ||||
| // Activate provides a mock function with given fields: ctx, u, r, link | ||||
| func (_m *Remote) Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	ret := _m.Called(ctx, u, r, link) | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, string) error); ok { | ||||
| 		r0 = rf(ctx, u, r, link) | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // Auth provides a mock function with given fields: ctx, token, secret | ||||
| func (_m *Remote) Auth(ctx context.Context, token string, secret string) (string, error) { | ||||
| 	ret := _m.Called(ctx, token, secret) | ||||
|  | ||||
| 	var r0 string | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, string, string) string); ok { | ||||
| 		r0 = rf(ctx, token, secret) | ||||
| 	} else { | ||||
| 		r0 = ret.Get(0).(string) | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { | ||||
| 		r1 = rf(ctx, token, secret) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Deactivate provides a mock function with given fields: ctx, u, r, link | ||||
| func (_m *Remote) Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	ret := _m.Called(ctx, u, r, link) | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, string) error); ok { | ||||
| 		r0 = rf(ctx, u, r, link) | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // Dir provides a mock function with given fields: ctx, u, r, b, f | ||||
| func (_m *Remote) Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*remote.FileMeta, error) { | ||||
| 	ret := _m.Called(ctx, u, r, b, f) | ||||
|  | ||||
| 	var r0 []*remote.FileMeta | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, *model.Build, string) []*remote.FileMeta); ok { | ||||
| 		r0 = rf(ctx, u, r, b, f) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]*remote.FileMeta) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, *model.User, *model.Repo, *model.Build, string) error); ok { | ||||
| 		r1 = rf(ctx, u, r, b, f) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // File provides a mock function with given fields: ctx, u, r, b, f | ||||
| func (_m *Remote) File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) { | ||||
| 	ret := _m.Called(ctx, u, r, b, f) | ||||
|  | ||||
| 	var r0 []byte | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, *model.Build, string) []byte); ok { | ||||
| 		r0 = rf(ctx, u, r, b, f) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]byte) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, *model.User, *model.Repo, *model.Build, string) error); ok { | ||||
| 		r1 = rf(ctx, u, r, b, f) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Hook provides a mock function with given fields: r | ||||
| func (_m *Remote) Hook(r *http.Request) (*model.Repo, *model.Build, error) { | ||||
| 	ret := _m.Called(r) | ||||
|  | ||||
| 	var r0 *model.Repo | ||||
| 	if rf, ok := ret.Get(0).(func(*http.Request) *model.Repo); ok { | ||||
| 		r0 = rf(r) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Repo) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 *model.Build | ||||
| 	if rf, ok := ret.Get(1).(func(*http.Request) *model.Build); ok { | ||||
| 		r1 = rf(r) | ||||
| 	} else { | ||||
| 		if ret.Get(1) != nil { | ||||
| 			r1 = ret.Get(1).(*model.Build) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r2 error | ||||
| 	if rf, ok := ret.Get(2).(func(*http.Request) error); ok { | ||||
| 		r2 = rf(r) | ||||
| 	} else { | ||||
| 		r2 = ret.Error(2) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1, r2 | ||||
| } | ||||
|  | ||||
| // Login provides a mock function with given fields: ctx, w, r | ||||
| func (_m *Remote) Login(ctx context.Context, w http.ResponseWriter, r *http.Request) (*model.User, error) { | ||||
| 	ret := _m.Called(ctx, w, r) | ||||
|  | ||||
| 	var r0 *model.User | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, http.ResponseWriter, *http.Request) *model.User); ok { | ||||
| 		r0 = rf(ctx, w, r) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.User) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, http.ResponseWriter, *http.Request) error); ok { | ||||
| 		r1 = rf(ctx, w, r) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Netrc provides a mock function with given fields: u, r | ||||
| func (_m *Remote) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) { | ||||
| 	ret := _m.Called(u, r) | ||||
|  | ||||
| 	var r0 *model.Netrc | ||||
| 	if rf, ok := ret.Get(0).(func(*model.User, *model.Repo) *model.Netrc); ok { | ||||
| 		r0 = rf(u, r) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Netrc) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(*model.User, *model.Repo) error); ok { | ||||
| 		r1 = rf(u, r) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Perm provides a mock function with given fields: ctx, u, owner, repo | ||||
| func (_m *Remote) Perm(ctx context.Context, u *model.User, owner string, repo string) (*model.Perm, error) { | ||||
| 	ret := _m.Called(ctx, u, owner, repo) | ||||
|  | ||||
| 	var r0 *model.Perm | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User, string, string) *model.Perm); ok { | ||||
| 		r0 = rf(ctx, u, owner, repo) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Perm) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, *model.User, string, string) error); ok { | ||||
| 		r1 = rf(ctx, u, owner, repo) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Repo provides a mock function with given fields: ctx, u, owner, name | ||||
| func (_m *Remote) Repo(ctx context.Context, u *model.User, owner string, name string) (*model.Repo, error) { | ||||
| 	ret := _m.Called(ctx, u, owner, name) | ||||
|  | ||||
| 	var r0 *model.Repo | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User, string, string) *model.Repo); ok { | ||||
| 		r0 = rf(ctx, u, owner, name) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).(*model.Repo) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, *model.User, string, string) error); ok { | ||||
| 		r1 = rf(ctx, u, owner, name) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Repos provides a mock function with given fields: ctx, u | ||||
| func (_m *Remote) Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	ret := _m.Called(ctx, u) | ||||
|  | ||||
| 	var r0 []*model.Repo | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User) []*model.Repo); ok { | ||||
| 		r0 = rf(ctx, u) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]*model.Repo) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, *model.User) error); ok { | ||||
| 		r1 = rf(ctx, u) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
|  | ||||
| // Status provides a mock function with given fields: ctx, u, r, b, link, proc | ||||
| func (_m *Remote) Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	ret := _m.Called(ctx, u, r, b, link, proc) | ||||
|  | ||||
| 	var r0 error | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User, *model.Repo, *model.Build, string, *model.Proc) error); ok { | ||||
| 		r0 = rf(ctx, u, r, b, link, proc) | ||||
| 	} else { | ||||
| 		r0 = ret.Error(0) | ||||
| 	} | ||||
|  | ||||
| 	return r0 | ||||
| } | ||||
|  | ||||
| // Teams provides a mock function with given fields: ctx, u | ||||
| func (_m *Remote) Teams(ctx context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	ret := _m.Called(ctx, u) | ||||
|  | ||||
| 	var r0 []*model.Team | ||||
| 	if rf, ok := ret.Get(0).(func(context.Context, *model.User) []*model.Team); ok { | ||||
| 		r0 = rf(ctx, u) | ||||
| 	} else { | ||||
| 		if ret.Get(0) != nil { | ||||
| 			r0 = ret.Get(0).([]*model.Team) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var r1 error | ||||
| 	if rf, ok := ret.Get(1).(func(context.Context, *model.User) error); ok { | ||||
| 		r1 = rf(ctx, u) | ||||
| 	} else { | ||||
| 		r1 = ret.Error(1) | ||||
| 	} | ||||
|  | ||||
| 	return r0, r1 | ||||
| } | ||||
| @@ -14,63 +14,61 @@ | ||||
|  | ||||
| package remote | ||||
|  | ||||
| //go:generate mockery -name Remote -output mock -case=underscore | ||||
| //go:generate mockery -name Remote -output mocks -case=underscore | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/woodpecker-ci/woodpecker/server/model" | ||||
|  | ||||
| 	"golang.org/x/net/context" | ||||
| ) | ||||
|  | ||||
| // TODO: use pagination | ||||
| // TODO: use context | ||||
| // TODO: add Driver() who return source forge back | ||||
|  | ||||
| type Remote interface { | ||||
| 	// Login authenticates the session and returns the | ||||
| 	// remote user details. | ||||
| 	Login(w http.ResponseWriter, r *http.Request) (*model.User, error) | ||||
| 	Login(ctx context.Context, w http.ResponseWriter, r *http.Request) (*model.User, error) | ||||
|  | ||||
| 	// Auth authenticates the session and returns the remote user | ||||
| 	// login for the given token and secret | ||||
| 	Auth(token, secret string) (string, error) | ||||
| 	Auth(ctx context.Context, token, secret string) (string, error) | ||||
|  | ||||
| 	// Teams fetches a list of team memberships from the remote system. | ||||
| 	Teams(u *model.User) ([]*model.Team, error) | ||||
| 	Teams(ctx context.Context, u *model.User) ([]*model.Team, error) | ||||
|  | ||||
| 	// Repo fetches the named repository from the remote system. | ||||
| 	Repo(u *model.User, owner, repo string) (*model.Repo, error) | ||||
| 	Repo(ctx context.Context, u *model.User, owner, name string) (*model.Repo, error) | ||||
|  | ||||
| 	// Repos fetches a list of repos from the remote system. | ||||
| 	Repos(u *model.User) ([]*model.Repo, error) | ||||
| 	Repos(ctx context.Context, u *model.User) ([]*model.Repo, error) | ||||
|  | ||||
| 	// Perm fetches the named repository permissions from | ||||
| 	// the remote system for the specified user. | ||||
| 	Perm(u *model.User, owner, repo string) (*model.Perm, error) | ||||
| 	Perm(ctx context.Context, u *model.User, owner, repo string) (*model.Perm, error) | ||||
|  | ||||
| 	// File fetches a file from the remote repository and returns in string | ||||
| 	// format. | ||||
| 	File(u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) | ||||
| 	File(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]byte, error) | ||||
|  | ||||
| 	// Dir fetches a folder from the remote repository | ||||
| 	Dir(u *model.User, r *model.Repo, b *model.Build, f string) ([]*FileMeta, error) | ||||
| 	Dir(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, f string) ([]*FileMeta, error) | ||||
|  | ||||
| 	// Status sends the commit status to the remote system. | ||||
| 	// An example would be the GitHub pull request status. | ||||
| 	Status(u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error | ||||
| 	Status(ctx context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error | ||||
|  | ||||
| 	// Netrc returns a .netrc file that can be used to clone | ||||
| 	// private repositories from a remote system. | ||||
| 	Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) | ||||
|  | ||||
| 	// Activate activates a repository by creating the post-commit hook. | ||||
| 	Activate(u *model.User, r *model.Repo, link string) error | ||||
| 	Activate(ctx context.Context, u *model.User, r *model.Repo, link string) error | ||||
|  | ||||
| 	// Deactivate deactivates a repository by removing all previously created | ||||
| 	// post-commit hooks matching the given link. | ||||
| 	Deactivate(u *model.User, r *model.Repo, link string) error | ||||
| 	Deactivate(ctx context.Context, u *model.User, r *model.Repo, link string) error | ||||
|  | ||||
| 	// Hook parses the post-commit hook from the Request body and returns the | ||||
| 	// required data in a standard format. | ||||
| @@ -93,46 +91,46 @@ func (a ByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] } | ||||
| // returns true if the token was refreshed, false if the token was not refreshed, | ||||
| // and error if it failed to refersh. | ||||
| type Refresher interface { | ||||
| 	Refresh(*model.User) (bool, error) | ||||
| 	Refresh(context.Context, *model.User) (bool, error) | ||||
| } | ||||
|  | ||||
| // Login authenticates the session and returns the | ||||
| // remote user details. | ||||
| func Login(c context.Context, w http.ResponseWriter, r *http.Request) (*model.User, error) { | ||||
| 	return FromContext(c).Login(w, r) | ||||
| 	return FromContext(c).Login(c, w, r) | ||||
| } | ||||
|  | ||||
| // Auth authenticates the session and returns the remote user | ||||
| // login for the given token and secret | ||||
| func Auth(c context.Context, token, secret string) (string, error) { | ||||
| 	return FromContext(c).Auth(token, secret) | ||||
| 	return FromContext(c).Auth(c, token, secret) | ||||
| } | ||||
|  | ||||
| // Teams fetches a list of team memberships from the remote system. | ||||
| func Teams(c context.Context, u *model.User) ([]*model.Team, error) { | ||||
| 	return FromContext(c).Teams(u) | ||||
| 	return FromContext(c).Teams(c, u) | ||||
| } | ||||
|  | ||||
| // Repo fetches the named repository from the remote system. | ||||
| func Repo(c context.Context, u *model.User, owner, repo string) (*model.Repo, error) { | ||||
| 	return FromContext(c).Repo(u, owner, repo) | ||||
| 	return FromContext(c).Repo(c, u, owner, repo) | ||||
| } | ||||
|  | ||||
| // Repos fetches a list of repos from the remote system. | ||||
| func Repos(c context.Context, u *model.User) ([]*model.Repo, error) { | ||||
| 	return FromContext(c).Repos(u) | ||||
| 	return FromContext(c).Repos(c, u) | ||||
| } | ||||
|  | ||||
| // Perm fetches the named repository permissions from | ||||
| // the remote system for the specified user. | ||||
| func Perm(c context.Context, u *model.User, owner, repo string) (*model.Perm, error) { | ||||
| 	return FromContext(c).Perm(u, owner, repo) | ||||
| 	return FromContext(c).Perm(c, u, owner, repo) | ||||
| } | ||||
|  | ||||
| // Status sends the commit status to the remote system. | ||||
| // An example would be the GitHub pull request status. | ||||
| func Status(c context.Context, u *model.User, r *model.Repo, b *model.Build, link string, proc *model.Proc) error { | ||||
| 	return FromContext(c).Status(u, r, b, link, proc) | ||||
| 	return FromContext(c).Status(c, u, r, b, link, proc) | ||||
| } | ||||
|  | ||||
| // Netrc returns a .netrc file that can be used to clone | ||||
| @@ -144,13 +142,13 @@ func Netrc(c context.Context, u *model.User, r *model.Repo) (*model.Netrc, error | ||||
| // Activate activates a repository by creating the post-commit hook and | ||||
| // adding the SSH deploy key, if applicable. | ||||
| func Activate(c context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	return FromContext(c).Activate(u, r, link) | ||||
| 	return FromContext(c).Activate(c, u, r, link) | ||||
| } | ||||
|  | ||||
| // Deactivate removes a repository by removing all the post-commit hooks | ||||
| // which are equal to link and removing the SSH deploy key. | ||||
| func Deactivate(c context.Context, u *model.User, r *model.Repo, link string) error { | ||||
| 	return FromContext(c).Deactivate(u, r, link) | ||||
| 	return FromContext(c).Deactivate(c, u, r, link) | ||||
| } | ||||
|  | ||||
| // Hook parses the post-commit hook from the Request body | ||||
| @@ -168,5 +166,5 @@ func Refresh(c context.Context, u *model.User) (bool, error) { | ||||
| 	if !ok { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	return refresher.Refresh(u) | ||||
| 	return refresher.Refresh(c, u) | ||||
| } | ||||
|   | ||||
| @@ -95,7 +95,7 @@ func SetPerm() gin.HandlerFunc { | ||||
| 					user.Login, repo.FullName, err) | ||||
| 			} | ||||
| 			if time.Unix(perm.Synced, 0).Add(time.Hour).Before(time.Now()) { | ||||
| 				perm, err = remote.FromContext(c).Perm(user, repo.Owner, repo.Name) | ||||
| 				perm, err = remote.FromContext(c).Perm(c, user, repo.Owner, repo.Name) | ||||
| 				if err == nil { | ||||
| 					log.Debugf("Synced user permission for %s %s", user.Login, repo.FullName) | ||||
| 					perm.Repo = repo.FullName | ||||
|   | ||||
| @@ -52,7 +52,7 @@ func Refresh(c *gin.Context) { | ||||
| 	// attempts to refresh the access token. If the | ||||
| 	// token is refreshed, we must also persist to the | ||||
| 	// database. | ||||
| 	ok, _ = refresher.Refresh(user) | ||||
| 	ok, _ = refresher.Refresh(c, user) | ||||
| 	if ok { | ||||
| 		err := store.UpdateUser(c, user) | ||||
| 		if err != nil { | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| package shared | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| @@ -27,81 +29,90 @@ func NewConfigFetcher(remote remote.Remote, user *model.User, repo *model.Repo, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Fetch | ||||
| // TODO: dedupe code | ||||
| func (cf *configFetcher) Fetch() (files []*remote.FileMeta, err error) { | ||||
| 	var file []byte | ||||
| 	config := strings.TrimSpace(cf.repo.Config) | ||||
|  | ||||
| // Fetch pipeline config from source forge | ||||
| func (cf *configFetcher) Fetch(ctx context.Context) (files []*remote.FileMeta, err error) { | ||||
| 	logrus.Tracef("Start Fetching config for '%s'", cf.repo.FullName) | ||||
|  | ||||
| 	for i := 0; i < 5; i++ { | ||||
| 		select { | ||||
| 		case <-time.After(time.Second * time.Duration(i)): | ||||
| 			if len(config) > 0 { | ||||
| 				// either a file | ||||
| 				if !strings.HasSuffix(config, "/") { | ||||
| 					file, err = cf.remote_.File(cf.user, cf.repo, cf.build, config) | ||||
| 					if err == nil && len(file) != 0 { | ||||
| 						logrus.Tracef("ConfigFetch[%s]: found file '%s'", cf.repo.FullName, config) | ||||
| 						return []*remote.FileMeta{{ | ||||
| 							Name: config, | ||||
| 							Data: file, | ||||
| 						}}, nil | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				// or a folder | ||||
| 				files, err = cf.remote_.Dir(cf.user, cf.repo, cf.build, strings.TrimSuffix(config, "/")) | ||||
| 				if err == nil { | ||||
| 					logrus.Tracef("ConfigFetch[%s]: found %d files in '%s'", cf.repo.FullName, len(files), config) | ||||
| 					return filterPipelineFiles(files), nil | ||||
| 				} | ||||
| 			} else { | ||||
| 				logrus.Tracef("ConfigFetch[%s]: user did not defined own config follow default procedure", cf.repo.FullName) | ||||
| 				// no user defined config so try .woodpecker/*.yml -> .woodpecker.yml -> .drone.yml | ||||
|  | ||||
| 				// test .woodpecker/ folder | ||||
| 				// if folder is not supported we will get a "Not implemented" error and continue | ||||
| 				config = ".woodpecker" | ||||
| 				files, err = cf.remote_.Dir(cf.user, cf.repo, cf.build, config) | ||||
| 				logrus.Tracef("ConfigFetch[%s]: found %d files in '%s'", cf.repo.FullName, len(files), config) | ||||
| 				files = filterPipelineFiles(files) | ||||
| 				if err == nil && len(files) != 0 { | ||||
| 					return files, nil | ||||
| 				} | ||||
|  | ||||
| 				config = ".woodpecker.yml" | ||||
| 				file, err = cf.remote_.File(cf.user, cf.repo, cf.build, config) | ||||
| 				if err == nil && len(file) != 0 { | ||||
| 					logrus.Tracef("ConfigFetch[%s]: found file '%s'", cf.repo.FullName, config) | ||||
| 					return []*remote.FileMeta{{ | ||||
| 						Name: ".woodpecker.yml", | ||||
| 						Data: file, | ||||
| 					}}, nil | ||||
| 				} | ||||
|  | ||||
| 				config = ".drone.yml" | ||||
| 				file, err = cf.remote_.File(cf.user, cf.repo, cf.build, config) | ||||
| 				if err == nil && len(file) != 0 { | ||||
| 					logrus.Tracef("ConfigFetch[%s]: found file '%s'", cf.repo.FullName, config) | ||||
| 					return []*remote.FileMeta{{ | ||||
| 						Name: ".drone.yml", | ||||
| 						Data: file, | ||||
| 					}}, nil | ||||
| 				} | ||||
|  | ||||
| 				if err == nil && len(files) == 0 { | ||||
| 					return nil, fmt.Errorf("ConfigFetcher: Fallback did not found config") | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// TODO: retry loop is inactive and could maybe be fixed/deleted | ||||
| 			return nil, err | ||||
| 	// try to fetch 3 times, timeout is one second longer each time | ||||
| 	for i := 0; i < 3; i++ { | ||||
| 		files, err = cf.fetch(ctx, time.Second*time.Duration(i), strings.TrimSpace(cf.repo.Config)) | ||||
| 		if errors.Is(err, context.DeadlineExceeded) { | ||||
| 			continue | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // fetch config by timeout | ||||
| // TODO: dedupe code | ||||
| func (cf *configFetcher) fetch(c context.Context, timeout time.Duration, config string) ([]*remote.FileMeta, error) { | ||||
| 	ctx, cancel := context.WithTimeout(c, timeout) | ||||
| 	defer cancel() | ||||
|  | ||||
| 	if len(config) > 0 { | ||||
| 		logrus.Tracef("ConfigFetch[%s]: use user config '%s'", cf.repo.FullName, config) | ||||
| 		// either a file | ||||
| 		if !strings.HasSuffix(config, "/") { | ||||
| 			file, err := cf.remote_.File(ctx, cf.user, cf.repo, cf.build, config) | ||||
| 			if err == nil && len(file) != 0 { | ||||
| 				logrus.Tracef("ConfigFetch[%s]: found file '%s'", cf.repo.FullName, config) | ||||
| 				return []*remote.FileMeta{{ | ||||
| 					Name: config, | ||||
| 					Data: file, | ||||
| 				}}, nil | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// or a folder | ||||
| 		files, err := cf.remote_.Dir(ctx, cf.user, cf.repo, cf.build, strings.TrimSuffix(config, "/")) | ||||
| 		if err == nil && len(files) != 0 { | ||||
| 			logrus.Tracef("ConfigFetch[%s]: found %d files in '%s'", cf.repo.FullName, len(files), config) | ||||
| 			return filterPipelineFiles(files), nil | ||||
| 		} | ||||
|  | ||||
| 		return nil, fmt.Errorf("config '%s' not found: %s", config, err) | ||||
| 	} | ||||
|  | ||||
| 	return []*remote.FileMeta{}, nil | ||||
| 	logrus.Tracef("ConfigFetch[%s]: user did not defined own config follow default procedure", cf.repo.FullName) | ||||
| 	// no user defined config so try .woodpecker/*.yml -> .woodpecker.yml -> .drone.yml | ||||
|  | ||||
| 	// test .woodpecker/ folder | ||||
| 	// if folder is not supported we will get a "Not implemented" error and continue | ||||
| 	config = ".woodpecker" | ||||
| 	files, err := cf.remote_.Dir(ctx, cf.user, cf.repo, cf.build, config) | ||||
| 	files = filterPipelineFiles(files) | ||||
| 	if err == nil && len(files) != 0 { | ||||
| 		logrus.Tracef("ConfigFetch[%s]: found %d files in '%s'", cf.repo.FullName, len(files), config) | ||||
| 		return files, nil | ||||
| 	} | ||||
|  | ||||
| 	config = ".woodpecker.yml" | ||||
| 	file, err := cf.remote_.File(ctx, cf.user, cf.repo, cf.build, config) | ||||
| 	if err == nil && len(file) != 0 { | ||||
| 		logrus.Tracef("ConfigFetch[%s]: found file '%s'", cf.repo.FullName, config) | ||||
| 		return []*remote.FileMeta{{ | ||||
| 			Name: config, | ||||
| 			Data: file, | ||||
| 		}}, nil | ||||
| 	} | ||||
|  | ||||
| 	config = ".drone.yml" | ||||
| 	file, err = cf.remote_.File(ctx, cf.user, cf.repo, cf.build, config) | ||||
| 	if err == nil && len(file) != 0 { | ||||
| 		logrus.Tracef("ConfigFetch[%s]: found file '%s'", cf.repo.FullName, config) | ||||
| 		return []*remote.FileMeta{{ | ||||
| 			Name: config, | ||||
| 			Data: file, | ||||
| 		}}, nil | ||||
| 	} | ||||
|  | ||||
| 	select { | ||||
| 	case <-ctx.Done(): | ||||
| 		return nil, ctx.Err() | ||||
| 	default: | ||||
| 		return []*remote.FileMeta{}, fmt.Errorf("ConfigFetcher: Fallback did not found config: %s", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func filterPipelineFiles(files []*remote.FileMeta) []*remote.FileMeta { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package shared_test | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"path/filepath" | ||||
| 	"testing" | ||||
| @@ -216,7 +217,7 @@ func TestFetch(t *testing.T) { | ||||
| 			r := new(mocks.Remote) | ||||
| 			dirs := map[string][]*remote.FileMeta{} | ||||
| 			for _, file := range tt.files { | ||||
| 				r.On("File", mock.Anything, mock.Anything, mock.Anything, file.name).Return(file.data, nil) | ||||
| 				r.On("File", mock.Anything, mock.Anything, mock.Anything, mock.Anything, file.name).Return(file.data, nil) | ||||
| 				path := filepath.Dir(file.name) | ||||
| 				if path != "." { | ||||
| 					dirs[path] = append(dirs[path], &remote.FileMeta{ | ||||
| @@ -227,12 +228,12 @@ func TestFetch(t *testing.T) { | ||||
| 			} | ||||
|  | ||||
| 			for path, files := range dirs { | ||||
| 				r.On("Dir", mock.Anything, mock.Anything, mock.Anything, path).Return(files, nil) | ||||
| 				r.On("Dir", mock.Anything, mock.Anything, mock.Anything, mock.Anything, path).Return(files, nil) | ||||
| 			} | ||||
|  | ||||
| 			// if the previous mocks do not match return not found errors | ||||
| 			r.On("File", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("File not found")) | ||||
| 			r.On("Dir", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("Directory not found")) | ||||
| 			r.On("File", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("File not found")) | ||||
| 			r.On("Dir", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, fmt.Errorf("Directory not found")) | ||||
|  | ||||
| 			configFetcher := shared.NewConfigFetcher( | ||||
| 				r, | ||||
| @@ -240,7 +241,7 @@ func TestFetch(t *testing.T) { | ||||
| 				repo, | ||||
| 				&model.Build{Commit: "89ab7b2d6bfb347144ac7c557e638ab402848fee"}, | ||||
| 			) | ||||
| 			files, err := configFetcher.Fetch() | ||||
| 			files, err := configFetcher.Fetch(context.Background()) | ||||
| 			if tt.expectedError && err == nil { | ||||
| 				t.Fatal("expected an error") | ||||
| 			} else if !tt.expectedError && err != nil { | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| package shared | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/woodpecker-ci/woodpecker/server/model" | ||||
| @@ -24,7 +25,7 @@ import ( | ||||
|  | ||||
| // UserSyncer syncs the user repository and permissions. | ||||
| type UserSyncer interface { | ||||
| 	Sync(user *model.User) error | ||||
| 	Sync(ctx context.Context, user *model.User) error | ||||
| } | ||||
|  | ||||
| type Syncer struct { | ||||
| @@ -62,9 +63,9 @@ func (s *Syncer) SetFilter(fn FilterFunc) { | ||||
| 	s.Match = fn | ||||
| } | ||||
|  | ||||
| func (s *Syncer) Sync(user *model.User) error { | ||||
| func (s *Syncer) Sync(ctx context.Context, user *model.User) error { | ||||
| 	unix := time.Now().Unix() - (3601) // force immediate expiration. note 1 hour expiration is hard coded at the moment | ||||
| 	repos, err := s.Remote.Repos(user) | ||||
| 	repos, err := s.Remote.Repos(ctx, user) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user