1
0
mirror of https://github.com/woodpecker-ci/woodpecker.git synced 2025-01-23 17:53:23 +02:00

Merge branch 'origin/main' into 'next-release/main'

This commit is contained in:
oauth 2024-12-30 06:13:44 +00:00
commit 42ea552386
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/drone/envsubst v1.0.3
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/gdgvda/cron v0.3.0
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/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
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.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
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, "hdd", engine.config.StorageClass)
assert.Equal(t, "1G", engine.config.VolumeSize)
assert.Equal(t, false, engine.config.StorageRwx)
assert.Equal(t, 1, len(engine.config.PodLabels))
assert.Equal(t, 1, len(engine.config.PodAnnotations))
assert.Equal(t, 1, len(engine.config.ImagePullSecretNames))
assert.Equal(t, false, engine.config.SecurityContext.RunAsNonRoot)
assert.False(t, engine.config.StorageRwx)
assert.Len(t, engine.config.PodLabels, 1)
assert.Len(t, engine.config.PodAnnotations, 1)
assert.Len(t, engine.config.ImagePullSecretNames, 1)
assert.False(t, engine.config.SecurityContext.RunAsNonRoot)
}

View File

@ -29,7 +29,7 @@ func TestNativeSecretsEnabled(t *testing.T) {
nsp := newNativeSecretsProcessor(&config{
NativeSecretsAllowFromStep: true,
}, nil)
assert.Equal(t, true, nsp.isEnabled())
assert.True(t, nsp.isEnabled())
}
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()
assert.NoError(t, err)

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,6 @@ import (
"testing"
"time"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
@ -29,346 +28,341 @@ import (
func TestHandleAuth(t *testing.T) {
gin.SetMode(gin.TestMode)
g := goblin.Goblin(t)
g.Describe("Login", func() {
user := &model.User{
ID: 1,
OrgID: 1,
ForgeID: 1,
ForgeRemoteID: "remote-id-1",
Login: "test",
Email: "test@example.com",
Admin: false,
}
org := &model.Org{
ID: 1,
Name: user.Login,
user := &model.User{
ID: 1,
OrgID: 1,
ForgeID: 1,
ForgeRemoteID: "remote-id-1",
Login: "test",
Email: "test@example.com",
Admin: false,
}
org := &model.Org{
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() {
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
assert.Equal(t, fmt.Sprintf("/login?%s", query.Encode()), c.Writer.Header().Get("Location"))
})
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")
t.Run("should fail if the state is wrong", func(t *testing.T) {
_manager := mocks_services.NewManager(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),
Method: http.MethodGet,
URL: &url.URL{
Scheme: "https",
Path: "/authorize",
RawQuery: query.Encode(),
},
query := url.Values{}
query.Set("code", "assumed_to_be_valid_code")
wrongToken := token.New(token.OAuthStateToken)
wrongToken.Set("forge_id", "1")
signedWrongToken, _ := wrongToken.Sign("wrong_secret")
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(g, fmt.Sprintf("/login?%s", query.Encode()), c.Writer.Header().Get("Location"))
})
assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
assert.Equal(t, forgeRedirectURL, c.Writer.Header().Get("Location"))
})
g.It("should fail if the state is wrong", func() {
_manager := mocks_services.NewManager(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)
t.Run("should register a new 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",
},
}
query := url.Values{}
query.Set("code", "assumed_to_be_valid_code")
_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)
_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)
wrongToken.Set("forge_id", "1")
signedWrongToken, _ := wrongToken.Sign("wrong_secret")
query.Set("state", signedWrongToken)
api.HandleAuth(c)
c.Request = &http.Request{
Header: make(http.Header),
URL: &url.URL{
Scheme: "https",
RawQuery: query.Encode(),
},
}
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"))
})
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())
assert.Equal(g, "/login?error=invalid_state", c.Writer.Header().Get("Location"))
})
_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", 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() {
_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",
},
}
api.HandleAuth(c)
_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 := ""
_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)
t.Run("should deny a new user if registration is closed", 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 = 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",
},
}
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())
assert.Equal(g, forgeRedirectURL, c.Writer.Header().Get("Location"))
})
api.HandleAuth(c)
g.It("should register a new 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",
},
}
assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
assert.Equal(t, "/login?error=registration_closed", c.Writer.Header().Get("Location"))
})
_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)
_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)
t.Run("should deny a user with missing org access", 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([]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",
},
}
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())
assert.Equal(g, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie"))
})
api.HandleAuth(c)
g.It("should login an existing 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",
},
}
assert.Equal(t, http.StatusSeeOther, c.Writer.Status())
assert.Equal(t, "/login?error=org_access_denied", c.Writer.Header().Get("Location"))
})
_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", org.ID).Return(org, nil)
_store.On("UpdateUser", mock.Anything).Return(nil)
_forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil)
t.Run("User org should be created if it does not exists", 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",
},
}
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())
assert.Equal(g, "/", c.Writer.Header().Get("Location"))
assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie"))
})
api.HandleAuth(c)
g.It("should deny a new user if registration is closed", 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 = 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",
},
}
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"))
})
_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)
t.Run("User org should be linked if it has the same name as the 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",
},
}
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())
assert.Equal(g, "/login?error=registration_closed", c.Writer.Header().Get("Location"))
})
api.HandleAuth(c)
g.It("should deny a user with missing org access", 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([]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",
},
}
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"))
})
_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)
t.Run("User org should be updated if the user name was changed", 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",
},
}
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())
assert.Equal(g, "/login?error=org_access_denied", c.Writer.Header().Get("Location"))
})
api.HandleAuth(c)
g.Describe("User org", func() {
g.It("should be created if it does not exists", 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(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"))
})
})
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"))
})
}

View File

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

View File

