1
0
mirror of https://github.com/woodpecker-ci/woodpecker.git synced 2025-11-23 21:44:44 +02:00

Migrate away from goblin (#4624)

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
This commit is contained in:
qwerty287
2024-12-30 08:08:53 +02:00
committed by GitHub
parent 9325e9e70b
commit afa6dee30b
31 changed files with 3030 additions and 3665 deletions

1
go.mod
View File

@@ -21,7 +21,6 @@ require (
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0
github.com/drone/envsubst v1.0.3 github.com/drone/envsubst v1.0.3
github.com/expr-lang/expr v1.16.9 github.com/expr-lang/expr v1.16.9
github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf
github.com/fsnotify/fsnotify v1.8.0 github.com/fsnotify/fsnotify v1.8.0
github.com/gdgvda/cron v0.3.0 github.com/gdgvda/cron v0.3.0
github.com/getkin/kin-openapi v0.128.1-0.20241224102021-cea0a13b906a github.com/getkin/kin-openapi v0.128.1-0.20241224102021-cea0a13b906a

2
go.sum
View File

@@ -134,8 +134,6 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf h1:NrF81UtW8gG2LBGkXFQFqlfNnvMt9WdB46sfdJY4oqc=
github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=

View File

@@ -45,9 +45,9 @@ func TestGettingConfig(t *testing.T) {
assert.Equal(t, "default", engine.config.Namespace) assert.Equal(t, "default", engine.config.Namespace)
assert.Equal(t, "hdd", engine.config.StorageClass) assert.Equal(t, "hdd", engine.config.StorageClass)
assert.Equal(t, "1G", engine.config.VolumeSize) assert.Equal(t, "1G", engine.config.VolumeSize)
assert.Equal(t, false, engine.config.StorageRwx) assert.False(t, engine.config.StorageRwx)
assert.Equal(t, 1, len(engine.config.PodLabels)) assert.Len(t, engine.config.PodLabels, 1)
assert.Equal(t, 1, len(engine.config.PodAnnotations)) assert.Len(t, engine.config.PodAnnotations, 1)
assert.Equal(t, 1, len(engine.config.ImagePullSecretNames)) assert.Len(t, engine.config.ImagePullSecretNames, 1)
assert.Equal(t, false, engine.config.SecurityContext.RunAsNonRoot) assert.False(t, engine.config.SecurityContext.RunAsNonRoot)
} }

View File

@@ -29,7 +29,7 @@ func TestNativeSecretsEnabled(t *testing.T) {
nsp := newNativeSecretsProcessor(&config{ nsp := newNativeSecretsProcessor(&config{
NativeSecretsAllowFromStep: true, NativeSecretsAllowFromStep: true,
}, nil) }, nil)
assert.Equal(t, true, nsp.isEnabled()) assert.True(t, nsp.isEnabled())
} }
func TestNativeSecretsDisabled(t *testing.T) { func TestNativeSecretsDisabled(t *testing.T) {
@@ -54,7 +54,7 @@ func TestNativeSecretsDisabled(t *testing.T) {
}, },
}, },
}) })
assert.Equal(t, false, nsp.isEnabled()) assert.False(t, nsp.isEnabled())
err := nsp.process() err := nsp.process()
assert.NoError(t, err) assert.NoError(t, err)

View File

@@ -17,42 +17,34 @@ package matrix
import ( import (
"testing" "testing"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
) )
func TestMatrix(t *testing.T) { func TestMatrix(t *testing.T) {
g := goblin.Goblin(t) axis, _ := ParseString(fakeMatrix)
g.Describe("Calculate matrix", func() { assert.Len(t, axis, 24)
axis, _ := ParseString(fakeMatrix)
g.It("Should calculate permutations", func() { set := map[string]bool{}
g.Assert(len(axis)).Equal(24) for _, perm := range axis {
}) set[perm.String()] = true
}
assert.Len(t, set, 24)
}
g.It("Should not duplicate permutations", func() { func TestMatrixEmpty(t *testing.T) {
set := map[string]bool{} axis, err := ParseString("")
for _, perm := range axis { assert.NoError(t, err)
set[perm.String()] = true assert.Empty(t, axis)
} }
g.Assert(len(set)).Equal(24)
})
g.It("Should return empty array if no matrix", func() { func TestMatrixIncluded(t *testing.T) {
axis, err := ParseString("") axis, err := ParseString(fakeMatrixInclude)
g.Assert(err).IsNil() assert.NoError(t, err)
g.Assert(len(axis) == 0).IsTrue() assert.Len(t, axis, 2)
}) assert.Equal(t, "1.5", axis[0]["go_version"])
assert.Equal(t, "1.6", axis[1]["go_version"])
g.It("Should return included axis", func() { assert.Equal(t, "3.4", axis[0]["python_version"])
axis, err := ParseString(fakeMatrixInclude) assert.Equal(t, "3.4", axis[1]["python_version"])
g.Assert(err).IsNil()
g.Assert(len(axis)).Equal(2)
g.Assert(axis[0]["go_version"]).Equal("1.5")
g.Assert(axis[1]["go_version"]).Equal("1.6")
g.Assert(axis[0]["python_version"]).Equal("3.4")
g.Assert(axis[1]["python_version"]).Equal("3.4")
})
})
} }
var fakeMatrix = ` var fakeMatrix = `

View File

@@ -15,10 +15,8 @@
package yaml package yaml
import ( import (
"slices"
"testing" "testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/pipeline/frontend/metadata" "go.woodpecker-ci.org/woodpecker/v3/pipeline/frontend/metadata"
@@ -26,116 +24,103 @@ import (
) )
func TestParse(t *testing.T) { func TestParse(t *testing.T) {
g := goblin.Goblin(t) t.Run("Should unmarshal a string", func(t *testing.T) {
out, err := ParseString(sampleYaml)
assert.NoError(t, err)
g.Describe("Parser", func() { assert.Contains(t, out.When.Constraints[0].Event, "tester")
g.Describe("Given a yaml file", func() {
g.It("Should unmarshal a string", func() {
out, err := ParseString(sampleYaml)
if err != nil {
g.Fail(err)
}
g.Assert(slices.Contains(out.When.Constraints[0].Event, "tester")).Equal(true) assert.Equal(t, "/go", out.Workspace.Base)
assert.Equal(t, "src/github.com/octocat/hello-world", out.Workspace.Path)
assert.Equal(t, "custom", out.Volumes.WorkflowVolumes[0].Name)
assert.Equal(t, "blockbridge", out.Volumes.WorkflowVolumes[0].Driver)
assert.Equal(t, "custom", out.Networks.WorkflowNetworks[0].Name)
assert.Equal(t, "overlay", out.Networks.WorkflowNetworks[0].Driver)
assert.Equal(t, "database", out.Services.ContainerList[0].Name)
assert.Equal(t, "mysql", out.Services.ContainerList[0].Image)
assert.Equal(t, "test", out.Steps.ContainerList[0].Name)
assert.Equal(t, "golang", out.Steps.ContainerList[0].Image)
assert.Equal(t, yaml_base_types.StringOrSlice{"go install", "go test"}, out.Steps.ContainerList[0].Commands)
assert.Equal(t, "build", out.Steps.ContainerList[1].Name)
assert.Equal(t, "golang", out.Steps.ContainerList[1].Image)
assert.Equal(t, yaml_base_types.StringOrSlice{"go build"}, out.Steps.ContainerList[1].Commands)
assert.Equal(t, "notify", out.Steps.ContainerList[2].Name)
assert.Equal(t, "slack", out.Steps.ContainerList[2].Image)
assert.Equal(t, "frontend", out.Labels["com.example.team"])
assert.Equal(t, "build", out.Labels["com.example.type"])
assert.Equal(t, "lint", out.DependsOn[0])
assert.Equal(t, "test", out.DependsOn[1])
assert.Equal(t, ("success"), out.RunsOn[0])
assert.Equal(t, ("failure"), out.RunsOn[1])
assert.False(t, out.SkipClone)
})
g.Assert(out.Workspace.Base).Equal("/go") t.Run("Should handle simple yaml anchors", func(t *testing.T) {
g.Assert(out.Workspace.Path).Equal("src/github.com/octocat/hello-world") out, err := ParseString(simpleYamlAnchors)
g.Assert(out.Volumes.WorkflowVolumes[0].Name).Equal("custom") assert.NoError(t, err)
g.Assert(out.Volumes.WorkflowVolumes[0].Driver).Equal("blockbridge") assert.Equal(t, "notify_success", out.Steps.ContainerList[0].Name)
g.Assert(out.Networks.WorkflowNetworks[0].Name).Equal("custom") assert.Equal(t, "plugins/slack", out.Steps.ContainerList[0].Image)
g.Assert(out.Networks.WorkflowNetworks[0].Driver).Equal("overlay") })
g.Assert(out.Services.ContainerList[0].Name).Equal("database")
g.Assert(out.Services.ContainerList[0].Image).Equal("mysql")
g.Assert(out.Steps.ContainerList[0].Name).Equal("test")
g.Assert(out.Steps.ContainerList[0].Image).Equal("golang")
g.Assert(out.Steps.ContainerList[0].Commands).Equal(yaml_base_types.StringOrSlice{"go install", "go test"})
g.Assert(out.Steps.ContainerList[1].Name).Equal("build")
g.Assert(out.Steps.ContainerList[1].Image).Equal("golang")
g.Assert(out.Steps.ContainerList[1].Commands).Equal(yaml_base_types.StringOrSlice{"go build"})
g.Assert(out.Steps.ContainerList[2].Name).Equal("notify")
g.Assert(out.Steps.ContainerList[2].Image).Equal("slack")
// g.Assert(out.Steps.ContainerList[2].NetworkMode).Equal("container:name")
g.Assert(out.Labels["com.example.team"]).Equal("frontend")
g.Assert(out.Labels["com.example.type"]).Equal("build")
g.Assert(out.DependsOn[0]).Equal("lint")
g.Assert(out.DependsOn[1]).Equal("test")
g.Assert(out.RunsOn[0]).Equal("success")
g.Assert(out.RunsOn[1]).Equal("failure")
g.Assert(out.SkipClone).Equal(false)
})
g.It("Should handle simple yaml anchors", func() { t.Run("Should unmarshal variables", func(t *testing.T) {
out, err := ParseString(simpleYamlAnchors) out, err := ParseString(sampleVarYaml)
if err != nil { assert.NoError(t, err)
g.Fail(err) assert.Equal(t, "notify_fail", out.Steps.ContainerList[0].Name)
} assert.Equal(t, "plugins/slack", out.Steps.ContainerList[0].Image)
g.Assert(out.Steps.ContainerList[0].Name).Equal("notify_success") assert.Equal(t, "notify_success", out.Steps.ContainerList[1].Name)
g.Assert(out.Steps.ContainerList[0].Image).Equal("plugins/slack") assert.Equal(t, "plugins/slack", out.Steps.ContainerList[1].Image)
})
g.It("Should unmarshal variables", func() { assert.Empty(t, out.Steps.ContainerList[0].When.Constraints)
out, err := ParseString(sampleVarYaml) assert.Equal(t, "notify_success", out.Steps.ContainerList[1].Name)
if err != nil { assert.Equal(t, "plugins/slack", out.Steps.ContainerList[1].Image)
g.Fail(err) assert.Equal(t, yaml_base_types.StringOrSlice{"success"}, out.Steps.ContainerList[1].When.Constraints[0].Event)
} })
g.Assert(out.Steps.ContainerList[0].Name).Equal("notify_fail") }
g.Assert(out.Steps.ContainerList[0].Image).Equal("plugins/slack")
g.Assert(out.Steps.ContainerList[1].Name).Equal("notify_success")
g.Assert(out.Steps.ContainerList[1].Image).Equal("plugins/slack")
g.Assert(len(out.Steps.ContainerList[0].When.Constraints)).Equal(0) func TestMatch(t *testing.T) {
g.Assert(out.Steps.ContainerList[1].Name).Equal("notify_success") matchConfig, err := ParseString(sampleYaml)
g.Assert(out.Steps.ContainerList[1].Image).Equal("plugins/slack") assert.NoError(t, err)
g.Assert(out.Steps.ContainerList[1].When.Constraints[0].Event).Equal(yaml_base_types.StringOrSlice{"success"})
})
matchConfig, err := ParseString(sampleYaml) t.Run("Should match event tester", func(t *testing.T) {
if err != nil { match, err := matchConfig.When.Match(metadata.Metadata{
g.Fail(err) Curr: metadata.Pipeline{
} Event: "tester",
},
}, false, nil)
assert.True(t, match)
assert.NoError(t, err)
})
g.It("Should match event tester", func() { t.Run("Should match event tester2", func(t *testing.T) {
match, err := matchConfig.When.Match(metadata.Metadata{ match, err := matchConfig.When.Match(metadata.Metadata{
Curr: metadata.Pipeline{ Curr: metadata.Pipeline{
Event: "tester", Event: "tester2",
}, },
}, false, nil) }, false, nil)
g.Assert(match).Equal(true) assert.True(t, match)
g.Assert(err).IsNil() assert.NoError(t, err)
}) })
g.It("Should match event tester2", func() { t.Run("Should match branch tester", func(t *testing.T) {
match, err := matchConfig.When.Match(metadata.Metadata{ match, err := matchConfig.When.Match(metadata.Metadata{
Curr: metadata.Pipeline{ Curr: metadata.Pipeline{
Event: "tester2", Commit: metadata.Commit{
}, Branch: "tester",
}, false, nil) },
g.Assert(match).Equal(true) },
g.Assert(err).IsNil() }, true, nil)
}) assert.True(t, match)
assert.NoError(t, err)
})
g.It("Should match branch tester", func() { t.Run("Should not match event push", func(t *testing.T) {
match, err := matchConfig.When.Match(metadata.Metadata{ match, err := matchConfig.When.Match(metadata.Metadata{
Curr: metadata.Pipeline{ Curr: metadata.Pipeline{
Commit: metadata.Commit{ Event: "push",
Branch: "tester", },
}, }, false, nil)
}, assert.False(t, match)
}, true, nil) assert.NoError(t, err)
g.Assert(match).Equal(true)
g.Assert(err).IsNil()
})
g.It("Should not match event push", func() {
match, err := matchConfig.When.Match(metadata.Metadata{
Curr: metadata.Pipeline{
Event: "push",
},
}, false, nil)
g.Assert(match).Equal(false)
g.Assert(err).IsNil()
})
})
}) })
} }
@@ -262,27 +247,19 @@ steps:
` `
func TestSlice(t *testing.T) { func TestSlice(t *testing.T) {
g := goblin.Goblin(t) t.Run("should marshal a not set slice to nil", func(t *testing.T) {
out, err := ParseString(sampleSliceYaml)
assert.NoError(t, err)
g.Describe("Parser", func() { assert.Nil(t, out.Steps.ContainerList[0].DependsOn)
g.It("should marshal a not set slice to nil", func() { assert.Empty(t, out.Steps.ContainerList[0].DependsOn)
out, err := ParseString(sampleSliceYaml) })
if err != nil {
g.Fail(err)
}
g.Assert(out.Steps.ContainerList[0].DependsOn).IsNil() t.Run("should marshal an empty slice", func(t *testing.T) {
g.Assert(len(out.Steps.ContainerList[0].DependsOn)).Equal(0) out, err := ParseString(sampleSliceYaml)
}) assert.NoError(t, err)
g.It("should marshal an empty slice", func() { assert.NotNil(t, out.Steps.ContainerList[1].DependsOn)
out, err := ParseString(sampleSliceYaml) assert.Empty(t, (out.Steps.ContainerList[1].DependsOn))
if err != nil {
g.Fail(err)
}
g.Assert(out.Steps.ContainerList[1].DependsOn).IsNotNil()
g.Assert(len(out.Steps.ContainerList[1].DependsOn)).Equal(0)
})
}) })
} }

View File

@@ -17,51 +17,39 @@ package base
import ( import (
"testing" "testing"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
func TestBoolTrue(t *testing.T) { func TestBoolTrue(t *testing.T) {
g := goblin.Goblin(t) t.Run("unmarshal true", func(t *testing.T) {
in := []byte("true")
out := BoolTrue{}
err := yaml.Unmarshal(in, &out)
assert.NoError(t, err)
assert.True(t, out.Bool())
})
g.Describe("Yaml bool type", func() { t.Run("unmarshal false", func(t *testing.T) {
g.Describe("given a yaml file", func() { in := []byte("false")
g.It("should unmarshal true", func() { out := BoolTrue{}
in := []byte("true") err := yaml.Unmarshal(in, &out)
out := BoolTrue{} assert.NoError(t, err)
err := yaml.Unmarshal(in, &out) assert.False(t, out.Bool())
if err != nil { })
g.Fail(err)
}
g.Assert(out.Bool()).Equal(true)
})
g.It("should unmarshal false", func() { t.Run("unmarshal true when empty", func(t *testing.T) {
in := []byte("false") in := []byte("")
out := BoolTrue{} out := BoolTrue{}
err := yaml.Unmarshal(in, &out) err := yaml.Unmarshal(in, &out)
if err != nil { assert.NoError(t, err)
g.Fail(err) assert.True(t, out.Bool())
} })
g.Assert(out.Bool()).Equal(false)
})
g.It("should unmarshal true when empty", func() { t.Run("throw error when invalid", func(t *testing.T) {
in := []byte("") in := []byte("abc") // string value should fail parse
out := BoolTrue{} out := BoolTrue{}
err := yaml.Unmarshal(in, &out) err := yaml.Unmarshal(in, &out)
if err != nil { assert.Error(t, err)
g.Fail(err)
}
g.Assert(out.Bool()).Equal(true)
})
g.It("should throw error when invalid", func() {
in := []byte("abc") // string value should fail parse
out := BoolTrue{}
err := yaml.Unmarshal(in, &out)
g.Assert(err).IsNotNil("expects error")
})
})
}) })
} }

View File

@@ -7,7 +7,6 @@ import (
"net/url" "net/url"
"testing" "testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
@@ -28,77 +27,70 @@ import (
func TestHook(t *testing.T) { func TestHook(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
g := goblin.Goblin(t) _manager := mocks_services.NewManager(t)
g.Describe("Hook", func() { _forge := mocks_forge.NewForge(t)
g.It("should handle a correct webhook payload", func() { _store := mocks_store.NewStore(t)
_manager := mocks_services.NewManager(t) _configService := mocks_config_service.NewService(t)
_forge := mocks_forge.NewForge(t) _secretService := mocks_secret_service.NewService(t)
_store := mocks_store.NewStore(t) _registryService := mocks_registry_service.NewService(t)
_configService := mocks_config_service.NewService(t) server.Config.Services.Manager = _manager
_secretService := mocks_secret_service.NewService(t) server.Config.Permissions.Open = true
_registryService := mocks_registry_service.NewService(t) server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Services.Manager = _manager server.Config.Permissions.Admins = permissions.NewAdmins(nil)
server.Config.Permissions.Open = true w := httptest.NewRecorder()
server.Config.Permissions.Orgs = permissions.NewOrgs(nil) c, _ := gin.CreateTestContext(w)
server.Config.Permissions.Admins = permissions.NewAdmins(nil) c.Set("store", _store)
w := httptest.NewRecorder() user := &model.User{
c, _ := gin.CreateTestContext(w) ID: 123,
c.Set("store", _store) }
user := &model.User{ repo := &model.Repo{
ID: 123, ID: 123,
} ForgeRemoteID: "123",
repo := &model.Repo{ Owner: "owner",
ID: 123, Name: "name",
ForgeRemoteID: "123", IsActive: true,
Owner: "owner", UserID: user.ID,
Name: "name", Hash: "secret-123-this-is-a-secret",
IsActive: true, }
UserID: user.ID, pipeline := &model.Pipeline{
Hash: "secret-123-this-is-a-secret", ID: 123,
} RepoID: repo.ID,
pipeline := &model.Pipeline{ Event: model.EventPush,
ID: 123, }
RepoID: repo.ID,
Event: model.EventPush,
}
repoToken := token.New(token.HookToken) repoToken := token.New(token.HookToken)
repoToken.Set("repo-id", fmt.Sprintf("%d", repo.ID)) repoToken.Set("repo-id", fmt.Sprintf("%d", repo.ID))
signedToken, err := repoToken.Sign("secret-123-this-is-a-secret") signedToken, err := repoToken.Sign("secret-123-this-is-a-secret")
if err != nil { assert.NoError(t, err)
g.Fail(err)
}
header := http.Header{} header := http.Header{}
header.Set("Authorization", fmt.Sprintf("Bearer %s", signedToken)) header.Set("Authorization", fmt.Sprintf("Bearer %s", signedToken))
c.Request = &http.Request{ c.Request = &http.Request{
Header: header, Header: header,
URL: &url.URL{ URL: &url.URL{
Scheme: "https", Scheme: "https",
}, },
} }
_manager.On("ForgeFromRepo", repo).Return(_forge, nil) _manager.On("ForgeFromRepo", repo).Return(_forge, nil)
_forge.On("Hook", mock.Anything, mock.Anything).Return(repo, pipeline, nil) _forge.On("Hook", mock.Anything, mock.Anything).Return(repo, pipeline, nil)
_store.On("GetRepo", repo.ID).Return(repo, nil) _store.On("GetRepo", repo.ID).Return(repo, nil)
_store.On("GetUser", user.ID).Return(user, nil) _store.On("GetUser", user.ID).Return(user, nil)
_store.On("UpdateRepo", repo).Return(nil) _store.On("UpdateRepo", repo).Return(nil)
_store.On("CreatePipeline", mock.Anything).Return(nil) _store.On("CreatePipeline", mock.Anything).Return(nil)
_manager.On("ConfigServiceFromRepo", repo).Return(_configService) _manager.On("ConfigServiceFromRepo", repo).Return(_configService)
_configService.On("Fetch", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) _configService.On("Fetch", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
_forge.On("Netrc", mock.Anything, mock.Anything).Return(&model.Netrc{}, nil) _forge.On("Netrc", mock.Anything, mock.Anything).Return(&model.Netrc{}, nil)
_store.On("GetPipelineLastBefore", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) _store.On("GetPipelineLastBefore", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
_manager.On("SecretServiceFromRepo", repo).Return(_secretService) _manager.On("SecretServiceFromRepo", repo).Return(_secretService)
_secretService.On("SecretListPipeline", repo, mock.Anything, mock.Anything).Return(nil, nil) _secretService.On("SecretListPipeline", repo, mock.Anything, mock.Anything).Return(nil, nil)
_manager.On("RegistryServiceFromRepo", repo).Return(_registryService) _manager.On("RegistryServiceFromRepo", repo).Return(_registryService)
_registryService.On("RegistryListPipeline", repo, mock.Anything).Return(nil, nil) _registryService.On("RegistryListPipeline", repo, mock.Anything).Return(nil, nil)
_manager.On("EnvironmentService").Return(nil) _manager.On("EnvironmentService").Return(nil)
_store.On("DeletePipeline", mock.Anything).Return(nil) _store.On("DeletePipeline", mock.Anything).Return(nil)
api.PostHook(c) api.PostHook(c)
assert.Equal(g, http.StatusNoContent, c.Writer.Status()) assert.Equal(t, http.StatusNoContent, c.Writer.Status())
assert.Equal(g, "true", w.Header().Get("Pipeline-Filtered")) assert.Equal(t, "true", w.Header().Get("Pipeline-Filtered"))
})
})
} }

View File

@@ -9,7 +9,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/franela/goblin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
@@ -29,346 +28,341 @@ import (
func TestHandleAuth(t *testing.T) { func TestHandleAuth(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
g := goblin.Goblin(t) user := &model.User{
g.Describe("Login", func() { ID: 1,
user := &model.User{ OrgID: 1,
ID: 1, ForgeID: 1,
OrgID: 1, ForgeRemoteID: "remote-id-1",
ForgeID: 1, Login: "test",
ForgeRemoteID: "remote-id-1", Email: "test@example.com",
Login: "test", Admin: false,
Email: "test@example.com", }
Admin: false, org := &model.Org{
} ID: 1,
org := &model.Org{ Name: user.Login,
ID: 1, }
Name: user.Login,
server.Config.Server.SessionExpires = time.Hour
t.Run("should handle errors from the callback", func(t *testing.T) {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
query := url.Values{}
query.Set("error", "invalid_scope")
query.Set("error_description", "The requested scope is invalid, unknown, or malformed")
query.Set("error_uri", "https://developer.atlassian.com/cloud/jira/platform/rest/#api-group-OAuth2-ErrorHandling")
c.Request = &http.Request{
Header: make(http.Header),
Method: http.MethodGet,
URL: &url.URL{
Scheme: "https",
Path: "/authorize",
RawQuery: query.Encode(),
},
} }
server.Config.Server.SessionExpires = time.Hour api.HandleAuth(c)
g.It("should handle errors from the callback", func() { assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
w := httptest.NewRecorder() assert.Equal(t, fmt.Sprintf("/login?%s", query.Encode()), c.Writer.Header().Get("Location"))
c, _ := gin.CreateTestContext(w) })
query := url.Values{} t.Run("should fail if the state is wrong", func(t *testing.T) {
query.Set("error", "invalid_scope") _manager := mocks_services.NewManager(t)
query.Set("error_description", "The requested scope is invalid, unknown, or malformed") _store := mocks_store.NewStore(t)
query.Set("error_uri", "https://developer.atlassian.com/cloud/jira/platform/rest/#api-group-OAuth2-ErrorHandling") server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{ query := url.Values{}
Header: make(http.Header), query.Set("code", "assumed_to_be_valid_code")
Method: http.MethodGet,
URL: &url.URL{ wrongToken := token.New(token.OAuthStateToken)
Scheme: "https", wrongToken.Set("forge_id", "1")
Path: "/authorize", signedWrongToken, _ := wrongToken.Sign("wrong_secret")
RawQuery: query.Encode(), query.Set("state", signedWrongToken)
},
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
RawQuery: query.Encode(),
},
}
api.HandleAuth(c)
assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
assert.Equal(t, "/login?error=invalid_state", c.Writer.Header().Get("Location"))
})
t.Run("should redirect to forge login page", func(t *testing.T) {
_manager := mocks_services.NewManager(t)
_forge := mocks_forge.NewForge(t)
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
_manager.On("ForgeByID", int64(1)).Return(_forge, nil)
forgeRedirectURL := ""
_forge.On("Login", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
state, ok := args.Get(1).(*forge_types.OAuthRequest)
if ok {
forgeRedirectURL = fmt.Sprintf("https://my-awesome-forge.com/oauth/authorize?client_id=client-id&state=%s", state.State)
} }
}).Return(nil, func(context.Context, *forge_types.OAuthRequest) string {
return forgeRedirectURL
}, nil)
api.HandleAuth(c) api.HandleAuth(c)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
assert.Equal(g, fmt.Sprintf("/login?%s", query.Encode()), c.Writer.Header().Get("Location")) assert.Equal(t, forgeRedirectURL, c.Writer.Header().Get("Location"))
}) })
g.It("should fail if the state is wrong", func() { t.Run("should register a new user", func(t *testing.T) {
_manager := mocks_services.NewManager(t) _manager := mocks_services.NewManager(t)
_store := mocks_store.NewStore(t) _forge := mocks_forge.NewForge(t)
server.Config.Services.Manager = _manager _store := mocks_store.NewStore(t)
server.Config.Permissions.Open = true server.Config.Services.Manager = _manager
server.Config.Permissions.Orgs = permissions.NewOrgs(nil) server.Config.Permissions.Open = true
server.Config.Permissions.Admins = permissions.NewAdmins(nil) server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
w := httptest.NewRecorder() server.Config.Permissions.Admins = permissions.NewAdmins(nil)
c, _ := gin.CreateTestContext(w) w := httptest.NewRecorder()
c.Set("store", _store) c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
query := url.Values{} _manager.On("ForgeByID", int64(1)).Return(_forge, nil)
query.Set("code", "assumed_to_be_valid_code") _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist)
_store.On("CreateUser", mock.Anything).Return(nil)
_store.On("OrgFindByName", user.Login).Return(nil, nil)
_store.On("OrgCreate", mock.Anything).Return(nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
wrongToken := token.New(token.OAuthStateToken) api.HandleAuth(c)
wrongToken.Set("forge_id", "1")
signedWrongToken, _ := wrongToken.Sign("wrong_secret")
query.Set("state", signedWrongToken)
c.Request = &http.Request{ assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
Header: make(http.Header), assert.Equal(t, "/", c.Writer.Header().Get("Location"))
URL: &url.URL{ assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie"))
Scheme: "https", })
RawQuery: query.Encode(),
},
}
api.HandleAuth(c) t.Run("should login an existing user", func(t *testing.T) {
_manager := mocks_services.NewManager(t)
_forge := mocks_forge.NewForge(t)
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) _manager.On("ForgeByID", int64(1)).Return(_forge, nil)
assert.Equal(g, "/login?error=invalid_state", c.Writer.Header().Get("Location")) _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
}) _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil)
_store.On("OrgGet", org.ID).Return(org, nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
g.It("should redirect to forge login page", func() { api.HandleAuth(c)
_manager := mocks_services.NewManager(t)
_forge := mocks_forge.NewForge(t)
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
_manager.On("ForgeByID", int64(1)).Return(_forge, nil) assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
assert.Equal(t, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie"))
})
forgeRedirectURL := "" t.Run("should deny a new user if registration is closed", func(t *testing.T) {
_forge.On("Login", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { _manager := mocks_services.NewManager(t)
state, ok := args.Get(1).(*forge_types.OAuthRequest) _forge := mocks_forge.NewForge(t)
if ok { _store := mocks_store.NewStore(t)
forgeRedirectURL = fmt.Sprintf("https://my-awesome-forge.com/oauth/authorize?client_id=client-id&state=%s", state.State) server.Config.Services.Manager = _manager
} server.Config.Permissions.Open = false
}).Return(nil, func(context.Context, *forge_types.OAuthRequest) string { server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
return forgeRedirectURL server.Config.Permissions.Admins = permissions.NewAdmins(nil)
}, nil) w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
api.HandleAuth(c) _manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) api.HandleAuth(c)
assert.Equal(g, forgeRedirectURL, c.Writer.Header().Get("Location"))
})
g.It("should register a new user", func() { assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
_manager := mocks_services.NewManager(t) assert.Equal(t, "/login?error=registration_closed", c.Writer.Header().Get("Location"))
_forge := mocks_forge.NewForge(t) })
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
_manager.On("ForgeByID", int64(1)).Return(_forge, nil) t.Run("should deny a user with missing org access", func(t *testing.T) {
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) _manager := mocks_services.NewManager(t)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist) _forge := mocks_forge.NewForge(t)
_store.On("CreateUser", mock.Anything).Return(nil) _store := mocks_store.NewStore(t)
_store.On("OrgFindByName", user.Login).Return(nil, nil) server.Config.Services.Manager = _manager
_store.On("OrgCreate", mock.Anything).Return(nil) server.Config.Permissions.Open = true
_store.On("UpdateUser", mock.Anything).Return(nil) server.Config.Permissions.Orgs = permissions.NewOrgs([]string{"org1"})
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
api.HandleAuth(c) _manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_forge.On("Teams", mock.Anything, user).Return([]*model.Team{
{
Login: "org2",
},
}, nil)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) api.HandleAuth(c)
assert.Equal(g, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie"))
})
g.It("should login an existing user", func() { assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
_manager := mocks_services.NewManager(t) assert.Equal(t, "/login?error=org_access_denied", c.Writer.Header().Get("Location"))
_forge := mocks_forge.NewForge(t) })
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
_manager.On("ForgeByID", int64(1)).Return(_forge, nil) t.Run("User org should be created if it does not exists", func(t *testing.T) {
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) _manager := mocks_services.NewManager(t)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) _forge := mocks_forge.NewForge(t)
_store.On("OrgGet", org.ID).Return(org, nil) _store := mocks_store.NewStore(t)
_store.On("UpdateUser", mock.Anything).Return(nil) server.Config.Services.Manager = _manager
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
user.OrgID = 0
api.HandleAuth(c) _manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil)
_store.On("OrgFindByName", user.Login).Return(nil, types.RecordNotExist)
_store.On("OrgCreate", mock.Anything).Return(nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) api.HandleAuth(c)
assert.Equal(g, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie"))
})
g.It("should deny a new user if registration is closed", func() { assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
_manager := mocks_services.NewManager(t) assert.Equal(t, "/", c.Writer.Header().Get("Location"))
_forge := mocks_forge.NewForge(t) assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie"))
_store := mocks_store.NewStore(t) })
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = false
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
_manager.On("ForgeByID", int64(1)).Return(_forge, nil) t.Run("User org should be linked if it has the same name as the user", func(t *testing.T) {
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) _manager := mocks_services.NewManager(t)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist) _forge := mocks_forge.NewForge(t)
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
user.OrgID = 0
api.HandleAuth(c) _manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil)
_store.On("OrgFindByName", user.Login).Return(org, nil)
_store.On("OrgUpdate", mock.Anything).Return(nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) api.HandleAuth(c)
assert.Equal(g, "/login?error=registration_closed", c.Writer.Header().Get("Location"))
})
g.It("should deny a user with missing org access", func() { assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
_manager := mocks_services.NewManager(t) assert.Equal(t, "/", c.Writer.Header().Get("Location"))
_forge := mocks_forge.NewForge(t) assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie"))
_store := mocks_store.NewStore(t) })
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs([]string{"org1"})
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
_manager.On("ForgeByID", int64(1)).Return(_forge, nil) t.Run("User org should be updated if the user name was changed", func(t *testing.T) {
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) _manager := mocks_services.NewManager(t)
_forge.On("Teams", mock.Anything, user).Return([]*model.Team{ _forge := mocks_forge.NewForge(t)
{ _store := mocks_store.NewStore(t)
Login: "org2", server.Config.Services.Manager = _manager
}, server.Config.Permissions.Open = true
}, nil) server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
org.Name = "not-the-user-name"
api.HandleAuth(c) _manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil)
_store.On("OrgGet", user.OrgID).Return(org, nil)
_store.On("OrgUpdate", mock.Anything).Return(nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) api.HandleAuth(c)
assert.Equal(g, "/login?error=org_access_denied", c.Writer.Header().Get("Location"))
})
g.Describe("User org", func() { assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
g.It("should be created if it does not exists", func() { assert.Equal(t, "/", c.Writer.Header().Get("Location"))
_manager := mocks_services.NewManager(t) assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie"))
_forge := mocks_forge.NewForge(t)
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
user.OrgID = 0
_manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil)
_store.On("OrgFindByName", user.Login).Return(nil, types.RecordNotExist)
_store.On("OrgCreate", mock.Anything).Return(nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
api.HandleAuth(c)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status())
assert.Equal(g, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie"))
})
g.It("should be linked if it has the same name as the user", func() {
_manager := mocks_services.NewManager(t)
_forge := mocks_forge.NewForge(t)
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
user.OrgID = 0
_manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil)
_store.On("OrgFindByName", user.Login).Return(org, nil)
_store.On("OrgUpdate", mock.Anything).Return(nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
api.HandleAuth(c)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status())
assert.Equal(g, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie"))
})
g.It("should be updated if the user name was changed", func() {
_manager := mocks_services.NewManager(t)
_forge := mocks_forge.NewForge(t)
_store := mocks_store.NewStore(t)
server.Config.Services.Manager = _manager
server.Config.Permissions.Open = true
server.Config.Permissions.Orgs = permissions.NewOrgs(nil)
server.Config.Permissions.Admins = permissions.NewAdmins(nil)
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
c.Set("store", _store)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
},
}
org.Name = "not-the-user-name"
_manager.On("ForgeByID", int64(1)).Return(_forge, nil)
_forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil)
_store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil)
_store.On("OrgGet", user.OrgID).Return(org, nil)
_store.On("OrgUpdate", mock.Anything).Return(nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
api.HandleAuth(c)
assert.Equal(g, http.StatusSeeOther, c.Writer.Status())
assert.Equal(g, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie"))
})
})
}) })
} }

