added support for convert plugins

pull/2820/head
Brad Rydzewski 2019-09-02 23:05:30 -07:00
parent e1ed2623b1
commit d9b529f2f6
26 changed files with 1429 additions and 48 deletions

View File

@ -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.
//

View File

@ -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 {

View File

@ -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)

35
core/convert.go Normal file
View File

@ -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)
}
)

34
core/validate.go Normal file
View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 {

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}

29
plugin/converter/noop.go Normal file
View File

@ -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
}

131
plugin/converter/remote.go Normal file
View File

@ -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,
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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{

View File

@ -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,