You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			254 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2021 Woodpecker Authors
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //      http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package gitlab
 | |
| 
 | |
| import (
 | |
| 	"crypto/md5"
 | |
| 	"encoding/hex"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/xanzy/go-gitlab"
 | |
| 
 | |
| 	"github.com/woodpecker-ci/woodpecker/server/model"
 | |
| 	"github.com/woodpecker-ci/woodpecker/shared/utils"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	mergeRefs = "refs/merge-requests/%d/head" // merge request merged with base
 | |
| )
 | |
| 
 | |
| func (g *Gitlab) convertGitlabRepo(_repo *gitlab.Project) (*model.Repo, error) {
 | |
| 	parts := strings.Split(_repo.PathWithNamespace, "/")
 | |
| 	// TODO(648) save repo id (support nested repos)
 | |
| 	owner := strings.Join(parts[:len(parts)-1], "/")
 | |
| 	name := parts[len(parts)-1]
 | |
| 	repo := &model.Repo{
 | |
| 		Owner:      owner,
 | |
| 		Name:       name,
 | |
| 		FullName:   _repo.PathWithNamespace,
 | |
| 		Avatar:     _repo.AvatarURL,
 | |
| 		Link:       _repo.WebURL,
 | |
| 		Clone:      _repo.HTTPURLToRepo,
 | |
| 		Branch:     _repo.DefaultBranch,
 | |
| 		Visibility: model.RepoVisibly(_repo.Visibility),
 | |
| 	}
 | |
| 
 | |
| 	if len(repo.Branch) == 0 { // TODO: do we need that?
 | |
| 		repo.Branch = "master"
 | |
| 	}
 | |
| 
 | |
| 	if len(repo.Avatar) != 0 && !strings.HasPrefix(repo.Avatar, "http") {
 | |
| 		repo.Avatar = fmt.Sprintf("%s/%s", g.URL, repo.Avatar)
 | |
| 	}
 | |
| 
 | |
| 	if g.PrivateMode {
 | |
| 		repo.IsSCMPrivate = true
 | |
| 	} else {
 | |
| 		repo.IsSCMPrivate = !_repo.Public
 | |
| 	}
 | |
| 
 | |
| 	return repo, nil
 | |
| }
 | |
| 
 | |
| func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (int, *model.Repo, *model.Build, error) {
 | |
| 	repo := &model.Repo{}
 | |
| 	build := &model.Build{}
 | |
| 
 | |
| 	target := hook.ObjectAttributes.Target
 | |
| 	source := hook.ObjectAttributes.Source
 | |
| 	obj := hook.ObjectAttributes
 | |
| 
 | |
| 	if target == nil && source == nil {
 | |
| 		return 0, nil, nil, fmt.Errorf("target and source keys expected in merge request hook")
 | |
| 	} else if target == nil {
 | |
| 		return 0, nil, nil, fmt.Errorf("target key expected in merge request hook")
 | |
| 	} else if source == nil {
 | |
| 		return 0, nil, nil, fmt.Errorf("source key expected in merge request hook")
 | |
| 	}
 | |
| 
 | |
| 	if target.PathWithNamespace != "" {
 | |
| 		var err error
 | |
| 		if repo.Owner, repo.Name, err = extractFromPath(target.PathWithNamespace); err != nil {
 | |
| 			return 0, nil, nil, err
 | |
| 		}
 | |
| 		repo.FullName = target.PathWithNamespace
 | |
| 	} else {
 | |
| 		repo.Owner = req.FormValue("owner")
 | |
| 		repo.Name = req.FormValue("name")
 | |
| 		repo.FullName = fmt.Sprintf("%s/%s", repo.Owner, repo.Name)
 | |
| 	}
 | |
| 
 | |
| 	repo.Link = target.WebURL
 | |
| 
 | |
| 	if target.GitHTTPURL != "" {
 | |
| 		repo.Clone = target.GitHTTPURL
 | |
| 	} else {
 | |
| 		repo.Clone = target.HTTPURL
 | |
| 	}
 | |
| 
 | |
| 	if target.DefaultBranch != "" {
 | |
| 		repo.Branch = target.DefaultBranch
 | |
| 	} else {
 | |
| 		repo.Branch = "master"
 | |
| 	}
 | |
| 
 | |
| 	if target.AvatarURL != "" {
 | |
| 		repo.Avatar = target.AvatarURL
 | |
| 	}
 | |
| 
 | |
| 	build.Event = model.EventPull
 | |
| 
 | |
| 	lastCommit := obj.LastCommit
 | |
| 
 | |
| 	build.Message = lastCommit.Message
 | |
| 	build.Commit = lastCommit.ID
 | |
| 	build.Remote = obj.Source.HTTPURL
 | |
| 
 | |
| 	build.Ref = fmt.Sprintf(mergeRefs, obj.IID)
 | |
| 	build.Branch = obj.SourceBranch
 | |
| 
 | |
| 	author := lastCommit.Author
 | |
| 
 | |
| 	build.Author = author.Name
 | |
| 	build.Email = author.Email
 | |
| 
 | |
| 	if len(build.Email) != 0 {
 | |
| 		build.Avatar = getUserAvatar(build.Email)
 | |
| 	}
 | |
| 
 | |
| 	build.Title = obj.Title
 | |
| 	build.Link = obj.URL
 | |
| 
 | |
| 	return obj.IID, repo, build, nil
 | |
| }
 | |