View File

@@ -19,82 +19,79 @@ import (
"testing" "testing"
"time" "time"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func TestCC(t *testing.T) { func TestCC(t *testing.T) {
g := goblin.Goblin(t) t.Run("create a project", func(t *testing.T) {
g.Describe("CC", func() { now := time.Now().Unix()
g.It("Should create a project", func() { nowFmt := time.Unix(now, 0).Format(time.RFC3339)
now := time.Now().Unix() r := &model.Repo{
nowFmt := time.Unix(now, 0).Format(time.RFC3339) FullName: "foo/bar",
r := &model.Repo{ }
FullName: "foo/bar", b := &model.Pipeline{
} Status: model.StatusSuccess,
b := &model.Pipeline{ Number: 1,
Status: model.StatusSuccess, Started: now,
Number: 1, }
Started: now, cc := New(r, b, "http://localhost/foo/bar/1")
}
cc := New(r, b, "http://localhost/foo/bar/1")
g.Assert(cc.Project.Name).Equal("foo/bar") assert.Equal(t, "foo/bar", cc.Project.Name)
g.Assert(cc.Project.Activity).Equal("Sleeping") assert.Equal(t, "Sleeping", cc.Project.Activity)
g.Assert(cc.Project.LastBuildStatus).Equal("Success") assert.Equal(t, "Success", cc.Project.LastBuildStatus)
g.Assert(cc.Project.LastBuildLabel).Equal("1") assert.Equal(t, "1", cc.Project.LastBuildLabel)
g.Assert(cc.Project.LastBuildTime).Equal(nowFmt) assert.Equal(t, nowFmt, cc.Project.LastBuildTime)
g.Assert(cc.Project.WebURL).Equal("http://localhost/foo/bar/1") assert.Equal(t, "http://localhost/foo/bar/1", cc.Project.WebURL)
}) })
g.It("Should properly label exceptions", func() { t.Run("properly label exceptions", func(t *testing.T) {
r := &model.Repo{FullName: "foo/bar"} r := &model.Repo{FullName: "foo/bar"}
b := &model.Pipeline{ b := &model.Pipeline{
Status: model.StatusError, Status: model.StatusError,
Number: 1, Number: 1,
Started: 1257894000, Started: 1257894000,
} }
cc := New(r, b, "http://localhost/foo/bar/1") cc := New(r, b, "http://localhost/foo/bar/1")
g.Assert(cc.Project.LastBuildStatus).Equal("Exception") assert.Equal(t, "Exception", cc.Project.LastBuildStatus)
g.Assert(cc.Project.Activity).Equal("Sleeping") assert.Equal(t, "Sleeping", cc.Project.Activity)
}) })
g.It("Should properly label success", func() { t.Run("properly label success", func(t *testing.T) {
r := &model.Repo{FullName: "foo/bar"} r := &model.Repo{FullName: "foo/bar"}
b := &model.Pipeline{ b := &model.Pipeline{
Status: model.StatusSuccess, Status: model.StatusSuccess,
Number: 1, Number: 1,
Started: 1257894000, Started: 1257894000,
} }
cc := New(r, b, "http://localhost/foo/bar/1") cc := New(r, b, "http://localhost/foo/bar/1")
g.Assert(cc.Project.LastBuildStatus).Equal("Success") assert.Equal(t, "Success", cc.Project.LastBuildStatus)
g.Assert(cc.Project.Activity).Equal("Sleeping") assert.Equal(t, "Sleeping", cc.Project.Activity)
}) })
g.It("Should properly label failure", func() { t.Run("properly label failure", func(t *testing.T) {
r := &model.Repo{FullName: "foo/bar"} r := &model.Repo{FullName: "foo/bar"}
b := &model.Pipeline{ b := &model.Pipeline{
Status: model.StatusFailure, Status: model.StatusFailure,
Number: 1, Number: 1,
Started: 1257894000, Started: 1257894000,
} }
cc := New(r, b, "http://localhost/foo/bar/1") cc := New(r, b, "http://localhost/foo/bar/1")
g.Assert(cc.Project.LastBuildStatus).Equal("Failure") assert.Equal(t, "Failure", cc.Project.LastBuildStatus)
g.Assert(cc.Project.Activity).Equal("Sleeping") assert.Equal(t, "Sleeping", cc.Project.Activity)
}) })
g.It("Should properly label running", func() { t.Run("properly label running", func(t *testing.T) {
r := &model.Repo{FullName: "foo/bar"} r := &model.Repo{FullName: "foo/bar"}
b := &model.Pipeline{ b := &model.Pipeline{
Status: model.StatusRunning, Status: model.StatusRunning,
Number: 1, Number: 1,
Started: 1257894000, Started: 1257894000,
} }
cc := New(r, b, "http://localhost/foo/bar/1") cc := New(r, b, "http://localhost/foo/bar/1")
g.Assert(cc.Project.Activity).Equal("Building") assert.Equal(t, "Building", cc.Project.Activity)
g.Assert(cc.Project.LastBuildStatus).Equal("Unknown") assert.Equal(t, "Unknown", cc.Project.LastBuildStatus)
g.Assert(cc.Project.LastBuildLabel).Equal("Unknown") assert.Equal(t, "Unknown", cc.Project.LastBuildLabel)
})
}) })
} }

View File

@@ -18,13 +18,12 @@ package bitbucket
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/internal" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/internal"
@@ -32,263 +31,182 @@ import (
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func Test_bitbucket(t *testing.T) { func TestNew(t *testing.T) {
forge, _ := New(&Opts{Client: "4vyW6b49Z", Secret: "a5012f6c6"})
f, _ := forge.(*config)
assert.Equal(t, DefaultURL, f.url)
assert.Equal(t, DefaultAPI, f.API)
assert.Equal(t, "4vyW6b49Z", f.Client)
assert.Equal(t, "a5012f6c6", f.Secret)
}
func TestBitbucket(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
s := httptest.NewServer(fixtures.Handler()) s := httptest.NewServer(fixtures.Handler())
defer s.Close()
c := &config{url: s.URL, API: s.URL} c := &config{url: s.URL, API: s.URL}
g := goblin.Goblin(t)
ctx := context.Background() ctx := context.Background()
g.Describe("Bitbucket client", func() {
g.After(func() {
s.Close()
})
g.It("Should return client with default endpoint", func() { forge, _ := New(&Opts{})
forge, _ := New(&Opts{Client: "4vyW6b49Z", Secret: "a5012f6c6"}) netrc, _ := forge.Netrc(fakeUser, fakeRepo)
assert.Equal(t, "bitbucket.org", netrc.Machine)
assert.Equal(t, "x-token-auth", netrc.Login)
assert.Equal(t, fakeUser.AccessToken, netrc.Password)
f, _ := forge.(*config) user, _, err := c.Login(ctx, &types.OAuthRequest{})
g.Assert(f.url).Equal(DefaultURL) assert.NoError(t, err)
g.Assert(f.API).Equal(DefaultAPI) assert.Nil(t, user)
g.Assert(f.Client).Equal("4vyW6b49Z")
g.Assert(f.Secret).Equal("a5012f6c6")
})
g.It("Should return the netrc file", func() { u, _, err := c.Login(ctx, &types.OAuthRequest{
forge, _ := New(&Opts{}) Code: "code",
netrc, _ := forge.Netrc(fakeUser, fakeRepo)
g.Assert(netrc.Machine).Equal("bitbucket.org")
g.Assert(netrc.Login).Equal("x-token-auth")
g.Assert(netrc.Password).Equal(fakeUser.AccessToken)
})
g.Describe("Given an authorization request", func() {
g.It("Should redirect to authorize", func() {
user, _, err := c.Login(ctx, &types.OAuthRequest{})
g.Assert(err).IsNil()
g.Assert(user).IsNil()
})
g.It("Should return authenticated user", func() {
u, _, err := c.Login(ctx, &types.OAuthRequest{
Code: "code",
})
g.Assert(err).IsNil()
g.Assert(u.Login).Equal(fakeUser.Login)
g.Assert(u.AccessToken).Equal("2YotnFZFEjr1zCsicMWpAA")
g.Assert(u.RefreshToken).Equal("tGzv3JOkF0XG5Qx2TlKWIA")
})
g.It("Should handle failure to exchange code", func() {
_, _, err := c.Login(ctx, &types.OAuthRequest{
Code: "code_bad_request",
})
g.Assert(err).IsNotNil()
})
g.It("Should handle failure to resolve user", func() {
_, _, err := c.Login(ctx, &types.OAuthRequest{
Code: "code_user_not_found",
})
g.Assert(err).IsNotNil()
})
})
g.Describe("Given an access token", func() {
g.It("Should return the authenticated user", func() {
login, err := c.Auth(ctx, fakeUser.AccessToken, fakeUser.RefreshToken)
g.Assert(err).IsNil()
g.Assert(login).Equal(fakeUser.Login)
})
g.It("Should handle a failure to resolve user", func() {
_, err := c.Auth(ctx, fakeUserNotFound.AccessToken, fakeUserNotFound.RefreshToken)
g.Assert(err).IsNotNil()
})
})
g.Describe("Given a refresh token", func() {
g.It("Should return a refresh access token", func() {
ok, err := c.Refresh(ctx, fakeUserRefresh)
g.Assert(err).IsNil()
g.Assert(ok).IsTrue()
g.Assert(fakeUserRefresh.AccessToken).Equal("2YotnFZFEjr1zCsicMWpAA")
g.Assert(fakeUserRefresh.RefreshToken).Equal("tGzv3JOkF0XG5Qx2TlKWIA")
})
g.It("Should handle an empty access token", func() {
ok, err := c.Refresh(ctx, fakeUserRefreshEmpty)
g.Assert(err).IsNotNil()
g.Assert(ok).IsFalse()
})
g.It("Should handle a failure to refresh", func() {
ok, err := c.Refresh(ctx, fakeUserRefreshFail)
g.Assert(err).IsNotNil()
g.Assert(ok).IsFalse()
})
})
g.Describe("When requesting a repository", func() {
g.It("Should return the details", func() {
repo, err := c.Repo(ctx, fakeUser, "", fakeRepo.Owner, fakeRepo.Name)
g.Assert(err).IsNil()
g.Assert(repo.FullName).Equal(fakeRepo.FullName)
})
g.It("Should handle not found errors", func() {
_, err := c.Repo(ctx, fakeUser, "", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
g.Assert(err).IsNotNil()
})
})
g.Describe("When requesting user repositories", func() {
g.It("Should return the details", func() {
repos, err := c.Repos(ctx, fakeUser)
g.Assert(err).IsNil()
g.Assert(repos[0].FullName).Equal(fakeRepo.FullName)
})
g.It("Should handle organization not found errors", func() {
_, err := c.Repos(ctx, fakeUserNoTeams)
g.Assert(err).IsNotNil()
})
g.It("Should handle not found errors", func() {
_, err := c.Repos(ctx, fakeUserNoRepos)
g.Assert(err).IsNotNil()
})
})
g.Describe("When requesting user teams", func() {
g.It("Should return the details", func() {
teams, err := c.Teams(ctx, fakeUser)
g.Assert(err).IsNil()
g.Assert(teams[0].Login).Equal("ueberdev42")
g.Assert(teams[0].Avatar).Equal("https://bitbucket.org/workspaces/ueberdev42/avatar/?ts=1658761964")
})
g.It("Should handle not found error", func() {
_, err := c.Teams(ctx, fakeUserNoTeams)
g.Assert(err).IsNotNil()
})
})
g.Describe("When downloading a file", func() {
g.It("Should return the bytes", func() {
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file")
g.Assert(err).IsNil()
g.Assert(len(raw) != 0).IsTrue()
})
g.It("Should handle not found error", func() {
_, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file_not_found")
g.Assert(err).IsNotNil()
g.Assert(errors.Is(err, &types.ErrConfigNotFound{})).IsTrue()
})
})
g.Describe("When requesting repo branch HEAD", func() {
g.It("Should return the details", func() {
branchHead, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_name")
g.Assert(err).IsNil()
g.Assert(branchHead.SHA).Equal("branch_head_name")
g.Assert(branchHead.ForgeURL).Equal("https://bitbucket.org/commitlink")
})
g.It("Should handle not found errors", func() {
_, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_not_found")
g.Assert(err).IsNotNil()
})
})
g.Describe("When requesting repo pull requests", func() {
listOpts := model.ListOptions{
All: false,
Page: 1,
PerPage: 10,
}
g.It("Should return the details", func() {
repoPRs, err := c.PullRequests(ctx, fakeUser, fakeRepo, &listOpts)
g.Assert(err).IsNil()
g.Assert(repoPRs[0].Title).Equal("PRs title")
g.Assert(repoPRs[0].Index).Equal(model.ForgeRemoteID("123"))
})
g.It("Should handle not found errors", func() {
_, err := c.PullRequests(ctx, fakeUser, fakeRepoNotFound, &listOpts)
g.Assert(err).IsNotNil()
})
})
g.Describe("When requesting repo directory contents", func() {
g.It("Should return the details", func() {
files, err := c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir")
g.Assert(err).IsNil()
g.Assert(len(files)).Equal(3)
g.Assert(files[0].Name).Equal("README.md")
g.Assert(string(files[0].Data)).Equal("dummy payload")
})
g.It("Should handle not found errors", func() {
_, err := c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir_not_found")
g.Assert(err).IsNotNil()
g.Assert(errors.Is(err, &types.ErrConfigNotFound{})).IsTrue()
})
})
g.Describe("When activating a repository", func() {
g.It("Should error when malformed hook", func() {
err := c.Activate(ctx, fakeUser, fakeRepo, "%gh&%ij")
g.Assert(err).IsNotNil()
})
g.It("Should create the hook", func() {
err := c.Activate(ctx, fakeUser, fakeRepo, "http://127.0.0.1")
g.Assert(err).IsNil()
})
})
g.Describe("When deactivating a repository", func() {
g.It("Should error when listing hooks fails", func() {
err := c.Deactivate(ctx, fakeUser, fakeRepoNoHooks, "http://127.0.0.1")
g.Assert(err).IsNotNil()
})
g.It("Should successfully remove hooks", func() {
err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://127.0.0.1")
g.Assert(err).IsNil()
})
g.It("Should successfully deactivate when hook already removed", func() {
err := c.Deactivate(ctx, fakeUser, fakeRepoEmptyHook, "http://127.0.0.1")
g.Assert(err).IsNil()
})
})
g.Describe("Given a list of hooks", func() {
g.It("Should return the matching hook", func() {
hooks := []*internal.Hook{
{URL: "http://127.0.0.1/hook"},
}
hook := matchingHooks(hooks, "http://127.0.0.1/")
g.Assert(hook).Equal(hooks[0])
})
g.It("Should handle no matches", func() {
hooks := []*internal.Hook{
{URL: "http://localhost/hook"},
}
hook := matchingHooks(hooks, "http://127.0.0.1/")
g.Assert(hook).IsNil()
})
g.It("Should handle malformed hook urls", func() {
var hooks []*internal.Hook
hook := matchingHooks(hooks, "%gh&%ij")
g.Assert(hook).IsNil()
})
})
g.It("Should update the status", func() {
err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
g.Assert(err).IsNil()
})
g.It("Should parse the hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{}
req.Header.Set(hookEvent, hookPush)
r, b, err := c.Hook(ctx, req)
g.Assert(err).IsNil()
g.Assert(r.FullName).Equal("martinherren1984/publictestrepo")
g.Assert(b.Commit).Equal("c14c1bb05dfb1fdcdf06b31485fff61b0ea44277")
})
}) })
assert.NoError(t, err)
assert.Equal(t, fakeUser.Login, u.Login)
assert.Equal(t, "2YotnFZFEjr1zCsicMWpAA", u.AccessToken)
assert.Equal(t, "tGzv3JOkF0XG5Qx2TlKWIA", u.RefreshToken)
_, _, err = c.Login(ctx, &types.OAuthRequest{
Code: "code_bad_request",
})
assert.Error(t, err)
_, _, err = c.Login(ctx, &types.OAuthRequest{
Code: "code_user_not_found",
})
assert.Error(t, err)
login, err := c.Auth(ctx, fakeUser.AccessToken, fakeUser.RefreshToken)
assert.NoError(t, err)
assert.Equal(t, fakeUser.Login, login)
_, err = c.Auth(ctx, fakeUserNotFound.AccessToken, fakeUserNotFound.RefreshToken)
assert.Error(t, err)
ok, err := c.Refresh(ctx, fakeUserRefresh)
assert.NoError(t, err)
assert.True(t, ok)
assert.Equal(t, "2YotnFZFEjr1zCsicMWpAA", fakeUserRefresh.AccessToken)
assert.Equal(t, "tGzv3JOkF0XG5Qx2TlKWIA", fakeUserRefresh.RefreshToken)
ok, err = c.Refresh(ctx, fakeUserRefreshEmpty)
assert.Error(t, err)
assert.False(t, ok)
ok, err = c.Refresh(ctx, fakeUserRefreshFail)
assert.Error(t, err)
assert.False(t, ok)
repo, err := c.Repo(ctx, fakeUser, "", fakeRepo.Owner, fakeRepo.Name)
assert.NoError(t, err)
assert.Equal(t, fakeRepo.FullName, repo.FullName)
_, err = c.Repo(ctx, fakeUser, "", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
assert.Error(t, err)
repos, err := c.Repos(ctx, fakeUser)
assert.NoError(t, err)
assert.Equal(t, fakeRepo.FullName, repos[0].FullName)
_, err = c.Repos(ctx, fakeUserNoTeams)
assert.Error(t, err)
_, err = c.Repos(ctx, fakeUserNoRepos)
assert.Error(t, err)
teams, err := c.Teams(ctx, fakeUser)
assert.NoError(t, err)
assert.Equal(t, "ueberdev42", teams[0].Login)
assert.Equal(t, "https://bitbucket.org/workspaces/ueberdev42/avatar/?ts=1658761964", teams[0].Avatar)
_, err = c.Teams(ctx, fakeUserNoTeams)
assert.Error(t, err)
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file")
assert.NoError(t, err)
assert.True(t, len(raw) != 0)
_, err = c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file_not_found")
assert.Error(t, err)
assert.ErrorIs(t, err, &types.ErrConfigNotFound{})
branchHead, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_name")
assert.NoError(t, err)
assert.Equal(t, "branch_head_name", branchHead.SHA)
assert.Equal(t, "https://bitbucket.org/commitlink", branchHead.ForgeURL)
_, err = c.BranchHead(ctx, fakeUser, fakeRepo, "branch_not_found")
assert.Error(t, err)
listOpts := model.ListOptions{
All: false,
Page: 1,
PerPage: 10,
}
repoPRs, err := c.PullRequests(ctx, fakeUser, fakeRepo, &listOpts)
assert.NoError(t, err)
assert.Equal(t, "PRs title", repoPRs[0].Title)
assert.Equal(t, model.ForgeRemoteID("123"), repoPRs[0].Index)
_, err = c.PullRequests(ctx, fakeUser, fakeRepoNotFound, &listOpts)
assert.Error(t, err)
files, err := c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir")
assert.NoError(t, err)
assert.Len(t, files, 3)
assert.Equal(t, "README.md", files[0].Name)
assert.Equal(t, "dummy payload", string(files[0].Data))
_, err = c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir_not_found")
assert.Error(t, err)
assert.ErrorIs(t, err, &types.ErrConfigNotFound{})
err = c.Activate(ctx, fakeUser, fakeRepo, "%gh&%ij")
assert.Error(t, err)
err = c.Activate(ctx, fakeUser, fakeRepo, "http://127.0.0.1")
assert.NoError(t, err)
err = c.Deactivate(ctx, fakeUser, fakeRepoNoHooks, "http://127.0.0.1")
assert.Error(t, err)
err = c.Deactivate(ctx, fakeUser, fakeRepo, "http://127.0.0.1")
assert.NoError(t, err)
err = c.Deactivate(ctx, fakeUser, fakeRepoEmptyHook, "http://127.0.0.1")
assert.NoError(t, err)
hooks := []*internal.Hook{
{URL: "http://127.0.0.1/hook"},
}
hook := matchingHooks(hooks, "http://127.0.0.1/")
assert.Equal(t, hooks[0], hook)
hooks = []*internal.Hook{
{URL: "http://localhost/hook"},
}
hook = matchingHooks(hooks, "http://127.0.0.1/")
assert.Nil(t, hook)
hooks = nil
hook = matchingHooks(hooks, "%gh&%ij")
assert.Nil(t, hook)
err = c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
assert.NoError(t, err)
buf := bytes.NewBufferString(fixtures.HookPush)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{}
req.Header.Set(hookEvent, hookPush)
r, b, err := c.Hook(ctx, req)
assert.NoError(t, err)
assert.Equal(t, "martinherren1984/publictestrepo", r.FullName)
assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit)
} }
var ( var (

View File

@@ -19,169 +19,158 @@ import (
"testing" "testing"
"time" "time"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"golang.org/x/oauth2" "golang.org/x/oauth2"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/internal" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/internal"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func Test_helper(t *testing.T) { func Test_convertStatus(t *testing.T) {
g := goblin.Goblin(t) assert.Equal(t, statusSuccess, convertStatus(model.StatusSuccess))
g.Describe("Bitbucket converter", func() { assert.Equal(t, statusPending, convertStatus(model.StatusPending))
g.It("should convert passing status", func() { assert.Equal(t, statusPending, convertStatus(model.StatusRunning))
g.Assert(convertStatus(model.StatusSuccess)).Equal(statusSuccess) assert.Equal(t, statusFailure, convertStatus(model.StatusFailure))
}) assert.Equal(t, statusFailure, convertStatus(model.StatusKilled))
assert.Equal(t, statusFailure, convertStatus(model.StatusError))
g.It("should convert pending status", func() { }
g.Assert(convertStatus(model.StatusPending)).Equal(statusPending)
g.Assert(convertStatus(model.StatusRunning)).Equal(statusPending) func Test_convertRepo(t *testing.T) {
}) from := &internal.Repo{
FullName: "octocat/hello-world",
g.It("should convert failing status", func() { IsPrivate: true,
g.Assert(convertStatus(model.StatusFailure)).Equal(statusFailure) Scm: "git",
g.Assert(convertStatus(model.StatusKilled)).Equal(statusFailure) }
g.Assert(convertStatus(model.StatusError)).Equal(statusFailure) from.Owner.Links.Avatar.Href = "http://..."
}) from.Links.HTML.Href = "https://bitbucket.org/foo/bar"
from.MainBranch.Name = "default"
g.It("should convert repository", func() { fromPerm := &internal.RepoPerm{
from := &internal.Repo{ Permission: "write",
FullName: "octocat/hello-world", }
IsPrivate: true,
Scm: "git", to := convertRepo(from, fromPerm)
} assert.Equal(t, from.Owner.Links.Avatar.Href, to.Avatar)
from.Owner.Links.Avatar.Href = "http://..." assert.Equal(t, from.FullName, to.FullName)
from.Links.HTML.Href = "https://bitbucket.org/foo/bar" assert.Equal(t, "octocat", to.Owner)
fromPerm := &internal.RepoPerm{ assert.Equal(t, "hello-world", to.Name)
Permission: "write", assert.Equal(t, "default", to.Branch)
} assert.Equal(t, from.IsPrivate, to.IsSCMPrivate)
assert.Equal(t, from.Links.HTML.Href, to.Clone)
to := convertRepo(from, fromPerm) assert.Equal(t, from.Links.HTML.Href, to.ForgeURL)
g.Assert(to.Avatar).Equal(from.Owner.Links.Avatar.Href) assert.True(t, to.Perm.Push)
g.Assert(to.FullName).Equal(from.FullName) assert.False(t, to.Perm.Admin)
g.Assert(to.Owner).Equal("octocat") }
g.Assert(to.Name).Equal("hello-world")
g.Assert(to.IsSCMPrivate).Equal(from.IsPrivate) func Test_convertWorkspace(t *testing.T) {
g.Assert(to.Clone).Equal(from.Links.HTML.Href) from := &internal.Workspace{Slug: "octocat"}
g.Assert(to.ForgeURL).Equal(from.Links.HTML.Href) from.Links.Avatar.Href = "http://..."
g.Assert(to.Perm.Push).IsTrue() to := convertWorkspace(from)
g.Assert(to.Perm.Admin).IsFalse() assert.Equal(t, from.Links.Avatar.Href, to.Avatar)
}) assert.Equal(t, from.Slug, to.Login)
}
g.It("should convert team", func() {
from := &internal.Workspace{Slug: "octocat"} func Test_convertWorkspaceList(t *testing.T) {
from.Links.Avatar.Href = "http://..." from := &internal.Workspace{Slug: "octocat"}
to := convertWorkspace(from) from.Links.Avatar.Href = "http://..."
g.Assert(to.Avatar).Equal(from.Links.Avatar.Href) to := convertWorkspaceList([]*internal.Workspace{from})
g.Assert(to.Login).Equal(from.Slug) assert.Equal(t, from.Links.Avatar.Href, to[0].Avatar)
}) assert.Equal(t, from.Slug, to[0].Login)
}
g.It("should convert team list", func() {
from := &internal.Workspace{Slug: "octocat"} func Test_convertUser(t *testing.T) {
from.Links.Avatar.Href = "http://..." token := &oauth2.Token{
to := convertWorkspaceList([]*internal.Workspace{from}) AccessToken: "foo",
g.Assert(to[0].Avatar).Equal(from.Links.Avatar.Href) RefreshToken: "bar",
g.Assert(to[0].Login).Equal(from.Slug) Expiry: time.Now(),
}) }
user := &internal.Account{Login: "octocat"}
g.It("should convert user", func() { user.Links.Avatar.Href = "http://..."
token := &oauth2.Token{
AccessToken: "foo", result := convertUser(user, token)
RefreshToken: "bar", assert.Equal(t, user.Links.Avatar.Href, result.Avatar)
Expiry: time.Now(), assert.Equal(t, user.Login, result.Login)
} assert.Equal(t, token.AccessToken, result.AccessToken)
user := &internal.Account{Login: "octocat"} assert.Equal(t, token.RefreshToken, result.RefreshToken)
user.Links.Avatar.Href = "http://..." assert.Equal(t, token.Expiry.UTC().Unix(), result.Expiry)
}
result := convertUser(user, token)
g.Assert(result.Avatar).Equal(user.Links.Avatar.Href) func Test_cloneLink(t *testing.T) {
g.Assert(result.Login).Equal(user.Login) repo := &internal.Repo{}
g.Assert(result.AccessToken).Equal(token.AccessToken) repo.Links.Clone = append(repo.Links.Clone, internal.Link{
g.Assert(result.RefreshToken).Equal(token.RefreshToken) Name: "https",
g.Assert(result.Expiry).Equal(token.Expiry.UTC().Unix()) Href: "https://bitbucket.org/foo/bar.git",
}) })
link := cloneLink(repo)
g.It("should use clone url", func() { assert.Equal(t, repo.Links.Clone[0].Href, link)
repo := &internal.Repo{}
repo.Links.Clone = append(repo.Links.Clone, internal.Link{ repo = &internal.Repo{}
Name: "https", repo.Links.HTML.Href = "https://foo:bar@bitbucket.org/foo/bar.git"
Href: "https://bitbucket.org/foo/bar.git", link = cloneLink(repo)
}) assert.Equal(t, "https://bitbucket.org/foo/bar.git", link)
link := cloneLink(repo) }
g.Assert(link).Equal(repo.Links.Clone[0].Href)
}) func Test_convertPullHook(t *testing.T) {
hook := &internal.PullRequestHook{}
g.It("should build clone url", func() { hook.Actor.Login = "octocat"
repo := &internal.Repo{} hook.Actor.Links.Avatar.Href = "https://..."
repo.Links.HTML.Href = "https://foo:bar@bitbucket.org/foo/bar.git" hook.PullRequest.Dest.Commit.Hash = "73f9c44d"
link := cloneLink(repo) hook.PullRequest.Dest.Branch.Name = "main"
g.Assert(link).Equal("https://bitbucket.org/foo/bar.git") hook.PullRequest.Dest.Repo.Links.HTML.Href = "https://bitbucket.org/foo/bar"
}) hook.PullRequest.Source.Branch.Name = "change"
hook.PullRequest.Source.Repo.FullName = "baz/bar"
g.It("should convert pull hook to pipeline", func() { hook.PullRequest.Source.Commit.Hash = "c8411d7"
hook := &internal.PullRequestHook{} hook.PullRequest.Links.HTML.Href = "https://bitbucket.org/foo/bar/pulls/5"
hook.Actor.Login = "octocat" hook.PullRequest.Title = "updated README"
hook.Actor.Links.Avatar.Href = "https://..." hook.PullRequest.Updated = time.Now()
hook.PullRequest.Dest.Commit.Hash = "73f9c44d" hook.PullRequest.ID = 1
hook.PullRequest.Dest.Branch.Name = "main"
hook.PullRequest.Dest.Repo.Links.HTML.Href = "https://bitbucket.org/foo/bar" pipeline := convertPullHook(hook)
hook.PullRequest.Source.Branch.Name = "change" assert.Equal(t, model.EventPull, pipeline.Event)
hook.PullRequest.Source.Repo.FullName = "baz/bar" assert.Equal(t, hook.Actor.Login, pipeline.Author)
hook.PullRequest.Source.Commit.Hash = "c8411d7" assert.Equal(t, hook.Actor.Links.Avatar.Href, pipeline.Avatar)
hook.PullRequest.Links.HTML.Href = "https://bitbucket.org/foo/bar/pulls/5" assert.Equal(t, hook.PullRequest.Source.Commit.Hash, pipeline.Commit)
hook.PullRequest.Title = "updated README" assert.Equal(t, hook.PullRequest.Source.Branch.Name, pipeline.Branch)
hook.PullRequest.Updated = time.Now() assert.Equal(t, hook.PullRequest.Links.HTML.Href, pipeline.ForgeURL)
hook.PullRequest.ID = 1 assert.Equal(t, "refs/pull-requests/1/from", pipeline.Ref)
assert.Equal(t, "change:main", pipeline.Refspec)
pipeline := convertPullHook(hook) assert.Equal(t, hook.PullRequest.Title, pipeline.Message)
g.Assert(pipeline.Event).Equal(model.EventPull) assert.Equal(t, hook.PullRequest.Updated.Unix(), pipeline.Timestamp)
g.Assert(pipeline.Author).Equal(hook.Actor.Login) }
g.Assert(pipeline.Avatar).Equal(hook.Actor.Links.Avatar.Href)
g.Assert(pipeline.Commit).Equal(hook.PullRequest.Source.Commit.Hash) func Test_convertPushHook(t *testing.T) {
g.Assert(pipeline.Branch).Equal(hook.PullRequest.Source.Branch.Name) change := internal.Change{}
g.Assert(pipeline.ForgeURL).Equal(hook.PullRequest.Links.HTML.Href) change.New.Target.Hash = "73f9c44d"
g.Assert(pipeline.Ref).Equal("refs/pull-requests/1/from") change.New.Name = "main"
g.Assert(pipeline.Refspec).Equal("change:main") change.New.Target.Links.HTML.Href = "https://bitbucket.org/foo/bar/commits/73f9c44d"
g.Assert(pipeline.Message).Equal(hook.PullRequest.Title) change.New.Target.Message = "updated README"
g.Assert(pipeline.Timestamp).Equal(hook.PullRequest.Updated.Unix()) change.New.Target.Date = time.Now()
}) change.New.Target.Author.Raw = "Test <test@domain.tld>"
g.It("should convert push hook to pipeline", func() { hook := internal.PushHook{}
change := internal.Change{} hook.Actor.Login = "octocat"
change.New.Target.Hash = "73f9c44d" hook.Actor.Links.Avatar.Href = "https://..."
change.New.Name = "main"
change.New.Target.Links.HTML.Href = "https://bitbucket.org/foo/bar/commits/73f9c44d" pipeline := convertPushHook(&hook, &change)
change.New.Target.Message = "updated README" assert.Equal(t, model.EventPush, pipeline.Event)
change.New.Target.Date = time.Now() assert.Equal(t, "test@domain.tld", pipeline.Email)
change.New.Target.Author.Raw = "Test <test@domain.tld>" assert.Equal(t, hook.Actor.Login, pipeline.Author)
assert.Equal(t, hook.Actor.Links.Avatar.Href, pipeline.Avatar)
hook := internal.PushHook{} assert.Equal(t, change.New.Target.Hash, pipeline.Commit)
hook.Actor.Login = "octocat" assert.Equal(t, change.New.Name, pipeline.Branch)
hook.Actor.Links.Avatar.Href = "https://..." assert.Equal(t, change.New.Target.Links.HTML.Href, pipeline.ForgeURL)
assert.Equal(t, "refs/heads/main", pipeline.Ref)
pipeline := convertPushHook(&hook, &change) assert.Equal(t, change.New.Target.Message, pipeline.Message)
g.Assert(pipeline.Event).Equal(model.EventPush) assert.Equal(t, change.New.Target.Date.Unix(), pipeline.Timestamp)
g.Assert(pipeline.Email).Equal("test@domain.tld") }
g.Assert(pipeline.Author).Equal(hook.Actor.Login)
g.Assert(pipeline.Avatar).Equal(hook.Actor.Links.Avatar.Href) func Test_convertPushHookTag(t *testing.T) {
g.Assert(pipeline.Commit).Equal(change.New.Target.Hash) change := internal.Change{}
g.Assert(pipeline.Branch).Equal(change.New.Name) change.New.Name = "v1.0.0"
g.Assert(pipeline.ForgeURL).Equal(change.New.Target.Links.HTML.Href) change.New.Type = "tag"
g.Assert(pipeline.Ref).Equal("refs/heads/main")
g.Assert(pipeline.Message).Equal(change.New.Target.Message) hook := internal.PushHook{}
g.Assert(pipeline.Timestamp).Equal(change.New.Target.Date.Unix())
}) pipeline := convertPushHook(&hook, &change)
assert.Equal(t, model.EventTag, pipeline.Event)
g.It("should convert tag hook to pipeline", func() { assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref)
change := internal.Change{}
change.New.Name = "v1.0.0"
change.New.Type = "tag"
hook := internal.PushHook{}
pipeline := convertPushHook(&hook, &change)
g.Assert(pipeline.Event).Equal(model.EventTag)
g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0")
})
})
} }

View File

@@ -1,4 +1,4 @@
// Copyright 2018 Drone.IO Inc. // // Copyright 2018 Drone.IO Inc.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ import (
"net/http" "net/http"
"testing" "testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/fixtures"
@@ -27,112 +26,101 @@ import (
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func Test_parser(t *testing.T) { func Test_parseHook(t *testing.T) {
g := goblin.Goblin(t) t.Run("unsupported hook", func(t *testing.T) {
g.Describe("Bitbucket parser", func() { buf := bytes.NewBufferString(fixtures.HookPush)
g.It("should ignore unsupported hook", func() { req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
buf := bytes.NewBufferString(fixtures.HookPush) req.Header = http.Header{}
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req.Header.Set(hookEvent, "issue:created")
req.Header = http.Header{}
req.Header.Set(hookEvent, "issue:created")
r, b, err := parseHook(req) r, b, err := parseHook(req)
g.Assert(r).IsNil() assert.Nil(t, r)
g.Assert(b).IsNil() assert.Nil(t, b)
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
}) })
g.Describe("Given a pull-request hook payload", func() { t.Run("malformed pull-request hook", func(t *testing.T) {
g.It("should return err when malformed", func() { buf := bytes.NewBufferString("[]")
buf := bytes.NewBufferString("[]") req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req.Header = http.Header{}
req.Header = http.Header{} req.Header.Set(hookEvent, hookPullCreated)
req.Header.Set(hookEvent, hookPullCreated)
_, _, err := parseHook(req) _, _, err := parseHook(req)
g.Assert(err).IsNotNil() assert.Error(t, err)
}) })
g.It("should return pull-request details", func() { t.Run("pull-request", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPull) buf := bytes.NewBufferString(fixtures.HookPull)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{} req.Header = http.Header{}
req.Header.Set(hookEvent, hookPullCreated) req.Header.Set(hookEvent, hookPullCreated)
r, b, err := parseHook(req) r, b, err := parseHook(req)
g.Assert(err).IsNil() assert.NoError(t, err)
g.Assert(r.FullName).Equal("user_name/repo_name") assert.Equal(t, "user_name/repo_name", r.FullName)
g.Assert(b.Event).Equal(model.EventPull) assert.Equal(t, model.EventPull, b.Event)
g.Assert(b.Commit).Equal("d3022fc0ca3d") assert.Equal(t, "d3022fc0ca3d", b.Commit)
}) })
g.It("should return pull-request details for a pull-request merged payload", func() { t.Run("pull-request merged", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequestMerged) buf := bytes.NewBufferString(fixtures.HookPullRequestMerged)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{} req.Header = http.Header{}
req.Header.Set(hookEvent, hookPullMerged) req.Header.Set(hookEvent, hookPullMerged)
r, b, err := parseHook(req) r, b, err := parseHook(req)
g.Assert(err).IsNil() assert.NoError(t, err)
g.Assert(r.FullName).Equal("anbraten/test-2") assert.Equal(t, "anbraten/test-2", r.FullName)
g.Assert(b.Event).Equal(model.EventPullClosed) assert.Equal(t, model.EventPullClosed, b.Event)
g.Assert(b.Commit).Equal("006704dbeab2") assert.Equal(t, "006704dbeab2", b.Commit)
}) })
g.It("should return pull-request details for a pull-request closed payload", func() { t.Run("pull-request closed", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequestDeclined) buf := bytes.NewBufferString(fixtures.HookPullRequestDeclined)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{} req.Header = http.Header{}
req.Header.Set(hookEvent, hookPullDeclined) req.Header.Set(hookEvent, hookPullDeclined)
r, b, err := parseHook(req) r, b, err := parseHook(req)
g.Assert(err).IsNil() assert.NoError(t, err)
g.Assert(r.FullName).Equal("anbraten/test-2") assert.Equal(t, "anbraten/test-2", r.FullName)
g.Assert(b.Event).Equal(model.EventPullClosed) assert.Equal(t, model.EventPullClosed, b.Event)
g.Assert(b.Commit).Equal("f90e18fc9d45") assert.Equal(t, "f90e18fc9d45", b.Commit)
}) })
})
g.Describe("Given a push hook payload", func() { t.Run("malformed push", func(t *testing.T) {
g.It("should return err when malformed", func() { buf := bytes.NewBufferString("[]")
buf := bytes.NewBufferString("[]") req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req.Header = http.Header{}
req.Header = http.Header{} req.Header.Set(hookEvent, hookPush)
req.Header.Set(hookEvent, hookPush)
_, _, err := parseHook(req) _, _, err := parseHook(req)
g.Assert(err).IsNotNil() assert.Error(t, err)
}) })
g.It("should return nil if missing commit sha", func() { t.Run("missing commit sha", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPushEmptyHash) buf := bytes.NewBufferString(fixtures.HookPushEmptyHash)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{} req.Header = http.Header{}
req.Header.Set(hookEvent, hookPush) req.Header.Set(hookEvent, hookPush)
r, b, err := parseHook(req) r, b, err := parseHook(req)
g.Assert(r).IsNil() assert.Nil(t, r)
g.Assert(b).IsNil() assert.Nil(t, b)
g.Assert(err).IsNil() assert.NoError(t, err)
}) })
g.It("should return push details", func() { t.Run("push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPush) buf := bytes.NewBufferString(fixtures.HookPush)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf) req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{} req.Header = http.Header{}
req.Header.Set(hookEvent, hookPush) req.Header.Set(hookEvent, hookPush)
r, b, err := parseHook(req) r, b, err := parseHook(req)
g.Assert(err).IsNil() assert.NoError(t, err)
g.Assert(r.FullName).Equal("martinherren1984/publictestrepo") assert.Equal(t, "martinherren1984/publictestrepo", r.FullName)
g.Assert(r.Clone).Equal("https://bitbucket.org/martinherren1984/publictestrepo") assert.Equal(t, "https://bitbucket.org/martinherren1984/publictestrepo", r.Clone)
g.Assert(b.Commit).Equal("c14c1bb05dfb1fdcdf06b31485fff61b0ea44277") assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit)
g.Assert(b.Message).Equal("a\n") assert.Equal(t, "a\n", b.Message)
})
})
g.Describe("Given a tag hook payload", func() {
// TODO
})
}) })
} }

