mirror of https://github.com/harness/drone.git
added support for convert plugins
parent
e1ed2623b1
commit
d9b529f2f6
|
@ -50,6 +50,7 @@ type (
|
|||
Authn Authentication
|
||||
Agent Agent
|
||||
AzureBlob AzureBlob
|
||||
Convert Convert
|
||||
Cron Cron
|
||||
Cloning Cloning
|
||||
Database Database
|
||||
|
@ -73,6 +74,7 @@ type (
|
|||
Session Session
|
||||
Status Status
|
||||
Users Users
|
||||
Validate Validate
|
||||
Webhook Webhook
|
||||
Yaml Yaml
|
||||
|
||||
|
@ -295,6 +297,20 @@ type (
|
|||
SkipVerify bool `envconfig:"DRONE_YAML_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// Convert provides the converter webhook configuration.
|
||||
Convert struct {
|
||||
Endpoint string `envconfig:"DRONE_CONVERT_PLUGIN_ENDPOINT"`
|
||||
Secret string `envconfig:"DRONE_CONVERT_PLUGIN_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_CONVERT_PLUGIN_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// Validate provides the validation webhook configuration.
|
||||
Validate struct {
|
||||
Endpoint string `envconfig:"DRONE_VALIDATE_PLUGIN_ENDPOINT"`
|
||||
Secret string `envconfig:"DRONE_VALIDATE_PLUGIN_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_VALIDATE_PLUGIN_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
//
|
||||
// Source code management.
|
||||
//
|
||||
|
|
|
@ -19,8 +19,10 @@ import (
|
|||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/plugin/admission"
|
||||
"github.com/drone/drone/plugin/config"
|
||||
"github.com/drone/drone/plugin/converter"
|
||||
"github.com/drone/drone/plugin/registry"
|
||||
"github.com/drone/drone/plugin/secret"
|
||||
"github.com/drone/drone/plugin/validator"
|
||||
"github.com/drone/drone/plugin/webhook"
|
||||
"github.com/drone/go-scm/scm"
|
||||
|
||||
|
@ -31,8 +33,10 @@ import (
|
|||
var pluginSet = wire.NewSet(
|
||||
provideAdmissionPlugin,
|
||||
provideConfigPlugin,
|
||||
provideConvertPlugin,
|
||||
provideRegistryPlugin,
|
||||
provideSecretPlugin,
|
||||
provideValidatePlugin,
|
||||
provideWebhookPlugin,
|
||||
)
|
||||
|
||||
|
@ -57,20 +61,39 @@ func provideConfigPlugin(client *scm.Client, contents core.FileService, conf spe
|
|||
conf.Yaml.Secret,
|
||||
conf.Yaml.SkipVerify,
|
||||
),
|
||||
config.Jsonnet(contents, conf.Jsonnet.Enabled),
|
||||
config.Repository(contents),
|
||||
)
|
||||
}
|
||||
|
||||
// provideConvertPlugin is a Wire provider function that returns
|
||||
// a yaml conversion plugin based on the environment
|
||||
// configuration.
|
||||
func provideConvertPlugin(client *scm.Client, conf spec.Config) core.ConvertService {
|
||||
return converter.Combine(
|
||||
converter.Legacy(false),
|
||||
converter.Starlark(false),
|
||||
converter.Jsonnet(
|
||||
conf.Jsonnet.Enabled,
|
||||
),
|
||||
converter.Memoize(
|
||||
converter.Remote(
|
||||
conf.Convert.Endpoint,
|
||||
conf.Convert.Secret,
|
||||
conf.Convert.SkipVerify,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// provideRegistryPlugin is a Wire provider function that
|
||||
// returns a registry plugin based on the environment
|
||||
// configuration.
|
||||
func provideRegistryPlugin(config spec.Config) core.RegistryService {
|
||||
return registry.Combine(
|
||||
registry.External(
|
||||
config.Secrets.Endpoint,
|
||||
config.Secrets.Password,
|
||||
config.Secrets.SkipVerify,
|
||||
config.Convert.Endpoint,
|
||||
config.Convert.Secret,
|
||||
config.Convert.SkipVerify,
|
||||
),
|
||||
registry.FileSource(
|
||||
config.Docker.Config,
|
||||
|
@ -93,6 +116,13 @@ func provideSecretPlugin(config spec.Config) core.SecretService {
|
|||
)
|
||||
}
|
||||
|
||||
// provideValidatePlugin is a Wire provider function that
|
||||
// returns a yaml validation plugin based on the environment
|
||||
// configuration.
|
||||
func provideValidatePlugin(conf spec.Config) core.ValidateService {
|
||||
return validator.Combine()
|
||||
}
|
||||
|
||||
// provideWebhookPlugin is a Wire provider function that returns
|
||||
// a webhook plugin based on the environment configuration.
|
||||
func provideWebhookPlugin(config spec.Config, system *core.System) core.WebhookSender {
|
||||
|
|
|
@ -51,13 +51,14 @@ func InitializeApplication(config2 config.Config) (application, error) {
|
|||
repositoryStore := provideRepoStore(db)
|
||||
fileService := provideContentService(client, renewer)
|
||||
configService := provideConfigPlugin(client, fileService, config2)
|
||||
convertService := provideConvertPlugin(client, config2)
|
||||
statusService := provideStatusService(client, renewer, config2)
|
||||
buildStore := provideBuildStore(db)
|
||||
stageStore := provideStageStore(db)
|
||||
scheduler := provideScheduler(stageStore, config2)
|
||||
system := provideSystem(config2)
|
||||
webhookSender := provideWebhookPlugin(config2, system)
|
||||
triggerer := trigger.New(configService, commitService, statusService, buildStore, scheduler, repositoryStore, userStore, webhookSender)
|
||||
triggerer := trigger.New(configService, convertService, commitService, statusService, buildStore, scheduler, repositoryStore, userStore, webhookSender)
|
||||
cronScheduler := cron2.New(commitService, cronStore, repositoryStore, userStore, triggerer)
|
||||
coreLicense := provideLicense(client, config2)
|
||||
datadog := provideDatadog(userStore, repositoryStore, buildStore, system, coreLicense, config2)
|
||||
|
@ -72,7 +73,7 @@ func InitializeApplication(config2 config.Config) (application, error) {
|
|||
secretStore := secret.New(db, encrypter)
|
||||
globalSecretStore := global.New(db, encrypter)
|
||||
stepStore := step.New(db)
|
||||
buildManager := manager.New(buildStore, configService, corePubsub, logStore, logStream, netrcService, repositoryStore, scheduler, secretStore, globalSecretStore, statusService, stageStore, stepStore, system, userStore, webhookSender)
|
||||
buildManager := manager.New(buildStore, configService, convertService, corePubsub, logStore, logStream, netrcService, repositoryStore, scheduler, secretStore, globalSecretStore, statusService, stageStore, stepStore, system, userStore, webhookSender)
|
||||
secretService := provideSecretPlugin(config2)
|
||||
registryService := provideRegistryPlugin(config2)
|
||||
runner := provideRunner(buildManager, secretService, registryService, config2)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// ConvertArgs represents a request to the pipeline
|
||||
// conversion service.
|
||||
ConvertArgs struct {
|
||||
User *User `json:"-"`
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Config *Config `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
// ConvertService converts non-native pipeline
|
||||
// configuration formats to native configuration
|
||||
// formats (e.g. jsonnet to yaml).
|
||||
ConvertService interface {
|
||||
Convert(context.Context, *ConvertArgs) (*Config, error)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// ValidateArgs represents a request to the pipeline
|
||||
// validation service.
|
||||
ValidateArgs struct {
|
||||
User *User `json:"-"`
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Config *Config `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
// ValidateService validates the yaml configuration
|
||||
// and returns an error if the yaml is deemed invalid.
|
||||
ValidateService interface {
|
||||
Validate(context.Context, *ValidateArgs) error
|
||||
}
|
||||
)
|
14
go.mod
14
go.mod
|
@ -17,10 +17,10 @@ require (
|
|||
github.com/docker/distribution v2.7.1+incompatible
|
||||
github.com/docker/go-connections v0.3.0
|
||||
github.com/docker/go-units v0.3.3
|
||||
github.com/drone/drone-go v1.0.5
|
||||
github.com/drone/drone-go v1.0.6
|
||||
github.com/drone/drone-runtime v1.1.0
|
||||
github.com/drone/drone-ui v0.0.0-20190826173727-43d81f243ef3
|
||||
github.com/drone/drone-yaml v1.2.3-0.20190807054305-a4a63fe917cb
|
||||
github.com/drone/drone-yaml v1.2.3-0.20190902155851-ad8ad9816fbf
|
||||
github.com/drone/envsubst v1.0.1
|
||||
github.com/drone/go-license v1.0.2
|
||||
github.com/drone/go-login v1.0.4-0.20190311170324-2a4df4f242a2
|
||||
|
@ -33,7 +33,7 @@ require (
|
|||
github.com/go-ini/ini v1.39.0
|
||||
github.com/go-sql-driver/mysql v1.4.0
|
||||
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506
|
||||
github.com/golang/mock v1.1.1
|
||||
github.com/golang/mock v1.3.1
|
||||
github.com/golang/protobuf v1.2.0
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c
|
||||
github.com/google/go-cmp v0.3.0
|
||||
|
@ -82,11 +82,11 @@ require (
|
|||
github.com/sirupsen/logrus v0.0.0-20181103062819-44067abb194b
|
||||
github.com/spf13/pflag v1.0.3
|
||||
github.com/unrolled/secure v0.0.0-20181022170031-4b6b7cf51606
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
||||
golang.org/x/sys v0.0.0-20181011152604-fa43e7bc11ba
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
|
||||
golang.org/x/text v0.3.0
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c
|
||||
google.golang.org/appengine v1.3.0
|
||||
|
|
16
go.sum
16
go.sum
|
@ -46,6 +46,8 @@ github.com/drone/drone-go v1.0.5-0.20190427184118-618e4496482e h1:Z9dJNcs1IpyS52
|
|||
github.com/drone/drone-go v1.0.5-0.20190427184118-618e4496482e/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
|
||||
github.com/drone/drone-go v1.0.5 h1:KCDzcPoz5yo5DC4sGcLl+6FsUYbCXjBj9d//b5WP5J0=
|
||||
github.com/drone/drone-go v1.0.5/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
|
||||
github.com/drone/drone-go v1.0.6 h1:YbMwEwlE3HC4InN0bT21EDvzImct5dGG1I56dSdUhjI=
|
||||
github.com/drone/drone-go v1.0.6/go.mod h1:GxyeGClYohaKNYJv/ZpsmVHtMJ7WhoT+uDaJNcDIrk4=
|
||||
github.com/drone/drone-runtime v0.0.0-20190210191445-ad403a0ca24e h1:Eq0QI9lKe6T5pziU/Kes1xX6QKAA6ZfnYvaZZeyY5TU=
|
||||
github.com/drone/drone-runtime v0.0.0-20190210191445-ad403a0ca24e/go.mod h1:I+wJO4yvngCUAro6wKjkMbuPPDI/jRynqU0LTW+8J44=
|
||||
github.com/drone/drone-runtime v1.0.3 h1:0p7ASt0WXbLZRzMOw20e1ahV3YkamRhtZFkm8UvM+JA=
|
||||
|
@ -114,6 +116,8 @@ github.com/drone/drone-yaml v1.2.2 h1:Srf8OlAHhR7SXX5Ax01dP5tpZENsrEKyg35E2nNkIe
|
|||
github.com/drone/drone-yaml v1.2.2/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10=
|
||||
github.com/drone/drone-yaml v1.2.3-0.20190807054305-a4a63fe917cb h1:YsuNqXQD8+FbFOsDZLYimmkzJxkN0h6gzAH1r0xk/qk=
|
||||
github.com/drone/drone-yaml v1.2.3-0.20190807054305-a4a63fe917cb/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10=
|
||||
github.com/drone/drone-yaml v1.2.3-0.20190902155851-ad8ad9816fbf h1:/devrXEXhpmOrJpPxYxxz3PInxqNzqo6hzxDYVfmwJg=
|
||||
github.com/drone/drone-yaml v1.2.3-0.20190902155851-ad8ad9816fbf/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10=
|
||||
github.com/drone/envsubst v1.0.1 h1:NOOStingM2sbBwsIUeQkKUz8ShwCUzmqMxWrpXItfPE=
|
||||
github.com/drone/envsubst v1.0.1/go.mod h1:bkZbnc/2vh1M12Ecn7EYScpI4YGYU0etwLJICOWi8Z0=
|
||||
github.com/drone/go-license v1.0.2 h1:7OwndfYk+Lp/cGHkxe4HUn/Ysrrw3WYH2pnd99yrkok=
|
||||
|
@ -162,6 +166,8 @@ github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506/go.mod h1:r8qH/GZQm5
|
|||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
|
||||
|
@ -266,6 +272,7 @@ github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 h1:x7xEyJDP7Hv3LVgvWhz
|
|||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
github.com/segmentio/ksuid v1.0.2 h1:9yBfKyw4ECGTdALaF09Snw3sLJmYIX6AbPJrAy6MrDc=
|
||||
github.com/segmentio/ksuid v1.0.2/go.mod h1:BXuJDr2byAiHuQaQtSKoXh1J0YmUDurywOXgB2w+OSU=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sirupsen/logrus v0.0.0-20181103062819-44067abb194b h1:dnSVC38LseSWVhj3WWqD3worKZY+EqoWwi+MMAKgPbs=
|
||||
github.com/sirupsen/logrus v0.0.0-20181103062819-44067abb194b/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
|
@ -285,23 +292,32 @@ golang.org/x/crypto v0.0.0-20181012144002-a92615f3c490 h1:va0qYsIOza3Nlf2IncFyOq
|
|||
golang.org/x/crypto v0.0.0-20181012144002-a92615f3c490/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 h1:uESlIz09WIHT2I+pasSXcpLYqYK8wHcdCetU3VuMBJE=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181005133103-4497e2df6f9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181011152604-fa43e7bc11ba h1:nZJIJPGow0Kf9bU9QTc1U6OXbs/7Hu4e+cNv+hxH+Zc=
|
||||
golang.org/x/sys v0.0.0-20181011152604-fa43e7bc11ba/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20181017214349-06f26fdaaa28/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
package mock
|
||||
|
||||
//go:generate mockgen -package=mock -destination=mock_gen.go github.com/drone/drone/core NetrcService,Renewer,HookParser,UserService,RepositoryService,CommitService,StatusService,HookService,FileService,Batcher,BuildStore,CronStore,LogStore,PermStore,SecretStore,GlobalSecretStore,StageStore,StepStore,RepositoryStore,UserStore,Scheduler,Session,OrganizationService,SecretService,RegistryService,ConfigService,Triggerer,Syncer,LogStream,WebhookSender,LicenseService
|
||||
//go:generate mockgen -package=mock -destination=mock_gen.go github.com/drone/drone/core ConvertService,NetrcService,Renewer,HookParser,UserService,RepositoryService,CommitService,StatusService,HookService,FileService,Batcher,BuildStore,CronStore,LogStore,PermStore,SecretStore,GlobalSecretStore,StageStore,StepStore,RepositoryStore,UserStore,Scheduler,Session,OrganizationService,SecretService,RegistryService,ConfigService,Triggerer,Syncer,LogStream,WebhookSender,LicenseService
|
||||
|
|
264
mock/mock_gen.go
264
mock/mock_gen.go
File diff suppressed because it is too large
Load Diff
|
@ -101,6 +101,7 @@ type (
|
|||
func New(
|
||||
builds core.BuildStore,
|
||||
config core.ConfigService,
|
||||
converter core.ConvertService,
|
||||
events core.Pubsub,
|
||||
logs core.LogStore,
|
||||
logz core.LogStream,
|
||||
|
@ -119,6 +120,7 @@ func New(
|
|||
return &Manager{
|
||||
Builds: builds,
|
||||
Config: config,
|
||||
Converter: converter,
|
||||
Events: events,
|
||||
Globals: globals,
|
||||
Logs: logs,
|
||||
|
@ -141,6 +143,7 @@ func New(
|
|||
type Manager struct {
|
||||
Builds core.BuildStore
|
||||
Config core.ConfigService
|
||||
Converter core.ConvertService
|
||||
Events core.Pubsub
|
||||
Globals core.GlobalSecretStore
|
||||
Logs core.LogStore
|
||||
|
@ -285,6 +288,12 @@ func (m *Manager) Details(ctx context.Context, id int64) (*Context, error) {
|
|||
logger.Warnln("manager: cannot find configuration")
|
||||
return nil, err
|
||||
}
|
||||
config, err = m.Converter.Convert(noContext, &core.ConvertArgs{
|
||||
Build: build,
|
||||
Config: config,
|
||||
Repo: repo,
|
||||
User: user,
|
||||
})
|
||||
var secrets []*core.Secret
|
||||
tmpSecrets, err := m.Secrets.List(noContext, repo.ID)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
// Combine combines the conversion services, provision support
|
||||
// for multiple conversion utilities.
|
||||
func Combine(services ...core.ConvertService) core.ConvertService {
|
||||
return &combined{services}
|
||||
}
|
||||
|
||||
type combined struct {
|
||||
sources []core.ConvertService
|
||||
}
|
||||
|
||||
func (c *combined) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
||||
for _, source := range c.sources {
|
||||
config, err := source.Convert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if config == nil {
|
||||
continue
|
||||
}
|
||||
if config.Data == "" {
|
||||
continue
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
return req.Config, nil
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/mock"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
var noContext = context.Background()
|
||||
|
||||
var mockFile = `
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: testing
|
||||
`
|
||||
|
||||
func TestCombine(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
args := &core.ConvertArgs{
|
||||
User: &core.User{Login: "octocat"},
|
||||
Repo: &core.Repository{Slug: "octocat/hello-world", Config: ".drone.yml"},
|
||||
Build: &core.Build{After: "6d144de7"},
|
||||
Config: &core.Config{},
|
||||
}
|
||||
|
||||
resp := &core.Config{Data: string(mockFile)}
|
||||
|
||||
service := mock.NewMockConvertService(controller)
|
||||
service.EXPECT().Convert(noContext, args).Return(resp, nil)
|
||||
|
||||
result, err := Combine(service).Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if result.Data != string(resp.Data) {
|
||||
t.Errorf("unexpected file contents")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCombineErr(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
resp := errors.New("")
|
||||
service := mock.NewMockConvertService(controller)
|
||||
service.EXPECT().Convert(noContext, nil).Return(nil, resp)
|
||||
|
||||
_, err := Combine(service).Convert(noContext, nil)
|
||||
if err != resp {
|
||||
t.Errorf("expected convert service error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCombineNoConfig(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
args := &core.ConvertArgs{
|
||||
User: &core.User{Login: "octocat"},
|
||||
Repo: &core.Repository{Slug: "octocat/hello-world", Config: ".drone.yml"},
|
||||
Build: &core.Build{After: "6d144de7"},
|
||||
}
|
||||
|
||||
resp := &core.Config{Data: string(mockFile)}
|
||||
|
||||
service1 := mock.NewMockConvertService(controller)
|
||||
service1.EXPECT().Convert(noContext, args).Return(nil, nil)
|
||||
|
||||
service2 := mock.NewMockConvertService(controller)
|
||||
service2.EXPECT().Convert(noContext, args).Return(&core.Config{}, nil)
|
||||
|
||||
service3 := mock.NewMockConvertService(controller)
|
||||
service3.EXPECT().Convert(noContext, args).Return(resp, nil)
|
||||
|
||||
result, err := Combine(service1, service2, service3).Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if result.Data != string(resp.Data) {
|
||||
t.Errorf("unexpected file contents")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCombineEmptyConfig(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
args := &core.ConvertArgs{
|
||||
User: &core.User{Login: "octocat"},
|
||||
Repo: &core.Repository{Slug: "octocat/hello-world", Config: ".drone.yml"},
|
||||
Build: &core.Build{After: "6d144de7"},
|
||||
Config: &core.Config{Data: string(mockFile)},
|
||||
}
|
||||
|
||||
service1 := mock.NewMockConvertService(controller)
|
||||
service1.EXPECT().Convert(noContext, args).Return(nil, nil)
|
||||
|
||||
result, err := Combine(service1).Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if result != args.Config {
|
||||
t.Errorf("unexpected file contents")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
|
||||
"github.com/google/go-jsonnet"
|
||||
)
|
||||
|
||||
// TODO(bradrydzewski) handle jsonnet imports
|
||||
// TODO(bradrydzewski) handle jsonnet object vs array output
|
||||
|
||||
// Jsonnet returns a conversion service that converts the
|
||||
// jsonnet file to a yaml file.
|
||||
func Jsonnet(enabled bool) core.ConvertService {
|
||||
return &jsonnetPlugin{
|
||||
enabled: enabled,
|
||||
}
|
||||
}
|
||||
|
||||
type jsonnetPlugin struct {
|
||||
enabled bool
|
||||
}
|
||||
|
||||
func (p *jsonnetPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
||||
if p.enabled == false {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// if the file extension is not jsonnet we can
|
||||
// skip this plugin by returning zero values.
|
||||
if strings.HasSuffix(req.Repo.Config, ".jsonnet") == false {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// create the jsonnet vm
|
||||
vm := jsonnet.MakeVM()
|
||||
vm.MaxStack = 500
|
||||
vm.StringOutput = false
|
||||
vm.ErrorFormatter.SetMaxStackTraceSize(20)
|
||||
|
||||
// convert the jsonnet file to yaml
|
||||
buf := new(bytes.Buffer)
|
||||
docs, err := vm.EvaluateSnippetStream(req.Repo.Config, req.Config.Data)
|
||||
if err != nil {
|
||||
doc, err2 := vm.EvaluateSnippet(req.Repo.Config, req.Config.Data)
|
||||
if err2 != nil {
|
||||
return nil, err
|
||||
}
|
||||
docs = append(docs, doc)
|
||||
}
|
||||
|
||||
// the jsonnet vm returns a stream of yaml documents
|
||||
// that need to be combined into a single yaml file.
|
||||
for _, doc := range docs {
|
||||
buf.WriteString("---")
|
||||
buf.WriteString("\n")
|
||||
buf.WriteString(doc)
|
||||
}
|
||||
|
||||
return &core.Config{
|
||||
Data: buf.String(),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
// Jsonnet returns a conversion service that converts the
|
||||
// jsonnet file to a yaml file.
|
||||
func Jsonnet(enabled bool) core.ConvertService {
|
||||
return new(noop)
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
const jsonnetFile = `{"foo": "bar"}`
|
||||
const jsonnetFileAfter = `---
|
||||
{
|
||||
"foo": "bar"
|
||||
}
|
||||
`
|
||||
|
||||
const jsonnetStream = `[{"foo": "bar"}]`
|
||||
const jsonnetStreamAfter = `---
|
||||
{
|
||||
"foo": "bar"
|
||||
}
|
||||
`
|
||||
|
||||
func TestJsonnet_Stream(t *testing.T) {
|
||||
args := &core.ConvertArgs{
|
||||
Repo: &core.Repository{Config: ".drone.jsonnet"},
|
||||
Config: &core.Config{Data: jsonnetStream},
|
||||
}
|
||||
service := Jsonnet(true)
|
||||
res, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if res == nil {
|
||||
t.Errorf("Expected a converted file, got nil")
|
||||
return
|
||||
}
|
||||
if got, want := res.Data, jsonnetStreamAfter; got != want {
|
||||
t.Errorf("Want converted file %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonnet_Snippet(t *testing.T) {
|
||||
args := &core.ConvertArgs{
|
||||
Repo: &core.Repository{Config: ".drone.jsonnet"},
|
||||
Config: &core.Config{Data: jsonnetFile},
|
||||
}
|
||||
service := Jsonnet(true)
|
||||
res, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if res == nil {
|
||||
t.Errorf("Expected a converted file, got nil")
|
||||
return
|
||||
}
|
||||
if got, want := res.Data, jsonnetFileAfter; got != want {
|
||||
t.Errorf("Want converted file %q, got %q", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonnet_Error(t *testing.T) {
|
||||
args := &core.ConvertArgs{
|
||||
Repo: &core.Repository{Config: ".drone.jsonnet"},
|
||||
Config: &core.Config{Data: "\\"}, // invalid jsonnet
|
||||
}
|
||||
service := Jsonnet(true)
|
||||
_, err := service.Convert(noContext, args)
|
||||
if err == nil {
|
||||
t.Errorf("Expect jsonnet parsing error, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonnet_Disabled(t *testing.T) {
|
||||
service := Jsonnet(false)
|
||||
res, err := service.Convert(noContext, nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if res != nil {
|
||||
t.Errorf("Expect nil response when disabled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonnet_NotJsonnet(t *testing.T) {
|
||||
args := &core.ConvertArgs{
|
||||
Repo: &core.Repository{Config: ".drone.yml"},
|
||||
}
|
||||
service := Jsonnet(true)
|
||||
res, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if res != nil {
|
||||
t.Errorf("Expect nil response when not jsonnet")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
// Legacy returns a conversion service that converts a
|
||||
// legacy 0.8 yaml file to a yaml file.
|
||||
func Legacy(enabled bool) core.ConvertService {
|
||||
return &legacyPlugin{
|
||||
enabled: enabled,
|
||||
}
|
||||
}
|
||||
|
||||
type legacyPlugin struct {
|
||||
enabled bool
|
||||
}
|
||||
|
||||
func (p *legacyPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
||||
if p.enabled == false {
|
||||
return nil, nil
|
||||
}
|
||||
return &core.Config{
|
||||
Data: req.Config.Data,
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// cache key pattern used in the cache, comprised of the
|
||||
// repository slug and commit sha.
|
||||
const keyf = "%d/%s"
|
||||
|
||||
// Memoize caches the conversion results for subsequent calls.
|
||||
// This micro-optimization is intended for multi-pipeline
|
||||
// projects that would otherwise covert the file for each
|
||||
// pipeline execution.
|
||||
func Memoize(base core.ConvertService) core.ConvertService {
|
||||
// simple cache prevents the same yaml file from being
|
||||
// requested multiple times in a short period.
|
||||
cache, _ := lru.New(25)
|
||||
return &memoize{base: base, cache: cache}
|
||||
}
|
||||
|
||||
type memoize struct {
|
||||
base core.ConvertService
|
||||
cache *lru.Cache
|
||||
}
|
||||
|
||||
func (c *memoize) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
||||
// this is a minor optimization that prevents caching if the
|
||||
// base converter is a remote converter and is disabled.
|
||||
if remote, ok := c.base.(*remote); ok == true && remote.endpoint == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// generate the key used to cache the converted file.
|
||||
key := fmt.Sprintf(keyf, req.Repo.ID, req.Build.After)
|
||||
|
||||
// some source control management systems (gogs) do not provide
|
||||
// the commit sha for tag webhooks. If no commit sha is available
|
||||
// the ref is used.
|
||||
if req.Build.After == "" {
|
||||
key = fmt.Sprintf(keyf, req.Repo.ID, req.Build.Ref)
|
||||
}
|
||||
|
||||
// check the cache for the file and return if exists.
|
||||
cached, ok := c.cache.Get(key)
|
||||
if ok {
|
||||
return cached.(*core.Config), nil
|
||||
}
|
||||
|
||||
// else convert the configuration file.
|
||||
config, err := c.base.Convert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if config.Data == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// if the configuration file was converted
|
||||
// it is temporarily cached.
|
||||
c.cache.Add(key, config)
|
||||
return config, nil
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/mock"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
func TestMemoize(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
conf := &core.Config{Data: "{kind: pipeline, type: docker, steps: []}"}
|
||||
args := &core.ConvertArgs{
|
||||
Build: &core.Build{After: "3950521325d4744760a96c18e3d0c67d86495af3"},
|
||||
Repo: &core.Repository{ID: 42},
|
||||
Config: conf,
|
||||
}
|
||||
|
||||
base := mock.NewMockConvertService(controller)
|
||||
base.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(args.Config, nil)
|
||||
|
||||
service := Memoize(base).(*memoize)
|
||||
_, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if got, want := service.cache.Len(), 1; got != want {
|
||||
t.Errorf("Expect %d items in cache, got %d", want, got)
|
||||
}
|
||||
|
||||
args.Config = nil // set to nil to prove we get the cached value
|
||||
res, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if res != conf {
|
||||
t.Errorf("Expect result from cache")
|
||||
}
|
||||
|
||||
if got, want := service.cache.Len(), 1; got != want {
|
||||
t.Errorf("Expect %d items in cache, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoize_Tag(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
args := &core.ConvertArgs{
|
||||
Build: &core.Build{Ref: "refs/tags/v1.0.0"},
|
||||
Repo: &core.Repository{ID: 42},
|
||||
Config: &core.Config{Data: "{kind: pipeline, type: docker, steps: []}"},
|
||||
}
|
||||
|
||||
base := mock.NewMockConvertService(controller)
|
||||
base.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(args.Config, nil)
|
||||
|
||||
service := Memoize(base).(*memoize)
|
||||
res, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if res != args.Config {
|
||||
t.Errorf("Expect result from cache")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoize_Empty(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
args := &core.ConvertArgs{
|
||||
Build: &core.Build{After: "3950521325d4744760a96c18e3d0c67d86495af3"},
|
||||
Repo: &core.Repository{ID: 42},
|
||||
Config: &core.Config{Data: ""}, // empty
|
||||
}
|
||||
|
||||
base := mock.NewMockConvertService(controller)
|
||||
base.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(args.Config, nil)
|
||||
|
||||
service := Memoize(base).(*memoize)
|
||||
res, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if res != nil {
|
||||
t.Errorf("Expect nil response")
|
||||
}
|
||||
if got, want := service.cache.Len(), 0; got != want {
|
||||
t.Errorf("Expect %d items in cache, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoize_Nil(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
args := &core.ConvertArgs{
|
||||
Build: &core.Build{After: "3950521325d4744760a96c18e3d0c67d86495af3"},
|
||||
Repo: &core.Repository{ID: 42},
|
||||
Config: nil,
|
||||
}
|
||||
|
||||
base := mock.NewMockConvertService(controller)
|
||||
base.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(args.Config, nil)
|
||||
|
||||
service := Memoize(base).(*memoize)
|
||||
res, err := service.Convert(noContext, args)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if res != nil {
|
||||
t.Errorf("Expect nil response")
|
||||
}
|
||||
if got, want := service.cache.Len(), 0; got != want {
|
||||
t.Errorf("Expect %d items in cache, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMemoize_Error(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
args := &core.ConvertArgs{
|
||||
Build: &core.Build{After: "3950521325d4744760a96c18e3d0c67d86495af3"},
|
||||
Repo: &core.Repository{ID: 42},
|
||||
}
|
||||
|
||||
want := errors.New("not found")
|
||||
base := mock.NewMockConvertService(controller)
|
||||
base.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(nil, want)
|
||||
|
||||
service := Memoize(base).(*memoize)
|
||||
_, err := service.Convert(noContext, args)
|
||||
if err == nil {
|
||||
t.Errorf("Expect error from base returned to caller")
|
||||
return
|
||||
}
|
||||
if got, want := service.cache.Len(), 0; got != want {
|
||||
t.Errorf("Expect %d items in cache, got %d", want, got)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
type noop struct{}
|
||||
|
||||
func (noop) Convert(context.Context, *core.ConvertArgs) (*core.Config, error) {
|
||||
return nil, nil
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone-go/drone"
|
||||
"github.com/drone/drone-go/plugin/converter"
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
// Remote returns a conversion service that converts the
|
||||
// configuration file using a remote http service.
|
||||
func Remote(endpoint, signer string, skipVerify bool) core.ConvertService {
|
||||
return &remote{
|
||||
endpoint: endpoint,
|
||||
secret: signer,
|
||||
skipVerify: skipVerify,
|
||||
}
|
||||
}
|
||||
|
||||
type remote struct {
|
||||
endpoint string
|
||||
secret string
|
||||
skipVerify bool
|
||||
}
|
||||
|
||||
func (g *remote) Convert(ctx context.Context, in *core.ConvertArgs) (*core.Config, error) {
|
||||
if g.endpoint == "" {
|
||||
return nil, nil
|
||||
}
|
||||
// include a timeout to prevent an API call from
|
||||
// hanging the build process indefinitely. The
|
||||
// external service must return a request within
|
||||
// one minute.
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Minute)
|
||||
defer cancel()
|
||||
|
||||
req := &converter.Request{
|
||||
Repo: toRepo(in.Repo),
|
||||
Build: toBuild(in.Build),
|
||||
Config: drone.Config{
|
||||
Data: in.Config.Data,
|
||||
},
|
||||
}
|
||||
client := converter.Client(g.endpoint, g.secret, g.skipVerify)
|
||||
res, err := client.Convert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// if no error is returned and the secret is empty,
|
||||
// this indicates the client returned No Content,
|
||||
// and we should exit with no secret, but no error.
|
||||
if res.Data == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &core.Config{
|
||||
Kind: res.Kind,
|
||||
Data: res.Data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toRepo(from *core.Repository) drone.Repo {
|
||||
return drone.Repo{
|
||||
ID: from.ID,
|
||||
UID: from.UID,
|
||||
UserID: from.UserID,
|
||||
Namespace: from.Namespace,
|
||||
Name: from.Name,
|
||||
Slug: from.Slug,
|
||||
SCM: from.SCM,
|
||||
HTTPURL: from.HTTPURL,
|
||||
SSHURL: from.SSHURL,
|
||||
Link: from.Link,
|
||||
Branch: from.Branch,
|
||||
Private: from.Private,
|
||||
Visibility: from.Visibility,
|
||||
Active: from.Active,
|
||||
Config: from.Config,
|
||||
Trusted: from.Trusted,
|
||||
Protected: from.Protected,
|
||||
Timeout: from.Timeout,
|
||||
}
|
||||
}
|
||||
|
||||
func toBuild(from *core.Build) drone.Build {
|
||||
return drone.Build{
|
||||
ID: from.ID,
|
||||
RepoID: from.RepoID,
|
||||
Trigger: from.Trigger,
|
||||
Number: from.Number,
|
||||
Parent: from.Parent,
|
||||
Status: from.Status,
|
||||
Error: from.Error,
|
||||
Event: from.Event,
|
||||
Action: from.Action,
|
||||
Link: from.Link,
|
||||
Timestamp: from.Timestamp,
|
||||
Title: from.Title,
|
||||
Message: from.Message,
|
||||
Before: from.Before,
|
||||
After: from.After,
|
||||
Ref: from.Ref,
|
||||
Fork: from.Fork,
|
||||
Source: from.Source,
|
||||
Target: from.Target,
|
||||
Author: from.Author,
|
||||
AuthorName: from.AuthorName,
|
||||
AuthorEmail: from.AuthorEmail,
|
||||
AuthorAvatar: from.AuthorAvatar,
|
||||
Sender: from.Sender,
|
||||
Params: from.Params,
|
||||
Deploy: from.Deploy,
|
||||
Started: from.Started,
|
||||
Finished: from.Finished,
|
||||
Created: from.Created,
|
||||
Updated: from.Updated,
|
||||
Version: from.Version,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package converter
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
// Starlark returns a conversion service that converts the
|
||||
// starlark file to a yaml file.
|
||||
func Starlark(enabled bool) core.ConvertService {
|
||||
return &starlarkPlugin{
|
||||
enabled: enabled,
|
||||
}
|
||||
}
|
||||
|
||||
type starlarkPlugin struct {
|
||||
enabled bool
|
||||
}
|
||||
|
||||
func (p *starlarkPlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*core.Config, error) {
|
||||
if p.enabled == false {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// if the file extension is not jsonnet we can
|
||||
// skip this plugin by returning zero values.
|
||||
switch {
|
||||
case strings.HasSuffix(req.Repo.Config, ".script"):
|
||||
case strings.HasSuffix(req.Repo.Config, ".star"):
|
||||
case strings.HasSuffix(req.Repo.Config, ".starlark"):
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// convert the jsonnet file to yaml
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
return &core.Config{
|
||||
Data: buf.String(),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build oss
|
||||
|
||||
package converter
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
// Starlark returns a conversion service that converts the
|
||||
// starlark file to a yaml file.
|
||||
func Starlark(enabled bool) core.ConvertService {
|
||||
return new(noop)
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2019 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
)
|
||||
|
||||
// Combine combines the conversion services, provision support
|
||||
// for multiple conversion utilities.
|
||||
func Combine(services ...core.ValidateService) core.ValidateService {
|
||||
return &combined{services}
|
||||
}
|
||||
|
||||
type combined struct {
|
||||
sources []core.ValidateService
|
||||
}
|
||||
|
||||
func (c *combined) Validate(ctx context.Context, req *core.ValidateArgs) error {
|
||||
for _, source := range c.sources {
|
||||
if err := source.Validate(ctx, req); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -33,6 +33,7 @@ import (
|
|||
|
||||
type triggerer struct {
|
||||
config core.ConfigService
|
||||
convert core.ConvertService
|
||||
commits core.CommitService
|
||||
status core.StatusService
|
||||
builds core.BuildStore
|
||||
|
@ -45,6 +46,7 @@ type triggerer struct {
|
|||
// New returns a new build triggerer.
|
||||
func New(
|
||||
config core.ConfigService,
|
||||
convert core.ConvertService,
|
||||
commits core.CommitService,
|
||||
status core.StatusService,
|
||||
builds core.BuildStore,
|
||||
|
@ -55,6 +57,7 @@ func New(
|
|||
) core.Triggerer {
|
||||
return &triggerer{
|
||||
config: config,
|
||||
convert: convert,
|
||||
commits: commits,
|
||||
status: status,
|
||||
builds: builds,
|
||||
|
@ -152,40 +155,39 @@ func (t *triggerer) Trigger(ctx context.Context, repo *core.Repository, base *co
|
|||
// obj = base.Ref
|
||||
// }
|
||||
// }
|
||||
|
||||
tmpBuild := &core.Build{
|
||||
RepoID: repo.ID,
|
||||
Trigger: base.Trigger,
|
||||
Parent: base.Parent,
|
||||
Status: core.StatusPending,
|
||||
Event: base.Event,
|
||||
Action: base.Action,
|
||||
Link: base.Link,
|
||||
// Timestamp: base.Timestamp,
|
||||
Title: base.Title,
|
||||
Message: base.Message,
|
||||
Before: base.Before,
|
||||
After: base.After,
|
||||
Ref: base.Ref,
|
||||
Fork: base.Fork,
|
||||
Source: base.Source,
|
||||
Target: base.Target,
|
||||
Author: base.Author,
|
||||
AuthorName: base.AuthorName,
|
||||
AuthorEmail: base.AuthorEmail,
|
||||
AuthorAvatar: base.AuthorAvatar,
|
||||
Params: base.Params,
|
||||
Cron: base.Cron,
|
||||
Deploy: base.Deployment,
|
||||
DeployID: base.DeploymentID,
|
||||
Sender: base.Sender,
|
||||
Created: time.Now().Unix(),
|
||||
Updated: time.Now().Unix(),
|
||||
}
|
||||
req := &core.ConfigArgs{
|
||||
User: user,
|
||||
Repo: repo,
|
||||
// TODO this is duplicated
|
||||
Build: &core.Build{
|
||||
RepoID: repo.ID,
|
||||
Trigger: base.Trigger,
|
||||
Parent: base.Parent,
|
||||
Status: core.StatusPending,
|
||||
Event: base.Event,
|
||||
Action: base.Action,
|
||||
Link: base.Link,
|
||||
// Timestamp: base.Timestamp,
|
||||
Title: base.Title,
|
||||
Message: base.Message,
|
||||
Before: base.Before,
|
||||
After: base.After,
|
||||
Ref: base.Ref,
|
||||
Fork: base.Fork,
|
||||
Source: base.Source,
|
||||
Target: base.Target,
|
||||
Author: base.Author,
|
||||
AuthorName: base.AuthorName,
|
||||
AuthorEmail: base.AuthorEmail,
|
||||
AuthorAvatar: base.AuthorAvatar,
|
||||
Params: base.Params,
|
||||
Cron: base.Cron,
|
||||
Deploy: base.Deployment,
|
||||
DeployID: base.DeploymentID,
|
||||
Sender: base.Sender,
|
||||
Created: time.Now().Unix(),
|
||||
Updated: time.Now().Unix(),
|
||||
},
|
||||
User: user,
|
||||
Repo: repo,
|
||||
Build: tmpBuild,
|
||||
}
|
||||
|
||||
raw, err := t.config.Find(ctx, req)
|
||||
|
@ -195,6 +197,18 @@ func (t *triggerer) Trigger(ctx context.Context, repo *core.Repository, base *co
|
|||
return nil, err
|
||||
}
|
||||
|
||||
raw, err = t.convert.Convert(ctx, &core.ConvertArgs{
|
||||
User: user,
|
||||
Repo: repo,
|
||||
Build: tmpBuild,
|
||||
Config: raw,
|
||||
})
|
||||
if err != nil {
|
||||
logger = logger.WithError(err)
|
||||
logger.Warnln("trigger: cannot convert yaml")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// this code is temporarily in place to detect and convert
|
||||
// the legacy yaml configuration file to the new format.
|
||||
raw.Data, err = converter.ConvertString(raw.Data, converter.Metadata{
|
||||
|
|
|
@ -60,6 +60,9 @@ func TestTrigger(t *testing.T) {
|
|||
mockConfigService := mock.NewMockConfigService(controller)
|
||||
mockConfigService.EXPECT().Find(gomock.Any(), gomock.Any()).Return(dummyYaml, nil)
|
||||
|
||||
mockConvertService := mock.NewMockConvertService(controller)
|
||||
mockConvertService.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(dummyYaml, nil)
|
||||
|
||||
mockStatus := mock.NewMockStatusService(controller)
|
||||
mockStatus.EXPECT().Send(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Do(checkStatus)
|
||||
|
||||
|
@ -74,6 +77,7 @@ func TestTrigger(t *testing.T) {
|
|||
|
||||
triggerer := New(
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
mockStatus,
|
||||
mockBuilds,
|
||||
|
@ -105,6 +109,7 @@ func TestTrigger_SkipCI(t *testing.T) {
|
|||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
dummyHookSkip := *dummyHook
|
||||
dummyHookSkip.Message = "foo [CI SKIP] bar"
|
||||
|
@ -129,6 +134,7 @@ func TestTrigger_NoOwner(t *testing.T) {
|
|||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
mockUsers,
|
||||
nil,
|
||||
)
|
||||
|
@ -158,6 +164,7 @@ func TestTrigger_MissingYaml(t *testing.T) {
|
|||
nil,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
mockUsers,
|
||||
nil,
|
||||
)
|
||||
|
@ -180,6 +187,9 @@ func TestTrigger_ErrorYaml(t *testing.T) {
|
|||
mockConfigService := mock.NewMockConfigService(controller)
|
||||
mockConfigService.EXPECT().Find(gomock.Any(), gomock.Any()).Return(dummyYamlInvalid, nil)
|
||||
|
||||
mockConvertService := mock.NewMockConvertService(controller)
|
||||
mockConvertService.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(dummyYamlInvalid, nil)
|
||||
|
||||
mockRepos := mock.NewMockRepositoryStore(controller)
|
||||
mockRepos.EXPECT().Increment(gomock.Any(), dummyRepo).Return(dummyRepo, nil)
|
||||
|
||||
|
@ -188,6 +198,7 @@ func TestTrigger_ErrorYaml(t *testing.T) {
|
|||
|
||||
triggerer := New(
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
nil,
|
||||
mockBuilds,
|
||||
|
@ -225,8 +236,12 @@ func TestTrigger_SkipBranch(t *testing.T) {
|
|||
mockConfigService := mock.NewMockConfigService(controller)
|
||||
mockConfigService.EXPECT().Find(gomock.Any(), gomock.Any()).Return(dummyYamlSkipBranch, nil)
|
||||
|
||||
mockConvertService := mock.NewMockConvertService(controller)
|
||||
mockConvertService.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(dummyYamlSkipBranch, nil)
|
||||
|
||||
triggerer := New(
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
|
@ -254,8 +269,12 @@ func TestTrigger_SkipEvent(t *testing.T) {
|
|||
mockConfigService := mock.NewMockConfigService(controller)
|
||||
mockConfigService.EXPECT().Find(gomock.Any(), gomock.Any()).Return(dummyYamlSkipEvent, nil)
|
||||
|
||||
mockConvertService := mock.NewMockConvertService(controller)
|
||||
mockConvertService.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(dummyYamlSkipEvent, nil)
|
||||
|
||||
triggerer := New(
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
|
@ -283,8 +302,12 @@ func TestTrigger_SkipAction(t *testing.T) {
|
|||
mockConfigService := mock.NewMockConfigService(controller)
|
||||
mockConfigService.EXPECT().Find(gomock.Any(), gomock.Any()).Return(dummyYamlSkipAction, nil)
|
||||
|
||||
mockConvertService := mock.NewMockConvertService(controller)
|
||||
mockConvertService.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(dummyYamlSkipAction, nil)
|
||||
|
||||
triggerer := New(
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
|
@ -316,8 +339,12 @@ func TestTrigger_ErrorIncrement(t *testing.T) {
|
|||
mockConfigService := mock.NewMockConfigService(controller)
|
||||
mockConfigService.EXPECT().Find(gomock.Any(), gomock.Any()).Return(dummyYaml, nil)
|
||||
|
||||
mockConvertService := mock.NewMockConvertService(controller)
|
||||
mockConvertService.EXPECT().Convert(gomock.Any(), gomock.Any()).Return(dummyYaml, nil)
|
||||
|
||||
triggerer := New(
|
||||
mockConfigService,
|
||||
mockConvertService,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
|
|
Loading…
Reference in New Issue