Harness move (#237)
* (feat) initial commit for harness code * (feat) harness, add update delete create filepull/239/head
parent
4428a9bf64
commit
ca3776c0f0
@ -0,0 +1,234 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type contentService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) {
|
||||
repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo)
|
||||
endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?%s&include_commit=true", repo, path, ref)
|
||||
out := new(fileContent)
|
||||
res, err := s.client.do(ctx, "GET", endpoint, nil, out)
|
||||
// decode raw output content
|
||||
raw, _ := base64.StdEncoding.DecodeString(out.Content.Data)
|
||||
return &scm.Content{
|
||||
Path: path,
|
||||
Sha: out.LatestCommit.Sha,
|
||||
BlobID: out.Sha,
|
||||
Data: raw,
|
||||
}, res, err
|
||||
}
|
||||
|
||||
func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
|
||||
repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo)
|
||||
endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo)
|
||||
a := action{
|
||||
Action: "CREATE",
|
||||
Path: path,
|
||||
Payload: string(params.Data),
|
||||
Encoding: "string",
|
||||
}
|
||||
in := editFile{
|
||||
Branch: params.Branch,
|
||||
Message: params.Message,
|
||||
Title: params.Message,
|
||||
Actions: []action{a},
|
||||
}
|
||||
|
||||
res, err := s.client.do(ctx, "POST", endpoint, in, nil)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
|
||||
repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo)
|
||||
endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo)
|
||||
a := action{
|
||||
Action: "UPDATE",
|
||||
Path: path,
|
||||
Payload: string(params.Data),
|
||||
Encoding: "string",
|
||||
}
|
||||
in := editFile{
|
||||
Branch: params.Branch,
|
||||
Message: params.Message,
|
||||
Title: params.Message,
|
||||
Actions: []action{a},
|
||||
}
|
||||
|
||||
res, err := s.client.do(ctx, "POST", endpoint, in, nil)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
|
||||
repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo)
|
||||
endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo)
|
||||
a := action{
|
||||
Action: "DELETE",
|
||||
Path: path,
|
||||
Encoding: "string",
|
||||
}
|
||||
in := editFile{
|
||||
Branch: params.Branch,
|
||||
Message: params.Message,
|
||||
Title: params.Message,
|
||||
Actions: []action{a},
|
||||
}
|
||||
|
||||
res, err := s.client.do(ctx, "POST", endpoint, in, nil)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func buildHarnessURI(account, organization, project, repo string) (uri string) {
|
||||
if account != "" {
|
||||
return fmt.Sprintf("%s/%s/%s/%s/+", account, organization, project, repo)
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) {
|
||||
repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo)
|
||||
endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?%s&include_commit=true", repo, path, ref)
|
||||
out := new(contentList)
|
||||
res, err := s.client.do(ctx, "GET", endpoint, nil, &out)
|
||||
return convertContentInfoList(out.Content.Entries), res, err
|
||||
}
|
||||
|
||||
type editFile struct {
|
||||
Actions []action `json:"actions"`
|
||||
Branch string `json:"branch"`
|
||||
Message string `json:"message"`
|
||||
NewBranch string `json:"new_branch"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
type action struct {
|
||||
Action string `json:"action"`
|
||||
Encoding string `json:"encoding"`
|
||||
Path string `json:"path"`
|
||||
Payload string `json:"payload"`
|
||||
Sha string `json:"sha"`
|
||||
}
|
||||
|
||||
type fileContent struct {
|
||||
Type string `json:"type"`
|
||||
Sha string `json:"sha"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
LatestCommit struct {
|
||||
Sha string `json:"sha"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
Author struct {
|
||||
Identity struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
} `json:"identity"`
|
||||
When time.Time `json:"when"`
|
||||
} `json:"author"`
|
||||
Committer struct {
|
||||
Identity struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
} `json:"identity"`
|
||||
When time.Time `json:"when"`
|
||||
} `json:"committer"`
|
||||
} `json:"latest_commit"`
|
||||
Content struct {
|
||||
Encoding string `json:"encoding"`
|
||||
Data string `json:"data"`
|
||||
Size int `json:"size"`
|
||||
} `json:"content"`
|
||||
}
|
||||
|
||||
type contentList struct {
|
||||
Type string `json:"type"`
|
||||
Sha string `json:"sha"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
LatestCommit struct {
|
||||
Sha string `json:"sha"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
Author struct {
|
||||
Identity struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
} `json:"identity"`
|
||||
When time.Time `json:"when"`
|
||||
} `json:"author"`
|
||||
Committer struct {
|
||||
Identity struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
} `json:"identity"`
|
||||
When time.Time `json:"when"`
|
||||
} `json:"committer"`
|
||||
} `json:"latest_commit"`
|
||||
Content struct {
|
||||
Entries []fileEntry `json:"entries"`
|
||||
} `json:"content"`
|
||||
}
|
||||
|
||||
type fileEntry struct {
|
||||
Type string `json:"type"`
|
||||
Sha string `json:"sha"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
LatestCommit struct {
|
||||
Sha string `json:"sha"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
Author struct {
|
||||
Identity struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
} `json:"identity"`
|
||||
When time.Time `json:"when"`
|
||||
} `json:"author"`
|
||||
Committer struct {
|
||||
Identity struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
} `json:"identity"`
|
||||
When time.Time `json:"when"`
|
||||
} `json:"committer"`
|
||||
} `json:"latest_commit"`
|
||||
}
|
||||
|
||||
func convertContentInfoList(from []fileEntry) []*scm.ContentInfo {
|
||||
to := []*scm.ContentInfo{}
|
||||
for _, v := range from {
|
||||
to = append(to, convertContentInfo(v))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertContentInfo(from fileEntry) *scm.ContentInfo {
|
||||
to := &scm.ContentInfo{
|
||||
Path: from.Path,
|
||||
Sha: from.LatestCommit.Sha,
|
||||
BlobID: from.Sha,
|
||||
}
|
||||
switch from.Type {
|
||||
case "file":
|
||||
to.Kind = scm.ContentKindFile
|
||||
case "dir":
|
||||
to.Kind = scm.ContentKindDirectory
|
||||
default:
|
||||
to.Kind = scm.ContentKindUnsupported
|
||||
}
|
||||
return to
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/drone/go-scm/scm/transport"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/h2non/gock"
|
||||
)
|
||||
|
||||
const (
|
||||
gockOrigin = "https://qa.harness.io/gateway/code"
|
||||
harnessOrg = "px7xd_BFRCi-pfWPYXVjvw"
|
||||
harnessAccount = "default"
|
||||
harnessProject = "codeciintegration"
|
||||
harnessRepo = "demo"
|
||||
harnessPAT = ""
|
||||
)
|
||||
|
||||
func TestContentFind(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(gockOrigin).
|
||||
Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/content/README.md").
|
||||
Reply(200).
|
||||
Type("plain/text").
|
||||
File("testdata/content.json")
|
||||
|
||||
client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject)
|
||||
client.Client = &http.Client{
|
||||
Transport: &transport.Custom{
|
||||
Before: func(r *http.Request) {
|
||||
r.Header.Set("x-api-key", harnessPAT)
|
||||
},
|
||||
},
|
||||
}
|
||||
result, _, err := client.Contents.Find(
|
||||
context.Background(),
|
||||
harnessRepo,
|
||||
"README.md",
|
||||
"98189d5cf2a751a6246c24a72945ba70839f1b20",
|
||||
)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if got, want := result.Path, "README.md"; got != want {
|
||||
t.Errorf("Want file Path %q, got %q", want, got)
|
||||
}
|
||||
if !strings.Contains(string(result.Data), "demo") {
|
||||
t.Errorf("Want file Data %q, must contain 'demo'", result.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContentCreate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(gockOrigin).
|
||||
Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits").
|
||||
Reply(200).
|
||||
Type("plain/text").
|
||||
BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}")
|
||||
|
||||
client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject)
|
||||
client.Client = &http.Client{
|
||||
Transport: &transport.Custom{
|
||||
Before: func(r *http.Request) {
|
||||
r.Header.Set("x-api-key", harnessPAT)
|
||||
},
|
||||
},
|
||||
}
|
||||
result, err := client.Contents.Create(
|
||||
context.Background(),
|
||||
harnessRepo,
|
||||
"README.2",
|
||||
&scm.ContentParams{
|
||||
Data: []byte("hello world"),
|
||||
Message: "create README.2",
|
||||
Branch: "main",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if result.Status != 200 {
|
||||
t.Errorf("Unexpected Results")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContentUpdate(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(gockOrigin).
|
||||
Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits").
|
||||
Reply(200).
|
||||
Type("plain/text").
|
||||
BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}")
|
||||
|
||||
client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject)
|
||||
client.Client = &http.Client{
|
||||
Transport: &transport.Custom{
|
||||
Before: func(r *http.Request) {
|
||||
r.Header.Set("x-api-key", harnessPAT)
|
||||
},
|
||||
},
|
||||
}
|
||||
result, err := client.Contents.Update(
|
||||
context.Background(),
|
||||
harnessRepo,
|
||||
"README.2",
|
||||
&scm.ContentParams{
|
||||
Data: []byte("hello world 2"),
|
||||
Message: "update README.2",
|
||||
Branch: "main",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if result.Status != 200 {
|
||||
t.Errorf("Unexpected Results")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContentDelete(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(gockOrigin).
|
||||
Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits").
|
||||
Reply(200).
|
||||
Type("plain/text").
|
||||
BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}")
|
||||
|
||||
client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject)
|
||||
client.Client = &http.Client{
|
||||
Transport: &transport.Custom{
|
||||
Before: func(r *http.Request) {
|
||||
r.Header.Set("x-api-key", harnessPAT)
|
||||
},
|
||||
},
|
||||
}
|
||||
result, err := client.Contents.Delete(
|
||||
context.Background(),
|
||||
harnessRepo,
|
||||
"README.2",
|
||||
&scm.ContentParams{
|
||||
Message: "delete README.2",
|
||||
Branch: "main",
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if result.Status != 200 {
|
||||
t.Errorf("Unexpected Results")
|
||||
}
|
||||
}
|
||||
|
||||
func TestContentList(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(gockOrigin).
|
||||
Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/content/docker").
|
||||
Reply(200).
|
||||
Type("application/json").
|
||||
File("testdata/content_list.json")
|
||||
|
||||
client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject)
|
||||
client.Client = &http.Client{
|
||||
Transport: &transport.Custom{
|
||||
Before: func(r *http.Request) {
|
||||
r.Header.Set("x-api-key", harnessPAT)
|
||||
},
|
||||
},
|
||||
}
|
||||
got, _, err := client.Contents.List(
|
||||
context.Background(),
|
||||
harnessRepo,
|
||||
"docker",
|
||||
"",
|
||||
scm.ListOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
want := []*scm.ContentInfo{}
|
||||
raw, _ := ioutil.ReadFile("testdata/content_list.json.golden")
|
||||
json.Unmarshal(raw, &want)
|
||||
|
||||
if diff := cmp.Diff(got, want); diff != "" {
|
||||
t.Errorf("Unexpected Results")
|
||||
t.Log(diff)
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type gitService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v1/repos/%s/branches/%s", repo, name)
|
||||
out := new(branch)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertBranch(out), res, err
|
||||
}
|
||||
|
||||
func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) {
|
||||
ref = scm.TrimRef(ref)
|
||||
path := fmt.Sprintf("api/v1/repos/%s/git/commits/%s", repo, url.PathEscape(ref))
|
||||
out := new(commitInfo)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertCommitInfo(out), res, err
|
||||
}
|
||||
|
||||
func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v1/repos/%s/branches?%s", repo, encodeListOptions(opts))
|
||||
out := []*branch{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertBranchList(out), res, err
|
||||
}
|
||||
|
||||
func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v1/repos/%s/commits", repo)
|
||||
out := []*commitInfo{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertCommitList(out), res, err
|
||||
}
|
||||
|
||||
func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
//
|
||||
// native data structures
|
||||
//
|
||||
|
||||
type (
|
||||
// gitea branch object.
|
||||
branch struct {
|
||||
Name string `json:"name"`
|
||||
Commit commit `json:"commit"`
|
||||
}
|
||||
|
||||
// gitea commit object.
|
||||
commit struct {
|
||||
ID string `json:"id"`
|
||||
Sha string `json:"sha"`
|
||||
Message string `json:"message"`
|
||||
URL string `json:"url"`
|
||||
Author signature `json:"author"`
|
||||
Committer signature `json:"committer"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// gitea commit info object.
|
||||
commitInfo struct {
|
||||
Sha string `json:"sha"`
|
||||
Commit commit `json:"commit"`
|
||||
Author user `json:"author"`
|
||||
Committer user `json:"committer"`
|
||||
}
|
||||
|
||||
// gitea signature object.
|
||||
signature struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// gitea tag object
|
||||
tag struct {
|
||||
Ref string `json:"ref"`
|
||||
URL string `json:"url"`
|
||||
Object struct {
|
||||
Type string `json:"type"`
|
||||
Sha string `json:"sha"`
|
||||
URL string `json:"url"`
|
||||
} `json:"object"`
|
||||
}
|
||||
)
|
||||
|
||||
//
|
||||
// native data structure conversion
|
||||
//
|
||||
|
||||
func convertBranchList(src []*branch) []*scm.Reference {
|
||||
dst := []*scm.Reference{}
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertBranch(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertBranch(src *branch) *scm.Reference {
|
||||
return &scm.Reference{
|
||||
Name: scm.TrimRef(src.Name),
|
||||
Path: scm.ExpandRef(src.Name, "refs/heads/"),
|
||||
Sha: src.Commit.ID,
|
||||
}
|
||||
}
|
||||
|
||||
func convertCommitList(src []*commitInfo) []*scm.Commit {
|
||||
dst := []*scm.Commit{}
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertCommitInfo(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertCommitInfo(src *commitInfo) *scm.Commit {
|
||||
return &scm.Commit{
|
||||
Sha: src.Sha,
|
||||
Link: src.Commit.URL,
|
||||
Message: src.Commit.Message,
|
||||
Author: convertUserSignature(src.Author),
|
||||
Committer: convertUserSignature(src.Committer),
|
||||
}
|
||||
}
|
||||
|
||||
func convertSignature(src signature) scm.Signature {
|
||||
return scm.Signature{
|
||||
Login: src.Username,
|
||||
Email: src.Email,
|
||||
Name: src.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func convertUserSignature(src user) scm.Signature {
|
||||
return scm.Signature{
|
||||
Login: userLogin(&src),
|
||||
Email: src.Email,
|
||||
Name: src.Fullname,
|
||||
Avatar: src.Avatar,
|
||||
}
|
||||
}
|
||||
|
||||
func convertTagList(src []*tag) []*scm.Reference {
|
||||
var dst []*scm.Reference
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertTag(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertTag(src *tag) *scm.Reference {
|
||||
return &scm.Reference{
|
||||
Name: scm.TrimRef(src.Ref),
|
||||
Path: src.Ref,
|
||||
Sha: src.Object.Sha,
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
@ -0,0 +1,108 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
// New returns a new gitness API client.
|
||||
func New(uri, account, organization, project string) (*scm.Client, error) {
|
||||
if !((organization == "" && account == "" && project == "") || (organization != "" && account != "" && project != "")) {
|
||||
return nil, fmt.Errorf("harness account, organization and project are required")
|
||||
}
|
||||
base, err := url.Parse(uri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !strings.HasSuffix(base.Path, "/") {
|
||||
base.Path = base.Path + "/"
|
||||
}
|
||||
client := &wrapper{new(scm.Client), account, organization, project}
|
||||
client.BaseURL = base
|
||||
// initialize services
|
||||
client.Driver = scm.DriverGitea
|
||||
client.Linker = &linker{base.String()}
|
||||
client.Contents = &contentService{client}
|
||||
client.Git = &gitService{client}
|
||||
client.Issues = &issueService{client}
|
||||
client.Milestones = &milestoneService{client}
|
||||
client.Organizations = &organizationService{client}
|
||||
client.PullRequests = &pullService{client}
|
||||
client.Repositories = &repositoryService{client}
|
||||
client.Releases = &releaseService{client}
|
||||
client.Reviews = &reviewService{client}
|
||||
client.Users = &userService{client}
|
||||
client.Webhooks = &webhookService{client}
|
||||
return client.Client, nil
|
||||
}
|
||||
|
||||
// wraper wraps the Client to provide high level helper functions
|
||||
// for making http requests and unmarshaling the response.
|
||||
type wrapper struct {
|
||||
*scm.Client
|
||||
account string
|
||||
organization string
|
||||
project string
|
||||
}
|
||||
|
||||
// do wraps the Client.Do function by creating the Request and
|
||||
// unmarshalling the response.
|
||||
func (c *wrapper) do(ctx context.Context, method, path string, in, out interface{}) (*scm.Response, error) {
|
||||
req := &scm.Request{
|
||||
Method: method,
|
||||
Path: path,
|
||||
}
|
||||
// if we are posting or putting data, we need to
|
||||
// write it to the body of the request.
|
||||
if in != nil {
|
||||
buf := new(bytes.Buffer)
|
||||
json.NewEncoder(buf).Encode(in)
|
||||
req.Header = map[string][]string{
|
||||
"Content-Type": {"application/json"},
|
||||
}
|
||||
req.Body = buf
|
||||
}
|
||||
|
||||
// execute the http request
|
||||
res, err := c.Client.Do(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
// if an error is encountered, unmarshal and return the
|
||||
// error response.
|
||||
if res.Status > 300 {
|
||||
return res, errors.New(
|
||||
http.StatusText(res.Status),
|
||||
)
|
||||
}
|
||||
|
||||
if out == nil {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// if raw output is expected, copy to the provided
|
||||
// buffer and exit.
|
||||
if w, ok := out.(io.Writer); ok {
|
||||
io.Copy(w, res.Body)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// if a json response is expected, parse and return
|
||||
// the json response.
|
||||
return res, json.NewDecoder(res.Body).Decode(out)
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// package gitea implements a Gogs client.
|
||||
package harness
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
client, err := New(gockOrigin, "", "", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if got, want := client.BaseURL.String(), fmt.Sprintf("%s/", gockOrigin); got != want {
|
||||
t.Errorf("Want Client URL %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_Error(t *testing.T) {
|
||||
_, err := New("http://a b.com/", "", "", "")
|
||||
if err == nil {
|
||||
t.Errorf("Expect error when invalid URL")
|
||||
}
|
||||
}
|
||||
|
||||
func testPage(res *scm.Response) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
if got, want := res.Page.Next, 2; got != want {
|
||||
t.Errorf("Want next page %d, got %d", want, got)
|
||||
}
|
||||
if got, want := res.Page.Prev, 1; got != want {
|
||||
t.Errorf("Want prev page %d, got %d", want, got)
|
||||
}
|
||||
if got, want := res.Page.First, 1; got != want {
|
||||
t.Errorf("Want first page %d, got %d", want, got)
|
||||
}
|
||||
if got, want := res.Page.Last, 5; got != want {
|
||||
t.Errorf("Want last page %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type issueService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *issueService) FindComment(ctx context.Context, repo string, index, id int) (*scm.Comment, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *issueService) List(ctx context.Context, repo string, opts scm.IssueListOptions) ([]*scm.Issue, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *issueService) ListComments(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *issueService) Create(ctx context.Context, repo string, input *scm.IssueInput) (*scm.Issue, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *issueService) CreateComment(ctx context.Context, repo string, index int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *issueService) DeleteComment(ctx context.Context, repo string, index, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *issueService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *issueService) Lock(ctx context.Context, repo string, number int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
//
|
||||
// native data structures
|
||||
//
|
||||
|
||||
type (
|
||||
// gitea issue response object.
|
||||
issue struct {
|
||||
ID int `json:"id"`
|
||||
Number int `json:"number"`
|
||||
User user `json:"user"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
State string `json:"state"`
|
||||
Labels []string `json:"labels"`
|
||||
Comments int `json:"comments"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated time.Time `json:"updated_at"`
|
||||
PullRequest *struct {
|
||||
Merged bool `json:"merged"`
|
||||
MergedAt interface{} `json:"merged_at"`
|
||||
} `json:"pull_request"`
|
||||
}
|
||||
|
||||
// gitea issue request object.
|
||||
issueInput struct {
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
// gitea issue comment response object.
|
||||
issueComment struct {
|
||||
ID int `json:"id"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
User user `json:"user"`
|
||||
Body string `json:"body"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// gitea issue comment request object.
|
||||
issueCommentInput struct {
|
||||
Body string `json:"body"`
|
||||
}
|
||||
)
|
||||
|
||||
//
|
||||
// native data structure conversion
|
||||
//
|
||||
|
||||
func convertIssueList(from []*issue) []*scm.Issue {
|
||||
to := []*scm.Issue{}
|
||||
for _, v := range from {
|
||||
to = append(to, convertIssue(v))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertIssue(from *issue) *scm.Issue {
|
||||
return &scm.Issue{
|
||||
Number: from.Number,
|
||||
Title: from.Title,
|
||||
Body: from.Body,
|
||||
Link: "", // TODO construct the link to the issue.
|
||||
Closed: from.State == "closed",
|
||||
Author: *convertUser(&from.User),
|
||||
Created: from.Created,
|
||||
Updated: from.Updated,
|
||||
}
|
||||
}
|
||||
|
||||
func convertIssueCommentList(from []*issueComment) []*scm.Comment {
|
||||
to := []*scm.Comment{}
|
||||
for _, v := range from {
|
||||
to = append(to, convertIssueComment(v))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertIssueComment(from *issueComment) *scm.Comment {
|
||||
return &scm.Comment{
|
||||
ID: from.ID,
|
||||
Body: from.Body,
|
||||
Author: *convertUser(&from.User),
|
||||
Created: from.CreatedAt,
|
||||
Updated: from.UpdatedAt,
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
@ -0,0 +1,27 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type linker struct {
|
||||
base string
|
||||
}
|
||||
|
||||
// Resource returns a link to the resource.
|
||||
func (l *linker) Resource(ctx context.Context, repo string, ref scm.Reference) (string, error) {
|
||||
return "", scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
// Diff returns a link to the diff.
|
||||
func (l *linker) Diff(ctx context.Context, repo string, source, target scm.Reference) (string, error) {
|
||||
return "", scm.ErrNotSupported
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
@ -0,0 +1,90 @@
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/drone/go-scm/scm/driver/internal/null"
|
||||
)
|
||||
|
||||
type milestoneService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
// stateType issue state type
|
||||
type stateType string
|
||||
|
||||
const (
|
||||
// stateOpen pr/issue is open
|
||||
stateOpen stateType = "open"
|
||||
// stateClosed pr/issue is closed
|
||||
stateClosed stateType = "closed"
|
||||
// stateAll is all
|
||||
stateAll stateType = "all"
|
||||
)
|
||||
|
||||
type milestone struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
State stateType `json:"state"`
|
||||
OpenIssues int `json:"open_issues"`
|
||||
ClosedIssues int `json:"closed_issues"`
|
||||
Created null.Time `json:"created_at"`
|
||||
Updated null.Time `json:"updated_at"`
|
||||
Closed null.Time `json:"closed_at"`
|
||||
Deadline null.Time `json:"due_on"`
|
||||
}
|
||||
|
||||
type milestoneInput struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
State stateType `json:"state"`
|
||||
Deadline null.Time `json:"due_on"`
|
||||
}
|
||||
|
||||
func convertMilestoneList(src []*milestone) []*scm.Milestone {
|
||||
var dst []*scm.Milestone
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertMilestone(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertMilestone(src *milestone) *scm.Milestone {
|
||||
if src == nil || src.Deadline.IsZero() {
|
||||
return nil
|
||||
}
|
||||
return &scm.Milestone{
|
||||
Number: int(src.ID),
|
||||
ID: int(src.ID),
|
||||
Title: src.Title,
|
||||
Description: src.Description,
|
||||
State: string(src.State),
|
||||
DueDate: src.Deadline.ValueOrZero(),
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
package harness
|
@ -0,0 +1,57 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type organizationService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organization, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// native data structures
|
||||
//
|
||||
|
||||
type org struct {
|
||||
Name string `json:"username"`
|
||||
Avatar string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
//
|
||||
// native data structure conversion
|
||||
//
|
||||
|
||||
func convertOrgList(from []*org) []*scm.Organization {
|
||||
to := []*scm.Organization{}
|
||||
for _, v := range from {
|
||||
to = append(to, convertOrg(v))
|
||||
}
|
||||
return to
|
||||
}
|
||||
|
||||
func convertOrg(from *org) *scm.Organization {
|
||||
return &scm.Organization{
|
||||
Name: from.Name,
|
||||
Avatar: from.Avatar,
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
@ -0,0 +1,157 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type pullService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *pullService) Find(ctx context.Context, repo string, index int) (*scm.PullRequest, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
|
||||
}
|
||||
|
||||
func (s *pullService) FindComment(context.Context, string, int, int) (*scm.Comment, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions) ([]*scm.Comment, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) ListCommits(context.Context, string, int, scm.ListOptions) ([]*scm.Commit, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) ListChanges(context.Context, string, int, scm.ListOptions) ([]*scm.Change, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) CreateComment(context.Context, string, int, *scm.CommentInput) (*scm.Comment, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) DeleteComment(context.Context, string, int, int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) Merge(ctx context.Context, repo string, index int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *pullService) Close(context.Context, string, int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
//
|
||||
// native data structures
|
||||
//
|
||||
|
||||
type pr struct {
|
||||
ID int `json:"id"`
|
||||
Number int `json:"number"`
|
||||
User user `json:"user"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
State string `json:"state"`
|
||||
HeadBranch string `json:"head_branch"`
|
||||
HeadRepo repository `json:"head_repo"`
|
||||
Head reference `json:"head"`
|
||||
BaseBranch string `json:"base_branch"`
|
||||
BaseRepo repository `json:"base_repo"`
|
||||
Base reference `json:"base"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
DiffURL string `json:"diff_url"`
|
||||
Mergeable bool `json:"mergeable"`
|
||||
Merged bool `json:"merged"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated time.Time `json:"updated_at"`
|
||||
Labels []struct {
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
} `json:"labels"`
|
||||
}
|
||||
|
||||
type reference struct {
|
||||
Repo repository `json:"repo"`
|
||||
Name string `json:"ref"`
|
||||
Sha string `json:"sha"`
|
||||
}
|
||||
|
||||
type prInput struct {
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Head string `json:"head"`
|
||||
Base string `json:"base"`
|
||||
}
|
||||
|
||||
//
|
||||
// native data structure conversion
|
||||
//
|
||||
|
||||
func convertPullRequests(src []*pr) []*scm.PullRequest {
|
||||
dst := []*scm.PullRequest{}
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertPullRequest(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertPullRequest(src *pr) *scm.PullRequest {
|
||||
var labels []scm.Label
|
||||
for _, label := range src.Labels {
|
||||
labels = append(labels, scm.Label{
|
||||
Name: label.Name,
|
||||
Color: label.Color,
|
||||
})
|
||||
}
|
||||
return &scm.PullRequest{
|
||||
Number: src.Number,
|
||||
Title: src.Title,
|
||||
Body: src.Body,
|
||||
Sha: src.Head.Sha,
|
||||
Source: src.Head.Name,
|
||||
Target: src.Base.Name,
|
||||
Link: src.HTMLURL,
|
||||
Diff: src.DiffURL,
|
||||
Fork: src.Base.Repo.FullName,
|
||||
Ref: fmt.Sprintf("refs/pull/%d/head", src.Number),
|
||||
Closed: src.State == "closed",
|
||||
Author: *convertUser(&src.User),
|
||||
Merged: src.Merged,
|
||||
Created: src.Created,
|
||||
Updated: src.Updated,
|
||||
Labels: labels,
|
||||
}
|
||||
}
|
||||
|
||||
func convertPullRequestFromIssue(src *issue) *scm.PullRequest {
|
||||
return &scm.PullRequest{
|
||||
Number: src.Number,
|
||||
Title: src.Title,
|
||||
Body: src.Body,
|
||||
Closed: src.State == "closed",
|
||||
Author: *convertUser(&src.User),
|
||||
Merged: src.PullRequest.Merged,
|
||||
Created: src.Created,
|
||||
Updated: src.Updated,
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
@ -0,0 +1,112 @@
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/drone/go-scm/scm/driver/internal/null"
|
||||
)
|
||||
|
||||
type releaseService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
type ReleaseInput struct {
|
||||
TagName string `json:"tag_name"`
|
||||
Target string `json:"target_commitish"`
|
||||
Title string `json:"name"`
|
||||
Note string `json:"body"`
|
||||
IsDraft bool `json:"draft"`
|
||||
IsPrerelease bool `json:"prerelease"`
|
||||
}
|
||||
|
||||
// release represents a repository release
|
||||
type release struct {
|
||||
ID int64 `json:"id"`
|
||||
TagName string `json:"tag_name"`
|
||||
Target string `json:"target_commitish"`
|
||||
Title string `json:"name"`
|
||||
Note string `json:"body"`
|
||||
URL string `json:"url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
TarURL string `json:"tarball_url"`
|
||||
ZipURL string `json:"zipball_url"`
|
||||
IsDraft bool `json:"draft"`
|
||||
IsPrerelease bool `json:"prerelease"`
|
||||
CreatedAt null.Time `json:"created_at"`
|
||||
PublishedAt null.Time `json:"published_at"`
|
||||
Publisher *user `json:"author"`
|
||||
Attachments []*Attachment `json:"assets"`
|
||||
}
|
||||
|
||||
type Attachment struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
DownloadCount int64 `json:"download_count"`
|
||||
Created null.Time `json:"created_at"`
|
||||
UUID string `json:"uuid"`
|
||||
DownloadURL string `json:"browser_download_url"`
|
||||
}
|
||||
|
||||
func convertRelease(src *release) *scm.Release {
|
||||
return &scm.Release{
|
||||
ID: int(src.ID),
|
||||
Title: src.Title,
|
||||
Description: src.Note,
|
||||
Link: convertAPIURLToHTMLURL(src.URL, src.TagName),
|
||||
Tag: src.TagName,
|
||||
Commitish: src.Target,
|
||||
Draft: src.IsDraft,
|
||||
Prerelease: src.IsPrerelease,
|
||||
Created: src.CreatedAt.ValueOrZero(),
|
||||
Published: src.PublishedAt.ValueOrZero(),
|
||||
}
|
||||
}
|
||||
|
||||
func convertReleaseList(src []*release) []*scm.Release {
|
||||
var dst []*scm.Release
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertRelease(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func releaseListOptionsToGiteaListOptions(in scm.ReleaseListOptions) ListOptions {
|
||||
return ListOptions{
|
||||
Page: in.Page,
|
||||
PageSize: in.Size,
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
package harness
|
@ -0,0 +1,273 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type repositoryService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v1/repos/%s", repo)
|
||||
out := new(repository)
|
||||
res, err := s.client.do(ctx, "GET", path, nil, out)
|
||||
return convertRepository(out), res, err
|
||||
}
|
||||
|
||||
func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v1/user/repos?%s", encodeListOptions(opts))
|
||||
out := []*repository{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertRepositoryList(out), res, err
|
||||
}
|
||||
|
||||
func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v1/repos/%s/hooks?%s", repo, encodeListOptions(opts))
|
||||
out := []*hook{}
|
||||
res, err := s.client.do(ctx, "GET", path, nil, &out)
|
||||
return convertHookList(out), res, err
|
||||
}
|
||||
|
||||
func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
|
||||
target, err := url.Parse(input.Target)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
params := target.Query()
|
||||
params.Set("secret", input.Secret)
|
||||
target.RawQuery = params.Encode()
|
||||
|
||||
path := fmt.Sprintf("api/v1/repos/%s/hooks", repo)
|
||||
in := new(hook)
|
||||
in.Type = "gitea"
|
||||
in.Active = true
|
||||
in.Config.Secret = input.Secret
|
||||
in.Config.ContentType = "json"
|
||||
in.Config.URL = target.String()
|
||||
in.Events = append(
|
||||
input.NativeEvents,
|
||||
convertHookEvent(input.Events)...,
|
||||
)
|
||||
out := new(hook)
|
||||
res, err := s.client.do(ctx, "POST", path, in, out)
|
||||
return convertHook(out), res, err
|
||||
}
|
||||
|
||||
func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) {
|
||||
path := fmt.Sprintf("api/v1/repos/%s/hooks/%s", repo, id)
|
||||
return s.client.do(ctx, "DELETE", path, nil, nil)
|
||||
}
|
||||
|
||||
//
|
||||
// native data structures
|
||||
//
|
||||
|
||||
type (
|
||||
// gitea repository resource.
|
||||
repository struct {
|
||||
ID int `json:"id"`
|
||||
Owner user `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
Private bool `json:"private"`
|
||||
Fork bool `json:"fork"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
SSHURL string `json:"ssh_url"`
|
||||
CloneURL string `json:"clone_url"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Permissions perm `json:"permissions"`
|
||||
Archived bool `json:"archived"`
|
||||
}
|
||||
|
||||
// gitea permissions details.
|
||||
perm struct {
|
||||
Admin bool `json:"admin"`
|
||||
Push bool `json:"push"`
|
||||
Pull bool `json:"pull"`
|
||||
}
|
||||
|
||||
// gitea hook resource.
|
||||
hook struct {
|
||||
ID int `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Events []string `json:"events"`
|
||||
Active bool `json:"active"`
|
||||
Config hookConfig `json:"config"`
|
||||
}
|
||||
|
||||
// gitea hook configuration details.
|
||||
hookConfig struct {
|
||||
URL string `json:"url"`
|
||||
ContentType string `json:"content_type"`
|
||||
Secret string `json:"secret"`
|
||||
}
|
||||
|
||||
// gitea status resource.
|
||||
status struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
State string `json:"status"`
|
||||
TargetURL string `json:"target_url"`
|
||||
Description string `json:"description"`
|
||||
Context string `json:"context"`
|
||||
}
|
||||
|
||||
// gitea status creation request.
|
||||
statusInput struct {
|
||||
State string `json:"state"`
|
||||
TargetURL string `json:"target_url"`
|
||||
Description string `json:"description"`
|
||||
Context string `json:"context"`
|
||||
}
|
||||
)
|
||||
|
||||
//
|
||||
// native data structure conversion
|
||||
//
|
||||
|
||||
func convertRepositoryList(src []*repository) []*scm.Repository {
|
||||
var dst []*scm.Repository
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertRepository(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertRepository(src *repository) *scm.Repository {
|
||||
return &scm.Repository{
|
||||
ID: strconv.Itoa(src.ID),
|
||||
Namespace: userLogin(&src.Owner),
|
||||
Name: src.Name,
|
||||
Perm: convertPerm(src.Permissions),
|
||||
Branch: src.DefaultBranch,
|
||||
Private: src.Private,
|
||||
Clone: src.CloneURL,
|
||||
CloneSSH: src.SSHURL,
|
||||
Link: src.HTMLURL,
|
||||
Archived: src.Archived,
|
||||
}
|
||||
}
|
||||
|
||||
func convertPerm(src perm) *scm.Perm {
|
||||
return &scm.Perm{
|
||||
Push: src.Push,
|
||||
Pull: src.Pull,
|
||||
Admin: src.Admin,
|
||||
}
|
||||
}
|
||||
|
||||
func convertHookList(src []*hook) []*scm.Hook {
|
||||
var dst []*scm.Hook
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertHook(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertHook(from *hook) *scm.Hook {
|
||||
return &scm.Hook{
|
||||
ID: strconv.Itoa(from.ID),
|
||||
Active: from.Active,
|
||||
Target: from.Config.URL,
|
||||
Events: from.Events,
|
||||
}
|
||||
}
|
||||
|
||||
func convertHookEvent(from scm.HookEvents) []string {
|
||||
var events []string
|
||||
if from.PullRequest {
|
||||
events = append(events, "pull_request")
|
||||
}
|
||||
if from.Issue {
|
||||
events = append(events, "issues")
|
||||
}
|
||||
if from.IssueComment || from.PullRequestComment {
|
||||
events = append(events, "issue_comment")
|
||||
}
|
||||
if from.Branch || from.Tag {
|
||||
events = append(events, "create")
|
||||
events = append(events, "delete")
|
||||
}
|
||||
if from.Push {
|
||||
events = append(events, "push")
|
||||
}
|
||||
return events
|
||||
}
|
||||
|
||||
func convertStatusList(src []*status) []*scm.Status {
|
||||
var dst []*scm.Status
|
||||
for _, v := range src {
|
||||
dst = append(dst, convertStatus(v))
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
func convertStatus(from *status) *scm.Status {
|
||||
return &scm.Status{
|
||||
State: convertState(from.State),
|
||||
Label: from.Context,
|
||||
Desc: from.Description,
|
||||
Target: from.TargetURL,
|
||||
}
|
||||
}
|
||||
|
||||
func convertState(from string) scm.State {
|
||||
switch from {
|
||||
case "error":
|
||||
return scm.StateError
|
||||
case "failure":
|
||||
return scm.StateFailure
|
||||
case "pending":
|
||||
return scm.StatePending
|
||||
case "success":
|
||||
return scm.StateSuccess
|
||||
default:
|
||||
return scm.StateUnknown
|
||||
}
|
||||
}
|
||||
|
||||
func convertFromState(from scm.State) string {
|
||||
switch from {
|
||||
case scm.StatePending, scm.StateRunning:
|
||||
return "pending"
|
||||
case scm.StateSuccess:
|
||||
return "success"
|
||||
case scm.StateFailure:
|
||||
return "failure"
|
||||
default:
|
||||
return "error"
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
//
|
||||
// repository sub-tests
|
||||
//
|
@ -0,0 +1,31 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type reviewService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *reviewService) Find(ctx context.Context, repo string, number, id int) (*scm.Review, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *reviewService) List(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Review, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *reviewService) Create(ctx context.Context, repo string, number int, input *scm.ReviewInput) (*scm.Review, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *reviewService) Delete(ctx context.Context, repo string, number, id int) (*scm.Response, error) {
|
||||
return nil, scm.ErrNotSupported
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"type": "file",
|
||||
"sha": "7839122fc2ec4af9d5a6c14c779a82a05c5769b5",
|
||||
"name": "README.md",
|
||||
"path": "README.md",
|
||||
"latest_commit": {
|
||||
"sha": "98189d5cf2a751a6246c24a72945ba70839f1b20",
|
||||
"title": "initial commit",
|
||||
"message": "initial commit",
|
||||
"author": {
|
||||
"identity": {
|
||||
"name": "gitness",
|
||||
"email": "system@gitness"
|
||||
},
|
||||
"when": "2023-02-02T14:12:13Z"
|
||||
},
|
||||
"committer": {
|
||||
"identity": {
|
||||
"name": "gitness",
|
||||
"email": "system@gitness"
|
||||
},
|
||||
"when": "2023-02-02T14:12:13Z"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"encoding": "base64",
|
||||
"data": "ZGVtbw0KdGVzdCBzdHJpbmc=",
|
||||
"size": 23
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
{
|
||||
"type": "dir",
|
||||
"sha": "4fdc5acb2f9074a6d6ec826f01518fb27fe20a06",
|
||||
"name": "",
|
||||
"path": "",
|
||||
"latest_commit": {
|
||||
"sha": "4381eecb9dd29c34972087c4185f392c20d9f7c0",
|
||||
"title": "move to version 1.1.2",
|
||||
"message": "move to version 1.1.2",
|
||||
"author": {
|
||||
"identity": {
|
||||
"name": "Johannes Batzill",
|
||||
"email": "johannes.batzill@harness.io"
|
||||
},
|
||||
"when": "2023-02-01T02:27:42Z"
|
||||
},
|
||||
"committer": {
|
||||
"identity": {
|
||||
"name": "Johannes Batzill",
|
||||
"email": "johannes.batzill@harness.io"
|
||||
},
|
||||
"when": "2023-02-01T02:27:42Z"
|
||||
}
|
||||
},
|
||||
"content": {
|
||||
"entries": [
|
||||
{
|
||||
"type": "file",
|
||||
"sha": "41fdf994e79e42bd4136c7e3004367f6d21d800d",
|
||||
"name": ".gitignore",
|
||||
"path": ".gitignore",
|
||||
"latest_commit": {
|
||||
"sha": "f8de11b6f3e4499889e16b989977c66c84ad02c9",
|
||||
"title": "add initial version of demo application",
|
||||
"message": "add initial version of demo application",
|
||||
"author": {
|
||||
"identity": {
|
||||
"name": "Johannes Batzill",
|
||||
"email": "johannes.batzill@harness.io"
|
||||
},
|
||||
"when": "2023-02-01T00:08:20Z"
|
||||
},
|
||||
"committer": {
|
||||
"identity": {
|
||||
"name": "Johannes Batzill",
|
||||
"email": "johannes.batzill@harness.io"
|
||||
},
|
||||
"when": "2023-02-01T00:08:20Z"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"sha": "261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64",
|
||||
"name": "LICENSE",
|
||||
"path": "LICENSE",
|
||||
"latest_commit": {
|
||||
"sha": "a2a1bb3664f096e69f4b15b80f4650cc9f8ae913",
|
||||
"title": "Initial commit",
|
||||
"message": "Initial commit",
|
||||
"author": {
|
||||
"identity": {
|
||||
"name": "Johannes Batzill",
|
||||
"email": "johannes.batzill@harness.io"
|
||||
},
|
||||
"when": "2023-01-31T23:54:24Z"
|
||||
},
|
||||
"committer": {
|
||||
"identity": {
|
||||
"name": "GitHub",
|
||||
"email": "noreply@github.com"
|
||||
},
|
||||
"when": "2023-01-31T23:54:24Z"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"Path": ".gitignore",
|
||||
"Sha": "f8de11b6f3e4499889e16b989977c66c84ad02c9",
|
||||
"BlobID": "41fdf994e79e42bd4136c7e3004367f6d21d800d",
|
||||
"kind": "file"
|
||||
},
|
||||
{
|
||||
"Path": "LICENSE",
|
||||
"Sha": "a2a1bb3664f096e69f4b15b80f4650cc9f8ae913",
|
||||
"BlobID": "261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64",
|
||||
"kind": "file"
|
||||
}
|
||||
]
|
@ -0,0 +1,172 @@
|
||||
{
|
||||
"secret": "12345",
|
||||
"action": "opened",
|
||||
"number": 1,
|
||||
"pull_request": {
|
||||
"id": 473,
|
||||
"url": "",
|
||||
"number": 1,
|
||||
"user": {
|
||||
"id": 6641,
|
||||
"login": "jcitizen",
|
||||
"full_name": "",
|
||||
"email": "jane@example.com",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon",
|
||||
"language": "en-US",
|
||||
"username": "jcitizen"
|
||||
},
|
||||
"title": "Add License File",
|
||||
"body": "Using a BSD License",
|
||||
"labels": [],
|
||||
"milestone": null,
|
||||
"assignee": null,
|
||||
"assignees": null,
|
||||
"state": "open",
|
||||
"comments": 0,
|
||||
"html_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1",
|
||||
"diff_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.diff",
|
||||
"patch_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.patch",
|
||||
"mergeable": true,
|
||||
"merged": false,
|
||||
"merged_at": null,
|
||||
"merge_commit_sha": null,
|
||||
"merged_by": null,
|
||||
"base": {
|
||||
"label": "master",
|
||||
"ref": "master",
|
||||
"sha": "39af58f1eff02aa308e16913e887c8d50362b474",
|
||||
"repo_id": 6589,
|
||||
"repo": {
|
||||
"id": 6589,
|
||||
"owner": {
|
||||
"id": 6641,
|
||||
"login": "jcitizen",
|
||||
"full_name": "",
|
||||
"email": "jane@example.com",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon",
|
||||
"language": "en-US",
|
||||
"username": "jcitizen"
|
||||
},
|
||||
"name": "my-repo",
|
||||
"full_name": "jcitizen/my-repo",
|
||||
"description": "",
|
||||
"empty": false,
|
||||
"private": false,
|
||||
"fork": false,
|
||||
"parent": null,
|
||||
"mirror": false,
|
||||
"size": 64,
|
||||
"html_url": "https://try.gitea.io/jcitizen/my-repo",
|
||||
"ssh_url": "git@try.gitea.io:jcitizen/my-repo.git",
|
||||
"clone_url": "https://try.gitea.io/jcitizen/my-repo.git",
|
||||
"website": "",
|
||||
"stars_count": 0,
|
||||
"forks_count": 0,
|
||||
"watchers_count": 1,
|
||||
"open_issues_count": 0,
|
||||
"default_branch": "master",
|
||||
"created_at": "2018-07-06T00:08:02Z",
|
||||
"updated_at": "2018-07-06T01:06:56Z",
|
||||
"permissions": {
|
||||
"admin": false,
|
||||
"push": false,
|
||||
"pull": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"label": "feature",
|
||||
"ref": "feature",
|
||||
"sha": "2eba238e33607c1fa49253182e9fff42baafa1eb",
|
||||
"repo_id": 6589,
|
||||
"repo": {
|
||||
"id": 6589,
|
||||
"owner": {
|
||||
"id": 6641,
|
||||
"login": "jcitizen",
|
||||
"full_name": "",
|
||||
"email": "jane@example.com",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon",
|
||||
"language": "en-US",
|
||||
"username": "jcitizen"
|
||||
},
|
||||
"name": "my-repo",
|
||||
"full_name": "jcitizen/my-repo",
|
||||
"description": "",
|
||||
"empty": false,
|
||||
"private": false,
|
||||
"fork": false,
|
||||
"parent": null,
|
||||
"mirror": false,
|
||||
"size": 64,
|
||||
"html_url": "https://try.gitea.io/jcitizen/my-repo",
|
||||
"ssh_url": "git@try.gitea.io:jcitizen/my-repo.git",
|
||||
"clone_url": "https://try.gitea.io/jcitizen/my-repo.git",
|
||||
"website": "",
|
||||
"stars_count": 0,
|
||||
"forks_count": 0,
|
||||
"watchers_count": 1,
|
||||
"open_issues_count": 0,
|
||||
"default_branch": "master",
|
||||
"created_at": "2018-07-06T00:08:02Z",
|
||||
"updated_at": "2018-07-06T01:06:56Z",
|
||||
"permissions": {
|
||||
"admin": false,
|
||||
"push": false,
|
||||
"pull": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"merge_base": "39af58f1eff02aa308e16913e887c8d50362b474",
|
||||
"due_date": null,
|
||||
"created_at": "2018-07-06T00:37:47Z",
|
||||
"updated_at": "2018-07-06T00:37:47Z",
|
||||
"closed_at": null
|
||||
},
|
||||
"repository": {
|
||||
"id": 6589,
|
||||
"owner": {
|
||||
"id": 6641,
|
||||
"login": "jcitizen",
|
||||
"full_name": "",
|
||||
"email": "jane@example.com",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon",
|
||||
"language": "en-US",
|
||||
"username": "jcitizen"
|
||||
},
|
||||
"name": "my-repo",
|
||||
"full_name": "jcitizen/my-repo",
|
||||
"description": "",
|
||||
"empty": false,
|
||||
"private": false,
|
||||
"fork": false,
|
||||
"parent": null,
|
||||
"mirror": false,
|
||||
"size": 64,
|
||||
"html_url": "https://try.gitea.io/jcitizen/my-repo",
|
||||
"ssh_url": "git@try.gitea.io:jcitizen/my-repo.git",
|
||||
"clone_url": "https://try.gitea.io/jcitizen/my-repo.git",
|
||||
"website": "",
|
||||
"stars_count": 0,
|
||||
"forks_count": 0,
|
||||
"watchers_count": 1,
|
||||
"open_issues_count": 0,
|
||||
"default_branch": "master",
|
||||
"created_at": "2018-07-06T00:08:02Z",
|
||||
"updated_at": "2018-07-06T01:06:56Z",
|
||||
"permissions": {
|
||||
"admin": false,
|
||||
"push": false,
|
||||
"pull": false
|
||||
}
|
||||
},
|
||||
"sender": {
|
||||
"id": 6641,
|
||||
"login": "jcitizen",
|
||||
"full_name": "",
|
||||
"email": "jane@example.com",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon",
|
||||
"language": "en-US",
|
||||
"username": "jcitizen"
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
{
|
||||
"Action": "opened",
|
||||
"Repo": {
|
||||
"ID": "6589",
|
||||
"Namespace": "jcitizen",
|
||||
"Name": "my-repo",
|
||||
"Perm": {
|
||||
"Pull": false,
|
||||
"Push": false,
|
||||
"Admin": false
|
||||
},
|
||||
"Branch": "master",
|
||||
"Private": false,
|
||||
"Clone": "https://try.gitea.io/jcitizen/my-repo.git",
|
||||
"CloneSSH": "git@try.gitea.io:jcitizen/my-repo.git",
|
||||
"Link": "https://try.gitea.io/jcitizen/my-repo",
|
||||
"Created": "0001-01-01T00:00:00Z",
|
||||
"Updated": "0001-01-01T00:00:00Z"
|
||||
},
|
||||
"PullRequest": {
|
||||
"Number": 1,
|
||||
"Title": "Add License File",
|
||||
"Body": "Using a BSD License",
|
||||
"Sha": "2eba238e33607c1fa49253182e9fff42baafa1eb",
|
||||
"Ref": "refs/pull/1/head",
|
||||
"Source": "feature",
|
||||
"Target": "master",
|
||||
"Fork": "jcitizen/my-repo",
|
||||
"Link": "https://try.gitea.io/jcitizen/my-repo/pulls/1",
|
||||
"Closed": false,
|
||||
"Merged": false,
|
||||
"Author": {
|
||||
"Login": "jcitizen",
|
||||
"Name": "",
|
||||
"Email": "jane@example.com",
|
||||
"Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon"
|
||||
},
|
||||
"Created": "0001-01-01T00:00:00Z",
|
||||
"Updated": "0001-01-01T00:00:00Z"
|
||||
},
|
||||
"Sender": {
|
||||
"Login": "jcitizen",
|
||||
"Name": "",
|
||||
"Email": "jane@example.com",
|
||||
"Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon"
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
type userService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) {
|
||||
out := new(user)
|
||||
res, err := s.client.do(ctx, "GET", "api/v1/user", nil, out)
|
||||
return convertUser(out), res, err
|
||||
}
|
||||
|
||||
func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) {
|
||||
return "", nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) {
|
||||
return nil, nil, scm.ErrNotSupported
|
||||
}
|
||||
|
||||
//
|
||||
// native data structures
|
||||
//
|
||||
|
||||
type user struct {
|
||||
ID int `json:"id"`
|
||||
Login string `json:"login"`
|
||||
Username string `json:"username"`
|
||||
Fullname string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Avatar string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
//
|
||||
// native data structure conversion
|
||||
//
|
||||
|
||||
func convertUser(src *user) *scm.User {
|
||||
return &scm.User{
|
||||
Login: userLogin(src),
|
||||
Avatar: src.Avatar,
|
||||
Email: src.Email,
|
||||
Name: src.Fullname,
|
||||
}
|
||||
}
|
||||
|
||||
func userLogin(src *user) string {
|
||||
if src.Username != "" {
|
||||
return src.Username
|
||||
}
|
||||
return src.Login
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
@ -0,0 +1,103 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
func encodeListOptions(opts scm.ListOptions) string {
|
||||
params := url.Values{}
|
||||
if opts.Page != 0 {
|
||||
params.Set("page", strconv.Itoa(opts.Page))
|
||||
}
|
||||
if opts.Size != 0 {
|
||||
params.Set("limit", strconv.Itoa(opts.Size))
|
||||
}
|
||||
return params.Encode()
|
||||
}
|
||||
|
||||
func encodeIssueListOptions(opts scm.IssueListOptions) string {
|
||||
params := url.Values{}
|
||||
if opts.Page != 0 {
|
||||
params.Set("page", strconv.Itoa(opts.Page))
|
||||
}
|
||||
if opts.Size != 0 {
|
||||
params.Set("limit", strconv.Itoa(opts.Size))
|
||||
}
|
||||
if opts.Open && opts.Closed {
|
||||
params.Set("state", "all")
|
||||
} else if opts.Closed {
|
||||
params.Set("state", "closed")
|
||||
}
|
||||
return params.Encode()
|
||||
}
|
||||
|
||||
func encodePullRequestListOptions(opts scm.PullRequestListOptions) string {
|
||||
params := url.Values{}
|
||||
if opts.Page != 0 {
|
||||
params.Set("page", strconv.Itoa(opts.Page))
|
||||
}
|
||||
if opts.Size != 0 {
|
||||
params.Set("limit", strconv.Itoa(opts.Size))
|
||||
}
|
||||
if opts.Open && opts.Closed {
|
||||
params.Set("state", "all")
|
||||
} else if opts.Closed {
|
||||
params.Set("state", "closed")
|
||||
}
|
||||
return params.Encode()
|
||||
}
|
||||
|
||||
// convertAPIURLToHTMLURL converts an release API endpoint into a html endpoint
|
||||
func convertAPIURLToHTMLURL(apiURL string, tagName string) string {
|
||||
// "url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123",
|
||||
// "html_url": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0",
|
||||
// the url field is the API url, not the html url, so until go-sdk v0.13.3, build it ourselves
|
||||
link, err := url.Parse(apiURL)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
pathParts := strings.Split(link.Path, "/")
|
||||
if len(pathParts) != 7 {
|
||||
return ""
|
||||
}
|
||||
link.Path = fmt.Sprintf("/%s/%s/releases/tag/%s", pathParts[4], pathParts[5], tagName)
|
||||
return link.String()
|
||||
}
|
||||
|
||||
func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string {
|
||||
params := url.Values{}
|
||||
if opts.Page != 0 {
|
||||
params.Set("page", strconv.Itoa(opts.Page))
|
||||
}
|
||||
if opts.Size != 0 {
|
||||
params.Set("per_page", strconv.Itoa(opts.Size))
|
||||
}
|
||||
if opts.Open && opts.Closed {
|
||||
params.Set("state", "all")
|
||||
} else if opts.Closed {
|
||||
params.Set("state", "closed")
|
||||
}
|
||||
return params.Encode()
|
||||
}
|
||||
|
||||
type ListOptions struct {
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
|
||||
func encodeReleaseListOptions(o ListOptions) string {
|
||||
query := make(url.Values)
|
||||
query.Add("page", fmt.Sprintf("%d", o.Page))
|
||||
query.Add("limit", fmt.Sprintf("%d", o.PageSize))
|
||||
return query.Encode()
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
)
|
||||
|
||||
func Test_encodeListOptions(t *testing.T) {
|
||||
opts := scm.ListOptions{
|
||||
Page: 10,
|
||||
Size: 30,
|
||||
}
|
||||
want := "limit=30&page=10"
|
||||
got := encodeListOptions(opts)
|
||||
if got != want {
|
||||
t.Errorf("Want encoded list options %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_encodeIssueListOptions(t *testing.T) {
|
||||
opts := scm.IssueListOptions{
|
||||
Page: 10,
|
||||
Size: 30,
|
||||
Open: true,
|
||||
Closed: true,
|
||||
}
|
||||
want := "limit=30&page=10&state=all"
|
||||
got := encodeIssueListOptions(opts)
|
||||
if got != want {
|
||||
t.Errorf("Want encoded issue list options %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_encodeIssueListOptions_Closed(t *testing.T) {
|
||||
opts := scm.IssueListOptions{
|
||||
Page: 10,
|
||||
Size: 30,
|
||||
Open: false,
|
||||
Closed: true,
|
||||
}
|
||||
want := "limit=30&page=10&state=closed"
|
||||
got := encodeIssueListOptions(opts)
|
||||
if got != want {
|
||||
t.Errorf("Want encoded issue list options %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_encodePullRequestListOptions(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := scm.PullRequestListOptions{
|
||||
Page: 10,
|
||||
Size: 30,
|
||||
Open: true,
|
||||
Closed: true,
|
||||
}
|
||||
want := "limit=30&page=10&state=all"
|
||||
got := encodePullRequestListOptions(opts)
|
||||
if got != want {
|
||||
t.Errorf("Want encoded pr list options %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_encodePullRequestListOptions_Closed(t *testing.T) {
|
||||
t.Parallel()
|
||||
opts := scm.PullRequestListOptions{
|
||||
Page: 10,
|
||||
Size: 30,
|
||||
Open: false,
|
||||
Closed: true,
|
||||
}
|
||||
want := "limit=30&page=10&state=closed"
|
||||
got := encodePullRequestListOptions(opts)
|
||||
if got != want {
|
||||
t.Errorf("Want encoded pr list options %q, got %q", want, got)
|
||||
}
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/drone/go-scm/scm/driver/internal/hmac"
|
||||
)
|
||||
|
||||
type webhookService struct {
|
||||
client *wrapper
|
||||
}
|
||||
|
||||
func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhook, error) {
|
||||
data, err := ioutil.ReadAll(
|
||||
io.LimitReader(req.Body, 10000000),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var hook scm.Webhook
|
||||
switch req.Header.Get("X-Gitea-Event") {
|
||||
case "push":
|
||||
hook, err = s.parsePushHook(data)
|
||||
case "create":
|
||||
hook, err = s.parseCreateHook(data)
|
||||
case "delete":
|
||||
hook, err = s.parseDeleteHook(data)
|
||||
case "issues":
|
||||
hook, err = s.parseIssueHook(data)
|
||||
case "issue_comment":
|
||||
hook, err = s.parseIssueCommentHook(data)
|
||||
case "pull_request":
|
||||
hook, err = s.parsePullRequestHook(data)
|
||||
default:
|
||||
return nil, scm.ErrUnknownEvent
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get the gitea signature key to verify the payload
|
||||
// signature. If no key is provided, no validation
|
||||
// is performed.
|
||||
key, err := fn(hook)
|
||||
if err != nil {
|
||||
return hook, err
|
||||
} else if key == "" {
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
secret := req.FormValue("secret")
|
||||
signature := req.Header.Get("X-Gitea-Signature")
|
||||
|
||||
// fail if no signature passed
|
||||
if signature == "" && secret == "" {
|
||||
return hook, scm.ErrSignatureInvalid
|
||||
}
|
||||
|
||||
// test signature if header not set and secret is in payload
|
||||
if signature == "" && secret != "" && secret != key {
|
||||
return hook, scm.ErrSignatureInvalid
|
||||
}
|
||||
|
||||
// test signature using header
|
||||
if signature != "" && !hmac.Validate(sha256.New, data, []byte(key), signature) {
|
||||
return hook, scm.ErrSignatureInvalid
|
||||
}
|
||||
|
||||
return hook, nil
|
||||
}
|
||||
|
||||
func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) {
|
||||
dst := new(pushHook)
|
||||
err := json.Unmarshal(data, dst)
|
||||
return convertPushHook(dst), err
|
||||
}
|
||||
|
||||
func (s *webhookService) parseCreateHook(data []byte) (scm.Webhook, error) {
|
||||
dst := new(createHook)
|
||||
err := json.Unmarshal(data, dst)
|
||||
switch dst.RefType {
|
||||
case "tag":
|
||||
return convertTagHook(dst, scm.ActionCreate), err
|
||||
case "branch":
|
||||
return convertBranchHook(dst, scm.ActionCreate), err
|
||||
default:
|
||||
return nil, scm.ErrUnknownEvent
|
||||
}
|
||||
}
|
||||
|
||||
func (s *webhookService) parseDeleteHook(data []byte) (scm.Webhook, error) {
|
||||
dst := new(createHook)
|
||||
err := json.Unmarshal(data, dst)
|
||||
switch dst.RefType {
|
||||
case "tag":
|
||||
return convertTagHook(dst, scm.ActionDelete), err
|
||||
case "branch":
|
||||
return convertBranchHook(dst, scm.ActionDelete), err
|
||||
default:
|
||||
return nil, scm.ErrUnknownEvent
|
||||
}
|
||||
}
|
||||
|
||||
func (s *webhookService) parseIssueHook(data []byte) (scm.Webhook, error) {
|
||||
dst := new(issueHook)
|
||||
err := json.Unmarshal(data, dst)
|
||||
return convertIssueHook(dst), err
|
||||
}
|
||||
|
||||
func (s *webhookService) parseIssueCommentHook(data []byte) (scm.Webhook, error) {
|
||||
dst := new(issueHook)
|
||||
err := json.Unmarshal(data, dst)
|
||||
if dst.Issue.PullRequest != nil {
|
||||
return convertPullRequestCommentHook(dst), err
|
||||
}
|
||||
return convertIssueCommentHook(dst), err
|
||||
}
|
||||
|
||||
func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) {
|
||||
dst := new(pullRequestHook)
|
||||
err := json.Unmarshal(data, dst)
|
||||
return convertPullRequestHook(dst), err
|
||||
}
|
||||
|
||||
//
|
||||
// native data structures
|
||||
//
|
||||
|
||||
type (
|
||||
// gitea push webhook payload
|
||||
pushHook struct {
|
||||
Ref string `json:"ref"`
|
||||
Before string `json:"before"`
|
||||
After string `json:"after"`
|
||||
Compare string `json:"compare_url"`
|
||||
Commits []commit `json:"commits"`
|
||||
Repository repository `json:"repository"`
|
||||
Pusher user `json:"pusher"`
|
||||
Sender user `json:"sender"`
|
||||
}
|
||||
|
||||
// gitea create webhook payload
|
||||
createHook struct {
|
||||
Ref string `json:"ref"`
|
||||
RefType string `json:"ref_type"`
|
||||
Sha string `json:"sha"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
Repository repository `json:"repository"`
|
||||
Sender user `json:"sender"`
|
||||
}
|
||||
|
||||
// gitea issue webhook payload
|
||||
issueHook struct {
|
||||
Action string `json:"action"`
|
||||
Issue issue `json:"issue"`
|
||||
Comment issueComment `json:"comment"`
|
||||
Repository repository `json:"repository"`
|
||||
Sender user `json:"sender"`
|
||||
}
|
||||
|
||||
// gitea pull request webhook payload
|
||||
pullRequestHook struct {
|
||||
Action string `json:"action"`
|
||||
Number int `json:"number"`
|
||||
PullRequest pr `json:"pull_request"`
|
||||
Repository repository `json:"repository"`
|
||||
Sender user `json:"sender"`
|
||||
}
|
||||
)
|
||||
|
||||
//
|
||||
// native data structure conversion
|
||||
//
|
||||
|
||||
func convertTagHook(dst *createHook, action scm.Action) *scm.TagHook {
|
||||
return &scm.TagHook{
|
||||
Action: action,
|
||||
Ref: scm.Reference{
|
||||
Name: dst.Ref,
|
||||
Sha: dst.Sha,
|
||||
},
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
|
||||
func convertBranchHook(dst *createHook, action scm.Action) *scm.BranchHook {
|
||||
return &scm.BranchHook{
|
||||
Action: action,
|
||||
Ref: scm.Reference{
|
||||
Name: dst.Ref,
|
||||
},
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
|
||||
func convertPushHook(dst *pushHook) *scm.PushHook {
|
||||
if len(dst.Commits) > 0 {
|
||||
var commits []scm.Commit
|
||||
for _, c := range dst.Commits {
|
||||
commits = append(commits,
|
||||
scm.Commit{
|
||||
Sha: c.ID,
|
||||
Message: c.Message,
|
||||
Link: c.URL,
|
||||
Author: scm.Signature{
|
||||
Login: c.Author.Username,
|
||||
Email: c.Author.Email,
|
||||
Name: c.Author.Name,
|
||||
Date: c.Timestamp,
|
||||
},
|
||||
Committer: scm.Signature{
|
||||
Login: c.Committer.Username,
|
||||
Email: c.Committer.Email,
|
||||
Name: c.Committer.Name,
|
||||
Date: c.Timestamp,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return &scm.PushHook{
|
||||
Ref: dst.Ref,
|
||||
Before: dst.Before,
|
||||
Commit: scm.Commit{
|
||||
Sha: dst.After,
|
||||
Message: dst.Commits[0].Message,
|
||||
Link: dst.Compare,
|
||||
Author: scm.Signature{
|
||||
Login: dst.Commits[0].Author.Username,
|
||||
Email: dst.Commits[0].Author.Email,
|
||||
Name: dst.Commits[0].Author.Name,
|
||||
Date: dst.Commits[0].Timestamp,
|
||||
},
|
||||
Committer: scm.Signature{
|
||||
Login: dst.Commits[0].Committer.Username,
|
||||
Email: dst.Commits[0].Committer.Email,
|
||||
Name: dst.Commits[0].Committer.Name,
|
||||
Date: dst.Commits[0].Timestamp,
|
||||
},
|
||||
},
|
||||
Commits: commits,
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
return &scm.PushHook{
|
||||
Ref: dst.Ref,
|
||||
Commit: scm.Commit{
|
||||
Sha: dst.After,
|
||||
Link: dst.Compare,
|
||||
Author: scm.Signature{
|
||||
Login: dst.Pusher.Login,
|
||||
Email: dst.Pusher.Email,
|
||||
Name: dst.Pusher.Fullname,
|
||||
},
|
||||
Committer: scm.Signature{
|
||||
Login: dst.Pusher.Login,
|
||||
Email: dst.Pusher.Email,
|
||||
Name: dst.Pusher.Fullname,
|
||||
},
|
||||
},
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
|
||||
func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook {
|
||||
return &scm.PullRequestHook{
|
||||
Action: convertAction(dst.Action),
|
||||
PullRequest: scm.PullRequest{
|
||||
Number: dst.PullRequest.Number,
|
||||
Title: dst.PullRequest.Title,
|
||||
Body: dst.PullRequest.Body,
|
||||
Closed: dst.PullRequest.State == "closed",
|
||||
Author: scm.User{
|
||||
Login: dst.PullRequest.User.Login,
|
||||
Email: dst.PullRequest.User.Email,
|
||||
Avatar: dst.PullRequest.User.Avatar,
|
||||
},
|
||||
Merged: dst.PullRequest.Merged,
|
||||
// Created: nil,
|
||||
// Updated: nil,
|
||||
Source: dst.PullRequest.Head.Name,
|
||||
Target: dst.PullRequest.Base.Name,
|
||||
Fork: dst.PullRequest.Head.Repo.FullName,
|
||||
Link: dst.PullRequest.HTMLURL,
|
||||
Ref: fmt.Sprintf("refs/pull/%d/head", dst.PullRequest.Number),
|
||||
Sha: dst.PullRequest.Head.Sha,
|
||||
},
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
|
||||
func convertPullRequestCommentHook(dst *issueHook) *scm.PullRequestCommentHook {
|
||||
return &scm.PullRequestCommentHook{
|
||||
Action: convertAction(dst.Action),
|
||||
PullRequest: *convertPullRequestFromIssue(&dst.Issue),
|
||||
Comment: *convertIssueComment(&dst.Comment),
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
|
||||
func convertIssueHook(dst *issueHook) *scm.IssueHook {
|
||||
return &scm.IssueHook{
|
||||
Action: convertAction(dst.Action),
|
||||
Issue: *convertIssue(&dst.Issue),
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
|
||||
func convertIssueCommentHook(dst *issueHook) *scm.IssueCommentHook {
|
||||
return &scm.IssueCommentHook{
|
||||
Action: convertAction(dst.Action),
|
||||
Issue: *convertIssue(&dst.Issue),
|
||||
Comment: *convertIssueComment(&dst.Comment),
|
||||
Repo: *convertRepository(&dst.Repository),
|
||||
Sender: *convertUser(&dst.Sender),
|
||||
}
|
||||
}
|
||||
|
||||
func convertAction(src string) (action scm.Action) {
|
||||
switch src {
|
||||
case "create", "created":
|
||||
return scm.ActionCreate
|
||||
case "delete", "deleted":
|
||||
return scm.ActionDelete
|
||||
case "update", "updated", "edit", "edited":
|
||||
return scm.ActionUpdate
|
||||
case "open", "opened":
|
||||
return scm.ActionOpen
|
||||
case "reopen", "reopened":
|
||||
return scm.ActionReopen
|
||||
case "close", "closed":
|
||||
return scm.ActionClose
|
||||
case "label", "labeled":
|
||||
return scm.ActionLabel
|
||||
case "unlabel", "unlabeled":
|
||||
return scm.ActionUnlabel
|
||||
case "merge", "merged":
|
||||
return scm.ActionMerge
|
||||
case "synchronize", "synchronized":
|
||||
return scm.ActionSync
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
// Copyright 2017 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package harness
|
Loading…
Reference in New Issue