View File

@@ -19,75 +19,74 @@ import (
"testing" "testing"
"time" "time"
"github.com/franela/goblin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucketdatacenter/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucketdatacenter/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func TestNew(t *testing.T) {
forge, err := New(Opts{
URL: "http://localhost:8080",
Username: "0ZXh0IjoiI",
Password: "I1NiIsInR5",
ClientID: "client-id",
ClientSecret: "client-secret",
})
assert.NoError(t, err)
assert.NotNil(t, forge)
cl, ok := forge.(*client)
assert.True(t, ok)
assert.Equal(t, &client{
url: "http://localhost:8080",
urlAPI: "http://localhost:8080/rest",
username: "0ZXh0IjoiI",
password: "I1NiIsInR5",
clientID: "client-id",
clientSecret: "client-secret",
}, cl)
}
func TestBitbucketDC(t *testing.T) { func TestBitbucketDC(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
s := fixtures.Server() s := fixtures.Server()
defer s.Close()
c := &client{ c := &client{
urlAPI: s.URL, urlAPI: s.URL,
} }
ctx := context.Background() ctx := context.Background()
g := goblin.Goblin(t)
g.Describe("Bitbucket DataCenter/Server", func() {
g.After(func() {
s.Close()
})
g.Describe("Creating a forge", func() { repo, err := c.Repo(ctx, fakeUser, model.ForgeRemoteID("1234"), "PRJ", "repo-slug")
g.It("Should return client with specified options", func() { assert.NoError(t, err)
forge, err := New(Opts{ assert.Equal(t, &model.Repo{
URL: "http://localhost:8080", Name: "repo-slug-2",
Username: "0ZXh0IjoiI", Owner: "PRJ",
Password: "I1NiIsInR5", Perm: &model.Perm{Pull: true, Push: true},
ClientID: "client-id", Branch: "main",
ClientSecret: "client-secret", IsSCMPrivate: true,
}) PREnabled: true,
g.Assert(err).IsNil() ForgeRemoteID: model.ForgeRemoteID("1234"),
g.Assert(forge).IsNotNil() FullName: "PRJ/repo-slug-2",
cl, ok := forge.(*client) }, repo)
g.Assert(ok).IsTrue()
g.Assert(cl.url).Equal("http://localhost:8080")
g.Assert(cl.username).Equal("0ZXh0IjoiI")
g.Assert(cl.password).Equal("I1NiIsInR5")
g.Assert(cl.clientID).Equal("client-id")
g.Assert(cl.clientSecret).Equal("client-secret")
})
})
g.Describe("Requesting a repository", func() { // org
g.It("should return repository details", func() { org, err := c.Org(ctx, fakeUser, "ORG")
repo, err := c.Repo(ctx, fakeUser, model.ForgeRemoteID("1234"), "PRJ", "repo-slug") assert.NoError(t, err)
g.Assert(err).IsNil() assert.Equal(t, &model.Org{
g.Assert(repo.Name).Equal("repo-slug-2") Name: "ORG",
g.Assert(repo.Owner).Equal("PRJ") IsUser: false,
g.Assert(repo.Perm).Equal(&model.Perm{Pull: true, Push: true}) }, org)
g.Assert(repo.Branch).Equal("main")
})
})
g.Describe("Getting organization", func() { // user
g.It("should map organization", func() { org, err = c.Org(ctx, fakeUser, "~ORG")
org, err := c.Org(ctx, fakeUser, "ORG") assert.NoError(t, err)
g.Assert(err).IsNil() assert.Equal(t, &model.Org{
g.Assert(org.Name).Equal("ORG") Name: "~ORG",
g.Assert(org.IsUser).IsFalse() IsUser: true,
}) }, org)
g.It("should map user organization", func() {
org, err := c.Org(ctx, fakeUser, "~ORG")
g.Assert(err).IsNil()
g.Assert(org.Name).Equal("~ORG")
g.Assert(org.IsUser).IsTrue()
})
})
})
} }
var fakeUser = &model.User{ var fakeUser = &model.User{

View File

@@ -18,288 +18,299 @@ import (
"testing" "testing"
"time" "time"
"github.com/franela/goblin"
bb "github.com/neticdk/go-bitbucket/bitbucket" bb "github.com/neticdk/go-bitbucket/bitbucket"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
//nolint:misspell func Test_convertStatus(t *testing.T) {
func TestHelper(t *testing.T) { tests := []struct {
g := goblin.Goblin(t) from model.StatusValue
g.Describe("Bitbucket Server converter", func() { to bb.BuildStatusState
g.It("should convert status", func() { }{
tests := []struct { {
from model.StatusValue from: model.StatusPending,
to bb.BuildStatusState to: bb.BuildStatusStateInProgress,
}{ },
{ {
from: model.StatusPending, from: model.StatusRunning,
to: bb.BuildStatusStateInProgress, to: bb.BuildStatusStateInProgress,
}, },
{ {
from: model.StatusRunning, from: model.StatusSuccess,
to: bb.BuildStatusStateInProgress, to: bb.BuildStatusStateSuccessful,
}, },
{ {
from: model.StatusSuccess, from: model.StatusValue("other"),
to: bb.BuildStatusStateSuccessful, to: bb.BuildStatusStateFailed,
}, },
{ }
from: model.StatusValue("other"), for _, tt := range tests {
to: bb.BuildStatusStateFailed, to := convertStatus(tt.from)
}, assert.Equal(t, tt.to, to)
} }
for _, tt := range tests { }
to := convertStatus(tt.from)
g.Assert(to).Equal(tt.to) func Test_convertRepo(t *testing.T) {
} from := &bb.Repository{
}) ID: uint64(1234),
Slug: "REPO",
g.It("should convert repository", func() { Project: &bb.Project{
from := &bb.Repository{ Key: "PRJ",
ID: uint64(1234), },
Slug: "REPO", Links: map[string][]bb.Link{
Project: &bb.Project{ "clone": {
Key: "PRJ", {
}, Name: "http",
Links: map[string][]bb.Link{ Href: "https://user@git.domain/clone",
"clone": { },
{ },
Name: "http", "self": {
Href: "https://user@git.domain/clone", {
}, Href: "https://git.domain/self",
}, },
"self": { },
{ },
Href: "https://git.domain/self", }
}, perm := &model.Perm{}
}, to := convertRepo(from, perm, "main")
},
} assert.Equal(t, &model.Repo{
perm := &model.Perm{} ForgeRemoteID: model.ForgeRemoteID("1234"),
to := convertRepo(from, perm, "main") Name: "REPO",
g.Assert(to.ForgeRemoteID).Equal(model.ForgeRemoteID("1234")) Owner: "PRJ",
g.Assert(to.Name).Equal("REPO") Branch: "main",
g.Assert(to.Owner).Equal("PRJ") FullName: "PRJ/REPO",
g.Assert(to.Branch).Equal("main") Perm: perm,
g.Assert(to.FullName).Equal("PRJ/REPO") Clone: "https://git.domain/clone",
g.Assert(to.Perm).Equal(perm) ForgeURL: "https://git.domain/self",
g.Assert(to.Clone).Equal("https://git.domain/clone") PREnabled: true,
}) IsSCMPrivate: true,
}, to)
g.It("should convert repository push event", func() { }
now := time.Now()
tests := []struct { func Test_convertRepositoryPushEvent(t *testing.T) {
from *bb.RepositoryPushEvent now := time.Now()
to *model.Pipeline tests := []struct {
}{ from *bb.RepositoryPushEvent
{ to *model.Pipeline
from: &bb.RepositoryPushEvent{}, }{
to: nil, {
}, from: &bb.RepositoryPushEvent{},
{ to: nil,
from: &bb.RepositoryPushEvent{ },
Changes: []bb.RepositoryPushEventChange{ {
{ from: &bb.RepositoryPushEvent{
FromHash: "1234567890abcdef", Changes: []bb.RepositoryPushEventChange{
ToHash: "0000000000000000000000000000000000000000", {
}, FromHash: "1234567890abcdef",
}, ToHash: "0000000000000000000000000000000000000000",
}, },
to: nil, },
}, },
{ to: nil,
from: &bb.RepositoryPushEvent{ },
Changes: []bb.RepositoryPushEventChange{ {
{ from: &bb.RepositoryPushEvent{
FromHash: "0000000000000000000000000000000000000000", Changes: []bb.RepositoryPushEventChange{
ToHash: "1234567890abcdef", {
Type: bb.RepositoryPushEventChangeTypeDelete, FromHash: "0000000000000000000000000000000000000000",
}, ToHash: "1234567890abcdef",
}, Type: bb.RepositoryPushEventChangeTypeDelete,
}, },
to: nil, },
}, },
{ to: nil,
from: &bb.RepositoryPushEvent{ },
Event: bb.Event{ {
Date: bb.ISOTime(now), from: &bb.RepositoryPushEvent{
Actor: bb.User{ Event: bb.Event{
Name: "John Doe", Date: bb.ISOTime(now),
Email: "john.doe@mail.com", Actor: bb.User{
Slug: "john.doe_mail.com", Name: "John Doe",
}, Email: "john.doe@mail.com",
}, Slug: "john.doe_mail.com",
Repository: bb.Repository{ },
Slug: "REPO", },
Project: &bb.Project{ Repository: bb.Repository{
Key: "PRJ", Slug: "REPO",
}, Project: &bb.Project{
}, Key: "PRJ",
Changes: []bb.RepositoryPushEventChange{ },
{ },
Ref: bb.RepositoryPushEventRef{ Changes: []bb.RepositoryPushEventChange{
ID: "refs/head/branch", {
DisplayID: "branch", Ref: bb.RepositoryPushEventRef{
}, ID: "refs/head/branch",
RefId: "refs/head/branch", DisplayID: "branch",
ToHash: "1234567890abcdef", },
}, RefId: "refs/head/branch",
}, ToHash: "1234567890abcdef",
}, },
to: &model.Pipeline{ },
Commit: "1234567890abcdef", },
Branch: "branch", to: &model.Pipeline{
Message: "", Commit: "1234567890abcdef",
Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", Branch: "branch",
Author: "John Doe", Message: "",
Email: "john.doe@mail.com", Avatar: "https://base.url/users/john.doe_mail.com/avatar.png",
Timestamp: now.UTC().Unix(), Author: "John Doe",
Ref: "refs/head/branch", Email: "john.doe@mail.com",
ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", Timestamp: now.UTC().Unix(),
Event: model.EventPush, Ref: "refs/head/branch",
}, ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef",
}, Event: model.EventPush,
} },
for _, tt := range tests { },
to := convertRepositoryPushEvent(tt.from, "https://base.url") }
g.Assert(to).Equal(tt.to) for _, tt := range tests {
} to := convertRepositoryPushEvent(tt.from, "https://base.url")
}) assert.Equal(t, tt.to, to)
}
g.It("should convert pull request event", func() { }
now := time.Now()
from := &bb.PullRequestEvent{ func Test_convertPullRequestEvent(t *testing.T) {
Event: bb.Event{ now := time.Now()
Date: bb.ISOTime(now), from := &bb.PullRequestEvent{
EventKey: bb.EventKeyPullRequestFrom, Event: bb.Event{
Actor: bb.User{ Date: bb.ISOTime(now),
Name: "John Doe", EventKey: bb.EventKeyPullRequestFrom,
Email: "john.doe@mail.com", Actor: bb.User{
Slug: "john.doe_mail.com", Name: "John Doe",
}, Email: "john.doe@mail.com",
}, Slug: "john.doe_mail.com",
PullRequest: bb.PullRequest{ },
ID: 123, },
Title: "my title", PullRequest: bb.PullRequest{
Source: bb.PullRequestRef{ ID: 123,
ID: "refs/head/branch", Title: "my title",
DisplayID: "branch", Source: bb.PullRequestRef{
Latest: "1234567890abcdef", ID: "refs/head/branch",
Repository: bb.Repository{ DisplayID: "branch",
Slug: "REPO", Latest: "1234567890abcdef",
Project: &bb.Project{ Repository: bb.Repository{
Key: "PRJ", Slug: "REPO",
}, Project: &bb.Project{
}, Key: "PRJ",
}, },
Target: bb.PullRequestRef{ },
ID: "refs/head/main", },
DisplayID: "main", Target: bb.PullRequestRef{
Latest: "abcdef1234567890", ID: "refs/head/main",
Repository: bb.Repository{ DisplayID: "main",
Slug: "REPO", Latest: "abcdef1234567890",
Project: &bb.Project{ Repository: bb.Repository{
Key: "PRJ", Slug: "REPO",
}, Project: &bb.Project{
}, Key: "PRJ",
}, },
}, },
} },
to := convertPullRequestEvent(from, "https://base.url") },
g.Assert(to.Commit).Equal("1234567890abcdef") }
g.Assert(to.Branch).Equal("branch") to := convertPullRequestEvent(from, "https://base.url")
g.Assert(to.Avatar).Equal("https://base.url/users/john.doe_mail.com/avatar.png") assert.Equal(t, &model.Pipeline{
g.Assert(to.Author).Equal("John Doe") Commit: "1234567890abcdef",
g.Assert(to.Email).Equal("john.doe@mail.com") Branch: "branch",
g.Assert(to.Timestamp).Equal(now.UTC().Unix()) Avatar: "https://base.url/users/john.doe_mail.com/avatar.png",
g.Assert(to.Ref).Equal("refs/pull-requests/123/from") Author: "John Doe",
g.Assert(to.ForgeURL).Equal("https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef") Email: "john.doe@mail.com",
g.Assert(to.Event).Equal(model.EventPull) Timestamp: now.UTC().Unix(),
g.Assert(to.Refspec).Equal("branch:main") Ref: "refs/pull-requests/123/from",
}) ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef",
Event: model.EventPull,
g.It("should close pull request", func() { Refspec: "branch:main",
now := time.Now() Title: "my title",
from := &bb.PullRequestEvent{ }, to)
Event: bb.Event{ }
Date: bb.ISOTime(now),
EventKey: bb.EventKeyPullRequestMerged, func Test_convertPullRequestCloseEvent(t *testing.T) {
Actor: bb.User{ now := time.Now()
Name: "John Doe", from := &bb.PullRequestEvent{
Email: "john.doe@mail.com", Event: bb.Event{
Slug: "john.doe_mail.com", Date: bb.ISOTime(now),
}, EventKey: bb.EventKeyPullRequestMerged,
}, Actor: bb.User{
PullRequest: bb.PullRequest{ Name: "John Doe",
ID: 123, Email: "john.doe@mail.com",
Title: "my title", Slug: "john.doe_mail.com",
Source: bb.PullRequestRef{ },
ID: "refs/head/branch", },
DisplayID: "branch", PullRequest: bb.PullRequest{
Latest: "1234567890abcdef", ID: 123,
Repository: bb.Repository{ Title: "my title",
Slug: "REPO", Source: bb.PullRequestRef{
Project: &bb.Project{ ID: "refs/head/branch",
Key: "PRJ", DisplayID: "branch",
}, Latest: "1234567890abcdef",
}, Repository: bb.Repository{
}, Slug: "REPO",
Target: bb.PullRequestRef{ Project: &bb.Project{
ID: "refs/head/main", Key: "PRJ",
DisplayID: "main", },
Latest: "abcdef1234567890", },
Repository: bb.Repository{ },
Slug: "REPO", Target: bb.PullRequestRef{
Project: &bb.Project{ ID: "refs/head/main",
Key: "PRJ", DisplayID: "main",
}, Latest: "abcdef1234567890",
}, Repository: bb.Repository{
}, Slug: "REPO",
}, Project: &bb.Project{
} Key: "PRJ",
to := convertPullRequestEvent(from, "https://base.url") },
g.Assert(to.Commit).Equal("1234567890abcdef") },
g.Assert(to.Branch).Equal("branch") },
g.Assert(to.Avatar).Equal("https://base.url/users/john.doe_mail.com/avatar.png") },
g.Assert(to.Author).Equal("John Doe") }
g.Assert(to.Email).Equal("john.doe@mail.com") to := convertPullRequestEvent(from, "https://base.url")
g.Assert(to.Timestamp).Equal(now.UTC().Unix()) assert.Equal(t, &model.Pipeline{
g.Assert(to.Ref).Equal("refs/pull-requests/123/from") Commit: "1234567890abcdef",
g.Assert(to.ForgeURL).Equal("https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef") Branch: "branch",
g.Assert(to.Event).Equal(model.EventPullClosed) Avatar: "https://base.url/users/john.doe_mail.com/avatar.png",
g.Assert(to.Refspec).Equal("branch:main") Author: "John Doe",
}) Email: "john.doe@mail.com",
Timestamp: now.UTC().Unix(),
g.It("should truncate author", func() { Ref: "refs/pull-requests/123/from",
tests := []struct { ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef",
from string Event: model.EventPullClosed,
to string Refspec: "branch:main",
}{ Title: "my title",
{ }, to)
from: "Some Short Author", }
to: "Some Short Author",
}, func Test_authorLabel(t *testing.T) {
{ tests := []struct {
from: "Some Very Long Author That May Include Multiple Names Here", from string
to: "Some Very Long Author That May Includ...", to string
}, }{
} {
for _, tt := range tests { from: "Some Short Author",
g.Assert(authorLabel(tt.from)).Equal(tt.to) to: "Some Short Author",
} },
}) {
from: "Some Very Long Author That May Include Multiple Names Here",
g.It("should convert user", func() { //nolint:misspell
from := &bb.User{ to: "Some Very Long Author That May Includ...",
Slug: "slug", },
Email: "john.doe@mail.com", }
} for _, tt := range tests {
to := convertUser(from, "https://base.url") assert.Equal(t, tt.to, authorLabel(tt.from))
g.Assert(to.Login).Equal("slug") }
g.Assert(to.Avatar).Equal("https://base.url/users/slug/avatar.png") }
g.Assert(to.Email).Equal("john.doe@mail.com")
}) func Test_convertUser(t *testing.T) {
}) from := &bb.User{
Slug: "slug",
Email: "john.doe@mail.com",
ID: 1,
}
to := convertUser(from, "https://base.url")
assert.Equal(t, &model.User{
Login: "slug",
Avatar: "https://base.url/users/slug/avatar.png",
Email: "john.doe@mail.com",
ForgeRemoteID: "1",
}, to)
} }

View File

@@ -20,7 +20,7 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )
@@ -30,20 +30,14 @@ func TestCurrentUser(t *testing.T) {
_, _ = w.Write([]byte(`tal@netic.dk`)) _, _ = w.Write([]byte(`tal@netic.dk`))
})) }))
g := goblin.Goblin(t) defer s.Close()
g.Describe("Bitbucket Current User", func() {
g.After(func() { ctx := context.Background()
s.Close() ts := mockSource("bearer-token")
}) client := NewClientWithToken(ctx, ts, s.URL)
g.It("should return current user id", func() { uid, err := client.FindCurrentUser(ctx)
ctx := context.Background() assert.NoError(t, err)
ts := mockSource("bearer-token") assert.Equal(t, "tal_netic.dk", uid)
client := NewClientWithToken(ctx, ts, s.URL)
uid, err := client.FindCurrentUser(ctx)
g.Assert(err).IsNil()
g.Assert(uid).Equal("tal_netic.dk")
})
})
} }
type mockSource string type mockSource string