@ -18,13 +18,12 @@ package bitbucket
import (
"bytes"
"context"
"errors"
"net/http"
"net/http/httptest"
"testing"
"github.com/franela/goblin"
"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/internal"
@ -32,263 +31,182 @@ import (
"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)
s := httptest.NewServer(fixtures.Handler())
defer s.Close()
c := &config{url: s.URL, API: s.URL}
g := goblin.Goblin(t)
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{Client: "4vyW6b49Z", Secret: "a5012f6c6"})
forge, _ := New(&Opts{})
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)
g.Assert(f.url).Equal(DefaultURL)
g.Assert(f.API).Equal(DefaultAPI)
g.Assert(f.Client).Equal("4vyW6b49Z")
g.Assert(f.Secret).Equal("a5012f6c6")
})
user, _, err := c.Login(ctx, &types.OAuthRequest{})
assert.NoError(t, err)
assert.Nil(t, user)
g.It("Should return the netrc file", func() {
forge, _ := New(&Opts{})
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")
})
u, _, err := c.Login(ctx, &types.OAuthRequest{
Code: "code",
})
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 (

View File

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

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

View File

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

View File

@ -18,288 +18,299 @@ import (
"testing"
"time"
"github.com/franela/goblin"
bb "github.com/neticdk/go-bitbucket/bitbucket"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
)
//nolint:misspell
func TestHelper(t *testing.T) {
g := goblin.Goblin(t)
g.Describe("Bitbucket Server converter", func() {
g.It("should convert status", func() {
tests := []struct {
from model.StatusValue
to bb.BuildStatusState
}{
{
from: model.StatusPending,
to: bb.BuildStatusStateInProgress,
},
{
from: model.StatusRunning,
to: bb.BuildStatusStateInProgress,
},
{
from: model.StatusSuccess,
to: bb.BuildStatusStateSuccessful,
},
{
from: model.StatusValue("other"),
to: bb.BuildStatusStateFailed,
},
}
for _, tt := range tests {
to := convertStatus(tt.from)
g.Assert(to).Equal(tt.to)
}
})
g.It("should convert repository", func() {
from := &bb.Repository{
ID: uint64(1234),
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
Links: map[string][]bb.Link{
"clone": {
{
Name: "http",
Href: "https://user@git.domain/clone",
},
},
"self": {
{
Href: "https://git.domain/self",
},
},
},
}
perm := &model.Perm{}
to := convertRepo(from, perm, "main")
g.Assert(to.ForgeRemoteID).Equal(model.ForgeRemoteID("1234"))
g.Assert(to.Name).Equal("REPO")
g.Assert(to.Owner).Equal("PRJ")
g.Assert(to.Branch).Equal("main")
g.Assert(to.FullName).Equal("PRJ/REPO")
g.Assert(to.Perm).Equal(perm)
g.Assert(to.Clone).Equal("https://git.domain/clone")
})
g.It("should convert repository push event", func() {
now := time.Now()
tests := []struct {
from *bb.RepositoryPushEvent
to *model.Pipeline
}{
{
from: &bb.RepositoryPushEvent{},
to: nil,
},
{
from: &bb.RepositoryPushEvent{
Changes: []bb.RepositoryPushEventChange{
{
FromHash: "1234567890abcdef",
ToHash: "0000000000000000000000000000000000000000",
},
},
},
to: nil,
},
{
from: &bb.RepositoryPushEvent{
Changes: []bb.RepositoryPushEventChange{
{
FromHash: "0000000000000000000000000000000000000000",
ToHash: "1234567890abcdef",
Type: bb.RepositoryPushEventChangeTypeDelete,
},
},
},
to: nil,
},
{
from: &bb.RepositoryPushEvent{
Event: bb.Event{
Date: bb.ISOTime(now),
Actor: bb.User{
Name: "John Doe",
Email: "john.doe@mail.com",
Slug: "john.doe_mail.com",
},
},
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
Changes: []bb.RepositoryPushEventChange{
{
Ref: bb.RepositoryPushEventRef{
ID: "refs/head/branch",
DisplayID: "branch",
},
RefId: "refs/head/branch",
ToHash: "1234567890abcdef",
},
},
},
to: &model.Pipeline{
Commit: "1234567890abcdef",
Branch: "branch",
Message: "",
Avatar: "https://base.url/users/john.doe_mail.com/avatar.png",
Author: "John Doe",
Email: "john.doe@mail.com",
Timestamp: now.UTC().Unix(),
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)
}
})
g.It("should convert pull request event", func() {
now := time.Now()
from := &bb.PullRequestEvent{
Event: bb.Event{
Date: bb.ISOTime(now),
EventKey: bb.EventKeyPullRequestFrom,
Actor: bb.User{
Name: "John Doe",
Email: "john.doe@mail.com",
Slug: "john.doe_mail.com",
},
},
PullRequest: bb.PullRequest{
ID: 123,
Title: "my title",
Source: bb.PullRequestRef{
ID: "refs/head/branch",
DisplayID: "branch",
Latest: "1234567890abcdef",
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
},
Target: bb.PullRequestRef{
ID: "refs/head/main",
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")
g.Assert(to.Timestamp).Equal(now.UTC().Unix())
g.Assert(to.Ref).Equal("refs/pull-requests/123/from")
g.Assert(to.ForgeURL).Equal("https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef")
g.Assert(to.Event).Equal(model.EventPull)
g.Assert(to.Refspec).Equal("branch:main")
})
g.It("should close pull request", func() {
now := time.Now()
from := &bb.PullRequestEvent{
Event: bb.Event{
Date: bb.ISOTime(now),
EventKey: bb.EventKeyPullRequestMerged,
Actor: bb.User{
Name: "John Doe",
Email: "john.doe@mail.com",
Slug: "john.doe_mail.com",
},
},
PullRequest: bb.PullRequest{
ID: 123,
Title: "my title",
Source: bb.PullRequestRef{
ID: "refs/head/branch",
DisplayID: "branch",
Latest: "1234567890abcdef",
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
},
Target: bb.PullRequestRef{
ID: "refs/head/main",
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")
g.Assert(to.Timestamp).Equal(now.UTC().Unix())
g.Assert(to.Ref).Equal("refs/pull-requests/123/from")
g.Assert(to.ForgeURL).Equal("https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef")
g.Assert(to.Event).Equal(model.EventPullClosed)
g.Assert(to.Refspec).Equal("branch:main")
})
g.It("should truncate author", func() {
tests := []struct {
from string
to string
}{
{
from: "Some Short Author",
to: "Some Short Author",
},
{
from: "Some Very Long Author That May Include Multiple Names Here",
to: "Some Very Long Author That May Includ...",
},
}
for _, tt := range tests {
g.Assert(authorLabel(tt.from)).Equal(tt.to)
}
})
g.It("should convert user", func() {
from := &bb.User{
Slug: "slug",
Email: "john.doe@mail.com",
}
to := convertUser(from, "https://base.url")
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_convertStatus(t *testing.T) {
tests := []struct {
from model.StatusValue
to bb.BuildStatusState
}{
{
from: model.StatusPending,
to: bb.BuildStatusStateInProgress,
},
{
from: model.StatusRunning,
to: bb.BuildStatusStateInProgress,
},
{
from: model.StatusSuccess,
to: bb.BuildStatusStateSuccessful,
},
{
from: model.StatusValue("other"),
to: bb.BuildStatusStateFailed,
},
}
for _, tt := range tests {
to := convertStatus(tt.from)
assert.Equal(t, tt.to, to)
}
}
func Test_convertRepo(t *testing.T) {
from := &bb.Repository{
ID: uint64(1234),
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
Links: map[string][]bb.Link{
"clone": {
{
Name: "http",
Href: "https://user@git.domain/clone",
},
},
"self": {
{
Href: "https://git.domain/self",
},
},
},
}
perm := &model.Perm{}
to := convertRepo(from, perm, "main")
assert.Equal(t, &model.Repo{
ForgeRemoteID: model.ForgeRemoteID("1234"),
Name: "REPO",
Owner: "PRJ",
Branch: "main",
FullName: "PRJ/REPO",
Perm: perm,
Clone: "https://git.domain/clone",
ForgeURL: "https://git.domain/self",
PREnabled: true,
IsSCMPrivate: true,
}, to)
}
func Test_convertRepositoryPushEvent(t *testing.T) {
now := time.Now()
tests := []struct {
from *bb.RepositoryPushEvent
to *model.Pipeline
}{
{
from: &bb.RepositoryPushEvent{},
to: nil,
},
{
from: &bb.RepositoryPushEvent{
Changes: []bb.RepositoryPushEventChange{
{
FromHash: "1234567890abcdef",
ToHash: "0000000000000000000000000000000000000000",
},
},
},
to: nil,
},
{
from: &bb.RepositoryPushEvent{
Changes: []bb.RepositoryPushEventChange{
{
FromHash: "0000000000000000000000000000000000000000",
ToHash: "1234567890abcdef",
Type: bb.RepositoryPushEventChangeTypeDelete,
},
},
},
to: nil,
},
{
from: &bb.RepositoryPushEvent{
Event: bb.Event{
Date: bb.ISOTime(now),
Actor: bb.User{
Name: "John Doe",
Email: "john.doe@mail.com",
Slug: "john.doe_mail.com",
},
},
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
Changes: []bb.RepositoryPushEventChange{
{
Ref: bb.RepositoryPushEventRef{
ID: "refs/head/branch",
DisplayID: "branch",
},
RefId: "refs/head/branch",
ToHash: "1234567890abcdef",
},
},
},
to: &model.Pipeline{
Commit: "1234567890abcdef",
Branch: "branch",
Message: "",
Avatar: "https://base.url/users/john.doe_mail.com/avatar.png",
Author: "John Doe",
Email: "john.doe@mail.com",
Timestamp: now.UTC().Unix(),
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")
assert.Equal(t, tt.to, to)
}
}
func Test_convertPullRequestEvent(t *testing.T) {
now := time.Now()
from := &bb.PullRequestEvent{
Event: bb.Event{
Date: bb.ISOTime(now),
EventKey: bb.EventKeyPullRequestFrom,
Actor: bb.User{
Name: "John Doe",
Email: "john.doe@mail.com",
Slug: "john.doe_mail.com",
},
},
PullRequest: bb.PullRequest{
ID: 123,
Title: "my title",
Source: bb.PullRequestRef{
ID: "refs/head/branch",
DisplayID: "branch",
Latest: "1234567890abcdef",
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
},
Target: bb.PullRequestRef{
ID: "refs/head/main",
DisplayID: "main",
Latest: "abcdef1234567890",
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
},
},
}
to := convertPullRequestEvent(from, "https://base.url")
assert.Equal(t, &model.Pipeline{
Commit: "1234567890abcdef",
Branch: "branch",
Avatar: "https://base.url/users/john.doe_mail.com/avatar.png",
Author: "John Doe",
Email: "john.doe@mail.com",
Timestamp: now.UTC().Unix(),
Ref: "refs/pull-requests/123/from",
ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef",
Event: model.EventPull,
Refspec: "branch:main",
Title: "my title",
}, to)
}
func Test_convertPullRequestCloseEvent(t *testing.T) {
now := time.Now()
from := &bb.PullRequestEvent{
Event: bb.Event{
Date: bb.ISOTime(now),
EventKey: bb.EventKeyPullRequestMerged,
Actor: bb.User{
Name: "John Doe",
Email: "john.doe@mail.com",
Slug: "john.doe_mail.com",
},
},
PullRequest: bb.PullRequest{
ID: 123,
Title: "my title",
Source: bb.PullRequestRef{
ID: "refs/head/branch",
DisplayID: "branch",
Latest: "1234567890abcdef",
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
},
Target: bb.PullRequestRef{
ID: "refs/head/main",
DisplayID: "main",
Latest: "abcdef1234567890",
Repository: bb.Repository{
Slug: "REPO",
Project: &bb.Project{
Key: "PRJ",
},
},
},
},
}
to := convertPullRequestEvent(from, "https://base.url")
assert.Equal(t, &model.Pipeline{
Commit: "1234567890abcdef",
Branch: "branch",
Avatar: "https://base.url/users/john.doe_mail.com/avatar.png",
Author: "John Doe",
Email: "john.doe@mail.com",
Timestamp: now.UTC().Unix(),
Ref: "refs/pull-requests/123/from",
ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef",
Event: model.EventPullClosed,
Refspec: "branch:main",
Title: "my title",
}, to)
}
func Test_authorLabel(t *testing.T) {
tests := []struct {
from string
to string
}{
{
from: "Some Short Author",
to: "Some Short Author",
},
{
from: "Some Very Long Author That May Include Multiple Names Here",
//nolint:misspell
to: "Some Very Long Author That May Includ...",
},
}
for _, tt := range tests {
assert.Equal(t, tt.to, authorLabel(tt.from))
}
}
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"
"testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert"
"golang.org/x/oauth2"
)
@ -30,20 +30,14 @@ func TestCurrentUser(t *testing.T) {
_, _ = w.Write([]byte(`tal@netic.dk`))
}))
g := goblin.Goblin(t)
g.Describe("Bitbucket Current User", func() {
g.After(func() {
s.Close()
})
g.It("should return current user id", func() {
ctx := context.Background()
ts := mockSource("bearer-token")
client := NewClientWithToken(ctx, ts, s.URL)
uid, err := client.FindCurrentUser(ctx)
g.Assert(err).IsNil()
g.Assert(uid).Equal("tal_netic.dk")
})
})
defer s.Close()
ctx := context.Background()
ts := mockSource("bearer-token")
client := NewClientWithToken(ctx, ts, s.URL)
uid, err := client.FindCurrentUser(ctx)
assert.NoError(t, err)
assert.Equal(t, "tal_netic.dk", uid)
}
type mockSource string

View File

@ -21,21 +21,32 @@ import (
"net/http/httptest"
"testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"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/store"
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) {
gin.SetMode(gin.TestMode)
s := httptest.NewServer(fixtures.Handler())
defer s.Close()
c, _ := New(Opts{
URL: s.URL,
SkipVerify: true,
@ -44,122 +55,83 @@ func Test_forgejo(t *testing.T) {
mockStore := mocks_store.NewStore(t)
ctx := store.InjectToContext(context.Background(), mockStore)
g := goblin.Goblin(t)
g.Describe("Forgejo", func() {
g.After(func() {
s.Close()
})
t.Run("netrc with user token", func(t *testing.T) {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(fakeUser, fakeRepo)
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() {
g.It("Should return client with specified options", func() {
forge, _ := New(Opts{
URL: "http://localhost:8080",
SkipVerify: true,
})
t.Run("repository details", func(t *testing.T) {
repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name)
assert.NoError(t, err)
assert.Equal(t, fakeRepo.Owner, repo.Owner)
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)
g.Assert(f.url).Equal("http://localhost:8080")
g.Assert(f.SkipVerify).Equal(true)
})
})
t.Run("repository list", func(t *testing.T) {
repos, err := c.Repos(ctx, fakeUser)
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() {
g.It("Should return a netrc with the user token", func() {
forge, _ := New(Opts{})
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("")
})
})
t.Run("register repository", func(t *testing.T) {
err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost")
assert.NoError(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.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()
})
})
t.Run("remove hooks", func(t *testing.T) {
err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost")
assert.NoError(t, err)
})
g.Describe("Requesting a repository list", func() {
g.It("Should return the repository list", func() {
repos, err := c.Repos(ctx, fakeUser)
g.Assert(err).IsNil()
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()
})
})
t.Run("repository file", func(t *testing.T) {
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml")
assert.NoError(t, err)
assert.Equal(t, "{ platform: linux/amd64 }", string(raw))
})
g.It("Should register repository hooks", func() {
err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost")
g.Assert(err).IsNil()
})
t.Run("pipeline status", func(t *testing.T) {
err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
assert.NoError(t, err)
})
g.It("Should remove repository hooks", func() {
err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost")
g.Assert(err).IsNil()
})
g.It("Should return a repository file", func() {
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml")
g.Assert(err).IsNil()
g.Assert(string(raw)).Equal("{ platform: linux/amd64 }")
})
g.It("Should return nil from send pipeline status", func() {
err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
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()
})
t.Run("PR hook", func(t *testing.T) {
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)
assert.NotNil(t, r)
assert.NotNil(t, b)
assert.NoError(t, err)
assert.Equal(t, model.EventPull, b.Event)
assert.Equal(t, []string{"README.md"}, b.ChangedFiles)
})
}

View File

@ -19,255 +19,252 @@ import (
"testing"
"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/model"
"go.woodpecker-ci.org/woodpecker/v3/shared/utils"
)
func Test_parse(t *testing.T) {
g := goblin.Goblin(t)
g.Describe("Forgejo", func() {
g.It("Should parse push hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePush(buf)
g.Assert(err).IsNil()
g.Assert(hook.Ref).Equal("refs/heads/main")
g.Assert(hook.After).Equal("ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Before).Equal("4b2626259b5a97b6b4eab5e6cca66adb986b672b")
g.Assert(hook.Compare).Equal("http://forgejo.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world")
g.Assert(hook.Repo.Owner.UserName).Equal("gordon")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Pusher.Email).Equal("gordon@golang.org")
g.Assert(hook.Pusher.UserName).Equal("gordon")
g.Assert(hook.Sender.UserName).Equal("gordon")
g.Assert(hook.Sender.AvatarURL).Equal("http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
})
func Test_parsePush(t *testing.T) {
t.Run("Should parse push hook payload", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePush(buf)
assert.NoError(t, err)
assert.Equal(t, "refs/heads/main", hook.Ref)
assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.After)
assert.Equal(t, "4b2626259b5a97b6b4eab5e6cca66adb986b672b", hook.Before)
assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5", hook.Compare)
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", hook.Repo.Owner.UserName)
assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
assert.True(t, hook.Repo.Private)
assert.Equal(t, "gordon@golang.org", hook.Pusher.Email)
assert.Equal(t, "gordon", hook.Pusher.UserName)
assert.Equal(t, "gordon", hook.Sender.UserName)
assert.Equal(t, "http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
})
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() {
buf := bytes.NewBufferString(fixtures.HookTag)
hook, err := parsePush(buf)
g.Assert(err).IsNil()
g.Assert(hook.Ref).Equal("v1.0.0")
g.Assert(hook.Sha).Equal("ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Owner.UserName).Equal("gordon")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Sender.UserName).Equal("gordon")
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
})
t.Run("Should return a Pipeline struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
pipeline := pipelineFromPush(hook)
assert.Equal(t, model.EventPush, pipeline.Event)
assert.Equal(t, hook.After, pipeline.Commit)
assert.Equal(t, hook.Ref, pipeline.Ref)
assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL)
assert.Equal(t, "main", pipeline.Branch)
assert.Equal(t, hook.Commits[0].Message, pipeline.Message)
assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar)
assert.Equal(t, hook.Sender.UserName, pipeline.Author)
assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles)
})
g.It("Should parse pull_request hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, err := parsePullRequest(buf)
g.Assert(err).IsNil()
g.Assert(hook.Action).Equal("opened")
g.Assert(hook.Number).Equal(int64(1))
t.Run("Should return a Repo struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(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)
})
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Owner.UserName).Equal("gordon")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Sender.UserName).Equal("gordon")
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(hook.PullRequest.Title).Equal("Update the README with new information")
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)
}
})
t.Run("Should return a Pipeline struct from a tag hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookTag)
hook, _ := parsePush(buf)
pipeline := pipelineFromTag(hook)
assert.Equal(t, model.EventTag, pipeline.Event)
assert.Equal(t, hook.Sha, pipeline.Commit)
assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref)
assert.Empty(t, pipeline.Branch)
assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL)
assert.Equal(t, "created tag v1.0.0", pipeline.Message)
})
}
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"
"testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"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/store"
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) {
gin.SetMode(gin.TestMode)
s := httptest.NewServer(fixtures.Handler())
defer s.Close()
c, _ := New(Opts{
URL: s.URL,
SkipVerify: true,
@ -45,122 +56,83 @@ func Test_gitea(t *testing.T) {
mockStore := mocks_store.NewStore(t)
ctx := store.InjectToContext(context.Background(), mockStore)
g := goblin.Goblin(t)
g.Describe("Gitea", func() {
g.After(func() {
s.Close()
})
t.Run("netrc with user token", func(t *testing.T) {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(fakeUser, fakeRepo)
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() {
g.It("Should return client with specified options", func() {
forge, _ := New(Opts{
URL: "http://localhost:8080",
SkipVerify: true,
})
t.Run("repository details", func(t *testing.T) {
repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name)
assert.NoError(t, err)
assert.Equal(t, fakeRepo.Owner, repo.Owner)
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)
g.Assert(f.url).Equal("http://localhost:8080")
g.Assert(f.SkipVerify).Equal(true)
})
})
t.Run("repository list", func(t *testing.T) {
repos, err := c.Repos(ctx, fakeUser)
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() {
g.It("Should return a netrc with the user token", func() {
forge, _ := New(Opts{})
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("")
})
})
t.Run("register repository", func(t *testing.T) {
err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost")
assert.NoError(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.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()
})
})
t.Run("remove hooks", func(t *testing.T) {
err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost")
assert.NoError(t, err)
})
g.Describe("Requesting a repository list", func() {
g.It("Should return the repository list", func() {
repos, err := c.Repos(ctx, fakeUser)
g.Assert(err).IsNil()
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()
})
})
t.Run("repository file", func(t *testing.T) {
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml")
assert.NoError(t, err)
assert.Equal(t, "{ platform: linux/amd64 }", string(raw))
})
g.It("Should register repository hooks", func() {
err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost")
g.Assert(err).IsNil()
})
t.Run("pipeline status", func(t *testing.T) {
err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
assert.NoError(t, err)
})
g.It("Should remove repository hooks", func() {
err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost")
g.Assert(err).IsNil()
})
g.It("Should return a repository file", func() {
raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml")
g.Assert(err).IsNil()
g.Assert(string(raw)).Equal("{ platform: linux/amd64 }")
})
g.It("Should return nil from send pipeline status", func() {
err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow)
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()
})
t.Run("PR hook", func(t *testing.T) {
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)
assert.NotNil(t, r)
assert.NotNil(t, b)
assert.NoError(t, err)
assert.Equal(t, model.EventPull, b.Event)
assert.Equal(t, []string{"README.md"}, b.ChangedFiles)
})
}

View File

@ -20,255 +20,252 @@ import (
"testing"
"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/model"
"go.woodpecker-ci.org/woodpecker/v3/shared/utils"
)
func Test_parse(t *testing.T) {
g := goblin.Goblin(t)
g.Describe("Gitea", func() {
g.It("Should parse push hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePush(buf)
g.Assert(err).IsNil()
g.Assert(hook.Ref).Equal("refs/heads/main")
g.Assert(hook.After).Equal("ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Before).Equal("4b2626259b5a97b6b4eab5e6cca66adb986b672b")
g.Assert(hook.Compare).Equal("http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world")
g.Assert(hook.Repo.Owner.UserName).Equal("gordon")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Pusher.Email).Equal("gordon@golang.org")
g.Assert(hook.Pusher.UserName).Equal("gordon")
g.Assert(hook.Sender.UserName).Equal("gordon")
g.Assert(hook.Sender.AvatarURL).Equal("http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
})
func Test_parsePush(t *testing.T) {
t.Run("Should parse push hook payload", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, err := parsePush(buf)
assert.NoError(t, err)
assert.Equal(t, "refs/heads/main", hook.Ref)
assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.After)
assert.Equal(t, "4b2626259b5a97b6b4eab5e6cca66adb986b672b", hook.Before)
assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5", hook.Compare)
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", hook.Repo.Owner.UserName)
assert.Equal(t, "gordon/hello-world", hook.Repo.FullName)
assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email)
assert.True(t, hook.Repo.Private)
assert.Equal(t, "gordon@golang.org", hook.Pusher.Email)
assert.Equal(t, "gordon", hook.Pusher.UserName)
assert.Equal(t, "gordon", hook.Sender.UserName)
assert.Equal(t, "http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL)
})
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() {
buf := bytes.NewBufferString(fixtures.HookTag)
hook, err := parsePush(buf)
g.Assert(err).IsNil()
g.Assert(hook.Ref).Equal("v1.0.0")
g.Assert(hook.Sha).Equal("ef98532add3b2feb7a137426bba1248724367df5")
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Owner.UserName).Equal("gordon")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Sender.UserName).Equal("gordon")
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
})
t.Run("Should return a Pipeline struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)
pipeline := pipelineFromPush(hook)
assert.Equal(t, model.EventPush, pipeline.Event)
assert.Equal(t, hook.After, pipeline.Commit)
assert.Equal(t, hook.Ref, pipeline.Ref)
assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL)
assert.Equal(t, "main", pipeline.Branch)
assert.Equal(t, hook.Commits[0].Message, pipeline.Message)
assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar)
assert.Equal(t, hook.Sender.UserName, pipeline.Author)
assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles)
})
g.It("Should parse pull_request hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPullRequest)
hook, err := parsePullRequest(buf)
g.Assert(err).IsNil()
g.Assert(hook.Action).Equal("opened")
g.Assert(hook.Number).Equal(int64(1))
t.Run("Should return a Repo struct from a push hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(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)
})
g.Assert(hook.Repo.Name).Equal("hello-world")
g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world")
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
g.Assert(hook.Repo.Owner.UserName).Equal("gordon")
g.Assert(hook.Repo.Private).Equal(true)
g.Assert(hook.Sender.UserName).Equal("gordon")
g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
g.Assert(hook.PullRequest.Title).Equal("Update the README with new information")
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)
}
})
t.Run("Should return a Pipeline struct from a tag hook", func(t *testing.T) {
buf := bytes.NewBufferString(fixtures.HookTag)
hook, _ := parsePush(buf)
pipeline := pipelineFromTag(hook)
assert.Equal(t, model.EventTag, pipeline.Event)
assert.Equal(t, hook.Sha, pipeline.Commit)
assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref)
assert.Empty(t, pipeline.Branch)
assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL)
assert.Equal(t, "created tag v1.0.0", pipeline.Message)
})
}
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 (
"testing"
"github.com/franela/goblin"
"github.com/google/go-github/v68/github"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
)
func Test_helper(t *testing.T) {
g := goblin.Goblin(t)
g.Describe("GitHub converter", func() {
g.It("should convert passing status", func() {
g.Assert(convertStatus(model.StatusSuccess)).Equal(statusSuccess)
})
func Test_convertStatus(t *testing.T) {
assert.Equal(t, statusSuccess, convertStatus(model.StatusSuccess))
assert.Equal(t, statusPending, convertStatus(model.StatusPending))
assert.Equal(t, statusPending, convertStatus(model.StatusRunning))
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() {
g.Assert(convertStatus(model.StatusPending)).Equal(statusPending)
g.Assert(convertStatus(model.StatusRunning)).Equal(statusPending)
})
func Test_convertDesc(t *testing.T) {
assert.Equal(t, descSuccess, convertDesc(model.StatusSuccess))
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() {
g.Assert(convertStatus(model.StatusFailure)).Equal(statusFailure)
})
g.It("should convert error status", func() {
g.Assert(convertStatus(model.StatusKilled)).Equal(statusError)
g.Assert(convertStatus(model.StatusError)).Equal(statusError)
})
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"),
func Test_convertRepoList(t *testing.T) {
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://..."),
}
to := convertTeam(from)
g.Assert(to.Login).Equal("octocat")
g.Assert(to.Avatar).Equal("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,
},
},
}
g.It("should convert team list", func() {
from := []*github.Organization{
{
Login: github.Ptr("octocat"),
AvatarURL: github.Ptr("http://..."),
},
}
to := convertTeamList(from)
g.Assert(to[0].Login).Equal("octocat")
g.Assert(to[0].Avatar).Equal("http://...")
})
to := convertRepoList(from)
assert.Equal(t, "http://...", to[0].Avatar)
assert.Equal(t, "octocat/hello-world", to[0].FullName)
assert.Equal(t, "octocat", to[0].Owner)
assert.Equal(t, "hello-world", to[0].Name)
}
g.It("should convert a repository from webhook", func() {
from := &github.PushEventRepository{Owner: &github.User{}}
from.Owner.Login = github.Ptr("octocat")
from.Owner.Name = github.Ptr("octocat")
from.Name = github.Ptr("hello-world")
from.FullName = github.Ptr("octocat/hello-world")
from.Private = github.Ptr(true)
from.HTMLURL = github.Ptr("https://github.com/octocat/hello-world")
from.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git")
from.DefaultBranch = github.Ptr("develop")
func Test_convertRepo(t *testing.T) {
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,
},
}
repo := convertRepoHook(from)
g.Assert(repo.Owner).Equal(*from.Owner.Login)
g.Assert(repo.Name).Equal(*from.Name)
g.Assert(repo.FullName).Equal(*from.FullName)
g.Assert(repo.IsSCMPrivate).Equal(*from.Private)
g.Assert(repo.ForgeURL).Equal(*from.HTMLURL)
g.Assert(repo.Clone).Equal(*from.CloneURL)
g.Assert(repo.Branch).Equal(*from.DefaultBranch)
})
to := convertRepo(&from)
assert.Equal(t, "http://...", to.Avatar)
assert.Equal(t, "octocat/hello-world", to.FullName)
assert.Equal(t, "octocat", to.Owner)
assert.Equal(t, "hello-world", to.Name)
assert.Equal(t, "develop", to.Branch)
assert.True(t, to.IsSCMPrivate)
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() {
from := &github.PullRequestEvent{
Action: github.Ptr(actionOpen),
PullRequest: &github.PullRequest{
State: github.Ptr(stateOpen),
HTMLURL: github.Ptr("https://github.com/octocat/hello-world/pulls/42"),
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)
})
func Test_convertPerm(t *testing.T) {
from := &github.Repository{
Permissions: map[string]bool{
"admin": true,
"push": true,
"pull": true,
},
}
g.It("should convert a deployment from webhook", func() {
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")
to := convertPerm(from.GetPermissions())
assert.True(t, to.Push)
assert.True(t, to.Pull)
assert.True(t, to.Admin)
}
_, pipeline := parseDeployHook(from)
g.Assert(pipeline.Event).Equal(model.EventDeploy)
g.Assert(pipeline.Branch).Equal("main")
g.Assert(pipeline.Ref).Equal("refs/heads/main")
g.Assert(pipeline.Commit).Equal(*from.Deployment.SHA)
g.Assert(pipeline.Message).Equal(*from.Deployment.Description)
g.Assert(pipeline.ForgeURL).Equal(*from.Deployment.URL)
g.Assert(pipeline.Author).Equal(*from.Sender.Login)
g.Assert(pipeline.Avatar).Equal(*from.Sender.AvatarURL)
})
func Test_convertTeam(t *testing.T) {
from := &github.Organization{
Login: github.Ptr("octocat"),
AvatarURL: github.Ptr("http://..."),
}
to := convertTeam(from)
assert.Equal(t, "octocat", to.Login)
assert.Equal(t, "http://...", to.Avatar)
}
g.It("should convert a push from webhook", func() {
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")
func Test_convertTeamList(t *testing.T) {
from := []*github.Organization{
{
Login: github.Ptr("octocat"),
AvatarURL: github.Ptr("http://..."),
},
}
to := convertTeamList(from)
assert.Equal(t, "octocat", to[0].Login)
assert.Equal(t, "http://...", to[0].Avatar)
}
_, pipeline := parsePushHook(from)
g.Assert(pipeline.Event).Equal(model.EventPush)
g.Assert(pipeline.Branch).Equal("main")
g.Assert(pipeline.Ref).Equal("refs/heads/main")
g.Assert(pipeline.Commit).Equal(*from.HeadCommit.ID)
g.Assert(pipeline.Message).Equal(*from.HeadCommit.Message)
g.Assert(pipeline.ForgeURL).Equal(*from.HeadCommit.URL)
g.Assert(pipeline.Author).Equal(*from.Sender.Login)
g.Assert(pipeline.Avatar).Equal(*from.Sender.AvatarURL)
g.Assert(pipeline.Email).Equal(*from.HeadCommit.Author.Email)
})
func Test_convertRepoHook(t *testing.T) {
t.Run("should convert a repository from webhook", func(t *testing.T) {
from := &github.PushEventRepository{Owner: &github.User{}}
from.Owner.Login = github.Ptr("octocat")
from.Owner.Name = github.Ptr("octocat")
from.Name = github.Ptr("hello-world")
from.FullName = github.Ptr("octocat/hello-world")
from.Private = github.Ptr(true)
from.HTMLURL = github.Ptr("https://github.com/octocat/hello-world")
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() {
from := &github.PushEvent{}
from.Ref = github.Ptr("refs/tags/v1.0.0")
_, pipeline := parsePushHook(from)
g.Assert(pipeline.Event).Equal(model.EventTag)
g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0")
})
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")
from.BaseRef = github.Ptr("refs/heads/main")
_, pipeline := parsePushHook(from)
g.Assert(pipeline.Event).Equal(model.EventTag)
g.Assert(pipeline.Branch).Equal("main")
})
g.It("should not convert tag's base_ref from webhook if not prefixed with 'ref/heads/'", func() {
from := &github.PushEvent{}
from.Ref = github.Ptr("refs/tags/v1.0.0")
from.BaseRef = github.Ptr("refs/refs/main")
_, pipeline := parsePushHook(from)
g.Assert(pipeline.Event).Equal(model.EventTag)
g.Assert(pipeline.Branch).Equal("refs/tags/v1.0.0")
})
repo := convertRepoHook(from)
assert.Equal(t, *from.Owner.Login, repo.Owner)
assert.Equal(t, *from.Name, repo.Name)
assert.Equal(t, *from.FullName, repo.FullName)
assert.Equal(t, *from.Private, repo.IsSCMPrivate)
assert.Equal(t, *from.HTMLURL, repo.ForgeURL)
assert.Equal(t, *from.CloneURL, repo.Clone)
assert.Equal(t, *from.DefaultBranch, repo.Branch)
})
}
func Test_parsePullHook(t *testing.T) {
from := &github.PullRequestEvent{
Action: github.Ptr(actionOpen),
PullRequest: &github.PullRequest{
State: github.Ptr(stateOpen),
HTMLURL: github.Ptr("https://github.com/octocat/hello-world/pulls/42"),
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)
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"
"testing"
"github.com/franela/goblin"
"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/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) {
gin.SetMode(gin.TestMode)
@ -36,80 +51,39 @@ func Test_github(t *testing.T) {
SkipVerify: true,
})
defer s.Close()
ctx := context.Background()
g := goblin.Goblin(t)
g.Describe("GitHub", func() {
g.After(func() {
s.Close()
})
g.Describe("Creating a forge", func() {
g.It("Should return client with specified options", func() {
forge, _ := New(Opts{
URL: "http://localhost:8080/",
Client: "0ZXh0IjoiI",
Secret: "I1NiIsInR5",
SkipVerify: true,
})
f, _ := forge.(*client)
g.Assert(f.url).Equal("http://localhost:8080")
g.Assert(f.API).Equal("http://localhost:8080/api/v3/")
g.Assert(f.Client).Equal("0ZXh0IjoiI")
g.Assert(f.Secret).Equal("I1NiIsInR5")
g.Assert(f.SkipVerify).Equal(true)
})
})
t.Run("netrc with user token", func(t *testing.T) {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(fakeUser, fakeRepo)
assert.Equal(t, "github.com", netrc.Machine)
assert.Equal(t, fakeUser.AccessToken, netrc.Login)
assert.Equal(t, "x-oauth-basic", netrc.Password)
})
t.Run("netrc with machine account", func(t *testing.T) {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(nil, fakeRepo)
assert.Equal(t, "github.com", netrc.Machine)
assert.Empty(t, netrc.Login)
assert.Empty(t, netrc.Password)
})
g.Describe("Generating a netrc file", func() {
g.It("Should return a netrc with the user token", func() {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(fakeUser, fakeRepo)
g.Assert(netrc.Machine).Equal("github.com")
g.Assert(netrc.Login).Equal(fakeUser.AccessToken)
g.Assert(netrc.Password).Equal("x-oauth-basic")
})
g.It("Should return a netrc with the machine account", func() {
forge, _ := New(Opts{})
netrc, _ := forge.Netrc(nil, fakeRepo)
g.Assert(netrc.Machine).Equal("github.com")
g.Assert(netrc.Login).Equal("")
g.Assert(netrc.Password).Equal("")
})
})
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")
})
t.Run("Should return the repository details", func(t *testing.T) {
repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name)
assert.NoError(t, err)
assert.Equal(t, fakeRepo.ForgeRemoteID, repo.ForgeRemoteID)
assert.Equal(t, fakeRepo.Owner, repo.Owner)
assert.Equal(t, fakeRepo.Name, repo.Name)
assert.Equal(t, fakeRepo.FullName, repo.FullName)
assert.True(t, repo.IsSCMPrivate)
assert.Equal(t, fakeRepo.Clone, repo.Clone)
assert.Equal(t, fakeRepo.ForgeURL, repo.ForgeURL)
})
t.Run("repo not found error", func(t *testing.T) {
_, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name)
assert.Error(t, err)
})
}