| 
 | |
| func convertPushHook(hook *gitlab.PushEvent) (*model.Repo, *model.Build, error) {
 | |
| 	repo := &model.Repo{}
 | |
| 	build := &model.Build{}
 | |
| 
 | |
| 	var err error
 | |
| 	if repo.Owner, repo.Name, err = extractFromPath(hook.Project.PathWithNamespace); err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 
 | |
| 	repo.Avatar = hook.Project.AvatarURL
 | |
| 	repo.Link = hook.Project.WebURL
 | |
| 	repo.Clone = hook.Project.GitHTTPURL
 | |
| 	repo.FullName = hook.Project.PathWithNamespace
 | |
| 	repo.Branch = hook.Project.DefaultBranch
 | |
| 
 | |
| 	switch hook.Project.Visibility {
 | |
| 	case gitlab.PrivateVisibility:
 | |
| 		repo.IsSCMPrivate = true
 | |
| 	case gitlab.InternalVisibility:
 | |
| 		repo.IsSCMPrivate = true
 | |
| 	case gitlab.PublicVisibility:
 | |
| 		repo.IsSCMPrivate = false
 | |
| 	}
 | |
| 
 | |
| 	build.Event = model.EventPush
 | |
| 	build.Commit = hook.After
 | |
| 	build.Branch = strings.TrimPrefix(hook.Ref, "refs/heads/")
 | |
| 	build.Ref = hook.Ref
 | |
| 
 | |
| 	// assume a capacity of 4 changed files per commit
 | |
| 	files := make([]string, 0, len(hook.Commits)*4)
 | |
| 	for _, cm := range hook.Commits {
 | |
| 		if hook.After == cm.ID {
 | |
| 			build.Author = cm.Author.Name
 | |
| 			build.Email = cm.Author.Email
 | |
| 			build.Message = cm.Message
 | |
| 			build.Timestamp = cm.Timestamp.Unix()
 | |
| 			if len(build.Email) != 0 {
 | |
| 				build.Avatar = getUserAvatar(build.Email)
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		files = append(files, cm.Added...)
 | |
| 		files = append(files, cm.Removed...)
 | |
| 		files = append(files, cm.Modified...)
 | |
| 	}
 | |
| 	build.ChangedFiles = utils.DedupStrings(files)
 | |
| 
 | |
| 	return repo, build, nil
 | |
| }
 | |
| 
 | |
| func convertTagHook(hook *gitlab.TagEvent) (*model.Repo, *model.Build, error) {
 | |
| 	repo := &model.Repo{}
 | |
| 	build := &model.Build{}
 | |
| 
 | |
| 	var err error
 | |
| 	if repo.Owner, repo.Name, err = extractFromPath(hook.Project.PathWithNamespace); err != nil {
 | |
| 		return nil, nil, err
 | |
| 	}
 | |
| 
 | |
| 	repo.Avatar = hook.Project.AvatarURL
 | |
| 	repo.Link = hook.Project.WebURL
 | |
| 	repo.Clone = hook.Project.GitHTTPURL
 | |
| 	repo.FullName = hook.Project.PathWithNamespace
 | |
| 	repo.Branch = hook.Project.DefaultBranch
 | |
| 
 | |
| 	switch hook.Project.Visibility {
 | |
| 	case gitlab.PrivateVisibility:
 | |
| 		repo.IsSCMPrivate = true
 | |
| 	case gitlab.InternalVisibility:
 | |
| 		repo.IsSCMPrivate = true
 | |
| 	case gitlab.PublicVisibility:
 | |
| 		repo.IsSCMPrivate = false
 | |
| 	}
 | |
| 
 | |
| 	build.Event = model.EventTag
 | |
| 	build.Commit = hook.After
 | |
| 	build.Branch = strings.TrimPrefix(hook.Ref, "refs/heads/")
 | |
| 	build.Ref = hook.Ref
 | |
| 
 | |
| 	for _, cm := range hook.Commits {
 | |
| 		if hook.After == cm.ID {
 | |
| 			build.Author = cm.Author.Name
 | |
| 			build.Email = cm.Author.Email
 | |
| 			build.Message = cm.Message
 | |
| 			build.Timestamp = cm.Timestamp.Unix()
 | |
| 			if len(build.Email) != 0 {
 | |
| 				build.Avatar = getUserAvatar(build.Email)
 | |
| 			}
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return repo, build, nil
 | |
| }
 | |
| 
 | |
| func getUserAvatar(email string) string {
 | |
| 	hasher := md5.New()
 | |
| 	hasher.Write([]byte(email))
 | |
| 
 | |
| 	return fmt.Sprintf(
 | |
| 		"%s/%v.jpg?s=%s",
 | |
| 		gravatarBase,
 | |
| 		hex.EncodeToString(hasher.Sum(nil)),
 | |
| 		"128",
 | |
| 	)
 | |
| }
 | |
| 
 | |
| func extractFromPath(str string) (string, string, error) {
 | |
| 	s := strings.Split(str, "/")
 | |
| 	if len(s) < 2 {
 | |
| 		return "", "", fmt.Errorf("Minimum match not found")
 | |
| 	}
 | |
| 	return s[0], s[1], nil
 | |
| }
 |