View File

@@ -21,21 +21,32 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/forgejo/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/forgejo/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/server/store" "go.woodpecker-ci.org/woodpecker/v3/server/store"
mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks" mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks"
"go.woodpecker-ci.org/woodpecker/v3/shared/utils"
) )
func TestNew(t *testing.T) {
forge, _ := New(Opts{
URL: "http://localhost:8080",
SkipVerify: true,
})
f, _ := forge.(*Forgejo)
assert.Equal(t, "http://localhost:8080", f.url)
assert.True(t, f.SkipVerify)
}
func Test_forgejo(t *testing.T) { func Test_forgejo(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
s := httptest.NewServer(fixtures.Handler()) s := httptest.NewServer(fixtures.Handler())
defer s.Close()
c, _ := New(Opts{ c, _ := New(Opts{
URL: s.URL, URL: s.URL,
SkipVerify: true, SkipVerify: true,
@@ -44,122 +55,83 @@ func Test_forgejo(t *testing.T) {
mockStore := mocks_store.NewStore(t) mockStore := mocks_store.NewStore(t)
ctx := store.InjectToContext(context.Background(), mockStore) ctx := store.InjectToContext(context.Background(), mockStore)
g := goblin.Goblin(t) t.Run("netrc with user token", func(t *testing.T) {
g.Describe("Forgejo", func() { forge, _ := New(Opts{})
g.After(func() { netrc, _ := forge.Netrc(fakeUser, fakeRepo)
s.Close() assert.Equal(t, "forgejo.org", netrc.Machine)
}) assert.Equal(t, fakeUser.Login, netrc.Login)
assert.Equal(t, fakeUser.AccessToken, netrc.Password)
})
t.Run("netrc with machine account", func(t *testing.T) {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(nil, fakeRepo)
assert.Equal(t, "forgejo.org", netrc.Machine)
assert.Empty(t, netrc.Login)
assert.Empty(t, netrc.Password)
})
g.Describe("Creating a forge", func() { t.Run("repository details", func(t *testing.T) {
g.It("Should return client with specified options", func() { repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name)
forge, _ := New(Opts{ assert.NoError(t, err)
URL: "http://localhost:8080", assert.Equal(t, fakeRepo.Owner, repo.Owner)
SkipVerify: true, assert.Equal(t, fakeRepo.Name, repo.Name)
}) assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repo.FullName)
assert.True(t, repo.IsSCMPrivate)
assert.Equal(t, "http://localhost/test_name/repo_name.git", repo.Clone)
assert.Equal(t, "http://localhost/test_name/repo_name", repo.ForgeURL)
})
t.Run("repo not found", func(t *testing.T) {
_, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
assert.Error(t, err)
})
f, _ := forge.(*Forgejo) t.Run("repository list", func(t *testing.T) {
g.Assert(f.url).Equal("http://localhost:8080") repos, err := c.Repos(ctx, fakeUser)
g.Assert(f.SkipVerify).Equal(true) assert.NoError(t, err)
}) assert.Equal(t, fakeRepo.ForgeRemoteID, repos[0].ForgeRemoteID)
}) assert.Equal(t, fakeRepo.Owner, repos[0].Owner)
assert.Equal(t, fakeRepo.Name, repos[0].Name)
assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repos[0].FullName)
})
t.Run("not found error", func(t *testing.T) {
_, err := c.Repos(ctx, fakeUserNoRepos)
assert.Error(t, err)
})
g.Describe("Generating a netrc file", func() { t.Run("register repository", func(t *testing.T) {
g.It("Should return a netrc with the user token", func() { err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost")
forge, _ := New(Opts{}) assert.NoError(t, err)
netrc, _ := forge.Netrc(fakeUser, fakeRepo) })
g.Assert(netrc.Machine).Equal("forgejo.org")
g.Assert(netrc.Login).Equal(fakeUser.Login)
g.Assert(netrc.Password).Equal(fakeUser.AccessToken)
})
g.It("Should return a netrc with the machine account", func() {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(nil, fakeRepo)
g.Assert(netrc.Machine).Equal("forgejo.org")
g.Assert(netrc.Login).Equal("")
g.Assert(netrc.Password).Equal("")
})
})
g.Describe("Requesting a repository", func() { t.Run("remove hooks", func(t *testing.T) {
g.It("Should return the repository details", func() { err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost")
repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) assert.NoError(t, err)
g.Assert(err).IsNil() })
g.Assert(repo.Owner).Equal(fakeRepo.Owner)
g.Assert(repo.Name).Equal(fakeRepo.Name)
g.Assert(repo.FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name)
g.Assert(repo.IsSCMPrivate).IsTrue()
g.Assert(repo.Clone).Equal("http://localhost/test_name/repo_name.git")
g.Assert(repo.ForgeURL).Equal("http://localhost/test_name/repo_name")
})
g.It("Should handle a not found error", func() {
_, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
g.Assert(err).IsNotNil()
})
})
g.Describe("Requesting a repository list", func() { t.Run("repository file", func(t *testing.T) {
g.It("Should return the repository list", func() { raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml")
repos, err := c.Repos(ctx, fakeUser) assert.NoError(t, err)
g.Assert(err).IsNil() assert.Equal(t, "{ platform: linux/amd64 }", string(raw))
g.Assert(repos[0].ForgeRemoteID).Equal(fakeRepo.ForgeRemoteID) })
g.Assert(repos[0].Owner).Equal(fakeRepo.Owner)
g.Assert(repos[0].Name).Equal(fakeRepo.Name)
g.Assert(repos[0].FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name)
})
g.It("Should handle a not found error", func() {
_, err := c.Repos(ctx, fakeUserNoRepos)
g.Assert(err).IsNotNil()
})
})
g.It("Should register repository hooks", func() { t.Run("pipeline status", func(t *testing.T) {
err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
g.Assert(err).IsNil() assert.NoError(t, err)
}) })
g.It("Should remove repository hooks", func() { t.Run("PR hook", func(t *testing.T) {
err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost") buf := bytes.NewBufferString(fixtures.HookPullRequest)
g.Assert(err).IsNil() req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
}) req.Header = http.Header{}
req.Header.Set(hookEvent, hookPullRequest)
g.It("Should return a repository file", func() { mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil)
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml") mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil)
g.Assert(err).IsNil() r, b, err := c.Hook(ctx, req)
g.Assert(string(raw)).Equal("{ platform: linux/amd64 }") assert.NotNil(t, r)
}) assert.NotNil(t, b)
assert.NoError(t, err)
g.It("Should return nil from send pipeline status", func() { assert.Equal(t, model.EventPull, b.Event)
err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) assert.Equal(t, []string{"README.md"}, b.ChangedFiles)
g.Assert(err).IsNil()
})
g.Describe("Given an authentication request", func() {
g.It("Should redirect to login form")
g.It("Should create an access token")
g.It("Should handle an access token error")
g.It("Should return the authenticated user")
})
g.Describe("Given a repository hook", func() {
g.It("Should skip non-push events")
g.It("Should return push details")
g.It("Should handle a parsing error")
})
g.It("Given a PR hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{}
req.Header.Set(hookEvent, hookPullRequest)
mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil)
mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil)
r, b, err := c.Hook(ctx, req)
g.Assert(r).IsNotNil()
g.Assert(b).IsNotNil()
g.Assert(err).IsNil()
g.Assert(b.Event).Equal(model.EventPull)
g.Assert(utils.EqualSliceValues(b.ChangedFiles, []string{"README.md"})).IsTrue()
})
}) })
} }

View File

@@ -19,255 +19,252 @@ import (
"testing" "testing"
"codeberg.org/mvdkleijn/forgejo-sdk/forgejo" "codeberg.org/mvdkleijn/forgejo-sdk/forgejo"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/forgejo/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/forgejo/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/shared/utils"
) )
func Test_parse(t *testing.T) { func Test_parsePush(t *testing.T) {
g := goblin.Goblin(t) t.Run("Should parse push hook payload", func(t *testing.T) {
g.Describe("Forgejo", func() { buf := bytes.NewBufferString(fixtures.HookPush)
g.It("Should parse push hook payload", func() { hook, err := parsePush(buf)
buf := bytes.NewBufferString(fixtures.HookPush) assert.NoError(t, err)
hook, err := parsePush(buf) assert.Equal(t, "refs/heads/main", hook.Ref)
g.Assert(err).IsNil() assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.After)
g.Assert(hook.Ref).Equal("refs/heads/main") assert.Equal(t, "4b2626259b5a97b6b4eab5e6cca66adb986b672b", hook.Before)
g.Assert(hook.After).Equal("ef98532add3b2feb7a137426bba1248724367df5") assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5", hook.Compare)
g.Assert(hook.Before).Equal("4b2626259b5a97b6b4eab5e6cca66adb986b672b") assert.Equal(t, "hello-world", hook.Repo.Name)
g.Assert(hook.Compare).Equal("http://forgejo.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5") assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world", hook.Repo.HTMLURL)
g.Assert(hook.Repo.Name).Equal("hello-world") assert.Equal(t, "gordon", hook.Repo.Owner.UserName)
g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world") assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
g.Assert(hook.Repo.Owner.UserName).Equal("gordon") assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") assert.True(t, hook.Repo.Private)
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") assert.Equal(t, "gordon@golang.org", hook.Pusher.Email)
g.Assert(hook.Repo.Private).Equal(true) assert.Equal(t, "gordon", hook.Pusher.UserName)
g.Assert(hook.Pusher.Email).Equal("gordon@golang.org") assert.Equal(t, "gordon", hook.Sender.UserName)
g.Assert(hook.Pusher.UserName).Equal("gordon") assert.Equal(t, "http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
g.Assert(hook.Sender.UserName).Equal("gordon") })
g.Assert(hook.Sender.AvatarURL).Equal("http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") t.Run("Should parse tag hook payload", func(t *testing.T) {
}) buf := bytes.NewBufferString(fixtures.HookTag)
hook, err := parsePush(buf)
assert.NoError(t, err)
assert.Equal(t, "v1.0.0", hook.Ref)
assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.Sha)
assert.Equal(t, "hello-world", hook.Repo.Name)
assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world", hook.Repo.HTMLURL)
assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
assert.Equal(t, "gordon", hook.Repo.Owner.UserName)
assert.True(t, hook.Repo.Private)
assert.Equal(t, "gordon", hook.Sender.UserName)
assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
})
g.It("Should parse tag hook payload", func() { t.Run("Should return a Pipeline struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookTag) buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePush(buf) hook, _ := parsePush(buf)
g.Assert(err).IsNil() pipeline := pipelineFromPush(hook)
g.Assert(hook.Ref).Equal("v1.0.0") assert.Equal(t, model.EventPush, pipeline.Event)
g.Assert(hook.Sha).Equal("ef98532add3b2feb7a137426bba1248724367df5") assert.Equal(t, hook.After, pipeline.Commit)
g.Assert(hook.Repo.Name).Equal("hello-world") assert.Equal(t, hook.Ref, pipeline.Ref)
g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world") assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL)
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") assert.Equal(t, "main", pipeline.Branch)
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") assert.Equal(t, hook.Commits[0].Message, pipeline.Message)
g.Assert(hook.Repo.Owner.UserName).Equal("gordon") assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar)
g.Assert(hook.Repo.Private).Equal(true) assert.Equal(t, hook.Sender.UserName, pipeline.Author)
g.Assert(hook.Sender.UserName).Equal("gordon") assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles)
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") })
})
g.It("Should parse pull_request hook payload", func() { t.Run("Should return a Repo struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest) buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePullRequest(buf) hook, _ := parsePush(buf)
g.Assert(err).IsNil() repo := toRepo(hook.Repo)
g.Assert(hook.Action).Equal("opened") assert.Equal(t, hook.Repo.Name, repo.Name)
g.Assert(hook.Number).Equal(int64(1)) assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner)
assert.Equal(t, "gordon/hello-world", repo.FullName)
assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL)
})
g.Assert(hook.Repo.Name).Equal("hello-world") t.Run("Should return a Pipeline struct from a tag hook", func(t *testing.T) {
g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world") buf := bytes.NewBufferString(fixtures.HookTag)
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") hook, _ := parsePush(buf)
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") pipeline := pipelineFromTag(hook)
g.Assert(hook.Repo.Owner.UserName).Equal("gordon") assert.Equal(t, model.EventTag, pipeline.Event)
g.Assert(hook.Repo.Private).Equal(true) assert.Equal(t, hook.Sha, pipeline.Commit)
g.Assert(hook.Sender.UserName).Equal("gordon") assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref)
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") assert.Empty(t, pipeline.Branch)
assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL)
g.Assert(hook.PullRequest.Title).Equal("Update the README with new information") assert.Equal(t, "created tag v1.0.0", pipeline.Message)
g.Assert(hook.PullRequest.Body).Equal("please merge")
g.Assert(hook.PullRequest.State).Equal(forgejo.StateOpen)
g.Assert(hook.PullRequest.Poster.UserName).Equal("gordon")
g.Assert(hook.PullRequest.Base.Name).Equal("main")
g.Assert(hook.PullRequest.Base.Ref).Equal("main")
g.Assert(hook.PullRequest.Head.Name).Equal("feature/changes")
g.Assert(hook.PullRequest.Head.Ref).Equal("feature/changes")
})
g.It("Should return a Pipeline struct from a push hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
pipeline := pipelineFromPush(hook)
g.Assert(pipeline.Event).Equal(model.EventPush)
g.Assert(pipeline.Commit).Equal(hook.After)
g.Assert(pipeline.Ref).Equal(hook.Ref)
g.Assert(pipeline.ForgeURL).Equal(hook.Commits[0].URL)
g.Assert(pipeline.Branch).Equal("main")
g.Assert(pipeline.Message).Equal(hook.Commits[0].Message)
g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(pipeline.Author).Equal(hook.Sender.UserName)
g.Assert(utils.EqualSliceValues(pipeline.ChangedFiles, []string{"CHANGELOG.md", "app/controller/application.rb"})).IsTrue()
})
g.It("Should return a Repo struct from a push hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
repo := toRepo(hook.Repo)
g.Assert(repo.Name).Equal(hook.Repo.Name)
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
g.Assert(repo.FullName).Equal("gordon/hello-world")
g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL)
})
g.It("Should return a Pipeline struct from a tag hook", func() {
buf := bytes.NewBufferString(fixtures.HookTag)
hook, _ := parsePush(buf)
pipeline := pipelineFromTag(hook)
g.Assert(pipeline.Event).Equal(model.EventTag)
g.Assert(pipeline.Commit).Equal(hook.Sha)
g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0")
g.Assert(pipeline.Branch).Equal("")
g.Assert(pipeline.ForgeURL).Equal("http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0")
g.Assert(pipeline.Message).Equal("created tag v1.0.0")
})
g.It("Should return a Pipeline struct from a pull_request hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
pipeline := pipelineFromPullRequest(hook)
g.Assert(pipeline.Event).Equal(model.EventPull)
g.Assert(pipeline.Commit).Equal(hook.PullRequest.Head.Sha)
g.Assert(pipeline.Ref).Equal("refs/pull/1/head")
g.Assert(pipeline.ForgeURL).Equal("http://forgejo.golang.org/gordon/hello-world/pull/1")
g.Assert(pipeline.Branch).Equal("main")
g.Assert(pipeline.Refspec).Equal("feature/changes:main")
g.Assert(pipeline.Message).Equal(hook.PullRequest.Title)
g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(pipeline.Author).Equal(hook.PullRequest.Poster.UserName)
})
g.It("Should return a Repo struct from a pull_request hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
repo := toRepo(hook.Repo)
g.Assert(repo.Name).Equal(hook.Repo.Name)
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
g.Assert(repo.FullName).Equal("gordon/hello-world")
g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL)
})
g.It("Should return a Perm struct from a Forgejo Perm", func() {
perms := []forgejo.Permission{
{
Admin: true,
Push: true,
Pull: true,
},
{
Admin: true,
Push: true,
Pull: false,
},
{
Admin: true,
Push: false,
Pull: false,
},
}
for _, from := range perms {
perm := toPerm(&from)
g.Assert(perm.Pull).Equal(from.Pull)
g.Assert(perm.Push).Equal(from.Push)
g.Assert(perm.Admin).Equal(from.Admin)
}
})
g.It("Should return a Team struct from a Forgejo Org", func() {
from := &forgejo.Organization{
UserName: "woodpecker",
AvatarURL: "/avatars/1",
}
to := toTeam(from, "http://localhost:80")
g.Assert(to.Login).Equal(from.UserName)
g.Assert(to.Avatar).Equal("http://localhost:80/avatars/1")
})
g.It("Should return a Repo struct from a Forgejo Repo", func() {
from := forgejo.Repository{
FullName: "gophers/hello-world",
Owner: &forgejo.User{
UserName: "gordon",
AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
CloneURL: "http://forgejo.golang.org/gophers/hello-world.git",
HTMLURL: "http://forgejo.golang.org/gophers/hello-world",
Private: true,
DefaultBranch: "main",
Permissions: &forgejo.Permission{Admin: true},
}
repo := toRepo(&from)
g.Assert(repo.FullName).Equal(from.FullName)
g.Assert(repo.Owner).Equal(from.Owner.UserName)
g.Assert(repo.Name).Equal("hello-world")
g.Assert(repo.Branch).Equal("main")
g.Assert(repo.ForgeURL).Equal(from.HTMLURL)
g.Assert(repo.Clone).Equal(from.CloneURL)
g.Assert(repo.Avatar).Equal(from.Owner.AvatarURL)
g.Assert(repo.IsSCMPrivate).Equal(from.Private)
g.Assert(repo.Perm.Admin).IsTrue()
})
g.It("Should correct a malformed avatar url", func() {
urls := []struct {
Before string
After string
}{
{
"http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"http://forgejo.golang.org/avatars/1",
"http://forgejo.golang.org/avatars/1",
},
{
"http://forgejo.golang.org//avatars/1",
"http://forgejo.golang.org/avatars/1",
},
}
for _, url := range urls {
got := fixMalformedAvatar(url.Before)
g.Assert(got).Equal(url.After)
}
})
g.It("Should expand the avatar url", func() {
urls := []struct {
Before string
After string
}{
{
"/avatars/1",
"http://forgejo.io/avatars/1",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"/forgejo/avatars/2",
"http://forgejo.io/forgejo/avatars/2",
},
}
repo := "http://forgejo.io/foo/bar"
for _, url := range urls {
got := expandAvatar(repo, url.Before)
g.Assert(got).Equal(url.After)
}
})
}) })
} }
func Test_parsePullRequest(t *testing.T) {
t.Run("Should parse pull_request hook payload", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, err := parsePullRequest(buf)
assert.NoError(t, err)
assert.Equal(t, "opened", hook.Action)
assert.Equal(t, int64(1), hook.Number)
assert.Equal(t, "hello-world", hook.Repo.Name)
assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world", hook.Repo.HTMLURL)
assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
assert.Equal(t, "gordon", hook.Repo.Owner.UserName)
assert.True(t, hook.Repo.Private)
assert.Equal(t, "gordon", hook.Sender.UserName)
assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
assert.Equal(t, "Update the README with new information", hook.PullRequest.Title)
assert.Equal(t, "please merge", hook.PullRequest.Body)
assert.Equal(t, forgejo.StateOpen, hook.PullRequest.State)
assert.Equal(t, "gordon", hook.PullRequest.Poster.UserName)
assert.Equal(t, "main", hook.PullRequest.Base.Name)
assert.Equal(t, "main", hook.PullRequest.Base.Ref)
assert.Equal(t, "feature/changes", hook.PullRequest.Head.Name)
assert.Equal(t, "feature/changes", hook.PullRequest.Head.Ref)
})
t.Run("Should return a Pipeline struct from a pull_request hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
pipeline := pipelineFromPullRequest(hook)
assert.Equal(t, model.EventPull, pipeline.Event)
assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit)
assert.Equal(t, "refs/pull/1/head", pipeline.Ref)
assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/pull/1", pipeline.ForgeURL)
assert.Equal(t, "main", pipeline.Branch)
assert.Equal(t, "feature/changes:main", pipeline.Refspec)
assert.Equal(t, hook.PullRequest.Title, pipeline.Message)
assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar)
assert.Equal(t, hook.PullRequest.Poster.UserName, pipeline.Author)
})
t.Run("Should return a Repo struct from a pull_request hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
repo := toRepo(hook.Repo)
assert.Equal(t, hook.Repo.Name, repo.Name)
assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner)
assert.Equal(t, "gordon/hello-world", repo.FullName)
assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL)
})
}
func Test_toPerm(t *testing.T) {
perms := []forgejo.Permission{
{
Admin: true,
Push: true,
Pull: true,
},
{
Admin: true,
Push: true,
Pull: false,
},
{
Admin: true,
Push: false,
Pull: false,
},
}
for _, from := range perms {
perm := toPerm(&from)
assert.Equal(t, from.Pull, perm.Pull)
assert.Equal(t, from.Push, perm.Push)
assert.Equal(t, from.Admin, perm.Admin)
}
}
func Test_toTeam(t *testing.T) {
from := &forgejo.Organization{
UserName: "woodpecker",
AvatarURL: "/avatars/1",
}
to := toTeam(from, "http://localhost:80")
assert.Equal(t, from.UserName, to.Login)
assert.Equal(t, "http://localhost:80/avatars/1", to.Avatar)
}
func Test_toRepo(t *testing.T) {
from := forgejo.Repository{
FullName: "gophers/hello-world",
Owner: &forgejo.User{
UserName: "gordon",
AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
CloneURL: "http://forgejo.golang.org/gophers/hello-world.git",
HTMLURL: "http://forgejo.golang.org/gophers/hello-world",
Private: true,
DefaultBranch: "main",
Permissions: &forgejo.Permission{Admin: true},
}
repo := toRepo(&from)
assert.Equal(t, from.FullName, repo.FullName)
assert.Equal(t, from.Owner.UserName, repo.Owner)
assert.Equal(t, "hello-world", repo.Name)
assert.Equal(t, "main", repo.Branch)
assert.Equal(t, from.HTMLURL, repo.ForgeURL)
assert.Equal(t, from.CloneURL, repo.Clone)
assert.Equal(t, from.Owner.AvatarURL, repo.Avatar)
assert.Equal(t, from.Private, repo.IsSCMPrivate)
assert.True(t, repo.Perm.Admin)
}
func Test_fixMalformedAvatar(t *testing.T) {
urls := []struct {
Before string
After string
}{
{
"http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"http://forgejo.golang.org/avatars/1",
"http://forgejo.golang.org/avatars/1",
},
{
"http://forgejo.golang.org//avatars/1",
"http://forgejo.golang.org/avatars/1",
},
}
for _, url := range urls {
got := fixMalformedAvatar(url.Before)
assert.Equal(t, url.After, got)
}
}
func Test_expandAvatar(t *testing.T) {
urls := []struct {
Before string
After string
}{
{
"/avatars/1",
"http://forgejo.io/avatars/1",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"/forgejo/avatars/2",
"http://forgejo.io/forgejo/avatars/2",
},
}
repo := "http://forgejo.io/foo/bar"
for _, url := range urls {
got := expandAvatar(repo, url.Before)
assert.Equal(t, url.After, got)
}
}

View File

@@ -22,21 +22,32 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/gitea/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/gitea/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/server/store" "go.woodpecker-ci.org/woodpecker/v3/server/store"
mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks" mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks"
"go.woodpecker-ci.org/woodpecker/v3/shared/utils"
) )
func TestNew(t *testing.T) {
forge, _ := New(Opts{
URL: "http://localhost:8080",
SkipVerify: true,
})
f, _ := forge.(*Gitea)
assert.Equal(t, "http://localhost:8080", f.url)
assert.True(t, f.SkipVerify)
}
func Test_gitea(t *testing.T) { func Test_gitea(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
s := httptest.NewServer(fixtures.Handler()) s := httptest.NewServer(fixtures.Handler())
defer s.Close()
c, _ := New(Opts{ c, _ := New(Opts{
URL: s.URL, URL: s.URL,
SkipVerify: true, SkipVerify: true,
@@ -45,122 +56,83 @@ func Test_gitea(t *testing.T) {
mockStore := mocks_store.NewStore(t) mockStore := mocks_store.NewStore(t)
ctx := store.InjectToContext(context.Background(), mockStore) ctx := store.InjectToContext(context.Background(), mockStore)
g := goblin.Goblin(t) t.Run("netrc with user token", func(t *testing.T) {
g.Describe("Gitea", func() { forge, _ := New(Opts{})
g.After(func() { netrc, _ := forge.Netrc(fakeUser, fakeRepo)
s.Close() assert.Equal(t, "gitea.com", netrc.Machine)
}) assert.Equal(t, fakeUser.Login, netrc.Login)
assert.Equal(t, fakeUser.AccessToken, netrc.Password)
})
t.Run("netrc with machine account", func(t *testing.T) {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(nil, fakeRepo)
assert.Equal(t, "gitea.com", netrc.Machine)
assert.Empty(t, netrc.Login)
assert.Empty(t, netrc.Password)
})
g.Describe("Creating a forge", func() { t.Run("repository details", func(t *testing.T) {
g.It("Should return client with specified options", func() { repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name)
forge, _ := New(Opts{ assert.NoError(t, err)
URL: "http://localhost:8080", assert.Equal(t, fakeRepo.Owner, repo.Owner)
SkipVerify: true, assert.Equal(t, fakeRepo.Name, repo.Name)
}) assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repo.FullName)
assert.True(t, repo.IsSCMPrivate)
assert.Equal(t, "http://localhost/test_name/repo_name.git", repo.Clone)
assert.Equal(t, "http://localhost/test_name/repo_name", repo.ForgeURL)
})
t.Run("repo not found", func(t *testing.T) {
_, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
assert.Error(t, err)
})
f, _ := forge.(*Gitea) t.Run("repository list", func(t *testing.T) {
g.Assert(f.url).Equal("http://localhost:8080") repos, err := c.Repos(ctx, fakeUser)
g.Assert(f.SkipVerify).Equal(true) assert.NoError(t, err)
}) assert.Equal(t, fakeRepo.ForgeRemoteID, repos[0].ForgeRemoteID)
}) assert.Equal(t, fakeRepo.Owner, repos[0].Owner)
assert.Equal(t, fakeRepo.Name, repos[0].Name)
assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repos[0].FullName)
})
t.Run("not found error", func(t *testing.T) {
_, err := c.Repos(ctx, fakeUserNoRepos)
assert.Error(t, err)
})
g.Describe("Generating a netrc file", func() { t.Run("register repository", func(t *testing.T) {
g.It("Should return a netrc with the user token", func() { err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost")
forge, _ := New(Opts{}) assert.NoError(t, err)
netrc, _ := forge.Netrc(fakeUser, fakeRepo) })
g.Assert(netrc.Machine).Equal("gitea.com")
g.Assert(netrc.Login).Equal(fakeUser.Login)
g.Assert(netrc.Password).Equal(fakeUser.AccessToken)
})
g.It("Should return a netrc with the machine account", func() {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(nil, fakeRepo)
g.Assert(netrc.Machine).Equal("gitea.com")
g.Assert(netrc.Login).Equal("")
g.Assert(netrc.Password).Equal("")
})
})
g.Describe("Requesting a repository", func() { t.Run("remove hooks", func(t *testing.T) {
g.It("Should return the repository details", func() { err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost")
repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) assert.NoError(t, err)
g.Assert(err).IsNil() })
g.Assert(repo.Owner).Equal(fakeRepo.Owner)
g.Assert(repo.Name).Equal(fakeRepo.Name)
g.Assert(repo.FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name)
g.Assert(repo.IsSCMPrivate).IsTrue()
g.Assert(repo.Clone).Equal("http://localhost/test_name/repo_name.git")
g.Assert(repo.ForgeURL).Equal("http://localhost/test_name/repo_name")
})
g.It("Should handle a not found error", func() {
_, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
g.Assert(err).IsNotNil()
})
})
g.Describe("Requesting a repository list", func() { t.Run("repository file", func(t *testing.T) {
g.It("Should return the repository list", func() { raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml")
repos, err := c.Repos(ctx, fakeUser) assert.NoError(t, err)
g.Assert(err).IsNil() assert.Equal(t, "{ platform: linux/amd64 }", string(raw))
g.Assert(repos[0].ForgeRemoteID).Equal(fakeRepo.ForgeRemoteID) })
g.Assert(repos[0].Owner).Equal(fakeRepo.Owner)
g.Assert(repos[0].Name).Equal(fakeRepo.Name)
g.Assert(repos[0].FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name)
})
g.It("Should handle a not found error", func() {
_, err := c.Repos(ctx, fakeUserNoRepos)
g.Assert(err).IsNotNil()
})
})
g.It("Should register repository hooks", func() { t.Run("pipeline status", func(t *testing.T) {
err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
g.Assert(err).IsNil() assert.NoError(t, err)
}) })
g.It("Should remove repository hooks", func() { t.Run("PR hook", func(t *testing.T) {
err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost") buf := bytes.NewBufferString(fixtures.HookPullRequest)
g.Assert(err).IsNil() req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
}) req.Header = http.Header{}
req.Header.Set(hookEvent, hookPullRequest)
g.It("Should return a repository file", func() { mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil)
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml") mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil)
g.Assert(err).IsNil() r, b, err := c.Hook(ctx, req)
g.Assert(string(raw)).Equal("{ platform: linux/amd64 }") assert.NotNil(t, r)
}) assert.NotNil(t, b)
assert.NoError(t, err)
g.It("Should return nil from send pipeline status", func() { assert.Equal(t, model.EventPull, b.Event)
err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) assert.Equal(t, []string{"README.md"}, b.ChangedFiles)
g.Assert(err).IsNil()
})
g.Describe("Given an authentication request", func() {
g.It("Should redirect to login form")
g.It("Should create an access token")
g.It("Should handle an access token error")
g.It("Should return the authenticated user")
})
g.Describe("Given a repository hook", func() {
g.It("Should skip non-push events")
g.It("Should return push details")
g.It("Should handle a parsing error")
})
g.It("Given a PR hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
req, _ := http.NewRequest(http.MethodPost, "/hook", buf)
req.Header = http.Header{}
req.Header.Set(hookEvent, hookPullRequest)
mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil)
mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil)
r, b, err := c.Hook(ctx, req)
g.Assert(r).IsNotNil()
g.Assert(b).IsNotNil()
g.Assert(err).IsNil()
g.Assert(b.Event).Equal(model.EventPull)
g.Assert(utils.EqualSliceValues(b.ChangedFiles, []string{"README.md"})).IsTrue()
})
}) })
} }