View File

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

View File

@ -23,7 +23,6 @@ import (
"strconv"
"testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/forge/gitlab/testdata"
@ -70,234 +69,214 @@ func Test_GitLab(t *testing.T) {
}
ctx := context.Background()
g := goblin.Goblin(t)
g.Describe("GitLab Plugin", func() {
// Test projects method
g.Describe("AllProjects", func() {
g.It("Should return only non-archived projects is hidden", func() {
client.HideArchives = true
_projects, err := client.Repos(ctx, &user)
assert.NoError(t, err)
assert.Len(t, _projects, 1)
})
// Test projects method
t.Run("Should return only non-archived projects is hidden", func(t *testing.T) {
client.HideArchives = true
_projects, err := client.Repos(ctx, &user)
assert.NoError(t, err)
assert.Len(t, _projects, 1)
})
g.It("Should return all the projects", func() {
client.HideArchives = false
_projects, err := client.Repos(ctx, &user)
t.Run("Should return all the projects", func(t *testing.T) {
client.HideArchives = false
_projects, err := client.Repos(ctx, &user)
g.Assert(err).IsNil()
g.Assert(len(_projects)).Equal(2)
})
})
assert.NoError(t, err)
assert.Len(t, _projects, 2)
})
// Test repository method
g.Describe("Repo", func() {
g.It("Should return valid repo", func() {
_repo, err := client.Repo(ctx, &user, "0", "diaspora", "diaspora-client")
assert.NoError(t, err)
assert.Equal(t, "diaspora-client", _repo.Name)
assert.Equal(t, "diaspora", _repo.Owner)
assert.True(t, _repo.IsSCMPrivate)
})
// Test repository method
t.Run("Should return valid repo", func(t *testing.T) {
_repo, err := client.Repo(ctx, &user, "0", "diaspora", "diaspora-client")
assert.NoError(t, err)
assert.Equal(t, "diaspora-client", _repo.Name)
assert.Equal(t, "diaspora", _repo.Owner)
assert.True(t, _repo.IsSCMPrivate)
})
g.It("Should return error, when repo not exist", func() {
_, err := client.Repo(ctx, &user, "0", "not-existed", "not-existed")
assert.Error(t, err)
})
t.Run("Should return error, when repo not exist", func(t *testing.T) {
_, err := client.Repo(ctx, &user, "0", "not-existed", "not-existed")
assert.Error(t, err)
})
g.It("Should return repo with push access, when user inherits membership from namespace", func() {
_repo, err := client.Repo(ctx, &user, "6", "brightbox", "puppet")
assert.NoError(t, err)
assert.True(t, _repo.Perm.Push)
})
})
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")
assert.NoError(t, err)
assert.True(t, _repo.Perm.Push)
})
// Test activate method
g.Describe("Activate", func() {
g.It("Should be success", func() {
err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token")
assert.NoError(t, err)
})
// Test activate method
t.Run("Activate, success", func(t *testing.T) {
err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token")
assert.NoError(t, err)
})
g.It("Should be failed, when token not given", func() {
err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook")
t.Run("Activate, failed no token", func(t *testing.T) {
err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook")
g.Assert(err).IsNotNil()
})
})
assert.Error(t, err)
})
// Test deactivate method
g.Describe("Deactivate", func() {
g.It("Should be success", func() {
err := client.Deactivate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token")
// Test deactivate method
t.Run("Deactivate", func(t *testing.T) {
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
g.Describe("Hook", func() {
g.Describe("Push hook", func() {
g.It("Should parse actual push hook", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPush),
)
req.Header = testdata.ServiceHookHeaders
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, pipeline.Event, model.EventPush)
assert.Equal(t, "test", hookRepo.Owner)
assert.Equal(t, "woodpecker", hookRepo.Name)
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
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)
}
})
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, pipeline.Event, model.EventPush)
assert.Equal(t, "test", hookRepo.Owner)
assert.Equal(t, "woodpecker", hookRepo.Name)
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
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)
}
})
})
t.Run("tag push hook", func(t *testing.T) {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookTag),
)
req.Header = testdata.ServiceHookHeaders
g.Describe("Tag push hook", func() {
g.It("Should parse tag push hook", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookTag),
)
req.Header = testdata.ServiceHookHeaders
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "test", hookRepo.Owner)
assert.Equal(t, "woodpecker", hookRepo.Name)
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
assert.Equal(t, "develop", hookRepo.Branch)
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)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "test", hookRepo.Owner)
assert.Equal(t, "woodpecker", hookRepo.Name)
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
assert.Equal(t, "develop", hookRepo.Branch)
assert.Equal(t, "refs/tags/v22", pipeline.Ref)
assert.Len(t, pipeline.ChangedFiles, 0)
assert.Equal(t, model.EventTag, pipeline.Event)
}
})
})
t.Run("merge request hook", func(t *testing.T) {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequest),
)
req.Header = testdata.ServiceHookHeaders
g.Describe("Merge request hook", func() {
g.It("Should parse merge request hook", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequest),
)
req.Header = testdata.ServiceHookHeaders
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
assert.Equal(t, "main", hookRepo.Branch)
assert.Equal(t, "anbraten", hookRepo.Owner)
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
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar)
assert.Equal(t, "main", hookRepo.Branch)
assert.Equal(t, "anbraten", hookRepo.Owner)
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)
}
})
t.Run("ignore merge request hook without changes", func(t *testing.T) {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestWithoutChanges),
)
req.Header = testdata.ServiceHookHeaders
g.It("Should ignore merge request hook without changes", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestWithoutChanges),
)
req.Header = testdata.ServiceHookHeaders
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.Nil(t, hookRepo)
assert.Nil(t, pipeline)
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
})
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.Nil(t, hookRepo)
assert.Nil(t, pipeline)
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
})
t.Run("ignore merge request approval", func(t *testing.T) {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestApproved),
)
req.Header = testdata.ServiceHookHeaders
g.It("Should ignore merge request approval", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestApproved),
)
req.Header = testdata.ServiceHookHeaders
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.Nil(t, hookRepo)
assert.Nil(t, pipeline)
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
})
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.Nil(t, hookRepo)
assert.Nil(t, pipeline)
assert.ErrorIs(t, err, &types.ErrIgnoreEvent{})
})
t.Run("parse merge request closed", func(t *testing.T) {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestClosed),
)
req.Header = testdata.ServiceHookHeaders
g.It("Should parse merge request hook when MR closed", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestClosed),
)
req.Header = testdata.ServiceHookHeaders
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "main", hookRepo.Branch)
assert.Equal(t, "anbraten", hookRepo.Owner)
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
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "main", hookRepo.Branch)
assert.Equal(t, "anbraten", hookRepo.Owner)
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)
}
})
t.Run("parse merge request merged", func(t *testing.T) {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestMerged),
)
req.Header = testdata.ServiceHookHeaders
g.It("Should parse merge request hook when merged", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.HookPullRequestMerged),
)
req.Header = testdata.ServiceHookHeaders
// TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "main", hookRepo.Branch)
assert.Equal(t, "anbraten", hookRepo.Owner)
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
hookRepo, pipeline, err := client.Hook(ctx, req)
assert.NoError(t, err)
if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) {
assert.Equal(t, "main", hookRepo.Branch)
assert.Equal(t, "anbraten", hookRepo.Owner)
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)
}
})
t.Run("release hook", func(t *testing.T) {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.WebhookReleaseBody),
)
req.Header = testdata.ReleaseHookHeaders
g.It("Should parse release request hook", func() {
req, _ := http.NewRequest(
testdata.ServiceHookMethod,
testdata.ServiceHookURL.String(),
bytes.NewReader(testdata.WebhookReleaseBody),
)
req.Header = testdata.ReleaseHookHeaders
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)
}
})
})
})
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"
"time"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc/metadata"
@ -30,92 +29,87 @@ import (
)
func TestRegisterAgent(t *testing.T) {
g := goblin.Goblin(t)
g.Describe("When existing agent Name is empty", func() {
g.It("Should update Name with hostname from metadata", func() {
store := mocks_store.NewStore(t)
storeAgent := new(model.Agent)
storeAgent.ID = 1337
updatedAgent := model.Agent{
ID: 1337,
Created: 0,
Updated: 0,
Name: "hostname",
OwnerID: 0,
Token: "",
LastContact: 0,
Platform: "platform",
Backend: "backend",
Capacity: 2,
Version: "version",
NoSchedule: false,
}
t.Run("When existing agent Name is empty it should update Name with hostname from metadata", func(t *testing.T) {
store := mocks_store.NewStore(t)
storeAgent := new(model.Agent)
storeAgent.ID = 1337
updatedAgent := model.Agent{
ID: 1337,
Created: 0,
Updated: 0,
Name: "hostname",
OwnerID: 0,
Token: "",
LastContact: 0,
Platform: "platform",
Backend: "backend",
Capacity: 2,
Version: "version",
NoSchedule: false,
}
store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil)
store.On("AgentUpdate", &updatedAgent).Once().Return(nil)
grpc := RPC{
store: store,
}
ctx := metadata.NewIncomingContext(
context.Background(),
metadata.Pairs("hostname", "hostname", "agent_id", "1337"),
)
agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{
Version: "version",
Platform: "platform",
Backend: "backend",
Capacity: 2,
})
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil)
store.On("AgentUpdate", &updatedAgent).Once().Return(nil)
grpc := RPC{
store: store,
}
ctx := metadata.NewIncomingContext(
context.Background(),
metadata.Pairs("hostname", "hostname", "agent_id", "1337"),
)
agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{
Version: "version",
Platform: "platform",
Backend: "backend",
Capacity: 2,
})
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
})
g.Describe("When existing agent hostname is present", func() {
g.It("Should not update the hostname", func() {
store := mocks_store.NewStore(t)
storeAgent := new(model.Agent)
storeAgent.ID = 1337
storeAgent.Name = "originalHostname"
updatedAgent := model.Agent{
ID: 1337,
Created: 0,
Updated: 0,
Name: "originalHostname",
OwnerID: 0,
Token: "",
LastContact: 0,
Platform: "platform",
Backend: "backend",
Capacity: 2,
Version: "version",
NoSchedule: false,
}
t.Run("When existing agent hostname is present it should not update the hostname", func(t *testing.T) {
store := mocks_store.NewStore(t)
storeAgent := new(model.Agent)
storeAgent.ID = 1337
storeAgent.Name = "originalHostname"
updatedAgent := model.Agent{
ID: 1337,
Created: 0,
Updated: 0,
Name: "originalHostname",
OwnerID: 0,
Token: "",
LastContact: 0,
Platform: "platform",
Backend: "backend",
Capacity: 2,
Version: "version",
NoSchedule: false,
}
store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil)
store.On("AgentUpdate", &updatedAgent).Once().Return(nil)
grpc := RPC{
store: store,
}
ctx := metadata.NewIncomingContext(
context.Background(),
metadata.Pairs("hostname", "newHostname", "agent_id", "1337"),
)
agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{
Version: "version",
Platform: "platform",
Backend: "backend",
Capacity: 2,
})
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil)
store.On("AgentUpdate", &updatedAgent).Once().Return(nil)
grpc := RPC{
store: store,
}
ctx := metadata.NewIncomingContext(
context.Background(),
metadata.Pairs("hostname", "newHostname", "agent_id", "1337"),
)
agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{
Version: "version",
Platform: "platform",
Backend: "backend",
Capacity: 2,
})
if !assert.NoError(t, err) {
return
}
assert.EqualValues(t, 1337, agentID)
})
}

