2021-10-03 12:42:47 +00:00
|
|
|
// 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"
|
2021-10-12 07:25:13 +00:00
|
|
|
|
|
|
|
"github.com/woodpecker-ci/woodpecker/server/model"
|
2022-01-17 22:46:59 +00:00
|
|
|
"github.com/woodpecker-ci/woodpecker/shared/utils"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
mergeRefs = "refs/merge-requests/%d/head" // merge request merged with base
|
2021-10-03 12:42:47 +00:00
|
|
|
)
|
|
|
|
|
Fix spelling: gitlab (#1411)
This is most of the GitLab changes that I dropped from #1405.
As before, I'm happy to adjust things...
<details><summary>Problematic Changes</summary>
Fwiw, this is the part that causes the tests to break (I don't
understand why, but I'm leaving this change out):
```patch
commit 703cbe3ed398bf32535120ead733b80aa145c8db
Author: Josh Soref <2119212+jsoref@users.noreply.github.com>
Date: Tue Nov 8 17:09:06 2022 -0500
event?! -- this seems broken
diff --git a/server/forge/gitlab/testdata/hooks.go b/server/forge/gitlab/testdata/hooks.go
index 7d39306..e394afc 100644
--- a/server/forge/gitlab/testdata/hooks.go
+++ b/server/forge/gitlab/testdata/hooks.go
@@ -27,7 +27,7 @@ var (
ServiceHookHeaders = http.Header{
"Content-Type": []string{"application/json"},
"User-Agent": []string{"GitLab/14.3.0"},
- "X-Gitlab-Event": []string{"Service Hook"},
+ "X-GitLab-Event": []string{"Service Hook"},
}
)
diff --git a/shared/token/token.go b/shared/token/token.go
index 3f15537..191e5ee 100644
--- a/shared/token/token.go
+++ b/shared/token/token.go
@@ -64,7 +64,7 @@ func ParseRequest(r *http.Request, fn SecretFunc) (*Token, error) {
return parse(bearer, fn)
}
- token = r.Header.Get("X-Gitlab-Token")
+ token = r.Header.Get("X-GitLab-Token")
if len(token) != 0 {
return parse(token, fn)
}
```
</details>
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
Co-authored-by: qwerty287 <80460567+qwerty287@users.noreply.github.com>
2022-11-09 16:16:17 +00:00
|
|
|
func (g *GitLab) convertGitLabRepo(_repo *gitlab.Project) (*model.Repo, error) {
|
2021-12-01 13:22:06 +00:00
|
|
|
parts := strings.Split(_repo.PathWithNamespace, "/")
|
2022-01-03 15:35:17 +00:00
|
|
|
// TODO(648) save repo id (support nested repos)
|
2022-01-05 20:50:23 +00:00
|
|
|
owner := strings.Join(parts[:len(parts)-1], "/")
|
|
|
|
name := parts[len(parts)-1]
|
2021-10-03 12:42:47 +00:00
|
|
|
repo := &model.Repo{
|
2022-11-04 23:35:06 +00:00
|
|
|
ForgeID: model.ForgeID(fmt.Sprint(_repo.ID)),
|
2022-01-31 14:38:00 +00:00
|
|
|
Owner: owner,
|
|
|
|
Name: name,
|
|
|
|
FullName: _repo.PathWithNamespace,
|
|
|
|
Avatar: _repo.AvatarURL,
|
|
|
|
Link: _repo.WebURL,
|
|
|
|
Clone: _repo.HTTPURLToRepo,
|
|
|
|
Branch: _repo.DefaultBranch,
|
|
|
|
Visibility: model.RepoVisibly(_repo.Visibility),
|
|
|
|
IsSCMPrivate: !_repo.Public,
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
return repo, nil
|
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (int, *model.Repo, *model.Pipeline, error) {
|
2021-10-03 12:42:47 +00:00
|
|
|
repo := &model.Repo{}
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline := &model.Pipeline{}
|
2021-10-03 12:42:47 +00:00
|
|
|
|
|
|
|
target := hook.ObjectAttributes.Target
|
|
|
|
source := hook.ObjectAttributes.Source
|
|
|
|
obj := hook.ObjectAttributes
|
|
|
|
|
|
|
|
if target == nil && source == nil {
|
2022-01-17 22:46:59 +00:00
|
|
|
return 0, nil, nil, fmt.Errorf("target and source keys expected in merge request hook")
|
2021-10-03 12:42:47 +00:00
|
|
|
} else if target == nil {
|
2022-01-17 22:46:59 +00:00
|
|
|
return 0, nil, nil, fmt.Errorf("target key expected in merge request hook")
|
2021-10-03 12:42:47 +00:00
|
|
|
} else if source == nil {
|
2022-01-17 22:46:59 +00:00
|
|
|
return 0, nil, nil, fmt.Errorf("source key expected in merge request hook")
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if target.PathWithNamespace != "" {
|
|
|
|
var err error
|
|
|
|
if repo.Owner, repo.Name, err = extractFromPath(target.PathWithNamespace); err != nil {
|
2022-01-17 22:46:59 +00:00
|
|
|
return 0, nil, nil, err
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2022-11-04 23:35:06 +00:00
|
|
|
repo.ForgeID = model.ForgeID(fmt.Sprint(obj.TargetProjectID))
|
2021-10-03 12:42:47 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Event = model.EventPull
|
2021-10-03 12:42:47 +00:00
|
|
|
|
|
|
|
lastCommit := obj.LastCommit
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Message = lastCommit.Message
|
|
|
|
pipeline.Commit = lastCommit.ID
|
2022-11-04 23:35:06 +00:00
|
|
|
pipeline.CloneURL = obj.Source.HTTPURL
|
2021-10-03 12:42:47 +00:00
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Ref = fmt.Sprintf(mergeRefs, obj.IID)
|
|
|
|
pipeline.Branch = obj.SourceBranch
|
2021-10-03 12:42:47 +00:00
|
|
|
|
|
|
|
author := lastCommit.Author
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Author = author.Name
|
|
|
|
pipeline.Email = author.Email
|
2021-10-03 12:42:47 +00:00
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
if len(pipeline.Email) != 0 {
|
|
|
|
pipeline.Avatar = getUserAvatar(pipeline.Email)
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Title = obj.Title
|
|
|
|
pipeline.Link = obj.URL
|
2021-10-03 12:42:47 +00:00
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
return obj.IID, repo, pipeline, nil
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
func convertPushHook(hook *gitlab.PushEvent) (*model.Repo, *model.Pipeline, error) {
|
2021-10-03 12:42:47 +00:00
|
|
|
repo := &model.Repo{}
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline := &model.Pipeline{}
|
2021-10-03 12:42:47 +00:00
|
|
|
|
|
|
|
var err error
|
|
|
|
if repo.Owner, repo.Name, err = extractFromPath(hook.Project.PathWithNamespace); err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2022-11-04 23:35:06 +00:00
|
|
|
repo.ForgeID = model.ForgeID(fmt.Sprint(hook.ProjectID))
|
2021-10-03 12:42:47 +00:00
|
|
|
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:
|
2021-11-22 11:55:13 +00:00
|
|
|
repo.IsSCMPrivate = true
|
2021-10-03 12:42:47 +00:00
|
|
|
case gitlab.InternalVisibility:
|
2021-11-22 11:55:13 +00:00
|
|
|
repo.IsSCMPrivate = true
|
2021-10-03 12:42:47 +00:00
|
|
|
case gitlab.PublicVisibility:
|
2021-11-22 11:55:13 +00:00
|
|
|
repo.IsSCMPrivate = false
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Event = model.EventPush
|
|
|
|
pipeline.Commit = hook.After
|
|
|
|
pipeline.Branch = strings.TrimPrefix(hook.Ref, "refs/heads/")
|
|
|
|
pipeline.Ref = hook.Ref
|
2021-10-03 12:42:47 +00:00
|
|
|
|
2022-01-17 22:46:59 +00:00
|
|
|
// assume a capacity of 4 changed files per commit
|
|
|
|
files := make([]string, 0, len(hook.Commits)*4)
|
2021-10-03 12:42:47 +00:00
|
|
|
for _, cm := range hook.Commits {
|
|
|
|
if hook.After == cm.ID {
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Author = cm.Author.Name
|
|
|
|
pipeline.Email = cm.Author.Email
|
|
|
|
pipeline.Message = cm.Message
|
|
|
|
pipeline.Timestamp = cm.Timestamp.Unix()
|
|
|
|
if len(pipeline.Email) != 0 {
|
|
|
|
pipeline.Avatar = getUserAvatar(pipeline.Email)
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-17 22:46:59 +00:00
|
|
|
|
|
|
|
files = append(files, cm.Added...)
|
|
|
|
files = append(files, cm.Removed...)
|
|
|
|
files = append(files, cm.Modified...)
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.ChangedFiles = utils.DedupStrings(files)
|
2021-10-03 12:42:47 +00:00
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
return repo, pipeline, nil
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
func convertTagHook(hook *gitlab.TagEvent) (*model.Repo, *model.Pipeline, error) {
|
2021-10-03 12:42:47 +00:00
|
|
|
repo := &model.Repo{}
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline := &model.Pipeline{}
|
2021-10-03 12:42:47 +00:00
|
|
|
|
|
|
|
var err error
|
|
|
|
if repo.Owner, repo.Name, err = extractFromPath(hook.Project.PathWithNamespace); err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2022-11-04 23:35:06 +00:00
|
|
|
repo.ForgeID = model.ForgeID(fmt.Sprint(hook.ProjectID))
|
2021-10-03 12:42:47 +00:00
|
|
|
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:
|
2021-11-22 11:55:13 +00:00
|
|
|
repo.IsSCMPrivate = true
|
2021-10-03 12:42:47 +00:00
|
|
|
case gitlab.InternalVisibility:
|
2021-11-22 11:55:13 +00:00
|
|
|
repo.IsSCMPrivate = true
|
2021-10-03 12:42:47 +00:00
|
|
|
case gitlab.PublicVisibility:
|
2021-11-22 11:55:13 +00:00
|
|
|
repo.IsSCMPrivate = false
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Event = model.EventTag
|
|
|
|
pipeline.Commit = hook.After
|
|
|
|
pipeline.Branch = strings.TrimPrefix(hook.Ref, "refs/heads/")
|
|
|
|
pipeline.Ref = hook.Ref
|
2021-10-03 12:42:47 +00:00
|
|
|
|
|
|
|
for _, cm := range hook.Commits {
|
|
|
|
if hook.After == cm.ID {
|
2022-10-18 01:24:12 +00:00
|
|
|
pipeline.Author = cm.Author.Name
|
|
|
|
pipeline.Email = cm.Author.Email
|
|
|
|
pipeline.Message = cm.Message
|
|
|
|
pipeline.Timestamp = cm.Timestamp.Unix()
|
|
|
|
if len(pipeline.Email) != 0 {
|
|
|
|
pipeline.Avatar = getUserAvatar(pipeline.Email)
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-18 01:24:12 +00:00
|
|
|
return repo, pipeline, nil
|
2021-10-03 12:42:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|