View File

@@ -20,255 +20,252 @@ import (
"testing" "testing"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/gitea/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/gitea/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
"go.woodpecker-ci.org/woodpecker/v3/shared/utils"
) )
func Test_parse(t *testing.T) { func Test_parsePush(t *testing.T) {
g := goblin.Goblin(t) t.Run("Should parse push hook payload", func(t *testing.T) {
g.Describe("Gitea", func() { buf := bytes.NewBufferString(fixtures.HookPush)
g.It("Should parse push hook payload", func() { hook, err := parsePush(buf)
buf := bytes.NewBufferString(fixtures.HookPush) assert.NoError(t, err)
hook, err := parsePush(buf) assert.Equal(t, "refs/heads/main", hook.Ref)
g.Assert(err).IsNil() assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.After)
g.Assert(hook.Ref).Equal("refs/heads/main") assert.Equal(t, "4b2626259b5a97b6b4eab5e6cca66adb986b672b", hook.Before)
g.Assert(hook.After).Equal("ef98532add3b2feb7a137426bba1248724367df5") assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5", hook.Compare)
g.Assert(hook.Before).Equal("4b2626259b5a97b6b4eab5e6cca66adb986b672b") assert.Equal(t, "hello-world", hook.Repo.Name)
g.Assert(hook.Compare).Equal("http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5") assert.Equal(t, "http://gitea.golang.org/gordon/hello-world", hook.Repo.HTMLURL)
g.Assert(hook.Repo.Name).Equal("hello-world") assert.Equal(t, "gordon", hook.Repo.Owner.UserName)
g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world") assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
g.Assert(hook.Repo.Owner.UserName).Equal("gordon") assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") assert.True(t, hook.Repo.Private)
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") assert.Equal(t, "gordon@golang.org", hook.Pusher.Email)
g.Assert(hook.Repo.Private).Equal(true) assert.Equal(t, "gordon", hook.Pusher.UserName)
g.Assert(hook.Pusher.Email).Equal("gordon@golang.org") assert.Equal(t, "gordon", hook.Sender.UserName)
g.Assert(hook.Pusher.UserName).Equal("gordon") assert.Equal(t, "http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
g.Assert(hook.Sender.UserName).Equal("gordon") })
g.Assert(hook.Sender.AvatarURL).Equal("http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") t.Run("Should parse tag hook payload", func(t *testing.T) {
}) buf := bytes.NewBufferString(fixtures.HookTag)
hook, err := parsePush(buf)
assert.NoError(t, err)
assert.Equal(t, "v1.0.0", hook.Ref)
assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.Sha)
assert.Equal(t, "hello-world", hook.Repo.Name)
assert.Equal(t, "http://gitea.golang.org/gordon/hello-world", hook.Repo.HTMLURL)
assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
assert.Equal(t, "gordon", hook.Repo.Owner.UserName)
assert.True(t, hook.Repo.Private)
assert.Equal(t, "gordon", hook.Sender.UserName)
assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
})
g.It("Should parse tag hook payload", func() { t.Run("Should return a Pipeline struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookTag) buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePush(buf) hook, _ := parsePush(buf)
g.Assert(err).IsNil() pipeline := pipelineFromPush(hook)
g.Assert(hook.Ref).Equal("v1.0.0") assert.Equal(t, model.EventPush, pipeline.Event)
g.Assert(hook.Sha).Equal("ef98532add3b2feb7a137426bba1248724367df5") assert.Equal(t, hook.After, pipeline.Commit)
g.Assert(hook.Repo.Name).Equal("hello-world") assert.Equal(t, hook.Ref, pipeline.Ref)
g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world") assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL)
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") assert.Equal(t, "main", pipeline.Branch)
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") assert.Equal(t, hook.Commits[0].Message, pipeline.Message)
g.Assert(hook.Repo.Owner.UserName).Equal("gordon") assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar)
g.Assert(hook.Repo.Private).Equal(true) assert.Equal(t, hook.Sender.UserName, pipeline.Author)
g.Assert(hook.Sender.UserName).Equal("gordon") assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles)
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") })
})
g.It("Should parse pull_request hook payload", func() { t.Run("Should return a Repo struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest) buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePullRequest(buf) hook, _ := parsePush(buf)
g.Assert(err).IsNil() repo := toRepo(hook.Repo)
g.Assert(hook.Action).Equal("opened") assert.Equal(t, hook.Repo.Name, repo.Name)
g.Assert(hook.Number).Equal(int64(1)) assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner)
assert.Equal(t, "gordon/hello-world", repo.FullName)
assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL)
})
g.Assert(hook.Repo.Name).Equal("hello-world") t.Run("Should return a Pipeline struct from a tag hook", func(t *testing.T) {
g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world") buf := bytes.NewBufferString(fixtures.HookTag)
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") hook, _ := parsePush(buf)
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") pipeline := pipelineFromTag(hook)
g.Assert(hook.Repo.Owner.UserName).Equal("gordon") assert.Equal(t, model.EventTag, pipeline.Event)
g.Assert(hook.Repo.Private).Equal(true) assert.Equal(t, hook.Sha, pipeline.Commit)
g.Assert(hook.Sender.UserName).Equal("gordon") assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref)
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") assert.Empty(t, pipeline.Branch)
assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL)
g.Assert(hook.PullRequest.Title).Equal("Update the README with new information") assert.Equal(t, "created tag v1.0.0", pipeline.Message)
g.Assert(hook.PullRequest.Body).Equal("please merge")
g.Assert(hook.PullRequest.State).Equal(gitea.StateOpen)
g.Assert(hook.PullRequest.Poster.UserName).Equal("gordon")
g.Assert(hook.PullRequest.Base.Name).Equal("main")
g.Assert(hook.PullRequest.Base.Ref).Equal("main")
g.Assert(hook.PullRequest.Head.Name).Equal("feature/changes")
g.Assert(hook.PullRequest.Head.Ref).Equal("feature/changes")
})
g.It("Should return a Pipeline struct from a push hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
pipeline := pipelineFromPush(hook)
g.Assert(pipeline.Event).Equal(model.EventPush)
g.Assert(pipeline.Commit).Equal(hook.After)
g.Assert(pipeline.Ref).Equal(hook.Ref)
g.Assert(pipeline.ForgeURL).Equal(hook.Commits[0].URL)
g.Assert(pipeline.Branch).Equal("main")
g.Assert(pipeline.Message).Equal(hook.Commits[0].Message)
g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(pipeline.Author).Equal(hook.Sender.UserName)
g.Assert(utils.EqualSliceValues(pipeline.ChangedFiles, []string{"CHANGELOG.md", "app/controller/application.rb"})).IsTrue()
})
g.It("Should return a Repo struct from a push hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
repo := toRepo(hook.Repo)
g.Assert(repo.Name).Equal(hook.Repo.Name)
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
g.Assert(repo.FullName).Equal("gordon/hello-world")
g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL)
})
g.It("Should return a Pipeline struct from a tag hook", func() {
buf := bytes.NewBufferString(fixtures.HookTag)
hook, _ := parsePush(buf)
pipeline := pipelineFromTag(hook)
g.Assert(pipeline.Event).Equal(model.EventTag)
g.Assert(pipeline.Commit).Equal(hook.Sha)
g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0")
g.Assert(pipeline.Branch).Equal("")
g.Assert(pipeline.ForgeURL).Equal("http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0")
g.Assert(pipeline.Message).Equal("created tag v1.0.0")
})
g.It("Should return a Pipeline struct from a pull_request hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
pipeline := pipelineFromPullRequest(hook)
g.Assert(pipeline.Event).Equal(model.EventPull)
g.Assert(pipeline.Commit).Equal(hook.PullRequest.Head.Sha)
g.Assert(pipeline.Ref).Equal("refs/pull/1/head")
g.Assert(pipeline.ForgeURL).Equal("http://gitea.golang.org/gordon/hello-world/pull/1")
g.Assert(pipeline.Branch).Equal("main")
g.Assert(pipeline.Refspec).Equal("feature/changes:main")
g.Assert(pipeline.Message).Equal(hook.PullRequest.Title)
g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(pipeline.Author).Equal(hook.PullRequest.Poster.UserName)
})
g.It("Should return a Repo struct from a pull_request hook", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
repo := toRepo(hook.Repo)
g.Assert(repo.Name).Equal(hook.Repo.Name)
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
g.Assert(repo.FullName).Equal("gordon/hello-world")
g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL)
})
g.It("Should return a Perm struct from a Gitea Perm", func() {
perms := []gitea.Permission{
{
Admin: true,
Push: true,
Pull: true,
},
{
Admin: true,
Push: true,
Pull: false,
},
{
Admin: true,
Push: false,
Pull: false,
},
}
for _, from := range perms {
perm := toPerm(&from)
g.Assert(perm.Pull).Equal(from.Pull)
g.Assert(perm.Push).Equal(from.Push)
g.Assert(perm.Admin).Equal(from.Admin)
}
})
g.It("Should return a Team struct from a Gitea Org", func() {
from := &gitea.Organization{
UserName: "woodpecker",
AvatarURL: "/avatars/1",
}
to := toTeam(from, "http://localhost:80")
g.Assert(to.Login).Equal(from.UserName)
g.Assert(to.Avatar).Equal("http://localhost:80/avatars/1")
})
g.It("Should return a Repo struct from a Gitea Repo", func() {
from := gitea.Repository{
FullName: "gophers/hello-world",
Owner: &gitea.User{
UserName: "gordon",
AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
CloneURL: "http://gitea.golang.org/gophers/hello-world.git",
HTMLURL: "http://gitea.golang.org/gophers/hello-world",
Private: true,
DefaultBranch: "main",
Permissions: &gitea.Permission{Admin: true},
}
repo := toRepo(&from)
g.Assert(repo.FullName).Equal(from.FullName)
g.Assert(repo.Owner).Equal(from.Owner.UserName)
g.Assert(repo.Name).Equal("hello-world")
g.Assert(repo.Branch).Equal("main")
g.Assert(repo.ForgeURL).Equal(from.HTMLURL)
g.Assert(repo.Clone).Equal(from.CloneURL)
g.Assert(repo.Avatar).Equal(from.Owner.AvatarURL)
g.Assert(repo.IsSCMPrivate).Equal(from.Private)
g.Assert(repo.Perm.Admin).IsTrue()
})
g.It("Should correct a malformed avatar url", func() {
urls := []struct {
Before string
After string
}{
{
"http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"http://gitea.golang.org/avatars/1",
"http://gitea.golang.org/avatars/1",
},
{
"http://gitea.golang.org//avatars/1",
"http://gitea.golang.org/avatars/1",
},
}
for _, url := range urls {
got := fixMalformedAvatar(url.Before)
g.Assert(got).Equal(url.After)
}
})
g.It("Should expand the avatar url", func() {
urls := []struct {
Before string
After string
}{
{
"/avatars/1",
"http://gitea.io/avatars/1",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"/gitea/avatars/2",
"http://gitea.io/gitea/avatars/2",
},
}
repo := "http://gitea.io/foo/bar"
for _, url := range urls {
got := expandAvatar(repo, url.Before)
g.Assert(got).Equal(url.After)
}
})
}) })
} }
func Test_parsePullRequest(t *testing.T) {
t.Run("Should parse pull_request hook payload", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, err := parsePullRequest(buf)
assert.NoError(t, err)
assert.Equal(t, "opened", hook.Action)
assert.Equal(t, int64(1), hook.Number)
assert.Equal(t, "hello-world", hook.Repo.Name)
assert.Equal(t, "http://gitea.golang.org/gordon/hello-world", hook.Repo.HTMLURL)
assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
assert.Equal(t, "gordon", hook.Repo.Owner.UserName)
assert.True(t, hook.Repo.Private)
assert.Equal(t, "gordon", hook.Sender.UserName)
assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
assert.Equal(t, "Update the README with new information", hook.PullRequest.Title)
assert.Equal(t, "please merge", hook.PullRequest.Body)
assert.Equal(t, gitea.StateOpen, hook.PullRequest.State)
assert.Equal(t, "gordon", hook.PullRequest.Poster.UserName)
assert.Equal(t, "main", hook.PullRequest.Base.Name)
assert.Equal(t, "main", hook.PullRequest.Base.Ref)
assert.Equal(t, "feature/changes", hook.PullRequest.Head.Name)
assert.Equal(t, "feature/changes", hook.PullRequest.Head.Ref)
})
t.Run("Should return a Pipeline struct from a pull_request hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
pipeline := pipelineFromPullRequest(hook)
assert.Equal(t, model.EventPull, pipeline.Event)
assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit)
assert.Equal(t, "refs/pull/1/head", pipeline.Ref)
assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/pull/1", pipeline.ForgeURL)
assert.Equal(t, "main", pipeline.Branch)
assert.Equal(t, "feature/changes:main", pipeline.Refspec)
assert.Equal(t, hook.PullRequest.Title, pipeline.Message)
assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar)
assert.Equal(t, hook.PullRequest.Poster.UserName, pipeline.Author)
})
t.Run("Should return a Repo struct from a pull_request hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, _ := parsePullRequest(buf)
repo := toRepo(hook.Repo)
assert.Equal(t, hook.Repo.Name, repo.Name)
assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner)
assert.Equal(t, "gordon/hello-world", repo.FullName)
assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL)
})
}
func Test_toPerm(t *testing.T) {
perms := []gitea.Permission{
{
Admin: true,
Push: true,
Pull: true,
},
{
Admin: true,
Push: true,
Pull: false,
},
{
Admin: true,
Push: false,
Pull: false,
},
}
for _, from := range perms {
perm := toPerm(&from)
assert.Equal(t, from.Pull, perm.Pull)
assert.Equal(t, from.Push, perm.Push)
assert.Equal(t, from.Admin, perm.Admin)
}
}
func Test_toTeam(t *testing.T) {
from := &gitea.Organization{
UserName: "woodpecker",
AvatarURL: "/avatars/1",
}
to := toTeam(from, "http://localhost:80")
assert.Equal(t, from.UserName, to.Login)
assert.Equal(t, "http://localhost:80/avatars/1", to.Avatar)
}
func Test_toRepo(t *testing.T) {
from := gitea.Repository{
FullName: "gophers/hello-world",
Owner: &gitea.User{
UserName: "gordon",
AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
CloneURL: "http://gitea.golang.org/gophers/hello-world.git",
HTMLURL: "http://gitea.golang.org/gophers/hello-world",
Private: true,
DefaultBranch: "main",
Permissions: &gitea.Permission{Admin: true},
}
repo := toRepo(&from)
assert.Equal(t, from.FullName, repo.FullName)
assert.Equal(t, from.Owner.UserName, repo.Owner)
assert.Equal(t, "hello-world", repo.Name)
assert.Equal(t, "main", repo.Branch)
assert.Equal(t, from.HTMLURL, repo.ForgeURL)
assert.Equal(t, from.CloneURL, repo.Clone)
assert.Equal(t, from.Owner.AvatarURL, repo.Avatar)
assert.Equal(t, from.Private, repo.IsSCMPrivate)
assert.True(t, repo.Perm.Admin)
}
func Test_fixMalformedAvatar(t *testing.T) {
urls := []struct {
Before string
After string
}{
{
"http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"http://gitea.golang.org/avatars/1",
"http://gitea.golang.org/avatars/1",
},
{
"http://gitea.golang.org//avatars/1",
"http://gitea.golang.org/avatars/1",
},
}
for _, url := range urls {
got := fixMalformedAvatar(url.Before)
assert.Equal(t, url.After, got)
}
}
func Test_expandAvatar(t *testing.T) {
urls := []struct {
Before string
After string
}{
{
"/avatars/1",
"http://gitea.io/avatars/1",
},
{
"//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
"http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87",
},
{
"/gitea/avatars/2",
"http://gitea.io/gitea/avatars/2",
},
}
repo := "http://gitea.io/foo/bar"
for _, url := range urls {
got := expandAvatar(repo, url.Before)
assert.Equal(t, url.After, got)
}
}

View File

@@ -18,280 +18,261 @@ package github
import ( import (
"testing" "testing"
"github.com/franela/goblin"
"github.com/google/go-github/v68/github" "github.com/google/go-github/v68/github"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func Test_helper(t *testing.T) { func Test_convertStatus(t *testing.T) {
g := goblin.Goblin(t) assert.Equal(t, statusSuccess, convertStatus(model.StatusSuccess))
g.Describe("GitHub converter", func() { assert.Equal(t, statusPending, convertStatus(model.StatusPending))
g.It("should convert passing status", func() { assert.Equal(t, statusPending, convertStatus(model.StatusRunning))
g.Assert(convertStatus(model.StatusSuccess)).Equal(statusSuccess) assert.Equal(t, statusFailure, convertStatus(model.StatusFailure))
}) assert.Equal(t, statusError, convertStatus(model.StatusKilled))
assert.Equal(t, statusError, convertStatus(model.StatusError))
}
g.It("should convert pending status", func() { func Test_convertDesc(t *testing.T) {
g.Assert(convertStatus(model.StatusPending)).Equal(statusPending) assert.Equal(t, descSuccess, convertDesc(model.StatusSuccess))
g.Assert(convertStatus(model.StatusRunning)).Equal(statusPending) assert.Equal(t, descPending, convertDesc(model.StatusPending))
}) assert.Equal(t, descPending, convertDesc(model.StatusRunning))
assert.Equal(t, descFailure, convertDesc(model.StatusFailure))
assert.Equal(t, descError, convertDesc(model.StatusKilled))
assert.Equal(t, descError, convertDesc(model.StatusError))
}
g.It("should convert failing status", func() { func Test_convertRepoList(t *testing.T) {
g.Assert(convertStatus(model.StatusFailure)).Equal(statusFailure) from := []*github.Repository{
}) {
Private: github.Ptr(false),
g.It("should convert error status", func() { FullName: github.Ptr("octocat/hello-world"),
g.Assert(convertStatus(model.StatusKilled)).Equal(statusError) Name: github.Ptr("hello-world"),
g.Assert(convertStatus(model.StatusError)).Equal(statusError) Owner: &github.User{
})
g.It("should convert passing desc", func() {
g.Assert(convertDesc(model.StatusSuccess)).Equal(descSuccess)
})
g.It("should convert pending desc", func() {
g.Assert(convertDesc(model.StatusPending)).Equal(descPending)
g.Assert(convertDesc(model.StatusRunning)).Equal(descPending)
})
g.It("should convert failing desc", func() {
g.Assert(convertDesc(model.StatusFailure)).Equal(descFailure)
})
g.It("should convert error desc", func() {
g.Assert(convertDesc(model.StatusKilled)).Equal(descError)
g.Assert(convertDesc(model.StatusError)).Equal(descError)
})
g.It("should convert repository list", func() {
from := []*github.Repository{
{
Private: github.Ptr(false),
FullName: github.Ptr("octocat/hello-world"),
Name: github.Ptr("hello-world"),
Owner: &github.User{
AvatarURL: github.Ptr("http://..."),
Login: github.Ptr("octocat"),
},
HTMLURL: github.Ptr("https://github.com/octocat/hello-world"),
CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"),
Permissions: map[string]bool{
"push": true,
"pull": true,
"admin": true,
},
},
}
to := convertRepoList(from)
g.Assert(to[0].Avatar).Equal("http://...")
g.Assert(to[0].FullName).Equal("octocat/hello-world")
g.Assert(to[0].Owner).Equal("octocat")
g.Assert(to[0].Name).Equal("hello-world")
})
g.It("should convert repository", func() {
from := github.Repository{
FullName: github.Ptr("octocat/hello-world"),
Name: github.Ptr("hello-world"),
HTMLURL: github.Ptr("https://github.com/octocat/hello-world"),
CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"),
DefaultBranch: github.Ptr("develop"),
Private: github.Ptr(true),
Owner: &github.User{
AvatarURL: github.Ptr("http://..."),
Login: github.Ptr("octocat"),
},
Permissions: map[string]bool{
"push": true,
"pull": true,
"admin": true,
},
}
to := convertRepo(&from)
g.Assert(to.Avatar).Equal("http://...")
g.Assert(to.FullName).Equal("octocat/hello-world")
g.Assert(to.Owner).Equal("octocat")
g.Assert(to.Name).Equal("hello-world")
g.Assert(to.Branch).Equal("develop")
g.Assert(to.IsSCMPrivate).IsTrue()
g.Assert(to.Clone).Equal("https://github.com/octocat/hello-world.git")
g.Assert(to.ForgeURL).Equal("https://github.com/octocat/hello-world")
})
g.It("should convert repository permissions", func() {
from := &github.Repository{
Permissions: map[string]bool{
"admin": true,
"push": true,
"pull": true,
},
}
to := convertPerm(from.GetPermissions())
g.Assert(to.Push).IsTrue()
g.Assert(to.Pull).IsTrue()
g.Assert(to.Admin).IsTrue()
})
g.It("should convert team", func() {
from := &github.Organization{
Login: github.Ptr("octocat"),
AvatarURL: github.Ptr("http://..."), AvatarURL: github.Ptr("http://..."),
} Login: github.Ptr("octocat"),
to := convertTeam(from) },
g.Assert(to.Login).Equal("octocat") HTMLURL: github.Ptr("https://github.com/octocat/hello-world"),
g.Assert(to.Avatar).Equal("http://...") CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"),
}) Permissions: map[string]bool{
"push": true,
"pull": true,
"admin": true,
},
},
}
g.It("should convert team list", func() { to := convertRepoList(from)
from := []*github.Organization{ assert.Equal(t, "http://...", to[0].Avatar)
{ assert.Equal(t, "octocat/hello-world", to[0].FullName)
Login: github.Ptr("octocat"), assert.Equal(t, "octocat", to[0].Owner)
AvatarURL: github.Ptr("http://..."), assert.Equal(t, "hello-world", to[0].Name)
}, }
}
to := convertTeamList(from)
g.Assert(to[0].Login).Equal("octocat")
g.Assert(to[0].Avatar).Equal("http://...")
})
g.It("should convert a repository from webhook", func() { func Test_convertRepo(t *testing.T) {
from := &github.PushEventRepository{Owner: &github.User{}} from := github.Repository{
from.Owner.Login = github.Ptr("octocat") FullName: github.Ptr("octocat/hello-world"),
from.Owner.Name = github.Ptr("octocat") Name: github.Ptr("hello-world"),
from.Name = github.Ptr("hello-world") HTMLURL: github.Ptr("https://github.com/octocat/hello-world"),
from.FullName = github.Ptr("octocat/hello-world") CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"),
from.Private = github.Ptr(true) DefaultBranch: github.Ptr("develop"),
from.HTMLURL = github.Ptr("https://github.com/octocat/hello-world") Private: github.Ptr(true),
from.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git") Owner: &github.User{
from.DefaultBranch = github.Ptr("develop") AvatarURL: github.Ptr("http://..."),
Login: github.Ptr("octocat"),
},
Permissions: map[string]bool{
"push": true,
"pull": true,
"admin": true,
},
}
repo := convertRepoHook(from) to := convertRepo(&from)
g.Assert(repo.Owner).Equal(*from.Owner.Login) assert.Equal(t, "http://...", to.Avatar)
g.Assert(repo.Name).Equal(*from.Name) assert.Equal(t, "octocat/hello-world", to.FullName)
g.Assert(repo.FullName).Equal(*from.FullName) assert.Equal(t, "octocat", to.Owner)
g.Assert(repo.IsSCMPrivate).Equal(*from.Private) assert.Equal(t, "hello-world", to.Name)
g.Assert(repo.ForgeURL).Equal(*from.HTMLURL) assert.Equal(t, "develop", to.Branch)
g.Assert(repo.Clone).Equal(*from.CloneURL) assert.True(t, to.IsSCMPrivate)
g.Assert(repo.Branch).Equal(*from.DefaultBranch) assert.Equal(t, "https://github.com/octocat/hello-world.git", to.Clone)
}) assert.Equal(t, "https://github.com/octocat/hello-world", to.ForgeURL)
}
g.It("should convert a pull request from webhook", func() { func Test_convertPerm(t *testing.T) {
from := &github.PullRequestEvent{ from := &github.Repository{
Action: github.Ptr(actionOpen), Permissions: map[string]bool{
PullRequest: &github.PullRequest{ "admin": true,
State: github.Ptr(stateOpen), "push": true,
HTMLURL: github.Ptr("https://github.com/octocat/hello-world/pulls/42"), "pull": true,
Number: github.Ptr(42), },
Title: github.Ptr("Updated README.md"), }
Base: &github.PullRequestBranch{
Ref: github.Ptr("main"),
},
Head: &github.PullRequestBranch{
Ref: github.Ptr("changes"),
SHA: github.Ptr("f72fc19"),
Repo: &github.Repository{
CloneURL: github.Ptr("https://github.com/octocat/hello-world-fork"),
},
},
User: &github.User{
Login: github.Ptr("octocat"),
AvatarURL: github.Ptr("https://avatars1.githubusercontent.com/u/583231"),
},
}, Sender: &github.User{
Login: github.Ptr("octocat"),
},
}
pull, _, pipeline, err := parsePullHook(from, true)
g.Assert(err).IsNil()
g.Assert(pull).IsNotNil()
g.Assert(pipeline.Event).Equal(model.EventPull)
g.Assert(pipeline.Branch).Equal(*from.PullRequest.Base.Ref)
g.Assert(pipeline.Ref).Equal("refs/pull/42/merge")
g.Assert(pipeline.Refspec).Equal("changes:main")
g.Assert(pipeline.Commit).Equal(*from.PullRequest.Head.SHA)
g.Assert(pipeline.Message).Equal(*from.PullRequest.Title)
g.Assert(pipeline.Title).Equal(*from.PullRequest.Title)
g.Assert(pipeline.Author).Equal(*from.PullRequest.User.Login)
g.Assert(pipeline.Avatar).Equal(*from.PullRequest.User.AvatarURL)
g.Assert(pipeline.Sender).Equal(*from.Sender.Login)
})
g.It("should convert a deployment from webhook", func() { to := convertPerm(from.GetPermissions())
from := &github.DeploymentEvent{Deployment: &github.Deployment{}, Sender: &github.User{}} assert.True(t, to.Push)
from.Deployment.Description = github.Ptr(":shipit:") assert.True(t, to.Pull)
from.Deployment.Environment = github.Ptr("production") assert.True(t, to.Admin)
from.Deployment.Task = github.Ptr("deploy") }
from.Deployment.ID = github.Ptr(int64(42))
from.Deployment.Ref = github.Ptr("main")
from.Deployment.SHA = github.Ptr("f72fc19")
from.Deployment.URL = github.Ptr("https://github.com/octocat/hello-world")
from.Sender.Login = github.Ptr("octocat")
from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231")
_, pipeline := parseDeployHook(from) func Test_convertTeam(t *testing.T) {
g.Assert(pipeline.Event).Equal(model.EventDeploy) from := &github.Organization{
g.Assert(pipeline.Branch).Equal("main") Login: github.Ptr("octocat"),
g.Assert(pipeline.Ref).Equal("refs/heads/main") AvatarURL: github.Ptr("http://..."),
g.Assert(pipeline.Commit).Equal(*from.Deployment.SHA) }
g.Assert(pipeline.Message).Equal(*from.Deployment.Description) to := convertTeam(from)
g.Assert(pipeline.ForgeURL).Equal(*from.Deployment.URL) assert.Equal(t, "octocat", to.Login)
g.Assert(pipeline.Author).Equal(*from.Sender.Login) assert.Equal(t, "http://...", to.Avatar)
g.Assert(pipeline.Avatar).Equal(*from.Sender.AvatarURL) }
})
g.It("should convert a push from webhook", func() { func Test_convertTeamList(t *testing.T) {
from := &github.PushEvent{Sender: &github.User{}, Repo: &github.PushEventRepository{}, HeadCommit: &github.HeadCommit{Author: &github.CommitAuthor{}}} from := []*github.Organization{
from.Sender.Login = github.Ptr("octocat") {
from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231") Login: github.Ptr("octocat"),
from.Repo.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git") AvatarURL: github.Ptr("http://..."),
from.HeadCommit.Author.Email = github.Ptr("github.Ptr(octocat@github.com") },
from.HeadCommit.Message = github.Ptr("updated README.md") }
from.HeadCommit.URL = github.Ptr("https://github.com/octocat/hello-world") to := convertTeamList(from)
from.HeadCommit.ID = github.Ptr("f72fc19") assert.Equal(t, "octocat", to[0].Login)
from.Ref = github.Ptr("refs/heads/main") assert.Equal(t, "http://...", to[0].Avatar)
}
_, pipeline := parsePushHook(from) func Test_convertRepoHook(t *testing.T) {
g.Assert(pipeline.Event).Equal(model.EventPush) t.Run("should convert a repository from webhook", func(t *testing.T) {
g.Assert(pipeline.Branch).Equal("main") from := &github.PushEventRepository{Owner: &github.User{}}
g.Assert(pipeline.Ref).Equal("refs/heads/main") from.Owner.Login = github.Ptr("octocat")
g.Assert(pipeline.Commit).Equal(*from.HeadCommit.ID) from.Owner.Name = github.Ptr("octocat")
g.Assert(pipeline.Message).Equal(*from.HeadCommit.Message) from.Name = github.Ptr("hello-world")
g.Assert(pipeline.ForgeURL).Equal(*from.HeadCommit.URL) from.FullName = github.Ptr("octocat/hello-world")
g.Assert(pipeline.Author).Equal(*from.Sender.Login) from.Private = github.Ptr(true)
g.Assert(pipeline.Avatar).Equal(*from.Sender.AvatarURL) from.HTMLURL = github.Ptr("https://github.com/octocat/hello-world")
g.Assert(pipeline.Email).Equal(*from.HeadCommit.Author.Email) from.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git")
}) from.DefaultBranch = github.Ptr("develop")
g.It("should convert a tag from webhook", func() { repo := convertRepoHook(from)
from := &github.PushEvent{} assert.Equal(t, *from.Owner.Login, repo.Owner)
from.Ref = github.Ptr("refs/tags/v1.0.0") assert.Equal(t, *from.Name, repo.Name)
assert.Equal(t, *from.FullName, repo.FullName)
_, pipeline := parsePushHook(from) assert.Equal(t, *from.Private, repo.IsSCMPrivate)
g.Assert(pipeline.Event).Equal(model.EventTag) assert.Equal(t, *from.HTMLURL, repo.ForgeURL)
g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0") assert.Equal(t, *from.CloneURL, repo.Clone)
}) assert.Equal(t, *from.DefaultBranch, repo.Branch)
})
g.It("should convert tag's base branch from webhook to pipeline's branch ", func() { }
from := &github.PushEvent{}
from.Ref = github.Ptr("refs/tags/v1.0.0") func Test_parsePullHook(t *testing.T) {
from.BaseRef = github.Ptr("refs/heads/main") from := &github.PullRequestEvent{
Action: github.Ptr(actionOpen),
_, pipeline := parsePushHook(from) PullRequest: &github.PullRequest{
g.Assert(pipeline.Event).Equal(model.EventTag) State: github.Ptr(stateOpen),
g.Assert(pipeline.Branch).Equal("main") HTMLURL: github.Ptr("https://github.com/octocat/hello-world/pulls/42"),
}) Number: github.Ptr(42),
Title: github.Ptr("Updated README.md"),
g.It("should not convert tag's base_ref from webhook if not prefixed with 'ref/heads/'", func() { Base: &github.PullRequestBranch{
from := &github.PushEvent{} Ref: github.Ptr("main"),
from.Ref = github.Ptr("refs/tags/v1.0.0") },
from.BaseRef = github.Ptr("refs/refs/main") Head: &github.PullRequestBranch{
Ref: github.Ptr("changes"),
_, pipeline := parsePushHook(from) SHA: github.Ptr("f72fc19"),
g.Assert(pipeline.Event).Equal(model.EventTag) Repo: &github.Repository{
g.Assert(pipeline.Branch).Equal("refs/tags/v1.0.0") CloneURL: github.Ptr("https://github.com/octocat/hello-world-fork"),
}) },
},
User: &github.User{
Login: github.Ptr("octocat"),
AvatarURL: github.Ptr("https://avatars1.githubusercontent.com/u/583231"),
},
}, Sender: &github.User{
Login: github.Ptr("octocat"),
},
}
pull, _, pipeline, err := parsePullHook(from, true)
assert.NoError(t, err)
assert.NotNil(t, pull)
assert.Equal(t, model.EventPull, pipeline.Event)
assert.Equal(t, *from.PullRequest.Base.Ref, pipeline.Branch)
assert.Equal(t, "refs/pull/42/merge", pipeline.Ref)
assert.Equal(t, "changes:main", pipeline.Refspec)
assert.Equal(t, *from.PullRequest.Head.SHA, pipeline.Commit)
assert.Equal(t, *from.PullRequest.Title, pipeline.Message)
assert.Equal(t, *from.PullRequest.Title, pipeline.Title)
assert.Equal(t, *from.PullRequest.User.Login, pipeline.Author)
assert.Equal(t, *from.PullRequest.User.AvatarURL, pipeline.Avatar)
assert.Equal(t, *from.Sender.Login, pipeline.Sender)
}
func Test_parseDeployHook(t *testing.T) {
from := &github.DeploymentEvent{Deployment: &github.Deployment{}, Sender: &github.User{}}
from.Deployment.Description = github.Ptr(":shipit:")
from.Deployment.Environment = github.Ptr("production")
from.Deployment.Task = github.Ptr("deploy")
from.Deployment.ID = github.Ptr(int64(42))
from.Deployment.Ref = github.Ptr("main")
from.Deployment.SHA = github.Ptr("f72fc19")
from.Deployment.URL = github.Ptr("https://github.com/octocat/hello-world")
from.Sender.Login = github.Ptr("octocat")
from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231")
_, pipeline := parseDeployHook(from)
assert.Equal(t, model.EventDeploy, pipeline.Event)
assert.Equal(t, "main", pipeline.Branch)
assert.Equal(t, "refs/heads/main", pipeline.Ref)
assert.Equal(t, *from.Deployment.SHA, pipeline.Commit)
assert.Equal(t, *from.Deployment.Description, pipeline.Message)
assert.Equal(t, *from.Deployment.URL, pipeline.ForgeURL)
assert.Equal(t, *from.Sender.Login, pipeline.Author)
assert.Equal(t, *from.Sender.AvatarURL, pipeline.Avatar)
}
func Test_parsePushHook(t *testing.T) {
t.Run("convert push from webhook", func(t *testing.T) {
from := &github.PushEvent{Sender: &github.User{}, Repo: &github.PushEventRepository{}, HeadCommit: &github.HeadCommit{Author: &github.CommitAuthor{}}}
from.Sender.Login = github.Ptr("octocat")
from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231")
from.Repo.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git")
from.HeadCommit.Author.Email = github.Ptr("github.Ptr(octocat@github.com")
from.HeadCommit.Message = github.Ptr("updated README.md")
from.HeadCommit.URL = github.Ptr("https://github.com/octocat/hello-world")
from.HeadCommit.ID = github.Ptr("f72fc19")
from.Ref = github.Ptr("refs/heads/main")
_, pipeline := parsePushHook(from)
assert.Equal(t, model.EventPush, pipeline.Event)
assert.Equal(t, "main", pipeline.Branch)
assert.Equal(t, "refs/heads/main", pipeline.Ref)
assert.Equal(t, *from.HeadCommit.ID, pipeline.Commit)
assert.Equal(t, *from.HeadCommit.Message, pipeline.Message)
assert.Equal(t, *from.HeadCommit.URL, pipeline.ForgeURL)
assert.Equal(t, *from.Sender.Login, pipeline.Author)
assert.Equal(t, *from.Sender.AvatarURL, pipeline.Avatar)
assert.Equal(t, *from.HeadCommit.Author.Email, pipeline.Email)
})
t.Run("convert tag from webhook", func(t *testing.T) {
from := &github.PushEvent{}
from.Ref = github.Ptr("refs/tags/v1.0.0")
_, pipeline := parsePushHook(from)
assert.Equal(t, model.EventTag, pipeline.Event)
assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref)
})
t.Run("convert tag's base branch to pipeline's branch ", func(t *testing.T) {
from := &github.PushEvent{}
from.Ref = github.Ptr("refs/tags/v1.0.0")
from.BaseRef = github.Ptr("refs/heads/main")
_, pipeline := parsePushHook(from)
assert.Equal(t, model.EventTag, pipeline.Event)
assert.Equal(t, "main", pipeline.Branch)
})
t.Run("not convert tag's base_ref from webhook if not prefixed with 'ref/heads/'", func(t *testing.T) {
from := &github.PushEvent{}
from.Ref = github.Ptr("refs/tags/v1.0.0")
from.BaseRef = github.Ptr("refs/refs/main")
_, pipeline := parsePushHook(from)
assert.Equal(t, model.EventTag, pipeline.Event)
assert.Equal(t, "refs/tags/v1.0.0", pipeline.Branch)
}) })
} }

View File

@@ -20,13 +20,28 @@ import (
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/github/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/github/fixtures"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func TestNew(t *testing.T) {
forge, _ := New(Opts{
URL: "http://localhost:8080/",
Client: "0ZXh0IjoiI",
Secret: "I1NiIsInR5",
SkipVerify: true,
})
f, _ := forge.(*client)
assert.Equal(t, "http://localhost:8080", f.url)
assert.Equal(t, "http://localhost:8080/api/v3/", f.API)
assert.Equal(t, "0ZXh0IjoiI", f.Client)
assert.Equal(t, "I1NiIsInR5", f.Secret)
assert.True(t, f.SkipVerify)
}
func Test_github(t *testing.T) { func Test_github(t *testing.T) {
gin.SetMode(gin.TestMode) gin.SetMode(gin.TestMode)
@@ -36,80 +51,39 @@ func Test_github(t *testing.T) {
SkipVerify: true, SkipVerify: true,
}) })
defer s.Close()
ctx := context.Background() ctx := context.Background()
g := goblin.Goblin(t)
g.Describe("GitHub", func() {
g.After(func() {
s.Close()
})
g.Describe("Creating a forge", func() { t.Run("netrc with user token", func(t *testing.T) {
g.It("Should return client with specified options", func() { forge, _ := New(Opts{})
forge, _ := New(Opts{ netrc, _ := forge.Netrc(fakeUser, fakeRepo)
URL: "http://localhost:8080/", assert.Equal(t, "github.com", netrc.Machine)
Client: "0ZXh0IjoiI", assert.Equal(t, fakeUser.AccessToken, netrc.Login)
Secret: "I1NiIsInR5", assert.Equal(t, "x-oauth-basic", netrc.Password)
SkipVerify: true, })
}) t.Run("netrc with machine account", func(t *testing.T) {
f, _ := forge.(*client) forge, _ := New(Opts{})
g.Assert(f.url).Equal("http://localhost:8080") netrc, _ := forge.Netrc(nil, fakeRepo)
g.Assert(f.API).Equal("http://localhost:8080/api/v3/") assert.Equal(t, "github.com", netrc.Machine)
g.Assert(f.Client).Equal("0ZXh0IjoiI") assert.Empty(t, netrc.Login)
g.Assert(f.Secret).Equal("I1NiIsInR5") assert.Empty(t, netrc.Password)
g.Assert(f.SkipVerify).Equal(true) })
})
})
g.Describe("Generating a netrc file", func() { t.Run("Should return the repository details", func(t *testing.T) {
g.It("Should return a netrc with the user token", func() { repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name)
forge, _ := New(Opts{}) assert.NoError(t, err)
netrc, _ := forge.Netrc(fakeUser, fakeRepo) assert.Equal(t, fakeRepo.ForgeRemoteID, repo.ForgeRemoteID)
g.Assert(netrc.Machine).Equal("github.com") assert.Equal(t, fakeRepo.Owner, repo.Owner)
g.Assert(netrc.Login).Equal(fakeUser.AccessToken) assert.Equal(t, fakeRepo.Name, repo.Name)
g.Assert(netrc.Password).Equal("x-oauth-basic") assert.Equal(t, fakeRepo.FullName, repo.FullName)
}) assert.True(t, repo.IsSCMPrivate)
g.It("Should return a netrc with the machine account", func() { assert.Equal(t, fakeRepo.Clone, repo.Clone)
forge, _ := New(Opts{}) assert.Equal(t, fakeRepo.ForgeURL, repo.ForgeURL)
netrc, _ := forge.Netrc(nil, fakeRepo) })
g.Assert(netrc.Machine).Equal("github.com") t.Run("repo not found error", func(t *testing.T) {
g.Assert(netrc.Login).Equal("") _, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
g.Assert(netrc.Password).Equal("") assert.Error(t, err)
})
})
g.Describe("Requesting a repository", func() {
g.It("Should return the repository details", func() {
repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name)
g.Assert(err).IsNil()
g.Assert(repo.ForgeRemoteID).Equal(fakeRepo.ForgeRemoteID)
g.Assert(repo.Owner).Equal(fakeRepo.Owner)
g.Assert(repo.Name).Equal(fakeRepo.Name)
g.Assert(repo.FullName).Equal(fakeRepo.FullName)
g.Assert(repo.IsSCMPrivate).IsTrue()
g.Assert(repo.Clone).Equal(fakeRepo.Clone)
g.Assert(repo.ForgeURL).Equal(fakeRepo.ForgeURL)
})
g.It("Should handle a not found error", func() {
_, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
g.Assert(err).IsNotNil()
})
})
g.It("Should return a user repository list")
g.It("Should return a user team list")
g.It("Should register repository hooks")
g.It("Should return a repository file")
g.Describe("Given an authentication request", func() {
g.It("Should redirect to the GitHub login page")
g.It("Should create an access token")
g.It("Should handle an access token error")
g.It("Should return the authenticated user")
g.It("Should handle authentication errors")
})
}) })
} }