View File

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

View File

@ -17,7 +17,7 @@ package secret_test
import (
"testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
@ -25,12 +25,8 @@ import (
mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks"
)
func TestSecretListPipeline(t *testing.T) {
g := goblin.Goblin(t)
mockStore := mocks_store.NewStore(t)
// global secret
globalSecret := &model.Secret{
var (
globalSecret = &model.Secret{
ID: 1,
OrgID: 0,
RepoID: 0,
@ -38,8 +34,7 @@ func TestSecretListPipeline(t *testing.T) {
Value: "value-global",
}
// org secret
orgSecret := &model.Secret{
orgSecret = &model.Secret{
ID: 2,
OrgID: 1,
RepoID: 0,
@ -47,53 +42,48 @@ func TestSecretListPipeline(t *testing.T) {
Value: "value-org",
}
// repo secret
repoSecret := &model.Secret{
repoSecret = &model.Secret{
ID: 3,
OrgID: 0,
RepoID: 1,
Name: "secret",
Value: "value-repo",
}
)
g.Describe("Priority of secrets", func() {
g.It("should get the repo secret", func() {
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
globalSecret,
orgSecret,
repoSecret,
}, nil)
func TestSecretListPipeline(t *testing.T) {
mockStore := mocks_store.NewStore(t)
s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
g.Assert(err).IsNil()
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
globalSecret,
orgSecret,
repoSecret,
}, nil)
g.Assert(len(s)).Equal(1)
g.Assert(s[0].Value).Equal("value-repo")
})
s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
assert.NoError(t, err)
g.It("should get the org secret", func() {
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
globalSecret,
orgSecret,
}, nil)
assert.Len(t, s, 1)
assert.Equal(t, "value-repo", s[0].Value)
s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
g.Assert(err).IsNil()
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
globalSecret,
orgSecret,
}, nil)
g.Assert(len(s)).Equal(1)
g.Assert(s[0].Value).Equal("value-org")
})
s, err = secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
assert.NoError(t, err)
g.It("should get the global secret", func() {
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
globalSecret,
}, nil)
assert.Len(t, s, 1)
assert.Equal(t, "value-org", s[0].Value)
s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
g.Assert(err).IsNil()
mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{
globalSecret,
}, nil)
g.Assert(len(s)).Equal(1)
g.Assert(s[0].Value).Equal("value-global")
})
})
s, err = secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{})
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
import (
"fmt"
"testing"
"time"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert"
"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))
defer closer()
g := goblin.Goblin(t)
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()
})
assert.NoError(t, store.CreateRepo(repo))
// before each test be sure to purge the package
// table data from the database.
g.BeforeEach(func() {
_, err := store.engine.Exec("DELETE FROM pipelines")
g.Assert(err).IsNil()
_, err = store.engine.Exec("DELETE FROM steps")
g.Assert(err).IsNil()
})
// Fail when the repo is not existing
pipeline := model.Pipeline{
RepoID: 100,
Status: model.StatusSuccess,
}
err := store.CreatePipeline(&pipeline)
assert.Error(t, err)
g.It("Should Fail early when the repo is not existing", func() {
pipeline := model.Pipeline{
RepoID: 100,
Status: model.StatusSuccess,
}
err := store.CreatePipeline(&pipeline)
g.Assert(err).IsNotNil()
count, err := store.GetPipelineCount()
assert.NoError(t, err)
assert.Zero(t, count)
count, err := store.GetPipelineCount()
g.Assert(err).IsNil()
g.Assert(count == 0).IsTrue()
fmt.Println("GOT COUNT", count)
})
// add pipeline
pipeline = model.Pipeline{
RepoID: repo.ID,
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() {
pipeline := model.Pipeline{
RepoID: repo.ID,
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()
assert.NoError(t, err)
assert.NotZero(t, count)
count, err := store.GetPipelineCount()
g.Assert(err).IsNil()
g.Assert(count > 0).IsTrue()
fmt.Println("GOT COUNT", count)
})
GetPipeline, err := store.GetPipeline(pipeline.ID)
assert.NoError(t, err)
assert.Equal(t, pipeline.ID, GetPipeline.ID)
assert.Equal(t, pipeline.RepoID, GetPipeline.RepoID)
assert.Equal(t, pipeline.Status, GetPipeline.Status)
g.It("Should Put a Pipeline", func() {
pipeline := model.Pipeline{
RepoID: repo.ID,
Number: 5,
Status: model.StatusSuccess,
Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
err := store.CreatePipeline(&pipeline)
g.Assert(err).IsNil()
pipeline.Status = model.StatusRunning
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)
})
// update pipeline
pipeline.Status = model.StatusRunning
err1 := store.UpdatePipeline(&pipeline)
GetPipeline, err2 := store.GetPipeline(pipeline.ID)
assert.NoError(t, err1)
assert.NoError(t, err2)
assert.Equal(t, pipeline.ID, GetPipeline.ID)
assert.Equal(t, pipeline.RepoID, GetPipeline.RepoID)
assert.Equal(t, pipeline.Status, GetPipeline.Status)
assert.Equal(t, pipeline.Number, GetPipeline.Number)
g.It("Should Get a Pipeline", func() {
pipeline := model.Pipeline{
RepoID: repo.ID,
Status: model.StatusSuccess,
}
err := store.CreatePipeline(&pipeline, []*model.Step{}...)
g.Assert(err).IsNil()
GetPipeline, err := store.GetPipeline(pipeline.ID)
g.Assert(err).IsNil()
g.Assert(pipeline.ID).Equal(GetPipeline.ID)
g.Assert(pipeline.RepoID).Equal(GetPipeline.RepoID)
g.Assert(pipeline.Status).Equal(GetPipeline.Status)
})
pipeline2 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusPending,
Event: model.EventPush,
Branch: "main",
}
err2 = store.CreatePipeline(pipeline2, []*model.Step{}...)
assert.NoError(t, err2)
GetPipeline, err3 := store.GetPipelineNumber(&model.Repo{ID: 1}, pipeline2.Number)
assert.NoError(t, err3)
assert.Equal(t, pipeline2.ID, GetPipeline.ID)
assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID)
assert.Equal(t, pipeline2.Number, GetPipeline.Number)
g.It("Should Get a Pipeline by Number", func() {
pipeline1 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusPending,
}
pipeline2 := &model.Pipeline{
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)
})
GetPipeline, err3 = store.GetPipelineLast(&model.Repo{ID: repo.ID}, pipeline2.Branch)
assert.NoError(t, err3)
assert.Equal(t, pipeline2.ID, GetPipeline.ID)
assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID)
assert.Equal(t, pipeline2.Number, GetPipeline.Number)
assert.Equal(t, pipeline2.Status, GetPipeline.Status)
g.It("Should Get the last Pipeline", func() {
pipeline1 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusFailure,
Branch: "main",
Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac",
Event: model.EventPush,
}
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)
})
pipeline3 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusRunning,
Branch: "main",
Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa",
}
err1 = store.CreatePipeline(pipeline3, []*model.Step{}...)
assert.NoError(t, err1)
g.It("Should Get the last Pipeline Before Pipeline N", func() {
pipeline1 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusFailure,
Branch: "main",
Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
pipeline2 := &model.Pipeline{
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)
})
GetPipeline, err4 := store.GetPipelineLastBefore(&model.Repo{ID: 1}, pipeline3.Branch, pipeline3.ID)
assert.NoError(t, err4)
assert.Equal(t, pipeline2.ID, GetPipeline.ID)
assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID)
assert.Equal(t, pipeline2.Number, GetPipeline.Number)
assert.Equal(t, pipeline2.Status, GetPipeline.Status)
assert.Equal(t, pipeline2.Branch, GetPipeline.Branch)
assert.Equal(t, pipeline2.Commit, GetPipeline.Commit)
}
g.It("Should get recent pipelines", func() {
pipeline1 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusFailure,
Event: model.EventCron,
Ref: "refs/heads/some-branch",
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)
func TestPipelineListFilter(t *testing.T) {
repo := &model.Repo{
UserID: 1,
FullName: "bradrydzewski/test",
Owner: "bradrydzewski",
Name: "test",
}
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Branch: "main",
})
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(1)
g.Assert(pipelines[0].ID).Equal(pipeline2.ID)
store, closer := newTestStore(t, new(model.Repo), new(model.Step), new(model.Pipeline))
defer closer()
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Events: []model.WebhookEvent{model.EventCron},
})
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(1)
g.Assert(pipelines[0].ID).Equal(pipeline1.ID)
assert.NoError(t, store.CreateRepo(repo))
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Events: []model.WebhookEvent{model.EventCron, model.EventPull},
RefContains: "32",
})
g.Assert(err).IsNil()
g.Assert(len(pipelines)).Equal(1)
g.Assert(pipelines[0].ID).Equal(pipeline2.ID)
})
pipeline1 := &model.Pipeline{
RepoID: repo.ID,
Status: model.StatusFailure,
Event: model.EventCron,
Ref: "refs/heads/some-branch",
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{}...)
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() {
pipeline1 := &model.Pipeline{
RepoID: repo.ID,
}
pipeline2 := &model.Pipeline{
RepoID: repo.ID,
}
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)
})
pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, nil)
assert.NoError(t, err)
assert.Len(t, (pipelines), 2)
assert.Equal(t, pipeline2.ID, pipelines[0].ID)
assert.Equal(t, pipeline2.RepoID, pipelines[0].RepoID)
assert.Equal(t, pipeline2.Status, pipelines[0].Status)
g.It("Should get pipelines filtered by status", func() {
pipeline1 := &model.Pipeline{
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)
})
pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{
Branch: "main",
})
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) {

View File

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

View File

@ -18,238 +18,79 @@ package datastore
import (
"testing"
"github.com/franela/goblin"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/server/model"
)
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()
g := goblin.Goblin(t)
g.Describe("User", func() {
// before each test be sure to purge the package
// 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()
})
count, err := store.GetUserCount()
assert.NoError(t, err)
assert.Zero(t, count)
g.It("Should Update a User", func() {
user := model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
err1 := store.CreateUser(&user)
err2 := store.UpdateUser(&user)
getUser, err3 := store.GetUser(user.ID)
g.Assert(err1).IsNil()
g.Assert(err2).IsNil()
g.Assert(err3).IsNil()
g.Assert(user.ID).Equal(getUser.ID)
})
user := model.User{
Login: "joe",
AccessToken: "f0b461ca586c27872b43a0685cbc2847",
RefreshToken: "976f22a5eef7caacb7e678d6c52f49b1",
Email: "foo@bar.com",
Avatar: "b9015b0857e16ac4d94a0ffd9a0b79c8",
}
err = store.CreateUser(&user)
assert.NoError(t, err)
assert.NotZero(t, user.ID)
g.It("Should Add a new User", func() {
user := model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
err := store.CreateUser(&user)
g.Assert(err).IsNil()
g.Assert(user.ID != 0).IsTrue()
})
err2 := store.UpdateUser(&user)
assert.NoError(t, err2)
g.It("Should Get a User", func() {
user := &model.User{
Login: "joe",
AccessToken: "f0b461ca586c27872b43a0685cbc2847",
RefreshToken: "976f22a5eef7caacb7e678d6c52f49b1",
Email: "foo@bar.com",
Avatar: "b9015b0857e16ac4d94a0ffd9a0b79c8",
}
getUser, err := store.GetUser(user.ID)
assert.NoError(t, err)
assert.Equal(t, user.ID, getUser.ID)
assert.Equal(t, user.Login, getUser.Login)
assert.Equal(t, user.AccessToken, getUser.AccessToken)
assert.Equal(t, user.RefreshToken, getUser.RefreshToken)
assert.Equal(t, user.Email, getUser.Email)
assert.Equal(t, user.Avatar, getUser.Avatar)
g.Assert(store.CreateUser(user)).IsNil()
getUser, err := store.GetUser(user.ID)
g.Assert(err).IsNil()
g.Assert(user.ID).Equal(getUser.ID)
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)
})
getUser, err = store.GetUserLogin(user.Login)
assert.NoError(t, err)
assert.Equal(t, user.ID, getUser.ID)
assert.Equal(t, user.Login, getUser.Login)
g.It("Should Get a User By Login", func() {
user := &model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
g.Assert(store.CreateUser(user))
getUser, err := store.GetUserLogin(user.Login)
g.Assert(err).IsNil()
g.Assert(user.ID).Equal(getUser.ID)
g.Assert(user.Login).Equal(getUser.Login)
})
// check unique login
user2 := model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "ab20g0ddaf012c744e136da16aa21ad9",
}
err2 = store.CreateUser(&user2)
assert.Error(t, err2)
g.It("Should Enforce Unique User Login", func() {
user1 := model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "e42080dddf012c718e476da161d21ad5",
}
user2 := model.User{
Login: "joe",
Email: "foo@bar.com",
AccessToken: "ab20g0ddaf012c744e136da16aa21ad9",
}
err1 := store.CreateUser(&user1)
err2 := store.CreateUser(&user2)
g.Assert(err1).IsNil()
g.Assert(err2 == nil).IsFalse()
})
user2 = model.User{
Login: "jane",
Email: "foo@bar.com",
AccessToken: "ab20g0ddaf012c744e136da16aa21ad9",
Hash: "A",
}
assert.NoError(t, store.CreateUser(&user2))
users, err := store.GetUserList(&model.ListOptions{Page: 1, PerPage: 50})
assert.NoError(t, err)
assert.Len(t, users, 2)
// "jane" user is first due to alphabetic sorting
assert.Equal(t, user2.Login, users[0].Login)
assert.Equal(t, user2.Email, users[0].Email)
assert.Equal(t, user2.AccessToken, users[0].AccessToken)
g.It("Should Get a User List", func() {
user1 := model.User{
Login: "jane",
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)
})
count, err = store.GetUserCount()
assert.NoError(t, err)
assert.EqualValues(t, 2, count)
g.It("Should Get a User Count", func() {
user1 := model.User{
Login: "jane",
Email: "foo@bar.com",
AccessToken: "ab20g0ddaf012c744e136da16aa21ad9",
Hash: "A",
}
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)
})
})
getUser, err1 := store.GetUser(user.ID)
assert.NoError(t, err1)
err2 = store.DeleteUser(getUser)
assert.NoError(t, err2)
_, err3 := store.GetUser(getUser.ID)
assert.Error(t, err3)
}

View File

@ -3,60 +3,51 @@ package token_test
import (
"testing"
"github.com/franela/goblin"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"go.woodpecker-ci.org/woodpecker/v3/shared/token"
)
func TestToken(t *testing.T) {
gin.SetMode(gin.TestMode)
const jwtSecret = "secret-to-sign-the-token"
g := goblin.Goblin(t)
g.Describe("Token", func() {
jwtSecret := "secret-to-sign-the-token"
func TestTokenValid(t *testing.T) {
_token := token.New(token.UserToken)
_token.Set("user-id", "1")
signedToken, err := _token.Sign(jwtSecret)
assert.NoError(t, err)
g.It("should parse a valid token", func() {
_token := token.New(token.UserToken)
_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)
})
parsed, err := token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) {
return jwtSecret, nil
})
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)
}