View File

@@ -22,7 +22,6 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/github/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/github/fixtures"
@@ -46,96 +45,85 @@ func testHookRequest(payload []byte, event string) *http.Request {
return req return req
} }
func Test_parser(t *testing.T) { func Test_parseHook(t *testing.T) {
g := goblin.Goblin(t) t.Run("ignore unsupported hook events", func(t *testing.T) {
g.Describe("GitHub parser", func() { req := testHookRequest([]byte(fixtures.HookPullRequest), "issues")
g.It("should ignore unsupported hook events", func() { p, r, b, err := parseHook(req, false)
req := testHookRequest([]byte(fixtures.HookPullRequest), "issues") assert.Nil(t, r)
p, r, b, err := parseHook(req, false) assert.Nil(t, b)
g.Assert(r).IsNil() assert.Nil(t, p)
g.Assert(b).IsNil() assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
g.Assert(p).IsNil() })
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
})
g.Describe("given a push hook", func() { t.Run("skip skip push hook when action is deleted", func(t *testing.T) {
g.It("should skip when action is deleted", func() { req := testHookRequest([]byte(fixtures.HookPushDeleted), hookPush)
req := testHookRequest([]byte(fixtures.HookPushDeleted), hookPush) p, r, b, err := parseHook(req, false)
p, r, b, err := parseHook(req, false) assert.Nil(t, r)
g.Assert(r).IsNil() assert.Nil(t, b)
g.Assert(b).IsNil() assert.NoError(t, err)
g.Assert(err).IsNil() assert.Nil(t, p)
g.Assert(p).IsNil() })
}) t.Run("push hook", func(t *testing.T) {
g.It("should extract repository and pipeline details", func() { req := testHookRequest([]byte(fixtures.HookPush), hookPush)
req := testHookRequest([]byte(fixtures.HookPush), hookPush) p, r, b, err := parseHook(req, false)
p, r, b, err := parseHook(req, false) assert.NoError(t, err)
g.Assert(err).IsNil() assert.Nil(t, p)
g.Assert(p).IsNil() assert.NotNil(t, r)
g.Assert(r).IsNotNil() assert.NotNil(t, b)
g.Assert(b).IsNotNil() assert.Equal(t, model.EventPush, b.Event)
g.Assert(b.Event).Equal(model.EventPush) sort.Strings(b.ChangedFiles)
sort.Strings(b.ChangedFiles) assert.Equal(t, []string{"pipeline/shared/replace_secrets.go", "pipeline/shared/replace_secrets_test.go"}, b.ChangedFiles)
g.Assert(b.ChangedFiles).Equal([]string{"pipeline/shared/replace_secrets.go", "pipeline/shared/replace_secrets_test.go"}) })
})
})
g.Describe("given a pull request hook", func() { t.Run("PR hook", func(t *testing.T) {
g.It("should handle a PR hook when PR got opened or pushed to", func() { req := testHookRequest([]byte(fixtures.HookPullRequest), hookPull)
req := testHookRequest([]byte(fixtures.HookPullRequest), hookPull) p, r, b, err := parseHook(req, false)
p, r, b, err := parseHook(req, false) assert.NoError(t, err)
g.Assert(err).IsNil() assert.NotNil(t, r)
g.Assert(r).IsNotNil() assert.NotNil(t, b)
g.Assert(b).IsNotNil() assert.NotNil(t, p)
g.Assert(p).IsNotNil() assert.Equal(t, model.EventPull, b.Event)
g.Assert(b.Event).Equal(model.EventPull) })
}) t.Run("PR closed hook", func(t *testing.T) {
g.It("should handle a PR closed hook when PR got closed", func() { req := testHookRequest([]byte(fixtures.HookPullRequestClosed), hookPull)
req := testHookRequest([]byte(fixtures.HookPullRequestClosed), hookPull) p, r, b, err := parseHook(req, false)
p, r, b, err := parseHook(req, false) assert.NoError(t, err)
g.Assert(err).IsNil() assert.NotNil(t, r)
g.Assert(r).IsNotNil() assert.NotNil(t, b)
g.Assert(b).IsNotNil() assert.NotNil(t, p)
g.Assert(p).IsNotNil() assert.Equal(t, model.EventPullClosed, b.Event)
g.Assert(b.Event).Equal(model.EventPullClosed) })
}) t.Run("PR merged hook", func(t *testing.T) {
g.It("should handle a PR closed hook when PR got merged", func() { req := testHookRequest([]byte(fixtures.HookPullRequestMerged), hookPull)
req := testHookRequest([]byte(fixtures.HookPullRequestMerged), hookPull) p, r, b, err := parseHook(req, false)
p, r, b, err := parseHook(req, false) assert.NoError(t, err)
g.Assert(err).IsNil() assert.NotNil(t, r)
g.Assert(r).IsNotNil() assert.NotNil(t, b)
g.Assert(b).IsNotNil() assert.NotNil(t, p)
g.Assert(p).IsNotNil() assert.Equal(t, model.EventPullClosed, b.Event)
g.Assert(b.Event).Equal(model.EventPullClosed) })
})
})
g.Describe("given a deployment hook", func() { t.Run("deploy hook", func(t *testing.T) {
g.It("should extract repository and pipeline details", func() { req := testHookRequest([]byte(fixtures.HookDeploy), hookDeploy)
req := testHookRequest([]byte(fixtures.HookDeploy), hookDeploy) p, r, b, err := parseHook(req, false)
p, r, b, err := parseHook(req, false) assert.NoError(t, err)
g.Assert(err).IsNil() assert.NotNil(t, r)
g.Assert(r).IsNotNil() assert.NotNil(t, b)
g.Assert(b).IsNotNil() assert.Nil(t, p)
g.Assert(p).IsNil() assert.Equal(t, model.EventDeploy, b.Event)
g.Assert(b.Event).Equal(model.EventDeploy) assert.Equal(t, "production", b.DeployTo)
g.Assert(b.DeployTo).Equal("production") assert.Equal(t, "deploy", b.DeployTask)
g.Assert(b.DeployTask).Equal("deploy") })
})
})
g.Describe("given a release hook", func() { t.Run("release hook", func(t *testing.T) {
g.It("should extract repository and build details", func() { req := testHookRequest([]byte(fixtures.HookRelease), hookRelease)
req := testHookRequest([]byte(fixtures.HookRelease), hookRelease) p, r, b, err := parseHook(req, false)
p, r, b, err := parseHook(req, false) assert.NoError(t, err)
g.Assert(err).IsNil() assert.NotNil(t, r)
g.Assert(r).IsNotNil() assert.NotNil(t, b)
g.Assert(b).IsNotNil() assert.Nil(t, p)
g.Assert(p).IsNil() assert.Equal(t, model.EventRelease, b.Event)
g.Assert(b.Event).Equal(model.EventRelease) assert.Len(t, strings.Split(b.Ref, "/"), 3)
g.Assert(len(strings.Split(b.Ref, "/")) == 3).IsTrue() assert.True(t, strings.HasPrefix(b.Ref, "refs/tags/"))
g.Assert(strings.HasPrefix(b.Ref, "refs/tags/")).IsTrue()
})
})
}) })
} }

View File

@@ -23,7 +23,6 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/gitlab/testdata" "go.woodpecker-ci.org/woodpecker/v3/server/forge/gitlab/testdata"
@@ -70,234 +69,214 @@ func Test_GitLab(t *testing.T) {
} }
ctx := context.Background() ctx := context.Background()
g := goblin.Goblin(t) // Test projects method
g.Describe("GitLab Plugin", func() { t.Run("Should return only non-archived projects is hidden", func(t *testing.T) {
// Test projects method client.HideArchives = true
g.Describe("AllProjects", func() { _projects, err := client.Repos(ctx, &user)
g.It("Should return only non-archived projects is hidden", func() { assert.NoError(t, err)
client.HideArchives = true assert.Len(t, _projects, 1)
_projects, err := client.Repos(ctx, &user) })
assert.NoError(t, err)
assert.Len(t, _projects, 1)
})
g.It("Should return all the projects", func() { t.Run("Should return all the projects", func(t *testing.T) {
client.HideArchives = false client.HideArchives = false
_projects, err := client.Repos(ctx, &user) _projects, err := client.Repos(ctx, &user)
g.Assert(err).IsNil() assert.NoError(t, err)
g.Assert(len(_projects)).Equal(2) assert.Len(t, _projects, 2)
}) })
})
// Test repository method // Test repository method
g.Describe("Repo", func() { t.Run("Should return valid repo", func(t *testing.T) {
g.It("Should return valid repo", func() { _repo, err := client.Repo(ctx, &user, "0", "diaspora", "diaspora-client")
_repo, err := client.Repo(ctx, &user, "0", "diaspora", "diaspora-client") assert.NoError(t, err)
assert.NoError(t, err) assert.Equal(t, "diaspora-client", _repo.Name)
assert.Equal(t, "diaspora-client", _repo.Name) assert.Equal(t, "diaspora", _repo.Owner)
assert.Equal(t, "diaspora", _repo.Owner) assert.True(t, _repo.IsSCMPrivate)
assert.True(t, _repo.IsSCMPrivate) })
})
g.It("Should return error, when repo not exist", func() { t.Run("Should return error, when repo not exist", func(t *testing.T) {
_, err := client.Repo(ctx, &user, "0", "not-existed", "not-existed") _, err := client.Repo(ctx, &user, "0", "not-existed", "not-existed")
assert.Error(t, err) assert.Error(t, err)
}) })
g.It("Should return repo with push access, when user inherits membership from namespace", func() { t.Run("Should return repo with push access, when user inherits membership from namespace", func(t *testing.T) {
_repo, err := client.Repo(ctx, &user, "6", "brightbox", "puppet") _repo, err := client.Repo(ctx, &user, "6", "brightbox", "puppet")
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, _repo.Perm.Push) assert.True(t, _repo.Perm.Push)
}) })
})
// Test activate method // Test activate method
g.Describe("Activate", func() { t.Run("Activate, success", func(t *testing.T) {
g.It("Should be success", func() { err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token")
err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token") assert.NoError(t, err)
assert.NoError(t, err) })
})
g.It("Should be failed, when token not given", func() { t.Run("Activate, failed no token", func(t *testing.T) {
err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook") err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook")
g.Assert(err).IsNotNil() assert.Error(t, err)
}) })
})
// Test deactivate method // Test deactivate method
g.Describe("Deactivate", func() { t.Run("Deactivate", func(t *testing.T) {
g.It("Should be success", func() { err := client.Deactivate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token")
err := client.Deactivate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token") assert.NoError(t, err)
})
g.Assert(err).IsNil() // Test hook method
}) t.Run("parse push hook", func(t *testing.T) {
}) req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPush),
)
req.Header = testdata.ServiceHookHeaders
// Test hook method hookRepo, pipeline, err := client.Hook(ctx, req)
g.Describe("Hook", func() { assert.NoError(t, err)
g.Describe("Push hook", func() { if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
g.It("Should parse actual push hook", func() { assert.Equal(t, pipeline.Event, model.EventPush)
req, _ := http.NewRequest( assert.Equal(t, "test", hookRepo.Owner)
testdata.ServiceHookMethod, assert.Equal(t, "woodpecker", hookRepo.Name)
testdata.ServiceHookURL.String(), assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
bytes.NewReader(testdata.HookPush), assert.Equal(t, "develop", hookRepo.Branch)
) assert.Equal(t, "refs/heads/main", pipeline.Ref)
req.Header = testdata.ServiceHookHeaders assert.Equal(t, []string{"cmd/cli/main.go"}, pipeline.ChangedFiles)
assert.Equal(t, model.EventPush, pipeline.Event)
}
})
hookRepo, pipeline, err := client.Hook(ctx, req) t.Run("tag push hook", func(t *testing.T) {
assert.NoError(t, err) req, _ := http.NewRequest(
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { testdata.ServiceHookMethod,
assert.Equal(t, pipeline.Event, model.EventPush) testdata.ServiceHookURL.String(),
assert.Equal(t, "test", hookRepo.Owner) bytes.NewReader(testdata.HookTag),
assert.Equal(t, "woodpecker", hookRepo.Name) )
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) req.Header = testdata.ServiceHookHeaders
assert.Equal(t, "develop", hookRepo.Branch)
assert.Equal(t, "refs/heads/main", pipeline.Ref)
assert.Equal(t, []string{"cmd/cli/main.go"}, pipeline.ChangedFiles)
assert.Equal(t, model.EventPush, pipeline.Event)
}
})
})
g.Describe("Tag push hook", func() { hookRepo, pipeline, err := client.Hook(ctx, req)
g.It("Should parse tag push hook", func() { assert.NoError(t, err)
req, _ := http.NewRequest( if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
testdata.ServiceHookMethod, assert.Equal(t, "test", hookRepo.Owner)
testdata.ServiceHookURL.String(), assert.Equal(t, "woodpecker", hookRepo.Name)
bytes.NewReader(testdata.HookTag), assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
) assert.Equal(t, "develop", hookRepo.Branch)
req.Header = testdata.ServiceHookHeaders assert.Equal(t, "refs/tags/v22", pipeline.Ref)
assert.Len(t, pipeline.ChangedFiles, 0)
assert.Equal(t, model.EventTag, pipeline.Event)
}
})
hookRepo, pipeline, err := client.Hook(ctx, req) t.Run("merge request hook", func(t *testing.T) {
assert.NoError(t, err) req, _ := http.NewRequest(
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { testdata.ServiceHookMethod,
assert.Equal(t, "test", hookRepo.Owner) testdata.ServiceHookURL.String(),
assert.Equal(t, "woodpecker", hookRepo.Name) bytes.NewReader(testdata.HookPullRequest),
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) )
assert.Equal(t, "develop", hookRepo.Branch) req.Header = testdata.ServiceHookHeaders
assert.Equal(t, "refs/tags/v22", pipeline.Ref)
assert.Len(t, pipeline.ChangedFiles, 0)
assert.Equal(t, model.EventTag, pipeline.Event)
}
})
})
g.Describe("Merge request hook", func() { // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
g.It("Should parse merge request hook", func() { hookRepo, pipeline, err := client.Hook(ctx, req)
req, _ := http.NewRequest( assert.NoError(t, err)
testdata.ServiceHookMethod, if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
testdata.ServiceHookURL.String(), assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
bytes.NewReader(testdata.HookPullRequest), assert.Equal(t, "main", hookRepo.Branch)
) assert.Equal(t, "anbraten", hookRepo.Owner)
req.Header = testdata.ServiceHookHeaders assert.Equal(t, "woodpecker", hookRepo.Name)
assert.Equal(t, "Update client.go 🎉", pipeline.Title)
assert.Len(t, pipeline.ChangedFiles, 0) // see L217
assert.Equal(t, model.EventPull, pipeline.Event)
}
})
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles t.Run("ignore merge request hook without changes", func(t *testing.T) {
hookRepo, pipeline, err := client.Hook(ctx, req) req, _ := http.NewRequest(
assert.NoError(t, err) testdata.ServiceHookMethod,
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { testdata.ServiceHookURL.String(),
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) bytes.NewReader(testdata.HookPullRequestWithoutChanges),
assert.Equal(t, "main", hookRepo.Branch) )
assert.Equal(t, "anbraten", hookRepo.Owner) req.Header = testdata.ServiceHookHeaders
assert.Equal(t, "woodpecker", hookRepo.Name)
assert.Equal(t, "Update client.go 🎉", pipeline.Title)
assert.Len(t, pipeline.ChangedFiles, 0) // see L217
assert.Equal(t, model.EventPull, pipeline.Event)
}
})
g.It("Should ignore merge request hook without changes", func() { // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
req, _ := http.NewRequest( hookRepo, pipeline, err := client.Hook(ctx, req)
testdata.ServiceHookMethod, assert.Nil(t, hookRepo)
testdata.ServiceHookURL.String(), assert.Nil(t, pipeline)
bytes.NewReader(testdata.HookPullRequestWithoutChanges), assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
) })
req.Header = testdata.ServiceHookHeaders
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles t.Run("ignore merge request approval", func(t *testing.T) {
hookRepo, pipeline, err := client.Hook(ctx, req) req, _ := http.NewRequest(
assert.Nil(t, hookRepo) testdata.ServiceHookMethod,
assert.Nil(t, pipeline) testdata.ServiceHookURL.String(),
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) bytes.NewReader(testdata.HookPullRequestApproved),
}) )
req.Header = testdata.ServiceHookHeaders
g.It("Should ignore merge request approval", func() { // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
req, _ := http.NewRequest( hookRepo, pipeline, err := client.Hook(ctx, req)
testdata.ServiceHookMethod, assert.Nil(t, hookRepo)
testdata.ServiceHookURL.String(), assert.Nil(t, pipeline)
bytes.NewReader(testdata.HookPullRequestApproved), assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
) })
req.Header = testdata.ServiceHookHeaders
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles t.Run("parse merge request closed", func(t *testing.T) {
hookRepo, pipeline, err := client.Hook(ctx, req) req, _ := http.NewRequest(
assert.Nil(t, hookRepo) testdata.ServiceHookMethod,
assert.Nil(t, pipeline) testdata.ServiceHookURL.String(),
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) bytes.NewReader(testdata.HookPullRequestClosed),
}) )
req.Header = testdata.ServiceHookHeaders
g.It("Should parse merge request hook when MR closed", func() { // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
req, _ := http.NewRequest( hookRepo, pipeline, err := client.Hook(ctx, req)
testdata.ServiceHookMethod, assert.NoError(t, err)
testdata.ServiceHookURL.String(), if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
bytes.NewReader(testdata.HookPullRequestClosed), assert.Equal(t, "main", hookRepo.Branch)
) assert.Equal(t, "anbraten", hookRepo.Owner)
req.Header = testdata.ServiceHookHeaders assert.Equal(t, "woodpecker-test", hookRepo.Name)
assert.Equal(t, "Add new file", pipeline.Title)
assert.Len(t, pipeline.ChangedFiles, 0) // see L217
assert.Equal(t, model.EventPullClosed, pipeline.Event)
}
})
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles t.Run("parse merge request merged", func(t *testing.T) {
hookRepo, pipeline, err := client.Hook(ctx, req) req, _ := http.NewRequest(
assert.NoError(t, err) testdata.ServiceHookMethod,
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { testdata.ServiceHookURL.String(),
assert.Equal(t, "main", hookRepo.Branch) bytes.NewReader(testdata.HookPullRequestMerged),
assert.Equal(t, "anbraten", hookRepo.Owner) )
assert.Equal(t, "woodpecker-test", hookRepo.Name) req.Header = testdata.ServiceHookHeaders
assert.Equal(t, "Add new file", pipeline.Title)
assert.Len(t, pipeline.ChangedFiles, 0) // see L217
assert.Equal(t, model.EventPullClosed, pipeline.Event)
}
})
g.It("Should parse merge request hook when merged", func() { // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
req, _ := http.NewRequest( hookRepo, pipeline, err := client.Hook(ctx, req)
testdata.ServiceHookMethod, assert.NoError(t, err)
testdata.ServiceHookURL.String(), if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
bytes.NewReader(testdata.HookPullRequestMerged), assert.Equal(t, "main", hookRepo.Branch)
) assert.Equal(t, "anbraten", hookRepo.Owner)
req.Header = testdata.ServiceHookHeaders assert.Equal(t, "woodpecker-test", hookRepo.Name)
assert.Equal(t, "Add new file", pipeline.Title)
assert.Len(t, pipeline.ChangedFiles, 0) // see L217
assert.Equal(t, model.EventPullClosed, pipeline.Event)
}
})
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles t.Run("release hook", func(t *testing.T) {
hookRepo, pipeline, err := client.Hook(ctx, req) req, _ := http.NewRequest(
assert.NoError(t, err) testdata.ServiceHookMethod,
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { testdata.ServiceHookURL.String(),
assert.Equal(t, "main", hookRepo.Branch) bytes.NewReader(testdata.WebhookReleaseBody),
assert.Equal(t, "anbraten", hookRepo.Owner) )
assert.Equal(t, "woodpecker-test", hookRepo.Name) req.Header = testdata.ReleaseHookHeaders
assert.Equal(t, "Add new file", pipeline.Title)
assert.Len(t, pipeline.ChangedFiles, 0) // see L217
assert.Equal(t, model.EventPullClosed, pipeline.Event)
}
})
g.It("Should parse release request hook", func() { hookRepo, pipeline, err := client.Hook(ctx, req)
req, _ := http.NewRequest( assert.NoError(t, err)
testdata.ServiceHookMethod, if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
testdata.ServiceHookURL.String(), assert.Equal(t, "refs/tags/0.0.2", pipeline.Ref)
bytes.NewReader(testdata.WebhookReleaseBody), assert.Equal(t, "ci", hookRepo.Name)
) assert.Equal(t, "created release Awesome version 0.0.2", pipeline.Message)
req.Header = testdata.ReleaseHookHeaders assert.Equal(t, model.EventRelease, pipeline.Event)
}
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "refs/tags/0.0.2", pipeline.Ref)
assert.Equal(t, "ci", hookRepo.Name)
assert.Equal(t, "created release Awesome version 0.0.2", pipeline.Message)
assert.Equal(t, model.EventRelease, pipeline.Event)
}
})
})
})
}) })
} }

View File

@@ -19,7 +19,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
@@ -30,92 +29,87 @@ import (
) )
func TestRegisterAgent(t *testing.T) { func TestRegisterAgent(t *testing.T) {
g := goblin.Goblin(t) t.Run("When existing agent Name is empty it should update Name with hostname from metadata", func(t *testing.T) {
g.Describe("When existing agent Name is empty", func() { store := mocks_store.NewStore(t)
g.It("Should update Name with hostname from metadata", func() { storeAgent := new(model.Agent)
store := mocks_store.NewStore(t) storeAgent.ID = 1337
storeAgent := new(model.Agent) updatedAgent := model.Agent{
storeAgent.ID = 1337 ID: 1337,
updatedAgent := model.Agent{ Created: 0,
ID: 1337, Updated: 0,
Created: 0, Name: "hostname",
Updated: 0, OwnerID: 0,
Name: "hostname", Token: "",
OwnerID: 0, LastContact: 0,
Token: "", Platform: "platform",
LastContact: 0, Backend: "backend",
Platform: "platform", Capacity: 2,
Backend: "backend", Version: "version",
Capacity: 2, NoSchedule: false,
Version: "version", }
NoSchedule: false,
}
store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil) store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil)
store.On("AgentUpdate", &updatedAgent).Once().Return(nil) store.On("AgentUpdate", &updatedAgent).Once().Return(nil)
grpc := RPC{ grpc := RPC{
store: store, store: store,
} }
ctx := metadata.NewIncomingContext( ctx := metadata.NewIncomingContext(
context.Background(), context.Background(),
metadata.Pairs("hostname", "hostname", "agent_id", "1337"), metadata.Pairs("hostname", "hostname", "agent_id", "1337"),
) )
agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{ agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{
Version: "version", Version: "version",
Platform: "platform", Platform: "platform",
Backend: "backend", Backend: "backend",
Capacity: 2, Capacity: 2,
})
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
}) })
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
}) })
g.Describe("When existing agent hostname is present", func() { t.Run("When existing agent hostname is present it should not update the hostname", func(t *testing.T) {
g.It("Should not update the hostname", func() { store := mocks_store.NewStore(t)
store := mocks_store.NewStore(t) storeAgent := new(model.Agent)
storeAgent := new(model.Agent) storeAgent.ID = 1337
storeAgent.ID = 1337 storeAgent.Name = "originalHostname"
storeAgent.Name = "originalHostname" updatedAgent := model.Agent{
updatedAgent := model.Agent{ ID: 1337,
ID: 1337, Created: 0,
Created: 0, Updated: 0,
Updated: 0, Name: "originalHostname",
Name: "originalHostname", OwnerID: 0,
OwnerID: 0, Token: "",
Token: "", LastContact: 0,
LastContact: 0, Platform: "platform",
Platform: "platform", Backend: "backend",
Backend: "backend", Capacity: 2,
Capacity: 2, Version: "version",
Version: "version", NoSchedule: false,
NoSchedule: false, }
}
store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil) store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil)
store.On("AgentUpdate", &updatedAgent).Once().Return(nil) store.On("AgentUpdate", &updatedAgent).Once().Return(nil)
grpc := RPC{ grpc := RPC{
store: store, store: store,
} }
ctx := metadata.NewIncomingContext( ctx := metadata.NewIncomingContext(
context.Background(), context.Background(),
metadata.Pairs("hostname", "newHostname", "agent_id", "1337"), metadata.Pairs("hostname", "newHostname", "agent_id", "1337"),
) )
agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{ agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{
Version: "version", Version: "version",
Platform: "platform", Platform: "platform",
Backend: "backend", Backend: "backend",
Capacity: 2, Capacity: 2,
})
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
}) })
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
}) })
} }

View File

@@ -17,90 +17,90 @@ package model
import ( import (
"testing" "testing"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
) )
func TestSecretValidate(t *testing.T) { func TestSecretValidate(t *testing.T) {
g := goblin.Goblin(t) tests := []struct {
g.Describe("Secret", func() { s Secret
g.It("should pass validation", func() { err bool
secret := Secret{ }{
{
s: Secret{
Name: "secretname", Name: "secretname",
Value: "secretvalue", Value: "secretvalue",
Events: []WebhookEvent{EventPush}, Events: []WebhookEvent{EventPush},
Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"},
} },
err := secret.Validate() err: false,
g.Assert(err).IsNil() },
}) {
g.Describe("should fail validation", func() { s: Secret{
g.It("when no name", func() { Value: "secretvalue",
secret := Secret{ Events: []WebhookEvent{EventPush},
Value: "secretvalue", Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"},
Events: []WebhookEvent{EventPush}, },
Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, err: true,
} },
err := secret.Validate() {
g.Assert(err).IsNotNil() s: Secret{
}) Name: "secretname",
g.It("when no value", func() { Events: []WebhookEvent{EventPush},
secret := Secret{ Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"},
Name: "secretname", },
Events: []WebhookEvent{EventPush}, err: true,
Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, },
} {
err := secret.Validate() s: Secret{
g.Assert(err).IsNotNil() Name: "secretname",
}) Value: "secretvalue",
g.It("when no events", func() { Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"},
secret := Secret{ },
Name: "secretname", err: true,
Value: "secretvalue", },
Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, {
} s: Secret{
err := secret.Validate() Name: "secretname",
g.Assert(err).IsNotNil() Value: "secretvalue",
}) Events: []WebhookEvent{EventPush},
g.It("wrong image: no value", func() { Images: []string{"wrong image:no"},
secret := Secret{ },
Name: "secretname", err: true,
Value: "secretvalue", },
Events: []WebhookEvent{EventPush}, {
Images: []string{"wrong image:no"}, s: Secret{
} Name: "secretname",
err := secret.Validate() Value: "secretvalue",
g.Assert(err).IsNotNil() Events: []WebhookEvent{EventPush},
}) Images: []string{"/library/mysql:latest", ":8443/mysql:latest", ":8443/library/mysql:latest", "/library/mysql", ":8443/mysql", ":8443/library/mysql"},
g.It("wrong image: no hostname", func() { },
secret := Secret{ err: true,
Name: "secretname", },
Value: "secretvalue", {
Events: []WebhookEvent{EventPush}, s: Secret{
Images: []string{"/library/mysql:latest", ":8443/mysql:latest", ":8443/library/mysql:latest", "/library/mysql", ":8443/mysql", ":8443/library/mysql"}, Name: "secretname",
} Value: "secretvalue",
err := secret.Validate() Events: []WebhookEvent{EventPush},
g.Assert(err).IsNotNil() Images: []string{"localregistry.test:/mysql:latest", "localregistry.test:/mysql"},
}) },
g.It("wrong image: no port number", func() { err: true,
secret := Secret{ },
Name: "secretname", {
Value: "secretvalue", s: Secret{
Events: []WebhookEvent{EventPush}, Name: "secretname",
Images: []string{"localregistry.test:/mysql:latest", "localregistry.test:/mysql"}, Value: "secretvalue",
} Events: []WebhookEvent{EventPush},
err := secret.Validate() Images: []string{"docker.io/library/mysql:", "alpine:", "localregistry.test:8443/mysql:", "localregistry.test:8443/library/mysql:"},
g.Assert(err).IsNotNil() },
}) err: true,
g.It("wrong image: no tag name", func() { },
secret := Secret{ }
Name: "secretname", for i, tt := range tests {
Value: "secretvalue", err := tt.s.Validate()
Events: []WebhookEvent{EventPush}, if tt.err {
Images: []string{"docker.io/library/mysql:", "alpine:", "localregistry.test:8443/mysql:", "localregistry.test:8443/library/mysql:"}, assert.Errorf(t, err, "expected secret validation error on index %d", i)
} } else {
err := secret.Validate() assert.NoErrorf(t, err, "unexpected secret validation error on index %d", i)
g.Assert(err).IsNotNil() }
}) }
})
})
} }

View File

@@ -17,7 +17,7 @@ package secret_test
import ( import (
"testing" "testing"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/mock"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
@@ -25,12 +25,8 @@ import (
mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks" mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks"
) )
func TestSecretListPipeline(t *testing.T) { var (
g := goblin.Goblin(t) globalSecret = &model.Secret{
mockStore := mocks_store.NewStore(t)
// global secret
globalSecret := &model.Secret{
ID: 1, ID: 1,
OrgID: 0, OrgID: 0,
RepoID: 0, RepoID: 0,
@@ -38,8 +34,7 @@ func TestSecretListPipeline(t *testing.T) {
Value: "value-global", Value: "value-global",
} }
// org secret orgSecret = &model.Secret{
orgSecret := &model.Secret{
ID: 2, ID: 2,
OrgID: 1, OrgID: 1,
RepoID: 0, RepoID: 0,
@@ -47,53 +42,48 @@ func TestSecretListPipeline(t *testing.T) {
Value: "value-org", Value: "value-org",
} }
// repo secret repoSecret = &model.Secret{
repoSecret := &model.Secret{
ID: 3, ID: 3,
OrgID: 0, OrgID: 0,
RepoID: 1, RepoID: 1,
Name: "secret", Name: "secret",
Value: "value-repo", Value: "value-repo",
} }
)
g.Describe("Priority of secrets", func() { func TestSecretListPipeline(t *testing.T) {
g.It("should get the repo secret", func() { mockStore := mocks_store.NewStore(t)
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
globalSecret,
orgSecret,
repoSecret,
}, nil)
s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
g.Assert(err).IsNil() globalSecret,
orgSecret,
repoSecret,
}, nil)
g.Assert(len(s)).Equal(1) s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
g.Assert(s[0].Value).Equal("value-repo") assert.NoError(t, err)
})
g.It("should get the org secret", func() { assert.Len(t, s, 1)
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ assert.Equal(t, "value-repo", s[0].Value)
globalSecret,
orgSecret,
}, nil)
s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
g.Assert(err).IsNil() globalSecret,
orgSecret,
}, nil)
g.Assert(len(s)).Equal(1) s, err = secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
g.Assert(s[0].Value).Equal("value-org") assert.NoError(t, err)
})
g.It("should get the global secret", func() { assert.Len(t, s, 1)
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ assert.Equal(t, "value-org", s[0].Value)
globalSecret,
}, nil)
s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
g.Assert(err).IsNil() globalSecret,
}, nil)
g.Assert(len(s)).Equal(1) s, err = secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
g.Assert(s[0].Value).Equal("value-global") assert.NoError(t, err)
})
}) assert.Len(t, s, 1)
assert.Equal(t, "value-global", s[0].Value)
} }

View File

@@ -16,11 +16,9 @@
package datastore package datastore
import ( import (
"fmt"
"testing" "testing"
"time" "time"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
@@ -38,275 +36,170 @@ func TestPipelines(t *testing.T) {
store, closer := newTestStore(t, new(model.Repo), new(model.Step), new(model.Pipeline)) store, closer := newTestStore(t, new(model.Repo), new(model.Step), new(model.Pipeline))
defer closer() defer closer()
g := goblin.Goblin(t) assert.NoError(t, store.CreateRepo(repo))
g.Describe("Pipelines", func() {
g.Before(func() {
_, err := store.engine.Exec("DELETE FROM repos")
g.Assert(err).IsNil()
g.Assert(store.CreateRepo(repo)).IsNil()
})
g.After(func() {
_, err := store.engine.Exec("DELETE FROM repos")
g.Assert(err).IsNil()
})
// before each test be sure to purge the package // Fail when the repo is not existing
// table data from the database. pipeline := model.Pipeline{
g.BeforeEach(func() { RepoID: 100,
_, err := store.engine.Exec("DELETE FROM pipelines") Status: model.StatusSuccess,
g.Assert(err).IsNil() }
_, err = store.engine.Exec("DELETE FROM steps") err := store.CreatePipeline(&pipeline)
g.Assert(err).IsNil() assert.Error(t, err)
})
g.It("Should Fail early when the repo is not existing", func() { count, err := store.GetPipelineCount()
pipeline := model.Pipeline{ assert.NoError(t, err)
RepoID: 100, assert.Zero(t, count)
Status: model.StatusSuccess,
}
err := store.CreatePipeline(&pipeline)
g.Assert(err).IsNotNil()
count, err := store.GetPipelineCount() // add pipeline
g.Assert(err).IsNil() pipeline = model.Pipeline{
g.Assert(count == 0).IsTrue() RepoID: repo.ID,
fmt.Println("GOT COUNT", count) Status: model.StatusSuccess,
}) Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac",
Branch: "some-branch",
}
err = store.CreatePipeline(&pipeline)
assert.NoError(t, err)
assert.NotZero(t, pipeline.ID)
assert.EqualValues(t, 1, pipeline.Number)
assert.Equal(t, "85f8c029b902ed9400bc600bac301a0aadb144ac", pipeline.Commit)
g.It("Should Post a Pipeline", func() { count, err = store.GetPipelineCount()
pipeline := model.Pipeline{ assert.NoError(t, err)
RepoID: repo.ID, assert.NotZero(t, count)
Status: model.StatusSuccess,
Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
err := store.CreatePipeline(&pipeline)
g.Assert(err).IsNil()
g.Assert(pipeline.ID != 0).IsTrue()
g.Assert(pipeline.Number).Equal(int64(1))
g.Assert(pipeline.Commit).Equal("85f8c029b902ed9400bc600bac301a0aadb144ac")
count, err := store.GetPipelineCount() GetPipeline, err := store.GetPipeline(pipeline.ID)
g.Assert(err).IsNil() assert.NoError(t, err)
g.Assert(count > 0).IsTrue() assert.Equal(t, pipeline.ID, GetPipeline.ID)
fmt.Println("GOT COUNT", count) assert.Equal(t, pipeline.RepoID, GetPipeline.RepoID)
}) assert.Equal(t, pipeline.Status, GetPipeline.Status)
g.It("Should Put a Pipeline", func() { // update pipeline
pipeline := model.Pipeline{ pipeline.Status = model.StatusRunning
RepoID: repo.ID, err1 := store.UpdatePipeline(&pipeline)
Number: 5, GetPipeline, err2 := store.GetPipeline(pipeline.ID)
Status: model.StatusSuccess, assert.NoError(t, err1)
Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", assert.NoError(t, err2)
} assert.Equal(t, pipeline.ID, GetPipeline.ID)
err := store.CreatePipeline(&pipeline) assert.Equal(t, pipeline.RepoID, GetPipeline.RepoID)
g.Assert(err).IsNil() assert.Equal(t, pipeline.Status, GetPipeline.Status)
pipeline.Status = model.StatusRunning assert.Equal(t, pipeline.Number, GetPipeline.Number)
err1 := store.UpdatePipeline(&pipeline)
GetPipeline, err2 := store.GetPipeline(pipeline.ID)
g.Assert(err1).IsNil()
g.Assert(err2).IsNil()
g.Assert(pipeline.ID).Equal(GetPipeline.ID)
g.Assert(pipeline.RepoID).Equal(GetPipeline.RepoID)
g.Assert(pipeline.Status).Equal(GetPipeline.Status)
g.Assert(pipeline.Number).Equal(GetPipeline.Number)
})
g.It("Should Get a Pipeline", func() { pipeline2 := &model.Pipeline{
pipeline := model.Pipeline{ RepoID: repo.ID,
RepoID: repo.ID, Status: model.StatusPending,
Status: model.StatusSuccess, Event: model.EventPush,
} Branch: "main",
err := store.CreatePipeline(&pipeline, []*model.Step{}...) }
g.Assert(err).IsNil() err2 = store.CreatePipeline(pipeline2, []*model.Step{}...)
GetPipeline, err := store.GetPipeline(pipeline.ID) assert.NoError(t, err2)
g.Assert(err).IsNil() GetPipeline, err3 := store.GetPipelineNumber(&model.Repo{ID: 1}, pipeline2.Number)
g.Assert(pipeline.ID).Equal(GetPipeline.ID) assert.NoError(t, err3)
g.Assert(pipeline.RepoID).Equal(GetPipeline.RepoID) assert.Equal(t, pipeline2.ID, GetPipeline.ID)
g.Assert(pipeline.Status).Equal(GetPipeline.Status) assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID)
}) assert.Equal(t, pipeline2.Number, GetPipeline.Number)
g.It("Should Get a Pipeline by Number", func() { GetPipeline, err3 = store.GetPipelineLast(&model.Repo{ID: repo.ID}, pipeline2.Branch)
pipeline1 := &model.Pipeline{ assert.NoError(t, err3)
RepoID: repo.ID, assert.Equal(t, pipeline2.ID, GetPipeline.ID)
Status: model.StatusPending, assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID)
} assert.Equal(t, pipeline2.Number, GetPipeline.Number)
pipeline2 := &model.Pipeline{ assert.Equal(t, pipeline2.Status, GetPipeline.Status)
RepoID: repo.ID,
Status: model.StatusPending,
}
err1 := store.CreatePipeline(pipeline1, []*model.Step{}...)
g.Assert(err1).IsNil()
err2 := store.CreatePipeline(pipeline2, []*model.Step{}...)
g.Assert(err2).IsNil()
GetPipeline, err3 := store.GetPipelineNumber(&model.Repo{ID: 1}, pipeline2.Number)
g.Assert(err3).IsNil()
g.Assert(pipeline2.ID).Equal(GetPipeline.ID)
g.Assert(pipeline2.RepoID).Equal(GetPipeline.RepoID)
g.Assert(pipeline2.Number).Equal(GetPipeline.Number)
})
g.It("Should Get the last Pipeline", func() { pipeline3 := &model.Pipeline{
pipeline1 := &model.Pipeline{ RepoID: repo.ID,
RepoID: repo.ID, Status: model.StatusRunning,
Status: model.StatusFailure, Branch: "main",
Branch: "main", Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa",
Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", }
Event: model.EventPush, err1 = store.CreatePipeline(pipeline3, []*model.Step{}...)
} assert.NoError(t, err1)
pipeline2 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusSuccess,
Branch: "main",
Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa",
Event: model.EventPush,
}
err1 := store.CreatePipeline(pipeline1, []*model.Step{}...)
err2 := store.CreatePipeline(pipeline2, []*model.Step{}...)
GetPipeline, err3 := store.GetPipelineLast(&model.Repo{ID: 1}, pipeline2.Branch)
g.Assert(err1).IsNil()
g.Assert(err2).IsNil()
g.Assert(err3).IsNil()
g.Assert(pipeline2.ID).Equal(GetPipeline.ID)
g.Assert(pipeline2.RepoID).Equal(GetPipeline.RepoID)
g.Assert(pipeline2.Number).Equal(GetPipeline.Number)
g.Assert(pipeline2.Status).Equal(GetPipeline.Status)
g.Assert(pipeline2.Branch).Equal(GetPipeline.Branch)
g.Assert(pipeline2.Commit).Equal(GetPipeline.Commit)
})
g.It("Should Get the last Pipeline Before Pipeline N", func() { GetPipeline, err4 := store.GetPipelineLastBefore(&model.Repo{ID: 1}, pipeline3.Branch, pipeline3.ID)
pipeline1 := &model.Pipeline{ assert.NoError(t, err4)
RepoID: repo.ID, assert.Equal(t, pipeline2.ID, GetPipeline.ID)
Status: model.StatusFailure, assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID)
Branch: "main", assert.Equal(t, pipeline2.Number, GetPipeline.Number)
Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", assert.Equal(t, pipeline2.Status, GetPipeline.Status)
} assert.Equal(t, pipeline2.Branch, GetPipeline.Branch)
pipeline2 := &model.Pipeline{ assert.Equal(t, pipeline2.Commit, GetPipeline.Commit)
RepoID: repo.ID, }
Status: model.StatusSuccess,
Branch: "main",
Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa",
}
pipeline3 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusRunning,
Branch: "main",
Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa",
}
err1 := store.CreatePipeline(pipeline1, []*model.Step{}...)
g.Assert(err1).IsNil()
err2 := store.CreatePipeline(pipeline2, []*model.Step{}...)
g.Assert(err2).IsNil()
err3 := store.CreatePipeline(pipeline3, []*model.Step{}...)
g.Assert(err3).IsNil()
GetPipeline, err4 := store.GetPipelineLastBefore(&model.Repo{ID: 1}, pipeline3.Branch, pipeline3.ID)
g.Assert(err4).IsNil()
g.Assert(pipeline2.ID).Equal(GetPipeline.ID)
g.Assert(pipeline2.RepoID).Equal(GetPipeline.RepoID)
g.Assert(pipeline2.Number).Equal(GetPipeline.Number)
g.Assert(pipeline2.Status).Equal(GetPipeline.Status)
g.Assert(pipeline2.Branch).Equal(GetPipeline.Branch)
g.Assert(pipeline2.Commit).Equal(GetPipeline.Commit)
})
g.It("Should get recent pipelines", func() { func TestPipelineListFilter(t *testing.T) {
pipeline1 := &model.Pipeline{ repo := &model.Repo{
RepoID: repo.ID, UserID: 1,
Status: model.StatusFailure, FullName: "bradrydzewski/test",
Event: model.EventCron, Owner: "bradrydzewski",
Ref: "refs/heads/some-branch", Name: "test",
Branch: "some-branch", }
}
pipeline2 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusSuccess,
Event: model.EventPull,
Ref: "refs/pull/32",
Branch: "main",
}
err := store.CreatePipeline(pipeline1, []*model.Step{}...)
g.Assert(err).IsNil()
err = store.CreatePipeline(pipeline2, []*model.Step{}...)
g.Assert(err).IsNil()
pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, nil)
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(2)
g.Assert(pipelines[0].ID).Equal(pipeline2.ID)
g.Assert(pipelines[0].RepoID).Equal(pipeline2.RepoID)
g.Assert(pipelines[0].Status).Equal(pipeline2.Status)
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ store, closer := newTestStore(t, new(model.Repo), new(model.Step), new(model.Pipeline))
Branch: "main", defer closer()
})
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(1)
g.Assert(pipelines[0].ID).Equal(pipeline2.ID)
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ assert.NoError(t, store.CreateRepo(repo))
Events: []model.WebhookEvent{model.EventCron},
})
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(1)
g.Assert(pipelines[0].ID).Equal(pipeline1.ID)
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ pipeline1 := &model.Pipeline{
Events: []model.WebhookEvent{model.EventCron, model.EventPull}, RepoID: repo.ID,
RefContains: "32", Status: model.StatusFailure,
}) Event: model.EventCron,
g.Assert(err).IsNil() Ref: "refs/heads/some-branch",
g.Assert(len(pipelines)).Equal(1) Branch: "some-branch",
g.Assert(pipelines[0].ID).Equal(pipeline2.ID) }
}) pipeline2 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusSuccess,
Event: model.EventPull,
Ref: "refs/pull/32",
Branch: "main",
}
err := store.CreatePipeline(pipeline1, []*model.Step{}...)
assert.NoError(t, err)
time.Sleep(1 * time.Second)
before := time.Now().Unix()
err = store.CreatePipeline(pipeline2, []*model.Step{}...)
assert.NoError(t, err)
g.It("Should get filtered pipelines", func() { pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, nil)
pipeline1 := &model.Pipeline{ assert.NoError(t, err)
RepoID: repo.ID, assert.Len(t, (pipelines), 2)
} assert.Equal(t, pipeline2.ID, pipelines[0].ID)
pipeline2 := &model.Pipeline{ assert.Equal(t, pipeline2.RepoID, pipelines[0].RepoID)
RepoID: repo.ID, assert.Equal(t, pipeline2.Status, pipelines[0].Status)
}
err1 := store.CreatePipeline(pipeline1, []*model.Step{}...)
g.Assert(err1).IsNil()
time.Sleep(1 * time.Second)
before := time.Now().Unix()
err2 := store.CreatePipeline(pipeline2, []*model.Step{}...)
g.Assert(err2).IsNil()
pipelines, err3 := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, &model.PipelineFilter{Before: before})
g.Assert(err3).IsNil()
g.Assert(len(pipelines)).Equal(1)
g.Assert(pipelines[0].ID).Equal(pipeline1.ID)
g.Assert(pipelines[0].RepoID).Equal(pipeline1.RepoID)
})
g.It("Should get pipelines filtered by status", func() { pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
pipeline1 := &model.Pipeline{ Branch: "main",
RepoID: repo.ID,
Status: model.StatusSuccess,
}
pipeline2 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusFailure,
}
pipeline3 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusRunning,
}
err1 := store.CreatePipeline(pipeline1, []*model.Step{}...)
g.Assert(err1).IsNil()
err2 := store.CreatePipeline(pipeline2, []*model.Step{}...)
g.Assert(err2).IsNil()
err3 := store.CreatePipeline(pipeline3, []*model.Step{}...)
g.Assert(err3).IsNil()
pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Status: model.StatusSuccess,
})
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(1)
g.Assert(pipelines[0].ID).Equal(pipeline1.ID)
g.Assert(pipelines[0].Status).Equal(model.StatusSuccess)
})
}) })
assert.NoError(t, err)
assert.Len(t, pipelines, 1)
assert.Equal(t, pipeline2.ID, pipelines[0].ID)
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Events: []model.WebhookEvent{model.EventCron},
})
assert.NoError(t, err)
assert.Len(t, pipelines, 1)
assert.Equal(t, pipeline1.ID, pipelines[0].ID)
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Events: []model.WebhookEvent{model.EventCron, model.EventPull},
RefContains: "32",
})
assert.NoError(t, err)
assert.Len(t, (pipelines), 1)
assert.Equal(t, pipeline2.ID, pipelines[0].ID)
pipelines, err3 := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, &model.PipelineFilter{Before: before})
assert.NoError(t, err3)
assert.Len(t, pipelines, 1)
assert.Equal(t, pipeline1.ID, pipelines[0].ID)
assert.Equal(t, pipeline1.RepoID, pipelines[0].RepoID)
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Status: model.StatusSuccess,
})
assert.NoError(t, err)
assert.Len(t, pipelines, 1)
assert.Equal(t, pipeline2.ID, pipelines[0].ID)
assert.Equal(t, model.StatusSuccess, pipelines[0].Status)
} }
func TestPipelineIncrement(t *testing.T) { func TestPipelineIncrement(t *testing.T) {

View File

@@ -18,146 +18,106 @@ package datastore
import ( import (
"testing" "testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func TestRepos(t *testing.T) { func TestCreateRepo(t *testing.T) {
store, closer := newTestStore(t, new(model.Repo), new(model.User), new(model.Pipeline)) store, closer := newTestStore(t, new(model.Repo))
defer closer() defer closer()
g := goblin.Goblin(t) repo := model.Repo{
g.Describe("Repo", func() { UserID: 1,
// before each test be sure to purge the package FullName: "bradrydzewski/test",
// table data from the database. Owner: "bradrydzewski",
g.BeforeEach(func() { Name: "test",
_, err := store.engine.Exec("DELETE FROM pipelines") }
g.Assert(err).IsNil() err := store.CreateRepo(&repo)
_, err = store.engine.Exec("DELETE FROM repos") assert.NoError(t, err)
g.Assert(err).IsNil() assert.NotZero(t, repo.ID)
_, err = store.engine.Exec("DELETE FROM users")
g.Assert(err).IsNil()
})
g.It("Should Set a Repo", func() { err2 := store.UpdateRepo(&repo)
repo := model.Repo{ getRepo, err3 := store.GetRepo(repo.ID)
UserID: 1,
FullName: "bradrydzewski/test",
Owner: "bradrydzewski",
Name: "test",
}
err1 := store.CreateRepo(&repo)
err2 := store.UpdateRepo(&repo)
getRepo, err3 := store.GetRepo(repo.ID)
g.Assert(err1).IsNil() assert.NoError(t, err2)
g.Assert(err2).IsNil() assert.NoError(t, err3)
g.Assert(err3).IsNil() assert.Equal(t, repo.ID, getRepo.ID)
g.Assert(repo.ID).Equal(getRepo.ID)
})
g.It("Should Add a Repo", func() { // test that repo has name/owner/fullname
repo := model.Repo{ assert.Error(t, store.CreateRepo(&model.Repo{
UserID: 1, UserID: 1,
FullName: "bradrydzewski/test", FullName: "bradrydzewski/",
Owner: "bradrydzewski", Owner: "bradrydzewski",
Name: "test", Name: "",
} }))
err := store.CreateRepo(&repo) assert.Error(t, store.CreateRepo(&model.Repo{
g.Assert(err).IsNil() UserID: 1,
g.Assert(repo.ID != 0).IsTrue() FullName: "/test",
}) Owner: "",
Name: "test",
}))
assert.Error(t, store.CreateRepo(&model.Repo{
UserID: 1,
FullName: "",
Owner: "bradrydzewski",
Name: "test",
}))
g.It("Should fail if repo has no name / owner / fullname", func() { // test unique name
g.Assert(store.CreateRepo(&model.Repo{ repo2 := model.Repo{
UserID: 1, UserID: 2,
FullName: "bradrydzewski/", FullName: "bradrydzewski/test",
Owner: "bradrydzewski", Owner: "bradrydzewski",
Name: "", Name: "test",
})).IsNotNil() }
g.Assert(store.CreateRepo(&model.Repo{ err2 = store.CreateRepo(&repo2)
UserID: 1, assert.Error(t, err2)
FullName: "/test", }
Owner: "",
Name: "test",
})).IsNotNil()
g.Assert(store.CreateRepo(&model.Repo{
UserID: 1,
FullName: "",
Owner: "bradrydzewski",
Name: "test",
})).IsNotNil()
})
g.It("Should Get a Repo by ID", func() { func TestGetRepo(t *testing.T) {
repo := model.Repo{ store, closer := newTestStore(t, new(model.Repo))
UserID: 1, defer closer()
FullName: "bradrydzewski/test", repo := model.Repo{
Owner: "bradrydzewski", UserID: 1,
Name: "test", FullName: "bradrydzewski/test",
} Owner: "bradrydzewski",
g.Assert(store.CreateRepo(&repo)).IsNil() Name: "test",
getrepo, err := store.GetRepo(repo.ID) }
g.Assert(err).IsNil() assert.NoError(t, store.CreateRepo(&repo))
g.Assert(repo.ID).Equal(getrepo.ID) getrepo, err := store.GetRepo(repo.ID)
g.Assert(repo.UserID).Equal(getrepo.UserID) assert.NoError(t, err)
g.Assert(repo.Owner).Equal(getrepo.Owner) assert.Equal(t, repo.ID, getrepo.ID)
g.Assert(repo.Name).Equal(getrepo.Name) assert.Equal(t, repo.UserID, getrepo.UserID)
}) assert.Equal(t, repo.Owner, getrepo.Owner)
assert.Equal(t, repo.Name, getrepo.Name)
}
g.It("Should Get a Repo by Name", func() { func TestGetRepoName(t *testing.T) {
repo := model.Repo{ store, closer := newTestStore(t, new(model.Repo))
UserID: 1, defer closer()
FullName: "bradrydzewski/test", repo := model.Repo{
Owner: "bradrydzewski", UserID: 1,
Name: "test", FullName: "bradrydzewski/TEST",
} Owner: "bradrydzewski",
g.Assert(store.CreateRepo(&repo)).IsNil() Name: "TEST",
getrepo, err := store.GetRepoName(repo.FullName) }
g.Assert(err).IsNil()
g.Assert(repo.ID).Equal(getrepo.ID)
g.Assert(repo.UserID).Equal(getrepo.UserID)
g.Assert(repo.Owner).Equal(getrepo.Owner)
g.Assert(repo.Name).Equal(getrepo.Name)
})
g.It("Should Get a Repo by Name (case-insensitive)", func() { assert.NoError(t, store.CreateRepo(&repo))
repo := model.Repo{ getrepo, err := store.GetRepoName(repo.FullName)
UserID: 1, assert.NoError(t, err)
FullName: "bradrydzewski/TEST", assert.Equal(t, repo.ID, getrepo.ID)
Owner: "bradrydzewski", assert.Equal(t, repo.UserID, getrepo.UserID)
Name: "TEST", assert.Equal(t, repo.Owner, getrepo.Owner)
} assert.Equal(t, repo.Name, getrepo.Name)
g.Assert(store.CreateRepo(&repo)).IsNil()
getrepo, err := store.GetRepoName("Bradrydzewski/test")
g.Assert(err).IsNil()
g.Assert(repo.ID).Equal(getrepo.ID)
g.Assert(repo.UserID).Equal(getrepo.UserID)
g.Assert(repo.Owner).Equal(getrepo.Owner)
g.Assert(repo.Name).Equal(getrepo.Name)
})
g.It("Should Enforce Unique Repo Name", func() { // case-insensitive
repo1 := model.Repo{ getrepo, err = store.GetRepoName("Bradrydzewski/test")
UserID: 1, assert.NoError(t, err)
FullName: "bradrydzewski/test", assert.Equal(t, repo.ID, getrepo.ID)
Owner: "bradrydzewski", assert.Equal(t, repo.UserID, getrepo.UserID)
Name: "test", assert.Equal(t, repo.Owner, getrepo.Owner)
} assert.Equal(t, repo.Name, getrepo.Name)
repo2 := model.Repo{
UserID: 2,
FullName: "bradrydzewski/test",
Owner: "bradrydzewski",
Name: "test",
}
err1 := store.CreateRepo(&repo1)
err2 := store.CreateRepo(&repo2)
g.Assert(err1).IsNil()
g.Assert(err2 == nil).IsFalse()
})
})
} }
func TestRepoList(t *testing.T) { func TestRepoList(t *testing.T) {

View File

@@ -18,238 +18,79 @@ package datastore
import ( import (
"testing" "testing"
"github.com/franela/goblin" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/model"
) )
func TestUsers(t *testing.T) { func TestUsers(t *testing.T) {
store, closer := newTestStore(t, new(model.User), new(model.Repo), new(model.Pipeline), new(model.Step), new(model.Perm), new(model.Org), new(model.Secret)) store, closer := newTestStore(t, new(model.User), new(model.Org), new(model.Secret), new(model.Repo), new(model.Perm))
defer closer() defer closer()
g := goblin.Goblin(t) count, err := store.GetUserCount()
g.Describe("User", func() { assert.NoError(t, err)
// before each test be sure to purge the package assert.Zero(t, count)
// table data from the database.
g.BeforeEach(func() {
_, err := store.engine.Exec("DELETE FROM users")
g.Assert(err).IsNil()
_, err = store.engine.Exec("DELETE FROM repos")
g.Assert(err).IsNil()
_, err = store.engine.Exec("DELETE FROM pipelines")
g.Assert(err).IsNil()
_, err = store.engine.Exec("DELETE FROM steps")
g.Assert(err).IsNil()
_, err = store.engine.Exec("DELETE FROM orgs")
g.Assert(err).IsNil()
})
g.It("Should Update a User", func() { user := model.User{
user := model.User{ Login: "joe",
Login: "joe", AccessToken: "f0b461ca586c27872b43a0685cbc2847",
Email: "foo@bar.com", RefreshToken: "976f22a5eef7caacb7e678d6c52f49b1",
AccessToken: "e42080dddf012c718e476da161d21ad5", Email: "foo@bar.com",
} Avatar: "b9015b0857e16ac4d94a0ffd9a0b79c8",
err1 := store.CreateUser(&user) }
err2 := store.UpdateUser(&user) err = store.CreateUser(&user)
getUser, err3 := store.GetUser(user.ID) assert.NoError(t, err)
g.Assert(err1).IsNil() assert.NotZero(t, user.ID)
g.Assert(err2).IsNil()
g.Assert(err3).IsNil()
g.Assert(user.ID).Equal(getUser.ID)
})
g.It("Should Add a new User", func() { err2 := store.UpdateUser(&user)
user := model.User{ assert.NoError(t, err2)
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
err := store.CreateUser(&user)
g.Assert(err).IsNil()
g.Assert(user.ID != 0).IsTrue()
})
g.It("Should Get a User", func() { getUser, err := store.GetUser(user.ID)
user := &model.User{ assert.NoError(t, err)
Login: "joe", assert.Equal(t, user.ID, getUser.ID)
AccessToken: "f0b461ca586c27872b43a0685cbc2847", assert.Equal(t, user.Login, getUser.Login)
RefreshToken: "976f22a5eef7caacb7e678d6c52f49b1", assert.Equal(t, user.AccessToken, getUser.AccessToken)
Email: "foo@bar.com", assert.Equal(t, user.RefreshToken, getUser.RefreshToken)
Avatar: "b9015b0857e16ac4d94a0ffd9a0b79c8", assert.Equal(t, user.Email, getUser.Email)
} assert.Equal(t, user.Avatar, getUser.Avatar)
g.Assert(store.CreateUser(user)).IsNil() getUser, err = store.GetUserLogin(user.Login)
getUser, err := store.GetUser(user.ID) assert.NoError(t, err)
g.Assert(err).IsNil() assert.Equal(t, user.ID, getUser.ID)
g.Assert(user.ID).Equal(getUser.ID) assert.Equal(t, user.Login, getUser.Login)
g.Assert(user.Login).Equal(getUser.Login)
g.Assert(user.AccessToken).Equal(getUser.AccessToken)
g.Assert(user.RefreshToken).Equal(getUser.RefreshToken)
g.Assert(user.Email).Equal(getUser.Email)
g.Assert(user.Avatar).Equal(getUser.Avatar)
})
g.It("Should Get a User By Login", func() { // check unique login
user := &model.User{ user2 := model.User{
Login: "joe", Login: "joe",
Email: "foo@bar.com", Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5", AccessToken: "ab20g0ddaf012c744e136da16aa21ad9",
} }
g.Assert(store.CreateUser(user)) err2 = store.CreateUser(&user2)
getUser, err := store.GetUserLogin(user.Login) assert.Error(t, err2)
g.Assert(err).IsNil()
g.Assert(user.ID).Equal(getUser.ID)
g.Assert(user.Login).Equal(getUser.Login)
})
g.It("Should Enforce Unique User Login", func() { user2 = model.User{
user1 := model.User{ Login: "jane",
Login: "joe", Email: "foo@bar.com",
Email: "foo@bar.com", AccessToken: "ab20g0ddaf012c744e136da16aa21ad9",
AccessToken: "e42080dddf012c718e476da161d21ad5", Hash: "A",
} }
user2 := model.User{ assert.NoError(t, store.CreateUser(&user2))
Login: "joe", users, err := store.GetUserList(&model.ListOptions{Page: 1, PerPage: 50})
Email: "foo@bar.com", assert.NoError(t, err)
AccessToken: "ab20g0ddaf012c744e136da16aa21ad9", assert.Len(t, users, 2)
} // "jane" user is first due to alphabetic sorting
err1 := store.CreateUser(&user1) assert.Equal(t, user2.Login, users[0].Login)
err2 := store.CreateUser(&user2) assert.Equal(t, user2.Email, users[0].Email)
g.Assert(err1).IsNil() assert.Equal(t, user2.AccessToken, users[0].AccessToken)
g.Assert(err2 == nil).IsFalse()
})
g.It("Should Get a User List", func() { count, err = store.GetUserCount()
user1 := model.User{ assert.NoError(t, err)
Login: "jane", assert.EqualValues(t, 2, count)
Email: "foo@bar.com",
AccessToken: "ab20g0ddaf012c744e136da16aa21ad9",
Hash: "A",
}
user2 := model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
g.Assert(store.CreateUser(&user1)).IsNil()
g.Assert(store.CreateUser(&user2)).IsNil()
users, err := store.GetUserList(&model.ListOptions{Page: 1, PerPage: 50})
g.Assert(err).IsNil()
g.Assert(len(users)).Equal(2)
g.Assert(users[0].Login).Equal(user1.Login)
g.Assert(users[0].Email).Equal(user1.Email)
g.Assert(users[0].AccessToken).Equal(user1.AccessToken)
})
g.It("Should Get a User Count", func() { getUser, err1 := store.GetUser(user.ID)
user1 := model.User{ assert.NoError(t, err1)
Login: "jane", err2 = store.DeleteUser(getUser)
Email: "foo@bar.com", assert.NoError(t, err2)
AccessToken: "ab20g0ddaf012c744e136da16aa21ad9", _, err3 := store.GetUser(getUser.ID)
Hash: "A", assert.Error(t, err3)
}
user2 := model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
Hash: "B",
}
g.Assert(store.CreateUser(&user1)).IsNil()
g.Assert(store.CreateUser(&user2)).IsNil()
count, err := store.GetUserCount()
g.Assert(err).IsNil()
g.Assert(count).Equal(int64(2))
})
g.It("Should Get a User Count Zero", func() {
count, err := store.GetUserCount()
g.Assert(err).IsNil()
g.Assert(count).Equal(int64(0))
})
g.It("Should Del a User", func() {
user := &model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
g.Assert(store.CreateUser(user)).IsNil()
user, err1 := store.GetUser(user.ID)
g.Assert(err1).IsNil()
err2 := store.DeleteUser(user)
g.Assert(err2).IsNil()
_, err3 := store.GetUser(user.ID)
g.Assert(err3).IsNotNil()
})
g.It("Should get the Pipeline feed for a User", func() {
user := &model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
g.Assert(store.CreateUser(user)).IsNil()
repo1 := &model.Repo{
Owner: "bradrydzewski",
Name: "test",
FullName: "bradrydzewski/test",
IsActive: true,
ForgeRemoteID: "1",
}
repo2 := &model.Repo{
Owner: "test",
Name: "test",
FullName: "test/test",
IsActive: true,
ForgeRemoteID: "2",
}
repo3 := &model.Repo{
Owner: "octocat",
Name: "hello-world",
FullName: "octocat/hello-world",
IsActive: true,
ForgeRemoteID: "3",
}
g.Assert(store.CreateRepo(repo1)).IsNil()
g.Assert(store.CreateRepo(repo2)).IsNil()
g.Assert(store.CreateRepo(repo3)).IsNil()
for _, perm := range []*model.Perm{
{UserID: user.ID, Repo: repo1, Push: true, Admin: false},
{UserID: user.ID, Repo: repo2, Push: false, Admin: true},
} {
g.Assert(store.PermUpsert(perm)).IsNil()
}
pipeline1 := &model.Pipeline{
RepoID: repo1.ID,
Status: model.StatusFailure,
}
pipeline2 := &model.Pipeline{
RepoID: repo1.ID,
Status: model.StatusSuccess,
}
pipeline3 := &model.Pipeline{
RepoID: repo2.ID,
Status: model.StatusSuccess,
}
pipeline4 := &model.Pipeline{
RepoID: repo3.ID,
Status: model.StatusSuccess,
}
g.Assert(store.CreatePipeline(pipeline1)).IsNil()
g.Assert(store.CreatePipeline(pipeline2)).IsNil()
g.Assert(store.CreatePipeline(pipeline3)).IsNil()
g.Assert(store.CreatePipeline(pipeline4)).IsNil()
pipelines, err := store.UserFeed(user)
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(3)
g.Assert(pipelines[0].RepoID).Equal(repo2.ID)
g.Assert(pipelines[1].RepoID).Equal(repo1.ID)
g.Assert(pipelines[2].RepoID).Equal(repo1.ID)
})
})
} }

View File

@@ -3,60 +3,51 @@ package token_test
import ( import (
"testing" "testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/shared/token" "go.woodpecker-ci.org/woodpecker/v3/shared/token"
) )
func TestToken(t *testing.T) { const jwtSecret = "secret-to-sign-the-token"
gin.SetMode(gin.TestMode)
g := goblin.Goblin(t) func TestTokenValid(t *testing.T) {
g.Describe("Token", func() { _token := token.New(token.UserToken)
jwtSecret := "secret-to-sign-the-token" _token.Set("user-id", "1")
signedToken, err := _token.Sign(jwtSecret)
assert.NoError(t, err)
g.It("should parse a valid token", func() { parsed, err := token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) {
_token := token.New(token.UserToken) return jwtSecret, nil
_token.Set("user-id", "1")
signedToken, err := _token.Sign(jwtSecret)
assert.NoError(g, err)
parsed, err := token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) {
return jwtSecret, nil
})
assert.NoError(g, err)
assert.NotNil(g, parsed)
assert.Equal(g, "1", parsed.Get("user-id"))
})
g.It("should fail to parse a token with a wrong type", func() {
_token := token.New(token.UserToken)
_token.Set("user-id", "1")
signedToken, err := _token.Sign(jwtSecret)
assert.NoError(g, err)
_, err = token.Parse([]token.Type{token.AgentToken}, signedToken, func(_ *token.Token) (string, error) {
return jwtSecret, nil
})
assert.ErrorIs(g, err, jwt.ErrInvalidType)
})
g.It("should fail to parse a token with a wrong secret", func() {
_token := token.New(token.UserToken)
_token.Set("user-id", "1")
signedToken, err := _token.Sign(jwtSecret)
assert.NoError(g, err)
_, err = token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) {
return "this-is-a-wrong-secret", nil
})
assert.ErrorIs(g, err, jwt.ErrSignatureInvalid)
})
}) })
assert.NoError(t, err)
assert.NotNil(t, parsed)
assert.Equal(t, "1", parsed.Get("user-id"))
}
func TestTokenWrongType(t *testing.T) {
_token := token.New(token.UserToken)
_token.Set("user-id", "1")
signedToken, err := _token.Sign(jwtSecret)
assert.NoError(t, err)
_, err = token.Parse([]token.Type{token.AgentToken}, signedToken, func(_ *token.Token) (string, error) {
return jwtSecret, nil
})
assert.ErrorIs(t, err, jwt.ErrInvalidType)
}
func TestTokenWrongSecret(t *testing.T) {
_token := token.New(token.UserToken)
_token.Set("user-id", "1")
signedToken, err := _token.Sign(jwtSecret)
assert.NoError(t, err)
_, err = token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) {
return "this-is-a-wrong-secret", nil
})
assert.ErrorIs(t, err, jwt.ErrSignatureInvalid)
} }